import csv
import functools
from itertools import product
import re
import random
import string

from loguru import logger

from apps.electives.models import ElectiveThematic, Elective, ElectiveKind, CreditUnitsKind, KindOfElective

def generate_random_error_name():
    return 'ErrorName___' + ''.join(random.choices(string.ascii_letters, k=6))

def create_short_thematic_keys():
    thematic_keys = {
        'А': 'Aлгебра',
        'АД': 'Анализ данных',
        'ДМЛ': 'Дискретная математика и логика',
        'ГиТ': 'Геометрия и топология',
        'МФ': 'Математическая физика',
        'ДУДС': 'Дифференциальные уравнения и динамические системы',
        'И': 'Информатика',
        'МА': 'Математический анализ',
        'П': 'Программирование',
        'По': 'Программирование (обязательные курсы СП)',
        'Р': 'Разное',
        'ТВ': 'Теория вероятностей',
        'ТИ': 'Теоретическая информатика',
    }
    for key, value in thematic_keys.items():
        thematic, created = ElectiveThematic.objects.get_or_create(
            name=value,
        )
        thematic.short_name = key
        if created:
            thematic.english_name = generate_random_error_name()
        thematic.save()

def parse_credit_types(type_row: str):
    type_row = type_row.replace(' ', '')
    kind_codes = type_row.split(',')
    return kind_codes

def parse_semesters(text_semesters: str):
    text_semesters = text_semesters.replace(' ', '')

    pattern1 = r'\w+(\d+)-(\d+)'
    pattern2 = r'\w(\d+),(\d+)'
    pattern3 = r'\w+(\d+)'

    has_odd_semester = False
    has_even_semester = False

    for text in text_semesters.split(','):
        match1 = re.findall(pattern1, text)
        match2 = re.findall(pattern2, text)
        match3 = re.findall(pattern3, text)

        if match1:
            has_odd_semester = True
            has_even_semester = True
        if match2:
            for match_ in match2:
                if any(int(sem) % 2 == 1 for sem in match_):
                    has_odd_semester = True
                if any(int(sem) % 2 == 2 for sem in match_):
                    has_even_semester = True
        if match3:
            for match_ in match3:
                has_odd_semester |= int(match_) % 2 == 1
                has_even_semester |= int(match_) % 2 == 0
    semesters = []
    if has_odd_semester:
        semesters.append(1)
    if has_even_semester:
        semesters.append(2)
    return semesters

def parse_row(row):
    codename = row['Иденти- фикатор']
    name = row['Название']
    english_name = row['Title']
    kinds = parse_credit_types(row['Тип курса'])
    text_teachers = row['Предлагает в 2022/23']
    authors = row['Автор программы']
    if text_teachers == '':
        text_teachers = authors
    semesters = parse_semesters(row['Для кого в 21/22 и семестры'])

    thematic_name = row['Раздел'].replace(' ', '').split(',')[0]

    languages = [
        lang for lang in row['Язык'].replace(' ', '').split(',')
        if len(lang) > 0
    ]
    description = row['Аннотация']
    english_description = row['Abstract']

    if len(languages) == 0 or len(semesters) == 0 or len(kinds) == 0 or len(codename) == 0:
        message = f'Incorrect row:\n {row}'
        # logger.error(message)
        return None, message

    if len(row['предлагаем? (если "да", то пустое место)']) != 0:
        message = f'This course is not presenting {row}'
        # logger.warning(message)
        return None, ''

    thematic, created = ElectiveThematic.objects.get_or_create(
        short_name=thematic_name,
    )
    if created:
        thematic.name = generate_random_error_name()
        thematic.english_name = generate_random_error_name()
    thematic.save()

    elective, _ = Elective.objects.get_or_create(
        codename=codename,
    )
    elective.thematic = thematic
    elective.name = name
    elective.english_name = english_name
    elective.text_teachers = text_teachers
    elective.description = description
    elective.english_description = english_description
    elective.save()

    for kind, semester, lang in product(kinds, semesters, languages):
        credit_units_kind, _ = CreditUnitsKind.objects.get_or_create(
            short_name=kind,
        )
        elective_kind, _ = ElectiveKind.objects.get_or_create(
            language=lang,
            credit_units_kind=credit_units_kind,
            semester=semester,
        )
        kind_of_elective, _ = KindOfElective.objects.get_or_create(
            elective=elective,
            kind=elective_kind,
        )
        kind_of_elective.exam_possibility = credit_units_kind.default_exam_possibility
        kind_of_elective.save()

    return elective, ''

def delete_old_electives(updated_codenames: list[str]):
    Elective.objects.exclude(codename__in=updated_codenames).delete()

def parse_elective_table(fin):
    reader = csv.DictReader(fin)

    codenames: list[str] = []
    report = []
    for row in reader:
        elective, report_messages = parse_row(row)
        if report_messages != '':
            report.append(report_messages)
        if elective is not None:
            codenames.append(elective.codename)
    delete_old_electives(codenames)
    return report

def run_with_local_table(path: str):
    with open(path, 'r', encoding='utf-8') as fin:
        parse_elective_table(fin)


#!/usr/bin/env python
# coding=utf-8
#pets = ['dog','cat','dog','goldfish','cat','rabbit','cat']
#print(pets)
#
#while 'cat' in pets:
#     pets.remove('cat')
#
#print(pets)
def describe_pet(animal_type,pet_name):
    """显示宠物信息"""
    print("\nI have a " +  animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet('hamster','harry')
describe_pet('dog','willie')

describe_pet(animal_type = 'hamster',pet_name = 'harry')
describe_pet(pet_name = 'tom',animal_type = 'cat')


#绘制已经被统计过的数据
#使用bar来描述直方图
#描述分布的状态
from matplotlib import pyplot as plt
from matplotlib import font_manager

my_font=font_manager.FontProperties(fname="/System/Library/Fonts/PingFang.ttc")

#数据
interval = [0,5,10,15,20,25,30,35,40,45,60,90]#x
width = [5,5,5,5,5,5,5,5,5,15,30,60]#组距
quantity = [836,2737,3723,3926,3596,1438,3273,642,824,613,215,47]#共有多少个长条

plt.figure(figsize=(20,8),dpi=80)
#描点
plt.bar(range(len(quantity)),quantity,width=1)#每个的width都有默认值
#设置刻度
_x=[i-0.5 for i in range(13)]#共有多少个刻度,不能忘记最后一个的值，更改
_xtables=interval+[150]#本来已经是一个列表，所以使用列表进行

plt.xticks(_x,_xtables)

plt.show()


import asyncio
from datetime import datetime

from telethon.errors import BadRequestError, FloodWaitError, ForbiddenError

from userbot import catub

from ..Config import Config
from ..core.logger import logging
from ..core.managers import edit_delete, edit_or_reply
from ..helpers import reply_id, time_formatter
from ..helpers.utils import _format
from ..sql_helper.bot_blacklists import check_is_black_list, get_all_bl_users
from ..sql_helper.bot_starters import del_starter_from_db, get_all_starters
from ..sql_helper.globals import addgvar, delgvar, gvarstatus
from . import BOTLOG, BOTLOG_CHATID
from .botmanagers import (
    ban_user_from_bot,
    get_user_and_reason,
    progress_str,
    unban_user_from_bot,
)

LOGS = logging.getLogger(__name__)

plugin_category = "bot"
botusername = Config.TG_BOT_USERNAME
cmhd = Config.COMMAND_HAND_LER

@catub.bot_cmd(pattern="^/help$", from_users=Config.OWNER_ID)
async def bot_help(event):
    await event.reply(
        f"""دستورات موجود در ربات عبارتند از:
**توجه : **__این دستورات فقط در این ربات کار می کنند__ {botusername}

• **دستور : **/uinfo <reply to user message>
• **اطلاعات : **__متوجه شده‌اید که استیکرها/اموجی‌های فوروارد شده دارای برچسب فوروارد نیستند، بنابراین می‌توانید کاربری را که آن پیام‌ها را با این دستور ارسال کرده است شناسایی کنید.__
• **توجه : **__برای همه پیام های فوروارد شده کار می کند. حتی برای کاربرانی که به هیچ کس اجازه ارسال پیام نمی دهند.__

• **دستور : **/ban <reason> or /ban <username/userid> <reason>
• **اطلاعات : **__به یک پیام کاربر با دلیل پاسخ دهید تا از آنجایی که شما از ربات منع شده اید به او اطلاع داده می شود و پیام های او بیشتر برای شما ارسال نمی شود.__
• **توجه : **__بدون ارسال دلیل کار نخواهد کرد __

• **دستور : **/unban <reason(optional)> or /unban <username/userid>
• **اطلاعات : **__به پیام کاربر پاسخ دهید یا نام کاربری/کاربر را برای لغو بن از ربات ارائه دهید.__
• **توجه : **__برای بررسی لیست کاربران بن شده استفاده کنید__ `{cmhd}bblist`.

• **دستور : **/broadcast
• **اطلاعات : **__به یک پیام پاسخ دهید تا برای هر کاربری که ربات شما را راه اندازی کرده است پخش شود. برای دریافت لیست کاربران استفاده کنید__ `{cmhd}bot_users`.
• **توجه : **__اگر کاربر ربات را متوقف/بلاک کرد، از پایگاه داده شما حذف خواهد شد که از لیست bot_starters پاک خواهد شد.__
"""
    )

@catub.bot_cmd(pattern="^/broadcast$", from_users=Config.OWNER_ID)
async def bot_broadcast(event):
    replied = await event.get_reply_message()
    if not replied:
        return await event.reply("ابتدا به پیامی برای پخش پاسخ دهید!")
    start_ = datetime.now()
    br_cast = await replied.reply("Broadcasting ...")
    blocked_users = []
    count = 0
    bot_users_count = len(get_all_starters())
    if bot_users_count == 0:
        return await event.reply("`هنوز کسی ربات شما را راه اندازی نکرده است.`")
    users = get_all_starters()
    if users is None:
        return await event.reply("`هنگام دریافت کاربران خطاهایی رخ داد.`")
    for user in users:
        try:
            await event.client.send_message(
                int(user.user_id), "🔊شما یک پیام **جدید**پخش کرده اید"
            )
            await event.client.send_message(int(user.user_id), replied)
            await asyncio.sleep(0.8)
        except FloodWaitError as e:
            await asyncio.sleep(e.seconds)
        except (BadRequestError, ValueError, ForbiddenError):
            del_starter_from_db(int(user.user_id))
        except Exception as e:
            LOGS.error(str(e))
            if BOTLOG:
                await event.client.send_message(
                    BOTLOG_CHATID, f"**خطا هنگام پخش❌**\n`{e}`"
                )

        else:
            count += 1
            if count % 5 == 0:
                try:
                    prog_ = (
                        "🔊 Broadcasting ...\n\n"
                        + progress_str(
                            total=bot_users_count,
                            current=count + len(blocked_users),
                        )
                        + f"\n\n• ✔ **موفق** :  `{count}`\n"
                        + f"• ✖ **ناموفق** :  `{len(blocked_users)}`"
                    )
                    await br_cast.edit(prog_)
                except FloodWaitError as e:
                    await asyncio.sleep(e.seconds)
    end_ = datetime.now()
    b_info = f"🔊 پیام با موفقیت پخش شد ➜  {count} users."
    if len(blocked_users) != 0:
        b_info += f"\n🚫  {len(blocked_users)} users اخیرا ربات شما را مسدود کرده است، بنابراین حذف شده اند."
    b_info += (
        f"\n⏳  فرآیند انجام شد: {time_formatter((end_ - start_).seconds)}."
    )
    await br_cast.edit(b_info, parse_mode="html")

@catub.cat_cmd(
    pattern="bot_users$",
    command=("bot_users", plugin_category),
    info={
        "header": "To get users list who started bot.",
        "description": "To get compelete list of users who started your bot",
        "usage": "{tr}bot_users",
    },
)
async def ban_starters(event):
    "To get list of users who started bot."
    ulist = get_all_starters()
    if len(ulist) == 0:
        return await edit_delete(event, "`هنوز کسی ربات شما را راه اندازی نکرده است.`")
    msg = "**The list of users who started your bot are :\n\n**"
    for user in ulist:
        msg += f"• 👤 {_format.mentionuser(user.first_name , user.user_id)}\n**ایدی:** `{user.user_id}`\n**نام:** @{user.username}\n**تاریخ: **__{user.date}__\n\n"
    await edit_or_reply(event, msg)

@catub.bot_cmd(pattern="^/ban\\s+([\\s\\S]*)", from_users=Config.OWNER_ID)
async def ban_botpms(event):
    user_id, reason = await get_user_and_reason(event)
    reply_to = await reply_id(event)
    if not user_id:
        return await event.client.send_message(
            event.chat_id, "`من نمی توانم کاربری برای بن پیدا کنم`", reply_to=reply_to
        )
    if not reason:
        return await event.client.send_message(
            event.chat_id, "`برای بن کردن کاربر ابتدا دلیل ارائه کنید`", reply_to=reply_to
        )
    try:
        user = await event.client.get_entity(user_id)
        user_id = user.id
    except Exception as e:
        return await event.reply(f"**Error:**\n`{e}`")
    if user_id == Config.OWNER_ID:
        return await event.reply("من نمی توانم شما را ممنوع کنم استاد")
    check = check_is_black_list(user.id)
    if check:
        return await event.client.send_message(
            event.chat_id,
            f"#Already_banned\
            \nکاربر از قبل در لیست کاربران بن وجود دارد.\
            \n**دلیل بن کردن ربات:** `{check.reason}`\
            \n**تاریخ:** `{check.date}`.",
        )
    msg = await ban_user_from_bot(user, reason, reply_to)
    await event.reply(msg)

@catub.bot_cmd(pattern="^/unban(?:\\s|$)([\\s\\S]*)", from_users=Config.OWNER_ID)
async def ban_botpms(event):
    user_id, reason = await get_user_and_reason(event)
    reply_to = await reply_id(event)
    if not user_id:
        return await event.client.send_message(
            event.chat_id, "`من نمی توانم کاربری برای لغو بن پیدا کنم`", reply_to=reply_to
        )
    try:
        user = await event.client.get_entity(user_id)
        user_id = user.id
    except Exception as e:
        return await event.reply(f"**Error:**\n`{e}`")
    check = check_is_black_list(user.id)
    if not check:
        return await event.client.send_message(
            event.chat_id,
            f"#User_Not_Banned\
            \n👤 {_format.mentionuser(user.first_name , user.id)} در لیست کاربران بن وجود ندارد.",
        )
    msg = await unban_user_from_bot(user, reason, reply_to)
    await event.reply(msg)

@catub.cat_cmd(
    pattern="bblist$",
    command=("bblist", plugin_category),
    info={
        "header": "To get users list who are banned in bot.",
        "description": "To get list of users who are banned in bot.",
        "usage": "{tr}bblist",
    },
)
async def ban_starters(event):
    "To get list of users who are banned in bot."
    ulist = get_all_bl_users()
    if len(ulist) == 0:
        return await edit_delete(event, "`هنوز کسی در ربات شما بن نشده است.`")
    msg = "**لیست کاربرانی که در ربات شما بن شده اند عبارتند از:\n\n**"
    for user in ulist:
        msg += f"• 👤 {_format.mentionuser(user.first_name , user.chat_id)}\n**ایدی:** `{user.chat_id}`\n**نام:** @{user.username}\n**تاریخ: **__{user.date}__\n**دلیل:** __{user.reason}__\n\n"
    await edit_or_reply(event, msg)

@catub.cat_cmd(
    pattern="bot_antif (on|off)$",
    command=("bot_antif", plugin_category),
    info={
        "header": "To enable or disable bot antiflood.",
        "description": "if it was turned on then after 10 messages or 10 edits of same messages in less time then your bot auto loacks them.",
        "usage": [
            "{tr}bot_antif on",
            "{tr}bot_antif off",
        ],
    },
)
async def ban_antiflood(event):
    "To enable or disable bot antiflood."
    input_str = event.pattern_match.group(1)
    if input_str == "on":
        if gvarstatus("bot_antif") is not None:
            return await edit_delete(event, "`قبلا آنتی اسپم فعال شده است`")
        addgvar("bot_antif", True)
        await edit_delete(event, "`آنتی اسپم فعال شد`")
    elif input_str == "off":
        if gvarstatus("bot_antif") is None:
            return await edit_delete(event, "`قبلا آنتی اسپم غیرفعال شده است`")
        delgvar("bot_antif")
        await edit_delete(event, "`آنتی اسپم غیرفعال شد`")


import os
from re import S

from numpy.lib.function_base import select
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

from nes_py.wrappers import JoypadSpace
import gym_super_mario_bros
from gym_super_mario_bros.actions import RIGHT_ONLY
from wrappers import wrapper
# from gym import wrappers

env = gym_super_mario_bros.make('SuperMarioBros-v0')
# env = wrappers.Monitor(env, "./gym-results", force=True)
env = JoypadSpace(env, RIGHT_ONLY)
env = wrapper(env)

initial_state = env.reset()
n_actions = env.action_space.n

import numpy as np
import random
import keras as k
from keras.models import Sequential
from keras.layers import Dense, Flatten, Dropout, Conv2D, MaxPooling2D

import logging
log_file = 'log.log'
logging.basicConfig(filename=log_file, level=logging.INFO, filemode='w')

def _log(message, level=logging.INFO):
    print(message)
    if level == logging.INFO:
        logging.info(message)
    else:
        logging.error(message)

# default env shape is 240x256x3 but with wrapper that changes
# to 84x84x4
def get_model(input_shape = (84,84,4), actions=n_actions):
    # model = Sequential([
    #     Dense(32, input_shape=input_shape, activation='relu'),
    #     Dropout(0.02),
    #     Dense(16, activation='relu'),
    #     Dropout(0.02),
    #     Flatten(),
    #     Dense(actions, activation = 'softmax')
    # ])
    model = Sequential([
        Conv2D(32, (3,3), input_shape=input_shape, activation='relu'),
        MaxPooling2D((2,2)),
        Conv2D(64, (3,3), activation='relu'),
        MaxPooling2D((2,2)),
        Conv2D(128, (3,3), activation='relu'),
        MaxPooling2D((2,2)),
        Flatten(),
        Dense(512, activation='relu'),
        Dense(actions, activation='softmax')
    ])
    model.compile()
    return model

def evaluate(model):
    state = env.reset()
    total_reward = 0
    time_wasting_count = 0
    while True:
        action = np.argmax(model.predict(np.array([state])))
        state, reward, done, info = env.step(action)
        total_reward += reward
        # print(f"this step {action} {reward}, {total_reward}, {done}")

        if info['life'] < 2:
            done = True
        else:
            if reward == -1:
                time_wasting_count += 1
            elif reward != 0:
                time_wasting_count = 0

            if time_wasting_count > 20:
                done = True
                total_reward -= info['time']

        # env.render()
        if done:
            # total_reward += _['score']
            print(f'this run {total_reward}, {done}')
            info['reward'] = reward
            print(info)
            env.reset()
            break
    return total_reward

def selection(models, evaluations, select_num, select_num2=None, gen=0):
    # find out the model ranks based on evaluation
    model_ranks = np.argsort(evaluations)[::-1]
    # sort evaluations
    evaluations = [evaluations[i] for i in model_ranks]
    _log(f'gen{gen} performances')
    _log(evaluations)
    # find and store best unique models
    best_unique = []
    best_unique_evals = []
    rest = []
    for i in model_ranks:
        if len(best_unique) < select_num and evaluations[i] not in best_unique_evals:
            best_unique.append(models[i])
            best_unique_evals.append(evaluations[i])
        else:
            rest.append(models[i])
    # if there arern't enough unique models add good ones from the rest
    more_best_req =  select_num - len(best_unique)
    best_set = best_unique+rest[:more_best_req]
    # archive best model for each gen
    best_set[0].save(f'./cnngamodels/gen{gen}')

    if select_num2:
        return best_set, rest[more_best_req:more_best_req+select_num2]
    else:
        return best_set

def unflatten(array, shapes):
    un_array = []
    i = 0
    for shape in shapes:
        size = np.product(shape)
        un_array.append(np.array(array[i:i+size]).reshape(shape))
        i += size
    return un_array

def crossover(models, n_children = 2):
    children = []
    for _ in range(n_children // 2):
        p1 = random.choice(models)
        p2 = random.choice(models)

        p1_weights = p1.get_weights()
        p2_weights = p2.get_weights()

        shapes = [w.shape for w in p1_weights]

        genes1 = np.concatenate([w.flatten() for w in p1_weights])
        genes2 = np.concatenate([w.flatten() for w in p2_weights])

        split = random.randint(0, len(genes1) - 1)

        child1 = get_model()
        child2 = get_model()

        child1_genes = np.array(genes1[0:split].tolist() + genes2[split:].tolist())
        child2_genes = np.array(genes2[0:split].tolist() + genes1[split:].tolist())

        child1.set_weights(unflatten(child1_genes, shapes))
        child2.set_weights(unflatten(child2_genes, shapes))

        children.append(child1)
        children.append(child2)

    return children
    # models.extend(children)
    # return models

def mutate(model, mutate_ratio=None):
    new_model = k.models.clone_model(model)
    weights = model.get_weights()
    shapes = [w.shape for w in weights]
    flat_weights = np.concatenate([w.flatten() for w in weights])
    for i in range(int(len(flat_weights)*mutate_ratio)) if mutate_ratio else range(random.randint(0, len(flat_weights) // 4)):
        mutate_i = random.randint(0, len(flat_weights) - 1)
    flat_weights[mutate_i] = np.random.randn()
    new_weights = unflatten(flat_weights, shapes)
    new_model.set_weights(new_weights)
    return new_model

def mutate_simple (model, prob=0.25):
    new_model = k.models.clone_model(model)
    if (random.uniform(0.0,1.0) < prob):
        weights = model.get_weights()
        shapes = [w.shape for w in weights]
        flat_weights = np.concatenate([w.flatten() for w in weights])
        mutate_i = random.randint(0, len(flat_weights) - 1)
        flat_weights[mutate_i] = np.random.randn()
        new_weights = unflatten(flat_weights, shapes)
        new_model.set_weights(new_weights)
    return new_model

GENERATIONS = 100 # number of generations to run
POPULATION = 50 # number of networks in a generation
SELECT_BEST = 10 # number of best networks to select
SELECT_SECOND_BEST = 20 # number of lesser networks to preserve (and mutate)
START_WITH_MODEL = './backupmodels/v4.1' # None if starting from scratch

if START_WITH_MODEL:
    base_model = k.models.load_model(START_WITH_MODEL)
    models = [ base_model ] + [ mutate_simple(base_model) for _ in range(POPULATION - 1)]
else:
    models = [ get_model() for _ in range(POPULATION) ]

evaluations = None
for gen in range(0, GENERATIONS):
    print(f"========================  Welcome to gen-{gen}  ==============================")
    # evaluate the models of current gen
    if evaluations:
        evaluations = evaluations[:SELECT_BEST] + [evaluate(model) for model in models[SELECT_BEST:]]
    else:
        evaluations = [evaluate(model) for model in models]
    ##### for just using one best set with limited mutation
    # get the best set of models to breed
    best_set = selection(models, evaluations, SELECT_BEST, gen=gen)
    # breed the best models with crossovers
    breeded_models = crossover(best_set, n_children = POPULATION - len(best_set))
    # possibly mutate the models
    models = best_set + [mutate_simple(model) for model in breeded_models]

    ##### for using best and second best set
    # # get the best set of models to breed
    # best_set, second_best_set = selection(models_sorted, evaluations, SELECT_BEST, SELECT_SECOND_BEST, gen)
    # # breed the best models with crossovers
    # breeded_models = crossover(models, n_children = POPULATION - len(best_set) - len(second_best_set))
    # # possibly mutate the models
    # models = best_set + [mutate(model) for model in breeded_models + second_best_set]

# evaluate the final generation as before
evaluations = [evaluate(model) for model in models]
model_ranks = np.argsort(evaluations)[::-1]
_log(f'gen{GENERATIONS} performances')
_log([evaluations[i] for i in model_ranks])
models[model_ranks[0]].save(f'./cnngamodels/gen{GENERATIONS}')

env.close()


"""I'm throwing this in because it is often useful in testing.

I often find module mock from the standard library overcomplicated for my
purposes.
"""

class MonkeyPatcher(object):

    _unset = object()

    def __init__(self, add_cleanup):
        self._add_cleanup = add_cleanup

    def monkey_patch(self, obj, name, value):
        orig_value = getattr(obj, name, self._unset)
        def revert():
            if orig_value is self._unset:
                delattr(obj, name)
            else:
                setattr(obj, name, orig_value)
        setattr(obj, name, value)
        self._add_cleanup(revert)
        return orig_value

    def add_to_list(self, list_, value):
        was_there_before = value in list_
        def revert():
            try:
                list_.remove(value)
            except ValueError:
                pass
        if not was_there_before:
            list_.append(value)
            self._add_cleanup(revert)
        return was_there_before


import matplotlib.pyplot as plt
import os
import numpy as np
import scipy.stats as stats
import time
from scipy.optimize import curve_fit
from tqdm import tqdm

class MakePlots:
    '''class to make plots with changing parameters'''
    def __init__(self, simulation):
        self.simulation = simulation

    def sensitivity_analysis(self, parameter, values, n_simulations):
        '''find burned trees for paramter values in given range'''
        results = []
        start_time = time.time()
        for i in range(0, len(values)):
            value = values[i]
            burned = []
            for _ in range(n_simulations):
                self.simulation.set_params(parameter, value)
                burned.append(self.simulation.get_burnt())

            # print("burned----", burned)
            mean = np.mean(burned)
            confidence_interval = stats.t.interval(0.95, len(burned)-1, loc=mean, scale=stats.sem(burned))
            results.append((value, mean, confidence_interval))

            # Saving burned list to excel file
            # workbook = openpyxl.load_workbook('Fire_data.xlsx')
            # sheet = workbook[parameter]
            # column_letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L']
            # column_letter = column_letters[i]
            # # Iterate over the numbers and add them to the column
            # for j, number in enumerate(burned, start=1):
            #     cell = f'{column_letter}{j}'
            #     sheet[cell].value = number
            # workbook.save('Fire_data.xlsx')

        # Define values, mean and CI
        values = [result[0] for result in results]
        means = np.array([result[1] for result in results])
        lower_ci = np.array([result[2][0] for result in results])
        upper_ci = np.array([result[2][1] for result in results])

        # Plot results
        plt.figure()
        plt.fill_between(values, lower_ci, upper_ci, alpha=0.3, label='95% Confidence interval')
        plt.plot(values, means, 'o-', label=parameter)
        # plt.errorbar(values, means, yerr=[means - lower_ci, upper_ci - means], marker='o', linestyle='', label=parameter)
        plt.xlabel(parameter)
        plt.ylabel('Burned Trees')
        plt.grid()
        plt.legend()

        # Saving in 'plots' folder
        filename = f'{parameter}_sensitivity_00.png'
        filepath = os.path.join('plots', filename)
        plt.savefig(filepath)
        plt.show()

        end_time = time.time()
        elapsed_time = end_time - start_time
        print(f"Computation time: {elapsed_time} seconds")

    def clustering_analysis(self):
        '''find burned trees for different degrees of clustering'''
        sim = self.simulation
        rows = sim.rows
        cols = sim.cols

        sim.make_deterministic() # turn off probabilities
        datapoints = 50 # how many densities to sweep
        density_param = np.linspace(0.35,0.6,datapoints)
        clustering = [0,0.5,1,1.5,2] # how much clustering to perform

        for i,c in enumerate(clustering): # for each degree of clustering

            points = []
            print('Clustering {} out of {}'.format(i,len(clustering)-1))

            for d in tqdm(density_param):

                sim.set_params('grid_density', d)

                sim.reset() # we reinitialize the forest to set the density

                sim.apply_voters_model(c) # we use the voters model to apply clustering

                density = sim.total_trees/rows/cols
                if density < 0.35:
                    continue #we are not interested if the density gets too low due to clustering

                morans_i = sim.morans_i() # we quantify the clustering
                sim.run()
                percentage_burnt = sim.burned_trees/sim.total_trees

                points.append([density,morans_i,percentage_burnt])
                np.save('points{}'.format(i),points) # save points to analyze interactively (jupyter notebook)

    def sigmoid(self, x, x0, k):
        y = 1 / (1 + np.exp(-k*(x-x0)))
        return y


import requests
import re
from bs4 import BeautifulSoup
from src.interfaces.subdomain_enumerator import SubdomainEnumerator
from time import sleep

class AskDorksAdapter(SubdomainEnumerator):

    def __init__(self) -> None:
        """This class will manage the enumeration logic using the Ask dorks

        """
        super().__init__()
        self.base_url = "https://www.ask.com/web"
        self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"}

    @property
    def queries(self):
        """Default AskDorkAdapter queries

        Returns:
            dict: returns a dict of params that will be used to enumerate subdomains\n
            for a given target uri
        """
        return {"q": self.target_uri}

    def add_dork_queries(self, query: str) -> None:
        """Add a new Ask dork query

        Args:
            query (str): should be a google dork\nex: f'inurl:{target_uri}'

        Returns:
            _type_: None
        """
        return super().add_dork_queries(query)

    def _process(self, query):
        # Loop through Ask's search pages, 10 results at a time
        for page in range(1, 5):
            params = self.queries
            params['page'] = str(page)
            response = requests.get(url=self.base_url, headers=self.headers, params=params, proxies=None, verify=False)
            if response.status_code == 200:
                try:
                    soup = BeautifulSoup(response.text, "html.parser")
                    links = soup.findAll("a")
                    for link in links:
                        subdomain = link.get("href")
                        yield subdomain
                except:
                    pass

            return []


import os
import sys
from pylab import *
import numpy as np
import netCDF4
from scipy.spatial import cKDTree

class woa():

  def __init__(self,ncfile='woa13_devac_04v2.nc',tidx=0):
    nc = netCDF4.Dataset(ncfile)
    sv = nc.variables
    latslice=slice(173,262)
    lonslice=slice(320,524)
    latslice=slice(None,None)
    lonslice=slice(None,None)
    self.lon = sv['lon'][lonslice]
    self.lat = sv['lat'][latslice]
    self.d = -sv['depth'][:]
    self.time = sv['time'][:]
    self.tidx = tidx
    self.s = sv['s_mn'][:,:,latslice,lonslice]
    self.t = sv['t_mn'][:,:,latslice,lonslice]
    self.lon2,self.lat2 = meshgrid(self.lon,self.lat)

    self.use_depth_slices=True

    if not(self.use_depth_slices):
      self.d3,self.lat3,self.lon3 = meshgrid(self.d,self.lat*100.,self.lon*100.,indexing='ij')
      vlon3 = self.lon3[where(self.s.mask[self.tidx]==False)]
      vlat3 = self.lat3[where(self.s.mask[self.tidx]==False)]
      vd3 = self.d3[where(self.s.mask[self.tidx]==False)]
      self.s_tree=cKDTree(zip(vlon3,vlat3,vd3))

      vlon3 = self.lon3[where(self.t.mask[self.tidx]==False)]
      vlat3 = self.lat3[where(self.t.mask[self.tidx]==False)]
      vd3 = self.d3[where(self.t.mask[self.tidx]==False)]
      self.t_tree=cKDTree(zip(vlon3,vlat3,vd3))

      self.s_var = self.s[self.tidx][where(self.s.mask[self.tidx]==False)].flatten()
      self.t_var = self.t[self.tidx][where(self.t.mask[self.tidx]==False)].flatten()

    else:
      #build trees
      self.s_tree={}
      self.t_tree={}
      self.svar={}
      self.tvar={}
      for ik,d in enumerate(self.d):
        #print('  build trees for depth %0.2f'%d)
        vlon = self.lon2[where(self.s.mask[self.tidx,ik]==False)]
        vlat = self.lat2[where(self.s.mask[self.tidx,ik]==False)]
        self.s_tree[ik] = cKDTree(zip(vlon,vlat))
        vlon = self.lon2[where(self.t.mask[self.tidx,ik]==False)]
        vlat = self.lat2[where(self.t.mask[self.tidx,ik]==False)]
        self.t_tree[ik] = cKDTree(zip(vlon,vlat))
        self.svar[ik] = self.s[self.tidx,ik][where(self.s.mask[self.tidx,ik]==False)].flatten()
        self.tvar[ik] = self.t[self.tidx,ik][where(self.t.mask[self.tidx,ik]==False)].flatten()

  def interpolate(self,depths,nodelon,nodelat,bidx=1,tidx=0):
    # start
    t = zeros((len(depths),))
    s = zeros((len(depths),))

    for ik,ndepth in enumerate(depths[bidx-1:]):
      # find vertical layer in climatology
      if self.use_depth_slices:
        didx = np.abs(self.d - ndepth).argmin()

      #didx = int(where(ddiff==ddiff.min())[0][0])
      #vlon = self.lon2[where(self.s.mask[self.tidx,didx]==False)]
      #vlat = self.lat2[where(self.s.mask[self.tidx,didx]==False)]
      #tree = cKDTree(zip(vlon,vlat))

      #svar = self.s[self.tidx,didx][where(self.s.mask[self.tidx,didx]==False)].flatten()
      #tvar = self.t[self.tidx,didx][where(self.t.mask[self.tidx,didx]==False)].flatten()

        dist,inds = self.s_tree[didx].query((nodelon,nodelat),k=4)
        w = 1 / dist
        s[bidx-1+ik] = np.sum(w*self.svar[didx][inds],axis=0) / np.sum(w,axis=0)

        dist,inds = self.t_tree[didx].query((nodelon,nodelat),k=4)
        w = 1 / dist
        t[bidx-1+ik] = np.sum(w*self.tvar[didx][inds],axis=0) / np.sum(w,axis=0)
      else:
        dist,inds = self.s_tree.query((nodelon*100.,nodelat*100.,ndepth))
        w = 1 / dist
        s[bidx-1+ik] = np.sum(w*self.s_var[inds],axis=0) / np.sum(w,axis=0)

        dist,inds = self.t_tree.query((nodelon*100.,nodelat*100.,ndepth))
        w = 1 / dist
        t[bidx-1+ik] = np.sum(w*self.t_var[inds],axis=0) / np.sum(w,axis=0)

    return (t.astype(np.float32),s.astype(np.float32))

if __name__=='__main__':

  #oa = woa(ncfile=sys.argv[1])
  oa = woa(ncfile='/work/gg0877/KST/MiMeMo/woa/woa_arctic_0.25.nc')

  depths=asarray([-5000.,-4000.,-3000.,-2000.,-1000.,-500.,-250.,-100.,0.0])
  nodelon=40.0
  nodelat=70.0

  t,s = oa.interpolate(depths,nodelon,nodelat,bidx=1)
  print('temp:')
  print(t)
  print('salt:')
  print(s)


from mcvirt.exceptions import ArgumentParserException

class PermissionParser(object):
    """Handle permission parser."""

    def __init__(self, subparser, parent_parser):
        """Create subparser for managing permissions VMs."""
        self.parent_subparser = subparser
        self.parent_parser = parent_parser

        # Get arguments for making permission changes
        self.permission_parser = self.parent_subparser.add_parser(
            'permission',
            help='Update user permissions',
            parents=[self.parent_parser]
        )
        self.permission_parser.set_defaults(func=self.handle_permission)

        self.permission_parser.add_argument(
            '--add-user',
            dest='add_user',
            metavar='Add user to user group',
            type=str,
            help=('DEPRECATED (will be removed in v10.0.0): '
                  'Adds a given user to a VM, allowing them to perform basic functions.')
        )
        self.permission_parser.add_argument(
            '--delete-user',
            dest='delete_user',
            metavar='Remove user from user group',
            type=str,
            help=('DEPRECATED (will be removed in v10.0.0): '
                  'Removes a given user from a VM. This prevents '
                  'them to perform basic functions.')
        )
        self.permission_parser.add_argument(
            '--add-owner',
            dest='add_owner',
            metavar='Add user to owner group',
            type=str,
            help=('DEPRECATED (will be removed in v10.0.0): '
                  'Adds a given user as an owner to a VM, '
                  'allowing them to perform basic functions and manager users.')
        )
        self.permission_parser.add_argument(
            '--delete-owner',
            dest='delete_owner',
            metavar='Remove user from owner group',
            type=str,
            help=('DEPRECATED (will be removed in v10.0.0): '
                  'Removes a given owner from a VM. '
                  'This prevents them to perform basic functions and manager users.')
        )
        self.permission_parser.add_argument(
            '--add-superuser',
            dest='add_superuser',
            metavar='Add user to superuser group',
            type=str,
            help=('Adds a given user to the global superuser role. '
                  'This allows the user to completely manage the MCVirt node/cluster')
        )
        self.permission_parser.add_argument(
            '--delete-superuser',
            dest='delete_superuser',
            metavar='Removes user from the superuser group',
            type=str,
            help='Removes a given user from the superuser group'
        )
        self.permission_target_group = self.permission_parser.add_mutually_exclusive_group(
            required=True
        )
        self.permission_target_group.add_argument('vm_name', metavar='VM Name',
                                                  type=str, help='Name of VM', nargs='?')
        self.permission_target_group.add_argument('--global', dest='global', action='store_true',
                                                  help='Set a global MCVirt permission')

        self.permission_target_group.add_argument(
            '--list',
            dest='list',
            action='store_true',
            help='List available permissions'
        )

    def handle_permission(self, p_, args):
        """Handle permission changes."""
        auth_object = p_.rpc.get_connection('auth')
        p_.rpc.annotate_object(auth_object)

        if args.list:
            p_.print_status(auth_object.list_permissions())
            return

        if (args.add_superuser or args.delete_superuser) and args.vm_name:
            raise ArgumentParserException('Superuser groups are global-only roles')

        if args.vm_name:
            vm_factory = p_.rpc.get_connection('virtual_machine_factory')
            vm_object = vm_factory.get_virtual_machine_by_name(args.vm_name)
            p_.rpc.annotate_object(vm_object)
            permission_destination_string = 'role on VM %s' % vm_object.get_name()
        else:
            vm_object = None
            permission_destination_string = 'global role'

        user_factory = p_.rpc.get_connection('user_factory')
        p_.rpc.annotate_object(user_factory)

        if args.add_user:
            user_object = user_factory.get_user_by_username(args.add_user)
            p_.rpc.annotate_object(user_object)
            group_factory = p_.rpc.get_connection('group_factory')
            group = group_factory.get_object_by_name('user')
            p_.rpc.annotate_object(group)
            group.add_user(
                user=user_object,
                virtual_machine=vm_object)
            p_.print_status(
                'Successfully added \'%s\' to \'user\' %s' %
                (args.add_user, permission_destination_string))

        if args.delete_user:
            user_object = user_factory.get_user_by_username(args.delete_user)
            p_.rpc.annotate_object(user_object)
            group_factory = p_.rpc.get_connection('group_factory')
            group = group_factory.get_object_by_name('user')
            p_.rpc.annotate_object(group)
            group.remove_user(
                user=user_object,
                virtual_machine=vm_object)
            p_.print_status(
                'Successfully removed \'%s\' from \'user\' %s' %
                (args.delete_user, permission_destination_string))

        if args.add_owner:
            user_object = user_factory.get_user_by_username(args.add_owner)
            p_.rpc.annotate_object(user_object)
            group_factory = p_.rpc.get_connection('group_factory')
            group = group_factory.get_object_by_name('owner')
            p_.rpc.annotate_object(group)
            group.add_user(
                user=user_object,
                virtual_machine=vm_object)
            p_.print_status(
                'Successfully added \'%s\' to \'owner\' %s' %
                (args.add_owner, permission_destination_string))

        if args.delete_owner:
            user_object = user_factory.get_user_by_username(args.delete_owner)
            p_.rpc.annotate_object(user_object)
            group_factory = p_.rpc.get_connection('group_factory')
            group = group_factory.get_object_by_name('owner')
            p_.rpc.annotate_object(group)
            group.remove_user(
                user=user_object,
                virtual_machine=vm_object)
            p_.print_status(
                'Successfully removed \'%s\' from \'owner\' %s' %
                (args.delete_owner, permission_destination_string))

        if args.add_superuser:
            user_object = user_factory.get_user_by_username(args.add_superuser)
            p_.rpc.annotate_object(user_object)
            auth_object.add_superuser(user_object=user_object)
            p_.print_status('Successfully added %s to the global superuser group' %
                            args.add_superuser)
        if args.delete_superuser:
            user_object = user_factory.get_user_by_username(args.delete_superuser)
            p_.rpc.annotate_object(user_object)
            auth_object.delete_superuser(user_object=user_object)
            p_.print_status('Successfully removed %s from the global superuser group ' %
                            args.delete_superuser)


'''
给定两个字符串 s1 和 s2，写一个函数来判断 s2 是否包含 s1 的排列。换句话说，第一个字符串的排列之一是第二个字符串的子串。
枚举每个子串：要求子串长度等于s1，并且子串中每个字母出现的次数等于s1中每个字母出现的次数，就说明是s1的一个排列
'''
'''
hashmap保存[i,j]区间的字符出现频率,看有没有等于s1的map的.如果没有,j++,i++,hashmap中减去过期的i对应的字符出现次数一次
因为此题里区间长度固定,所以i和j同步增加,所以此题用i的for循环代替i和jwhile循环
'''
from collections import Counter

def checkInclusion(s1: str, s2: str):
    """
    :type s1: str
    :type s2: str
    :rtype: bool
    """
    # c1 = Counter(s1)
    # for left in range(len(s2) - len(s1)+1):
    #     right = left + len(s1) - 1
    #     #判断[left,right]内的子串是不是s1的排列
    #     c2 = Counter(s2[left:right+1])
    #     if c1.items() == c2.items():
    #         return True
    # return False
    if len(s1) > len(s2):
        return False
    c1 = [0] * 26
    c2 = [0] * 26
    for i in range(len(s1)):
        c1[ord(s1[i]) - ord("a")] += 1
        c2[ord(s2[i]) - ord("a")] += 1
    for left in range(len(s2) - len(s1)): #本来应该到len(s2) - len(s1)+1开区间,但是因为下面有right+1,为防止数组越界,for里少判断最后一组
        right = left + len(s1) -1
        #[left,right]内的子串的出现频率保存在滑动的hashmap即c1,c2中
        if c1 == c2:
            return True
        #统计滑动窗口下一位的字符出现频率
        c2[ord(s2[right+1]) - ord("a")] +=1
        #减去将要过期的left的字符的出现频率
        c2[ord(s2[left]) - ord("a")] -= 1
    #因为for里少判断了最后一组,所以最后返回前要判断最后一组(for里已经更新了最后一组的map)
    return c1 == c2

print(checkInclusion("ab", "eidbaoo"))

字符串/567.字符串的排列.py


import os
import cv2
import pickle
import argparse
import numpy as np
import matplotlib.pyplot as plt

from tqdm import tqdm

"""
DOCS:
    - https://github.com/jiyangzhao/pyehd/blob/main/pyehd.py
    - https://www.youtube.com/watch?v=Z7NlH4HC0dw&ab_channel=ExploringTechnologies
    - https://www.section.io/engineering-education/how-to-use-edge-histogram-descriptor-to-retrieve-images-in-matlab/

    - "P:/cbir/DOCUMENTS/documents/Descriptors_of_Mpeg7/Ycrcb_Color_histogram_and_EHD.pdf"
    - "P:/cbir/DOCUMENTS/documents/Descriptors_of_Mpeg7/Wavelet_features_CLD_EHD_of_Mpeg7/41800235.pdf"
    - "P:/cbir/DOCUMENTS/documents/Descriptors_of_Mpeg7/CLD_EHD.pdf"
    - "P:/cbir/DOCUMENTS/documents/Descriptors_of_Mpeg7/Color_and_Texture_Descriptors.pdf"
"""

parser = argparse.ArgumentParser()
parser.add_argument('--store_database', type=bool, default=False, help="store database or search image")
parser.add_argument('--query_image_path', type=str, default='', help="store database or search image")
args = parser.parse_args()

class EHDExtractor:
    def __init__(self):
        pass

    # function to get EHD vector
    def extract_ehd(self, image_path):
        image = cv2.imread(image_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # convert to gray
        h, w = np.shape(image) # get the shape of image

        M = 4 * np.ceil(h/4)
        N = 4 * np.ceil(w/4)
        image = np.reshape(image,(int(M),int(N))) # Making image dim. divisible completely by 4
        AllBins = np.zeros((17, 5)) # initializing Bins
        p = 0
        L = 0
        for _ in range(4):
            K = 0
            for _ in range(4):
                block = image[K:K+int(M/4), L:L+int(N/4)] # Extracting (M/4,N/4) block
                AllBins[p,:] = self.getbins(np.double(block))
                K = K + int(M/4)
                p = p + 1
            L = L + int(N/4)
        GlobalBin = np.mean(AllBins[:-1, :], axis=0) # getting global Bin
        AllBins[16,:] = GlobalBin
        # ehd = np.reshape(AllBins,[1,85])
        ehd = np.reshape(AllBins, -1)
        return ehd

    # function for getting Bin values for each block
    def getbins(self, image_block):
        M, N = image_block.shape
        M = 2 * np.ceil(M/2)
        N = 2 * np.ceil(N/2)
        # print(M)
        # print(N)
        image_block = np.reshape(image_block,(int(M),int(N))) # Making block dimension divisible by 2
        bins = np.zeros((1,5)) # initialize Bin
        """Operations, define constant"""
        V = np.array([[1,-1],[1,-1]]) # vertical edge operator
        H = np.array([[1,1],[-1,-1]]) # horizontal edge operator
        D45 = np.array([[1.414,0],[0,-1.414]])# diagonal 45 edge operator
        D135 = np.array([[0,1.414],[-1.414,0]]) # diagonal 135 edge operator
        Isot = np.array([[2,-2],[-2,2]]) # isotropic edge operator
        T = 50 # threshold

        nobr = int(M/2) # loop limits
        nobc = int(N/2) # loop limits
        L = 0

        """loops of operating"""
        for _ in range(nobc):
            K = 0
            for _ in range(nobr):
                block = image_block[K:K+2, L:L+2] # Extracting 2x2 block
                pv = np.abs(np.sum(block*V)) # apply operators
                ph = np.abs(np.sum(block*H))
                pd45 = np.abs(np.sum(block*D45))
                pd135 = np.abs(np.sum(block*D135))
                pisot = np.abs(np.sum(block*Isot))
                parray = [pv,ph,pd45,pd135,pisot]
                index = np.argmax(parray) # get the index of max value
                value = parray[index] # get the max value
                # print('value: '+str(value))
                if value >= T:
                    bins[0,index]=bins[0,index]+1 # update bins values
                K = K+2
            L = L+2
        # bins = bins / (nobr * nobc)
        return bins

    def store_database(self, data_folder):
        features_db = []
        paths_db = []

        """
        COREL DATASET
        """
        for sub_folder in os.listdir(data_folder):
            print(f"=====> {sub_folder}")
            sub_folder_path = data_folder + sub_folder + '/'
            for file_name in tqdm(os.listdir(sub_folder_path)):
                if file_name.endswith('.jpg'):
                    image_path = sub_folder_path + file_name
                    features = self.extract_ehd(image_path=image_path)
                    features_db.append(features)
                    paths_db.append(image_path)

        # """
        # WANG DATASET
        # """
        # for file_name in tqdm(os.listdir(data_folder)):
        #     if file_name.endswith('.jpg'):
        #         image_path = data_folder + file_name
        #         features = extract_ehd(image_path=image_path)
        #         features_db.append(features)
        #         paths_db.append(image_path)

        pickle.dump(features_db, open("./database/features_Gray_CorelDataset.pkl", 'wb'))
        pickle.dump(paths_db, open("./database/paths_Gray_CorelDataset.pkl", 'wb'))
        print("STORE DATABASE SUCCESSFULLY!")

    def search_image(self, query_image_path, features_db, paths_db):
        features_db = pickle.load(open(features_db, 'rb'))
        paths_db = pickle.load(open(paths_db, 'rb'))
        query_image_features = self.extract_ehd(image_path=query_image_path)

        distances = np.linalg.norm(features_db - query_image_features, axis=1)
        K = 50
        indexs = np.argsort(distances)[:K]

        nearest_images = [(features_db[id], paths_db[id], distances[id]) for id in indexs]

        # grid_size = int(math.sqrt(K))
        grid_row = 5
        grid_col = 10
        fig, axes = plt.subplots(grid_row, grid_col, figsize=(12, 6))
        k = 0
        for i in range(grid_row):
            for j in range(grid_col):
                if i == 0 and j == 0:
                    axes[i, j].set_title("Query")
                    image = cv2.imread(query_image_path)
                    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
                    axes[i, j].imshow(image)
                    axes[i, j].axis('off')
                    k += 1
                else:
                    features_vector, file_path, distance = nearest_images[k-1]
                    # axes[i, j].set_title(distance)
                    image = cv2.imread(file_path)
                    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
                    axes[i, j].imshow(image)
                    axes[i, j].axis('off')
                    k += 1
        plt.tight_layout()
        plt.show()

if __name__ == '__main__':
    # DATA_FOLDER = 'P:/cbir/DATA/wang/image.orig/'
    DATA_FOLDER = 'P:/cbir/DATA/corel/CorelDB/'

    create_db = args.store_database
    query_image_path = args.query_image_path

    runner = EHDExtractor()

    if create_db:
        """
        Store database
        """
        runner.store_database(data_folder=DATA_FOLDER)
    else:
        """
        Search image
        """
        features_db_file = "./database/features_Gray_CorelDataset.pkl"
        file_path_db_file = "./database/paths_Gray_CorelDataset.pkl"
        nearest_images = runner.search_image(query_image_path=query_image_path, features_db=features_db_file, paths_db=file_path_db_file)


import motmetrics as mm
import numpy as np

class MOTMetric(object):

    def __init__(self, ground_truth, tracks, max_d2):
        assert len(ground_truth) == len(tracks)

        self.__has_truth = np.array([bool(d) for d in ground_truth]).any()
        self.__has_hyps = np.array([bool(d) for d in tracks]).any()

        self.acc = mm.MOTAccumulator(auto_id=True)

        for t, objects in enumerate(ground_truth):
            obj_ids = list(objects.keys())
            obj_states = np.array(list(objects.values()))
            hyp_ids = list(tracks[t].keys())
            hyp_states = np.array(list(tracks[t].values()))

            C = mm.distances.norm2squared_matrix(obj_states, hyp_states, max_d2)

            self.acc.update(
                obj_ids,
                hyp_ids,
                C
            )

    def summary(self):
        mh = mm.metrics.create()
        summary = mh.compute(self.acc, metrics=mm.metrics.motchallenge_metrics, name='metrics')
        return mm.io.render_summary(
            summary,
            formatters=mh.formatters,
            namemap=mm.io.motchallenge_metric_names
        )

    def MOTP(self):
        """
        Multiple Object Tracking Precision

        The total position error for all matched object-hypothesis, averaged by the total
        number of matches made. It shows the ability of the tracker to estimate precise
        object positions, independent of its skill at recognizing object configurations,
        keeping consistent trajectories, etc.

        returns a scalar <= 1.0
        """
        if self.__has_hyps and self.__has_truth:
            mh = mm.metrics.create()
            summary = mh.compute(self.acc, metrics=['motp'], return_dataframe=False)
            motp = summary['motp']
            if np.isnan(motp):
                return 0.0
            else:
                return 1.0 - motp
        elif self.__has_hyps:
            return 0.0
        elif self.__has_truth:
            return 0.0
        else:
            return 1.0

    def MOTA(self):
        """
        Multiple Object Tracking Accuracy

        The MOT A accounts for all object configuration errors made by the tracker:
        false positives, misses and mismatches over all object-hypothesis assignments.

        returns a scalar in (-inf, 1.0]
        """
        if self.__has_hyps and self.__has_truth:
            mh = mm.metrics.create()
            summary = mh.compute(self.acc, metrics=['mota'], return_dataframe=False)
            return summary['mota']
        elif self.__has_hyps:
            return 0.0
        elif self.__has_truth:
            return 0.0
        else:
            return 1.0


import torch
from torch import nn

from utils import (basename_noext, get_fashion_mnist_labels,
                   kmp_duplicate_lib_ok, load_data_fashion_mnist, predict,
                   savefig, train_ani)

kmp_duplicate_lib_ok()
torch.set_printoptions(linewidth=120)

def main():
    batch_size = 256
    num_epochs = 10
    lr = 0.1

    train_dataloader, test_dataloader = load_data_fashion_mnist(batch_size)

    net = nn.Sequential(nn.Flatten(),
                        nn.Linear(784, 256, device="cuda"),
                        nn.ReLU(),
                        nn.Linear(256, 10, device="cuda"))

    def init_weights(m):
        if isinstance(m, nn.Linear):
            nn.init.normal_(m.weight, std=0.01)
            nn.init.zeros_(m.bias)

    net.apply(init_weights)

    loss = nn.CrossEntropyLoss(reduction='none')
    trainer = torch.optim.SGD(net.parameters(), lr=lr)

    train_ani(net, train_dataloader, test_dataloader, loss, num_epochs, trainer, "cuda")

    savefig(f'out/{basename_noext(__file__)}_train.png')

    predict(net, test_dataloader, 18, "cuda")

    savefig(f'out/{basename_noext(__file__)}_pred.png')

if __name__ == '__main__':
    main()


# Композиция алгоритмов
# Градиентный бустинг
# Подбор гиперпараметров

import matplotlib.pyplot as plot
import numpy as np
import pandas
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier, RandomForestClassifier
from sklearn.metrics import log_loss

from source import create_answer_file

def log_loss_results(model, X, y):
    # staged_decision_function - для предсказания качества
    # на обучающей и тестовой выборке на каждой итерации.
    return [
        log_loss(y, [1.0 / (1.0 + np.exp(-y_pred)) for y_pred in pred])
        for pred in model.staged_decision_function(X)
    ]

def create_plots(learning_rate, test_loss, train_loss):
    # График значений log-loss на обучающей и тестовой выборках.
    plot.figure()
    plot.plot(test_loss, 'r', linewidth=2)
    plot.plot(train_loss, 'g', linewidth=2)
    plot.legend(['test', 'train'])
    plot.savefig('../images/rate_' + str(learning_rate) + '.png')

def get_min_loss(test_loss):
    # Минимальное значение метрики и номер итерации, на которой оно достигается.
    min_loss_value = min(test_loss)
    min_loss_index = test_loss.index(min_loss_value)
    return min_loss_value, min_loss_index

def model_test(learning_rate):
    model = GradientBoostingClassifier(learning_rate=learning_rate, n_estimators=250,
                                       verbose=True, random_state=241)
    model.fit(X_train, y_train)

    train_loss = log_loss_results(model, X_train, y_train)
    test_loss = log_loss_results(model, X_test, y_test)
    create_plots(learning_rate, test_loss, train_loss)
    return get_min_loss(test_loss)

data = pandas.read_csv(r'..\data\gbm-data.csv')
X = data.loc[:, 'D1':'D1776'].values
y = data['Activity'].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.8, random_state=241)

min_loss_results = {
    learning_rate: model_test(learning_rate)
    for learning_rate in [1, 0.5, 0.3, 0.2, 0.1]
}

# переобучение (overfitting) или недообучение (underfitting) - определяется по графикам
create_answer_file('w5_2.txt', 'overfitting')

# минимальное значение log-loss и номер итерации,
# на котором оно достигается, при learning_rate = 0.2.
min_loss_value, min_loss_index = min_loss_results[0.2]
create_answer_file('w5_3.txt', '{:0.2f} {}'.format(min_loss_value, min_loss_index))

# RandomForestClassifier с количеством деревьев, равным количеству итераций, на котором
# достигается наилучшее качество у градиентного бустинга
model = RandomForestClassifier(n_estimators=min_loss_index, random_state=241)
model.fit(X_train, y_train)

test_loss = log_loss(y_test, model.predict_proba(X_test)[:, 1])
create_answer_file('w5_4.txt', f'{test_loss}')


def main():
    # Create a dictionary to store the books
    books = {}

    while True:
        print("\nBookshop Management System")
        print("1. Add a book")
        print("2. Search for a book")
        print("3. Display all books")
        print("4. Exit")

        choice = input("Enter your choice: ")

        if choice == '1':
            title = input("Enter the book's title: ")
            author = input("Enter the author's name: ")
            books[title] = author  # Add the book to the dictionary
            print(f"Book '{title}' by {author} added.")
        elif choice == '2':
            search_term = input("Enter the author's name or the book's title: ")
            if search_term in books:
                print(f"The book '{search_term}' is available by {books[search_term]}.")
            else:
                print(f"The book '{search_term}' is not available.")
        elif choice == '3':
            if books:
                print("List of Available Books:")
                for title, author in books.items():
                    print(f"Title: {title}, Author: {author}")
            else:
                print("No books available in the store.")
        elif choice == '4':
            break
        else:
            print("Invalid choice. Please try again.")

if __name__ == "__main__":
    main()


from keras.layers import Input, Conv2D, Conv2DTranspose
from keras.layers import MaxPooling2D, UpSampling2D, AveragePooling2D
from keras.layers import BatchNormalization, Activation, concatenate, Lambda, add, Dropout
from keras.models import Model
import keras.backend as K
from keras import optimizers

# lr = 0.00001
# lr = 1e-6
# decay = 1e-6
# decay = 0

# Batch Normalization
is_batch_norm = True
# is_batch_norm = False

# DropOut
# is_drop_out = True
is_drop_out = False

# difference_scaling = 100

depth_threshold = 0.2
difference_threshold = 0.01
difference_threshold = 10

''' U-Net '''
def build_unet_model(batch_shape,
                    ch_num,
                    drop_rate=0.1,
                    transfer_learn=False,
                    transfer_encoder=False,
                    lr=0.001,
                    scaling=1
                    ):
    def encode_block(x, ch):
        def base_block(x):
            x = BatchNormalization()(x)
            x = Activation('tanh')(x)
            x = Dropout(rate=drop_rate)(x)
            x = Conv2D(ch, (3, 3), padding='same')(x)
            return x

        x = base_block(x)
        x = base_block(x)
        return x

    def decode_block(x, c, ch):
        ch = ch
        def base_block(x):
            x = BatchNormalization()(x)
            x = Activation('tanh')(x)
            x = Dropout(rate=drop_rate)(x)
            x = Conv2DTranspose(ch, (3, 3), padding='same')(x)
            return x

        x = Conv2DTranspose(ch, (3, 3), padding='same')(x)
        x = UpSampling2D((2, 2))(x)
        x = concatenate([x, c])

        x = base_block(x)
        x = base_block(x)
        return x

    input_batch = Input(shape=(*batch_shape, ch_num))
    e0 = Conv2D(8, (1, 1), padding='same')(input_batch)
    e0 = Activation('tanh')(e0)

    e0 = encode_block(e0, 16)

    e1 = AveragePooling2D((2, 2))(e0)
    e1 = encode_block(e1, 32)

    e2 = AveragePooling2D((2, 2))(e1)
    e2 = encode_block(e2, 64)

    e3 = AveragePooling2D((2, 2))(e2)
    e3 = encode_block(e3, 128)

    d2 = decode_block(e3, e2, 64)
    d1 = decode_block(d2, e1, 32)
    d0 = decode_block(d1, e0, 16)

    # d0 = Conv2D(2, (1, 1), padding='same')(d0)
    # output_batch = Activation('tanh')(d0)
    # output_batch = Conv2D(2, (1, 1), padding='same')(d0)
    output_batch = Conv2D(1, (1, 1), padding='same')(d0)

    def mean_squared_error_with_mask(y_true, y_pred):
        difference = y_true[:, :, :, 0]
        depth_gap = y_true[:, :, :, 1]
        # mask = y_true[:, :, :, 1]

        difference *= scaling

        is_gap_available = depth_gap > depth_threshold
        # is_depth_close = difference < difference_threshold
        is_depth_close = K.all(K.stack([K.abs(difference) < difference_threshold,
                                        is_gap_available], axis=0), axis=0)
        mask = K.cast(is_depth_close, 'float32')

        mask_length = K.sum(mask)
        err = K.sum(K.square(difference - y_pred[:, :, :, 0]) * mask) / mask_length # MSE
        # err = K.mean(K.square(difference - y_pred[:, :, :, 0]) * mask)
        # err = K.sum(K.abs(difference - y_pred[:, :, :, 0]) * mask) / mask_length # MAE
        return err

    model = Model(input_batch, output_batch)

    # Transfer Learning
    if transfer_learn:
        for l in model.layers[:38]:
            l.trainable = False
    elif transfer_encoder:
        for l in model.layers[38:]:
            l.trainable = False

    # adam = optimizers.Adam(lr=lr, decay=decay)
    adam = optimizers.Adam(lr=lr)
    model.compile(
                # optimizer='adam',
                optimizer=adam,
                metrics=['accuracy'],
                loss=mean_squared_error_with_mask
                # loss='mean_squared_error'
                # loss='mean_absolute_error'
                )
    return model

''' U-ResNet '''
def build_resnet_model(batch_shape,
                        ch_num,
                        depth_threshold=0.1,
                        difference_threshold=0.05,
                        drop_rate=0.1,
                        scaling=100):
    def encode_block(x, ch):
        def base_block(x):
            x = BatchNormalization()(x)
            x = Activation('tanh')(x)
            x = Dropout(rate=drop_rate)(x)
            x = Conv2D(ch, (3, 3), padding='same')(x)
            return x

        s = Conv2D(ch, (1, 1), padding='same')(x)
        x = base_block(x)
        x = base_block(x)
        x = add([x, s])
        return x

    def decode_block(x, c, ch):
        ch = ch
        def base_block(x):
            x = BatchNormalization()(x)
            x = Activation('tanh')(x)
            x = Dropout(rate=drop_rate)(x)
            x = Conv2DTranspose(ch, (3, 3), padding='same')(x)
            return x

        x = Conv2DTranspose(ch, (3, 3), padding='same')(x)
        x = UpSampling2D((2, 2))(x)
        x = concatenate([x, c])

        s = Conv2D(ch, (1, 1), padding='same')(x)
        x = base_block(x)
        x = base_block(x)
        x = add([x, s])
        return x

    input_batch = Input(shape=(*batch_shape, ch_num))

    e0 = AveragePooling2D((2, 2))(input_batch)
    e0 = UpSampling2D((2, 2))(e0)
    e0 = Conv2D(8, (1, 1), padding='same')(e0)

    # e0 = Conv2D(8, (1, 1), padding='same')(input_batch)
    e0 = Activation('tanh')(e0)

    e0 = encode_block(e0, 16)

    e1 = AveragePooling2D((2, 2))(e0)
    e1 = encode_block(e1, 32)

    e2 = AveragePooling2D((2, 2))(e1)
    e2 = encode_block(e2, 64)

    e3 = AveragePooling2D((2, 2))(e2)
    # e3 = encode_block(e2, 128)
    e3 = encode_block(e3, 128)

    d2 = decode_block(e3, e2, 64)
    d1 = decode_block(d2, e1, 32)
    d0 = decode_block(d1, e0, 16)

    d0 = Conv2D(2, (1, 1), padding='same')(d0)
    output_batch = Activation('tanh')(d0)

    def mean_squared_error_difference_learn(y_true, y_pred):
        depth_gt = y_true[:, :, :, 0]
        depth_gap = y_true[:, :, :, 1]

        is_gt_available = depth_gt > depth_threshold
        is_gap_unavailable = depth_gap < depth_threshold

        is_depth_close = K.all(K.stack([
            K.abs(depth_gap - depth_gt) < difference_threshold, is_gt_available], axis=0), axis=0)

        # difference learn
        gt = depth_gt - depth_gap

        # scale
        gt = gt * scaling

        # complement
        is_complement = False
        if is_complement:
            is_to_interpolate = K.all(K.stack(
                [is_gt_available, is_gap_unavailable], axis=0),
                                    axis=0)
            is_valid = K.any(K.stack([is_to_interpolate, is_depth_close], axis=0),
                            axis=0)
            # is_valid = K.cast(is_valid, float)
            is_valid = K.cast(is_valid, 'float32')
        else:
            # is_valid = K.cast(is_depth_close, float)
            is_valid = K.cast(is_depth_close, 'float32')

        valid_length = K.sum(is_valid)
        # err = K.sum(K.square(gt - y_pred[:, :, :, 0]) * is_valid)  / valid_length # MSE
        err = K.sum(K.abs(gt - y_pred[:, :, :, 0]) * is_valid)  / valid_length # MAE
        return err

    model = Model(input_batch, output_batch)
    # adam = optimizers.Adam(lr=lr, decay=decay)
    model.compile(optimizer='adam',
                  metrics=['accuracy'],
                #   loss=mean_squared_error_difference_learn
                #   loss='mean_squared_error'
                  loss='mean_absolute_error'
                  )
    return model


# Fill in the blanks to make the factorial function return the factorial of n.
# Then, print the first 10 factorials (from 0 to 9) with the corresponding number.
# Remember that the factorial of a number is defined as the product of an integer and all integers before it.
# For example, the factorial of five (5!) is equal to 1*2*3*4*5=120. Also recall that the factorial of zero (0!) is equal to 1.

'''def factorial(n):
    result = 1
    for x in range(1, n):
        result = x * result
    return result

for n in range(0, 10):
    print(n, factorial(n + 1))'''

# Write a script that prints the multiples of 7 between 0 and 100.
# Print one multiple per line and avoid printing any numbers that aren't multiples of 7.
# Remember that 0 is also a multiple of 7.
'''for i in range(0, 100):
    if i % 7 == 0:
        print(i)'''

# Complete the function digits(n) that returns how many digits the number has. For example: 25 has 2 digits and 144 has 3 digits.
# Tip: you can figure out the digits of a number by dividing it by 10 once per digit until there are no digits left.
'''
def digits(n):
	count = 0
	if n == 0:
	  	count += 1
	while (n>0):
		count += 1
		n = n // 10
	return count

print(digits(25))   # Should print 2
print(digits(144))  # Should print 3
print(digits(1000)) # Should print 4
print(digits(0))    # Should print 1
'''

# The even_numbers function returns a space-separated string of all positive numbers that are divisible by 2, up to and including the maximum that's passed into the function.
# For example, even_numbers(6) returns “2 4 6”. Fill in the blank to make this work.
'''
def even_numbers(maximum):
	return_string = ""
	for x in range(2,maximum+1):
		if x%2==0:
			return_string += str(x) + " "
	return return_string.strip()

print(even_numbers(6))  # Should be 2 4 6
print(even_numbers(10)) # Should be 2 4 6 8 10
print(even_numbers(1))  # No numbers displayed
print(even_numbers(3))  # Should be 2
print(even_numbers(0))  # No numbers displayed
'''

# The counter function counts down from start to stop when start is bigger than stop, and counts up from start to stop otherwise.
# Fill in the blanks to make this work correctly.

'''def counter(start, stop):
    x = start
    if x >= stop:
        return_string = "Counting down: "
        while x >= stop:
            return_string += str(x)
            if x > stop:
                return_string += ","
            x -= 1
    else:
        return_string = "Counting up: "
        while x <= stop:
            return_string += str(x)
            if x < stop:
                return_string += ","
            x += 1
    return return_string

print(counter(1, 10))  # Should be "Counting up: 1,2,3,4,5,6,7,8,9,10"
print(counter(2, 1))  # Should be "Counting down: 2,1"
print(counter(5, 5))  # Should be "Counting up: 5"
'''

'''def count_users(group):
    count = 0
    for member in get_members(group):
        if is_group(member):
            count += count_users(member)
        else:
            count+=1
    return count

print(count_users("sales")) # Should be 3
print(count_users("engineering")) # Should be 8
print(count_users("everyone")) # Should be 18'''

'''def sum_positive_numbers(n):
  if n < 1:
    return 0
  else:
    return n + sum_positive_numbers(n-1)

print(sum_positive_numbers(3)) # Should be 6
print(sum_positive_numbers(5)) # Should be 15'''

# The replace_ending function replaces the old string in a sentence with the new string, but only if the sentence ends with the old string.
# If there is more than one occurrence of the old string in the sentence, only the one at the end is replaced, not all of them.
# For example, replace_ending("abcabc", "abc", "xyz") should return abcxyz, not xyzxyz or xyzabc.
# The string comparison is case-sensitive, so replace_ending("abcabc", "ABC", "xyz") should return abcabc (no changes made).

'''def replace_ending(sentence, old, new):
    if sentence.endswith(old):
        i = sentence.rfind(old)
        new_sentence = sentence[:i] + new
        return new_sentence

    return sentence

print(replace_ending("It's raining cats and cats", "cats", "dogs"))
print(replace_ending("She sells seashells by the seashore", "seashells", "donuts"))
print(replace_ending("The weather is nice in May", "may", "april"))
print(replace_ending("The weather is nice in May", "May", "April"))'''

# The is_palindrome function checks if a string is a palindrome.
# A palindrome is a string that can be equally read from left to right or right to left, omitting blank spaces, and ignoring capitalization.
# Examples of palindromes are words like kayak and radar, and phrases like "Never Odd or Even".
# Fill in the blanks in this function to return True if the passed string is a palindrome, False if not.
'''def is_palindrome(input_string):
    new_string = ""
    reverse_string = ""
    for letter in input_string:
        if letter != ' ':
            new_string += letter
            reverse_string = letter + reverse_string
    if new_string.lower() == reverse_string.lower():
        return True
    return False

print(is_palindrome("Never Odd or Even"))
print(is_palindrome("abc"))
print(is_palindrome("kayak"))'''

text = [('Ken', 30, "Chef"), ("Pat", 35, 'Lawyer'), ('Amanda', 25, "Engineer")]

for a, b, c in text:
    print("{} is {} years old and works as {}".format(a, b, c))

Coursera Certification Course/Google Crash Course Python/Function (OOP)/Function(2).py


from Products.Five.browser import BrowserView
from Products.CMFCore.utils import getToolByName
from plone import api
import logging

logger = logging.getLogger(".SetEditor")

class SetEditor(BrowserView):
    def __call__(self):

       #get facebook's users account
        acl_users = api.portal.get_tool(name='acl_users')
        cs_facebook_users = getattr(acl_users, 'cs-facebook-users', '')
        facebookUsers = cs_facebook_users.enumerateUsers()
        users = list()
        for fbUser in facebookUsers:
            users.append(fbUser['id'])

        for userId in users:
            user = api.user.get(userid=userId)
#            user.setMemberProperties({'wysiwyg_editor': ''})

#        import pdb; pdb.set_trace()
#        members = api.user.get_users()
#        for member in members:
#            import pdb; pdb.set_trace()
#            if len(member.getRoles()) < 2 or 'Member' not in member.getRoles():
#                logger.error('id: %s , has a wrong roles setting.' % member.id)
#                member.setMemberProperties({'wysiwyg_editor': 'CKeditor'})
#                continue
#            if len(member.getRoles()) == 2:
#                member.setMemberProperties({'wysiwyg_editor': 'CKeditor'})
#            else:
#            member.setMemberProperties({'wysiwyg_editor': 'TinyMCE'})
#            member.wysiwyg_editor = "TinyMCE"
            logger.info('%s : %s : %s\n' % (user.id,
                                            user.getProperty('wysiwyg_editor', None),
                                            str(user.getRoles())))


# import tensorflow as tf
from tensorflow.keras.models import Sequential # 순차적(Sequential) 모델을 쓸것이다.
from tensorflow.keras.layers import Dense
import numpy as np

#1. 데이터
x = np.array([1, 2, 3])
y = np.array([1, 2, 3])

#2. 모델구성
model = Sequential()
model.add(Dense(1, input_dim=1))

#3. 컴파일, 훈련
model.compile(loss='mse', optimizer ='adam')#loss 값은 작으면 좋다 , loss 에 mse 값을 감축시키는 역할을 해줌(optimizer)

model.fit(x, y, epochs=3900, batch_size=1)#epochs = 훈련양

#4. 평가, 예측
loss = model.evaluate(x, y)
print('loss : ',loss)
result = model.predict([4])
print('4의 예측값 : ', result)

'''
loss :  0.0015667766565456986
4의 예측값 :  [[3.9181228]]
'''
#4000 가까이 실행을 돌리면 최적의 값을 낼수 있음
#많은 데이터를 비교해본다고 정확하진 않음
#로스값이 작을수록 정확하다


import tarfile
import pickle
import random
import numpy as np
import matplotlib.pyplot as plt
import h5py

#---------------------------------------------------------------zero padding---------------------------------------------------------------------
def zero_pad(X, pad):
    """
    Pad with zeros all images of the dataset X. The padding is applied to the height and width of an image,
    as illustrated in Figure 1.
    """
    X_pad = np.pad(X, ((0,0), (pad,pad), (pad,pad), (0,0)), 'constant')
    return X_pad

def conv_single_step(a_slice_prev, W, b):
    """
    Apply one filter defined by parameters W on a single slice (a_slice_prev) of the output activation
    of the previous layer.
    """
    s = a_slice_prev * W
    Z = np.sum(s)
    Z = Z + b

    return Z
#---------------------------------------------------------------forward propogation---------------------------------------------------------------------
def conv_forward(A_prev, W, b, hparameters):
    """
    Implements the forward propagation for a convolution function
    """
    (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape
    (f, f, n_C_prev, n_C) = W.shape
    stride = hparameters["stride"]
    pad = hparameters["pad"]
    n_H = int((n_H_prev - f + 2*pad) / stride + 1)
    n_W = int((n_W_prev - f + 2*pad) / stride + 1)
    Z = np.zeros((m, n_H, n_W, n_C))
    A_prev_pad = zero_pad(A_prev, pad)

    for i in range(m):
        a_prev_pad = A_prev_pad[i, :, :, :]
        for h in range(n_H):
            for w in range(n_W):
                for c in range(n_C):
                    vert_start = stride * h
                    vert_end = vert_start + f
                    horiz_start = stride * w
                    horiz_end = horiz_start + f
                    a_slice_prev = a_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :]
                    Z[i, h, w, c] = conv_single_step(a_slice_prev, W[:, :, :, c], b[:, :, :, c])
    assert(Z.shape == (m, n_H, n_W, n_C))
    cache = (A_prev, W, b, hparameters)
    return Z, cache
#---------------------------------------------------------------forward pooling---------------------------------------------------------------------
def pool_forward(A_prev, hparameters, mode = "max"):
    """
    Implements the forward pass of the pooling layer
    """
    (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape
    f = hparameters["f"]
    stride = hparameters["stride"]
    n_H = int(1 + (n_H_prev - f) / stride)
    n_W = int(1 + (n_W_prev - f) / stride)
    n_C = n_C_prev
    A = np.zeros((m, n_H, n_W, n_C))
    for i in range(m):
        for h in range(n_H):
            for w in range(n_W):
                for c in range (n_C):
                    vert_start = h * stride
                    vert_end = vert_start + f
                    horiz_start = w * stride
                    horiz_end = horiz_start + f
                    a_prev_slice = A_prev[i, vert_start:vert_end, horiz_start:horiz_end, c]
                    if mode == "max":
                        A[i, h, w, c] = np.max(a_prev_slice)
                    elif mode == "average":
                        A[i, h, w, c] = np.mean(a_prev_slice)
    cache = (A_prev, hparameters)
    assert(A.shape == (m, n_H, n_W, n_C))
    return A, cache
#---------------------------------------------------------------backward propogation---------------------------------------------------------------------

def conv_backward(dZ, cache):
    """
    Implement the backward propagation for a convolution function
    """
    (A_prev, W, b, hparameters) = cache
    (m, n_H_prev, n_W_prev, n_C_prev) = A_prev.shape
    (f, f, n_C_prev, n_C) = W.shape
    stride = hparameters['stride']
    pad = hparameters['pad']
    (m, n_H, n_W, n_C) = dZ.shape
    dA_prev = np.zeros((m, n_H_prev, n_W_prev, n_C_prev))
    dW = np.zeros((f, f, n_C_prev, n_C))
    db = np.zeros((1, 1, 1, n_C))
    A_prev_pad = zero_pad(A_prev, pad)
    dA_prev_pad = zero_pad(dA_prev, pad)

    for i in range(m):
        a_prev_pad = A_prev_pad[i, :, :, :]
        da_prev_pad = dA_prev_pad[i, :, :, :]

        for h in range(n_H):
            for w in range(n_W):
                for c in range(n_C):
                    vert_start = h * stride
                    vert_end = vert_start + f
                    horiz_start = w * stride
                    horiz_end = horiz_start + f
                    a_slice = a_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :]
                    da_prev_pad[vert_start:vert_end, horiz_start:horiz_end, :] += W[:,:,:,c] * dZ[i, h, w, c]
                    dW[:,:,:,c] += a_slice * dZ[i, h, w, c]
                    db[:,:,:,c] += dZ[i, h, w, c]
        dA_prev[i, :, :, :] = da_prev_pad[pad:-pad, pad:-pad, :]
    assert(dA_prev.shape == (m, n_H_prev, n_W_prev, n_C_prev))

    return dA_prev, dW, db

def create_mask_from_window(x):
    """
    Creates a mask from an input matrix x, to identify the max entry of x.
    """
    mask = (x == np.max(x))
    return mask

#---------------------------------------------------------------backward pooling---------------------------------------------------------------------
def distribute_value(dz, shape):
    """
    Distributes the input value in the matrix of dimension shape
    """
    (n_H, n_W) = shape
    average = dz / (n_H * n_W)
    a = average * np.ones(shape)

    return a
def pool_backward(dA, cache, mode = "max"):
    """
    Implements the backward pass of the pooling layer
    """
    (A_prev, hparameters) = cache
    stride = hparameters['stride']
    f = hparameters['f']
    m, n_H_prev, n_W_prev, n_C_prev = A_prev.shape
    m, n_H, n_W, n_C = dA.shape
    dA_prev = np.zeros(np.shape(A_prev))

    for i in range(m):
        a_prev = A_prev[i, :, :, :]

        for h in range(n_H):
            for w in range(n_W):
                for c in range(n_C):
                    vert_start = h * stride
                    vert_end = vert_start + f
                    horiz_start = w * stride
                    horiz_end = horiz_start + f
                    if mode == "max":
                        a_prev_slice = a_prev[vert_start:vert_end, horiz_start:horiz_end, c]
                        mask = create_mask_from_window(a_prev_slice)
                        dA_prev[i, vert_start: vert_end, horiz_start: horiz_end, c] += np.multiply(mask, dA[i, h, w, c])

                    elif mode == "average":

                        da = dA[i, h, w, c]
                        shape = (f, f)
                        dA_prev[i, vert_start: vert_end, horiz_start: horiz_end, c] += distribute_value(da, shape)
    assert(dA_prev.shape == A_prev.shape)
    return dA_prev

#---------------------------------------------------------------loading dataset---------------------------------------------------------------------

import tensorflow as tf #to plot histograms
from urllib.request import urlretrieve
from os.path import isfile, isdir
from tqdm import tqdm

cifar10_dataset_folder_path = 'cifar-10-batches-py'
n_batches = 5
valid_features = []
valid_labels = []
class DownloadProgress(tqdm):
    last_block = 0

    def hook(self, block_num=1, block_size=1, total_size=None):
        self.total = total_size
        self.update((block_num - self.last_block) * block_size)
        self.last_block = block_num

def load_label_names():
    return ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']

def load_cfar10_batch(cifar10_dataset_folder_path, batch_id):
    with open(cifar10_dataset_folder_path + '/data_batch_' + str(batch_id), mode='rb') as file:
        # note the encoding type is 'latin1'
        batch = pickle.load(file, encoding='latin1')

    features = batch['data'].reshape((len(batch['data']), 3, 32, 32)).transpose(0, 2, 3, 1)
    labels = batch['labels']

    return features, labels

def display_stats(cifar10_dataset_folder_path, batch_id, sample_id):
    features, labels = load_cfar10_batch(cifar10_dataset_folder_path, batch_id)

    if not (0 <= sample_id < len(features)):
        print('{} samples in batch {}.  {} is out of range.'.format(len(features), batch_id, sample_id))
        return None

    print('\nStats of batch #{}:'.format(batch_id))
    print('# of Samples: {}\n'.format(len(features)))

    label_names = load_label_names()
    label_counts = dict(zip(*np.unique(labels, return_counts=True)))
    for key, value in label_counts.items():
        print('Label Counts of [{}]({}) : {}'.format(key, label_names[key].upper(), value))

    sample_image = features[sample_id]
    sample_label = labels[sample_id]

    print('\nExample of Image {}:'.format(sample_id))
    print('Image - Min Value: {} Max Value: {}'.format(sample_image.min(), sample_image.max()))
    print('Image - Shape: {}'.format(sample_image.shape))
    print('Label - Label Id: {} Name: {}'.format(sample_label, label_names[sample_label]))

def normalize(x):

    min_val = np.min(x)
    max_val = np.max(x)
    x = (x-min_val) / (max_val-min_val)
    return x

def one_hot_encode(x):
    encoded = np.zeros((len(x), 10))

    for idx, val in enumerate(x):
        encoded[idx][val] = 1

    return encoded
#---------------------------------------------------------------preprocessing---------------------------------------------------------------------
def _preprocess_and_save(normalize, one_hot_encode, features, labels, filename):
    features = normalize(features)
    labels = one_hot_encode(labels)

    pickle.dump((features, labels), open(filename, 'wb'))

def preprocess_and_save_data(cifar10_dataset_folder_path, normalize, one_hot_encode):

    for batch_i in range(1, n_batches + 1):
        features, labels = load_cfar10_batch(cifar10_dataset_folder_path, batch_i)

        index_of_validation = int(len(features) * 0.1)
        _preprocess_and_save(normalize, one_hot_encode,
                             features[:-index_of_validation], labels[:-index_of_validation],
                             'preprocess_batch_' + str(batch_i) + '.p')

        valid_features.extend(features[-index_of_validation:])
        valid_labels.extend(labels[-index_of_validation:])

    _preprocess_and_save(normalize, one_hot_encode,
                         np.array(valid_features), np.array(valid_labels),
                         'preprocess_validation.p')

    with open(cifar10_dataset_folder_path + '/test_batch', mode='rb') as file:
        batch = pickle.load(file, encoding='latin1')

    test_features = batch['data'].reshape((len(batch['data']), 3, 32, 32)).transpose(0, 2, 3, 1)
    test_labels = batch['labels']

    _preprocess_and_save(normalize, one_hot_encode,
                         np.array(test_features), np.array(test_labels),
                         'preprocess_training.p')

def load_preprocess_training_batch(batch_id, batch_size):

    filename = 'preprocess_batch_' + str(batch_id) + '.p'
    features, labels = pickle.load(open(filename, mode='rb'))

    return batch_features_labels(features, labels, batch_size)

def batch_features_labels(features, labels, batch_size):

    for start in range(0, len(features), batch_size):
        end = min(start + batch_size, len(features))
        yield features[start:end], labels[start:end]

tf.reset_default_graph()

x = tf.placeholder(tf.float32, shape=(None, 32, 32, 3), name='input_x')
y =  tf.placeholder(tf.float32, shape=(None, 10), name='output_y')
keep_prob = tf.placeholder(tf.float32, name='keep_prob')

def conv_net(x, keep_prob):
    conv1_filter = tf.Variable(tf.truncated_normal(shape=[3, 3, 3, 64], mean=0, stddev=0.08))
    conv2_filter = tf.Variable(tf.truncated_normal(shape=[3, 3, 64, 128], mean=0, stddev=0.08))
    conv3_filter = tf.Variable(tf.truncated_normal(shape=[5, 5, 128, 256], mean=0, stddev=0.08))
    conv4_filter = tf.Variable(tf.truncated_normal(shape=[5, 5, 256, 512], mean=0, stddev=0.08))

    conv1 = tf.nn.conv2d(x, conv1_filter, strides=[1,1,1,1], padding='SAME')
    conv1 = tf.nn.relu(conv1)
    conv1_pool = tf.nn.max_pool(conv1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    conv1_bn = tf.layers.batch_normalization(conv1_pool)
    conv2 = tf.nn.conv2d(conv1_bn, conv2_filter, strides=[1,1,1,1], padding='SAME')
    conv2 = tf.nn.relu(conv2)
    conv2_pool = tf.nn.max_pool(conv2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    conv2_bn = tf.layers.batch_normalization(conv2_pool)
    conv3 = tf.nn.conv2d(conv2_bn, conv3_filter, strides=[1,1,1,1], padding='SAME')
    conv3 = tf.nn.relu(conv3)
    conv3_pool = tf.nn.max_pool(conv3, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    conv3_bn = tf.layers.batch_normalization(conv3_pool)
    conv4 = tf.nn.conv2d(conv3_bn, conv4_filter, strides=[1,1,1,1], padding='SAME')
    conv4 = tf.nn.relu(conv4)
    conv4_pool = tf.nn.max_pool(conv4, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    conv4_bn = tf.layers.batch_normalization(conv4_pool)
    flat = tf.contrib.layers.flatten(conv4_bn)
    full1 = tf.contrib.layers.fully_connected(inputs=flat, num_outputs=128, activation_fn=tf.nn.relu)
    full1 = tf.nn.dropout(full1, keep_prob)
    full1 = tf.layers.batch_normalization(full1)
    full2 = tf.contrib.layers.fully_connected(inputs=full1, num_outputs=256, activation_fn=tf.nn.relu)
    full2 = tf.nn.dropout(full2, keep_prob)
    full2 = tf.layers.batch_normalization(full2)
    full3 = tf.contrib.layers.fully_connected(inputs=full2, num_outputs=512, activation_fn=tf.nn.relu)
    full3 = tf.nn.dropout(full3, keep_prob)
    full3 = tf.layers.batch_normalization(full3)
    full4 = tf.contrib.layers.fully_connected(inputs=full3, num_outputs=1024, activation_fn=tf.nn.relu)
    full4 = tf.nn.dropout(full4, keep_prob)
    full4 = tf.layers.batch_normalization(full4)
    out = tf.contrib.layers.fully_connected(inputs=full3, num_outputs=10, activation_fn=None)
    return out
#---------------------------------------------------------------training---------------------------------------------------------------------
def train_neural_network(session, optimizer, keep_probability, feature_batch, label_batch):
    session.run(optimizer,
                feed_dict={
                    x: feature_batch,
                    y: label_batch,
                    keep_prob: keep_probability
                })

def print_stats(session, feature_batch, label_batch, cost, accuracy):
    loss = session.run(cost,
                    feed_dict={
                        x: feature_batch,
                        y: label_batch,
                        keep_prob: 1.
                    })
    valid_acc = session.run(accuracy,
                         feed_dict={
                             x: valid_features,
                             y: valid_labels,
                             keep_prob: 1.
                         })

    print('Loss: {:>10.4f} Validation Accuracy: {:.6f}'.format(loss, valid_acc))
if not isfile('cifar-10-python.tar.gz'):
    with DownloadProgress(unit='B', unit_scale=True, miniters=1, desc='CIFAR-10 Dataset') as pbar:
        urlretrieve(
            'https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz',
            'cifar-10-python.tar.gz',
            pbar.hook)

if not isdir(cifar10_dataset_folder_path):
    with tarfile.open('cifar-10-python.tar.gz') as tar:
        tar.extractall()
        tar.close()

batch_id = 3
sample_id = 7000
display_stats(cifar10_dataset_folder_path, batch_id, sample_id)

preprocess_and_save_data(cifar10_dataset_folder_path, normalize, one_hot_encode)

valid_features, valid_labels = pickle.load(open('preprocess_validation.p', mode='rb'))

epochs = 10
batch_size = 128
keep_probability = 0.7
learning_rate = 0.001

logits = conv_net(x, keep_prob)
model = tf.identity(logits, name='logits')

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

correct_pred = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32), name='accuracy')

save_model_path = './image_classification'
#---------------------------------------------------------------plotting histograms using tensorflow saved model from abve---------------------------------------------------------------------
print('Training...')
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for epoch in range(epochs):
        n_batches = 5
        for batch_i in range(1, n_batches + 1):
            for batch_features, batch_labels in load_preprocess_training_batch(batch_i, batch_size):
                train_neural_network(sess, optimizer, keep_probability, batch_features, batch_labels)

            print('Epoch {:>2}, CIFAR-10 Batch {}:  '.format(epoch + 1, batch_i), end='')
            print_stats(sess, batch_features, batch_labels, cost, accuracy)

    saver = tf.train.Saver()
    save_path = saver.save(sess, save_model_path)


from typing import Sequence

import pandas as pd

from ...datasets.base import Dataset
from ...llm.evaluators import RequirementEvaluator
from ...llm.generators import AdversarialDataGenerator
from ...llm.testcase import TestcaseRequirementsGenerator
from ...models.base.model import BaseModel
from ...testing.tests.llm import test_llm_output_against_requirement
from ..issues import Issue
from ..scanner import logger

class RequirementBasedDetector:
    def __init__(self, num_requirements=4, num_samples=5):
        self.num_requirements = num_requirements
        self.num_samples = num_samples

    def run(self, model: BaseModel, dataset: Dataset) -> Sequence[Issue]:
        issue_description = self.get_issue_description()

        logger.info(f"{self.__class__.__name__}: Generating test case requirements")
        requirements_gen = TestcaseRequirementsGenerator(issue_description)
        requirements = requirements_gen.generate_requirements(model, self.num_requirements)

        logger.info(f"{self.__class__.__name__}: Evaluating test cases")
        issues = []
        for requirement in requirements:
            logger.info(f"{self.__class__.__name__}: Evaluating requirement: {requirement}")
            dg = AdversarialDataGenerator(issue_description=issue_description, requirement=requirement)
            eval_dataset = dg.generate_dataset(model, self.num_samples)

            evaluator = RequirementEvaluator([requirement])
            eval_result = evaluator.evaluate(model, eval_dataset)

            if eval_result.failed:
                issues.append(
                    self.make_issue(model, eval_dataset, requirement, pd.DataFrame(eval_result.failure_examples))
                )
                logger.info(
                    f"{self.__class__.__name__}: Test case failed ({len(eval_result.failure_examples)} failed examples)"
                )
            else:
                logger.info(f"{self.__class__.__name__}: Test case passed")

        return issues

    def make_issue(self, model: BaseModel, dataset: Dataset, requirement: str, examples: pd.DataFrame) -> Issue:
        return Issue(
            model,
            dataset,
            group=self._issue_group,
            level=self._issue_level,
            description="The model does not satisfy the following requirement: " + requirement,
            examples=examples,
            meta={
                "domain": requirement,
                "requirement": requirement,
                "deviation": f"{len(examples)} failing sample{'s' if len(examples) > 1 else ''} found",
                "hide_index": True,
            },
            tests=_generate_output_requirement_tests,
        )

def _generate_output_requirement_tests(issue: Issue):
    return {
        issue.meta["requirement"]: test_llm_output_against_requirement(
            dataset=issue.dataset, requirement=issue.meta["requirement"]
        )
    }


import os
import argparse
import pandas as pd
import numpy as np
from PIL import Image

from data_processing.recover_dataset import CIFAR100Coarse

def get_novel_class(data_folder, train):
    # Download the CIFAR100 Data
    cifar100_data = CIFAR100Coarse(
        root=data_folder,
        train=train,
        download=True
    )

    images = cifar100_data.data
    labels = np.asarray(cifar100_data.targets)

    # Filter out all reptile images
    non_reptile_images = images[np.squeeze(labels != 15)]

    random_indices = np.random.choice(
        len(non_reptile_images),
        size=200,
        replace=False
    )

    random_images = non_reptile_images[random_indices]

    return random_images

def create_arg_parser():
    parser = argparse.ArgumentParser(description='Download images for sub classes')
    parser.add_argument('--training_label_path', required=True, help='the path to training label')
    parser.add_argument('--new_train_label_path', required=True, help='The output_folder')
    parser.add_argument('--cifar_data_folder', required=True, help='The output_folder')
    parser.add_argument('--image_folder', required=True, help='The output_folder')
    parser.add_argument('--is_train', action='store_true')
    return parser

def main(args):
    subclass_mapping = pd.read_csv(args.training_label_path, header=0)

    if not os.path.exists(args.image_folder):
        os.makedirs(args.image_folder)

    last_image_number = max(
        [int(item[1][:-4]) for item in subclass_mapping.image.iteritems()]
    ) + 1

    novel_images = get_novel_class(args.cifar_data_folder, args.is_train)

    new_images = []
    for img_array in novel_images:
        img = Image.fromarray(img_array)
        image_name = f'{last_image_number}.jpg'
        img.save(os.path.join(args.image_folder, image_name))
        last_image_number += 1
        # 89 is the novel index
        if args.is_train:
            new_images.append((image_name, 3, 89))
        else:
            new_images.append((image_name, 89))

    pd.concat(
        [subclass_mapping,
         pd.DataFrame(new_images, columns=subclass_mapping.columns)]
    ).to_csv(args.new_train_label_path, index=False)

if __name__ == "__main__":
    main(create_arg_parser().parse_args())


#Stephen Greene
#LR Circuit
#ODEs Runge-Kutta

import numpy as np
import matplotlib.pyplot as plt
#for square wave
from scipy import signal

#defining dI/dt
def f(T,I):
    return 1.0/0.9*(V(T)-8.0*I)

#defining square wave
def V(T):
    return signal.square(np.pi*2.0*T)

#ask user for input
#array for time and current, step size
n = int(input('Please enter value for n:  '))
T = np.linspace(0,4,n)
I = np.empty(n)
h = 4.0/n
I[0] = 1 #starting current

#Runge-Kutta 4 Method
for i in range(n-1):
    r1 = h*f(T[i],I[i])
    r2 = h*f(T[i]+(h/2.0),I[i]+(r1/2.0))
    r3 = h*f(T[i]+(h/2.0),I[i]+(r2/2.0))
    r4 = h*f(T[i]+h,I[i]+r3)

    I[i+1] = I[i]+(r1/6.0)+(r2/3.0)+(r3/3.0)+(r4/6.0)

#plotting
plt.plot(T,I, label ='I(t)')
plt.plot(T,V(T), label ='V(t)')
plt.plot(T,f(T,I), label = 'dI(T)/dT(T)')
plt.title('LR Circuit')
plt.xlabel('Time (s)')
plt.ylabel('I (T)')
plt.grid()
plt.legend()
plt.show()


"""initial_empty

Revision ID: fde77a68e3dd
Revises:
Create Date: 2022-12-05 17:14:59.972979

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'fde77a68e3dd'
down_revision = None
branch_labels = None
depends_on = None

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('bus_stops',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('stop_id', sa.String(length=10), nullable=False),
    sa.Column('number', sa.String(length=10), nullable=False),
    sa.Column('name', sa.String(length=60), nullable=False),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('stop_id', 'number', name='unique_stop_id_number')
    )
    op.create_table('lines',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('line_number', sa.String(length=10), nullable=False),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('line_number')
    )
    op.create_table('bus_stop_data',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('bus_stop_id', sa.Integer(), nullable=False),
    sa.Column('street_id', sa.String(length=20), nullable=True),
    sa.Column('geo_width', sa.String(length=20), nullable=False),
    sa.Column('geo_length', sa.String(length=20), nullable=False),
    sa.Column('direction', sa.String(length=60), nullable=True),
    sa.Column('valid_from', sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(['bus_stop_id'], ['bus_stops.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('bus_stop_id', 'valid_from', name='unique_stop_id_date')
    )
    op.create_table('bus_stop_lines',
    sa.Column('bus_stop_id', sa.Integer(), nullable=False),
    sa.Column('line_id', sa.Integer(), nullable=False),
    sa.ForeignKeyConstraint(['bus_stop_id'], ['bus_stops.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['line_id'], ['lines.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('bus_stop_id', 'line_id')
    )
    op.create_table('tables',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('brigade', sa.String(length=10), nullable=False),
    sa.Column('direction', sa.String(length=50), nullable=False),
    sa.Column('route', sa.String(length=20), nullable=False),
    sa.Column('time', sa.Time(), nullable=False),
    sa.Column('bus_stop', sa.Integer(), nullable=False),
    sa.Column('line', sa.Integer(), nullable=False),
    sa.ForeignKeyConstraint(['bus_stop'], ['bus_stops.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['line'], ['lines.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('brigade', 'bus_stop', 'line', 'time', name='one_brigade_of_line_on_stop_at_time')
    )
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('tables')
    op.drop_table('bus_stop_lines')
    op.drop_table('bus_stop_data')
    op.drop_table('lines')
    op.drop_table('bus_stops')
    # ### end Alembic commands ###