import pandas as pd
import json
import os
import time
from datetime import datetime, timedelta
from pytrends.request import TrendReq

# code to export search periods JSON.stringify(arr.map(x => ({name: x.name, from: `${x.year_start}-${x.month_start.toString().padStart(2,'0')}-${x.day_start.toString().padStart(2,'0')} ${x.hour_start.toString().padStart(2,'0')}:00:00`, to: `${x.year_end}-${x.month_end.toString().padStart(2,'0')}-${x.day_end.toString().padStart(2,'0')} ${x.hour_end.toString().padStart(2,'0')}:59:59`})))

searchTermsFile = 'searchTerms.json'
searchPeriodsFile = 'searchPeriods.json'
resutlsFile = 'results7.xlsx'

trendsSleep = 10

lookBackMonths = 2

geos = ['IL'] #['IL', 'PS']

def loadJsonFile(file):
    with open(file, encoding='utf-8') as f:
        return json.load(f)

searchTerms = loadJsonFile(searchTermsFile)
periods = loadJsonFile(searchPeriodsFile)

pytrend = TrendReq()

dfs = []

for p in periods:
    name = p["name"]
    for geo in geos:
        for searchTerm in searchTerms:
            periodStartDate = datetime.strptime(p["period_start_date"], "%Y-%m-%d") + timedelta(days=3)
            periodEndDate = datetime.strptime(p["period_end_date"], "%Y-%m-%d")
            maxPeriodEndDate = periodStartDate + timedelta(days=30*lookBackMonths)
            if periodEndDate > maxPeriodEndDate:
                periodEndDate = maxPeriodEndDate
            while periodStartDate < periodEndDate:
                startDate = periodStartDate - timedelta(days=30*lookBackMonths)
                endDate = periodStartDate.strftime("%Y-%m-%d")
                curFilename = name + ' ' + geo + ' ' + endDate + ' ' + searchTerm + '.pkl'
                if not os.path.exists(curFilename) and not os.path.exists(curFilename+'2') and not os.path.exists(curFilename+'22'):
                    print('"' + name + '" (' + geo + ') ' + endDate + ': ' + searchTerm)
                    retryNum = 1
                    retryCount = 15
                    pytrend.build_payload(kw_list=[f'"{[searchTerm]}"'], geo=geo, timeframe=f'{startDate.strftime("%Y-%m-%d")} {endDate}')
                    while retryNum <= retryCount:
                        try:
                            curDf = pytrend.interest_over_time()
                            curDf['periodName'] = name
                            curDf['geo'] = geo
                            curDf['searchTerm'] = searchTerm
                            curDf.rename(columns = { f'"{[searchTerm]}"': searchTerm}, inplace=True)
                            #print(curDf.to_string())
                            curDf.to_pickle(curFilename)
                            dfs.append(curDf)
                            time.sleep(trendsSleep)
                            break
                        except:
                            retryNum += 1
                            if retryNum > retryCount:
                                raise
                            time.sleep(20)
                else:
                    if os.path.exists(curFilename):
                        curDf = pd.read_pickle(curFilename)
                    elif os.path.exists(curFilename+'2'):
                        curDf = pd.read_pickle(curFilename+'2')
                    else:
                        curDf = pd.read_pickle(curFilename+'22')
                    #curDf.rename(columns = { f'"{[searchTerm]}"': searchTerm}, inplace=True)
                    dfs.append(curDf)
                periodStartDate = periodStartDate + timedelta(days=1)

df = pd.concat(dfs)
df.sort_values(df.columns[0])

df.to_excel(resutlsFile)

print('done')


# -*- coding: utf-8 -*-
"""
Created on Wed Jun  9 09:35:48 2021

@author: MJH
"""
import tensorflow as tf

def scaled_dot_product_attention(query, key, value, mask = None):
    # query 크기 : (batch_size, num_heads, query의 문장 길이, d_model/num_heads)
    # key 크기 : (batch_size, num_heads, key의 문장 길이, d_model/num_heads)
    # value 크기 : (batch_size, num_heads, value의 문장 길이, d_model/num_heads)
    # padding_mask : (batch_size, 1, 1, key의 문장 길이)

    # Q와 K의 곱. 어텐션 스코어 행렬.
    matmul_qk = tf.matmul(query, key, transpose_b=True)

    # 스케일링
    # dk의 루트값으로 나눠준다.
    depth = tf.cast(tf.shape(key)[-1], tf.float32)
    logits = matmul_qk / tf.math.sqrt(depth)

    # 마스킹. 어텐션 스코어 행렬의 마스킹 할 위치에 매우 작은 음수값을 넣는다.
    # 매우 작은 값이므로 소프트맥스 함수를 지나면 행렬의 해당 위치의 값은 0이 된다.
    if mask is not None:
        logits += (mask * -1e9)

    # 소프트맥스 함수는 마지막 차원인 key의 문장 길이 방향으로 수행된다.
    # attention weight : (batch_size, num_heads, query의 문장 길이, key의 문장 길이)
    attention_weights = tf.nn.softmax(logits, axis=-1)

    # output : (batch_size, num_heads, query의 문장 길이, d_model/num_heads)
    output = tf.matmul(attention_weights, value)

    return output, attention_weights


import bs4
from bs4 import BeautifulSoup
import requests
import csv

baseURL = 'http://www.innatthecrossroads.com/home/game-thrones-recipes/recipes-by-meal/'
pages = [
    'main-courses',
    'sides',
    'breakfast',
    'soupsstews',
    'pies',
    'bread',
    'vegetarian',
    'desserts',
    'beverages',
]
outputFile = open('Game of Thrones', 'w')
for page in pages:
    page = requests.get(baseURL + page)
    soup = BeautifulSoup(page.content, 'lxml')
    menus = soup.find('article')
    for item in menus.find_all('li'):
        outputFile.write(item.text + '\n')

outputFile.close()


from PIL import Image
import numpy as np
from collections import Counter

# Ordena a quantidade de ocorrencia da intensidade
def contar_numeros(image):
    pixels = image.flatten()
    counts = Counter(pixels).items()
    return sorted(counts, key=lambda x: x[::-1])

# Constroe árvore de cima para baixo
def construir_arvore(counts):
    nodes = [entry[::-1] for entry in counts] # Reverter cada tupla (símbolo, contagem)
    while len(nodes) > 1:
        leastTwo = tuple(nodes[0:2])  # Obter os 2 para combinar
        theRest = nodes[2:] # Todos os outros
        combFreq = leastTwo[0][0] + leastTwo[1][0] # Frequência do ponto de ramificação
        nodes = theRest + [(combFreq, leastTwo)] # Adicionar ponto de ramificação ao final
        nodes.sort(key=lambda x: x[0])  # Usando x[0] para ordenar pela frequência
    return nodes[0] # Retornar a única árvore dentro da lista

# Função usada para retornar somente os simbolos ordenados por frequencia da arvore
def podar(tree):
    p = tree[1]
    if type(p) is tuple:
        return (podar(p[0]), podar(p[1]))
    return p

def descer_arvore(codes, node, pat):
    if type(node) == tuple: # Ponto de ramificação.
        descer_arvore(codes, node[0], pat + [0]) # Faça o ramo esquerdo.
        descer_arvore(codes, node[1], pat + [1]) # Em seguida, faça o ramo direito.
    else:
        codes[node] = pat # Uma folha

def criar_dicionario(tree): # Faz a inicialização do dicionário que vai ser usado para acessar os códigos na arvore
    codes = {}
    descer_arvore(codes, tree, [])
    return codes

def binario_lista(n): # Converter um inteiro em na menor lista de bits
    return [n] if (n <= 1) else binario_lista(n >> 1) + [n & 1]

def lista_binario(bits):
    result = 0
    for bit in bits: # Converter uma lista de bits em um inteiro
        result = (result << 1) | bit
    return result

def preencher(bits, n):
    # Preenche a lista de bits até que ela tenha um total de n digitos
    assert(n >= len(bits))
    return ([0] * (n - len(bits)) + bits)

class OutputBitStream(object):
    # Inicializa um arquivo que será usado para escrever
    def __init__(self, file_name):
        self.file_name = file_name
        self.file = open(self.file_name, 'wb')
        self.bytes_written = 0
        self.buffer = []

    # Usado para escerver um bit no buffer
    def write_bit(self, value):
        self.write_bits([value])

    # Se o buffer for maior que 8, escrevemos os bits no arquivo
    def write_bits(self, values):
        self.buffer += values
        while len(self.buffer) >= 8:
            self._save_byte()

    def flush(self):
        if len(self.buffer) > 0:  # Adiciona zeros para completar o byte e depois o escreve
            self.buffer += [0] * (8 - len(self.buffer))
            self._save_byte()
        assert(len(self.buffer) == 0)

    # Sava as informações no arquivo
    def _save_byte(self):
        bits = self.buffer[:8]
        self.buffer[:] = self.buffer[8:]

        byte_value = lista_binario(bits)
        if 0 <= byte_value <= 255:
            self.file.write(bytes([byte_value]))
            self.bytes_written += 1
        else:
            raise ValueError(f"Invalid byte value: {byte_value}")

    # garante que tudo seja escrito no arquivo antes de fechá-lo
    def close(self):
        self.flush()
        self.file.close()

def codificar_cabecalho(image, bitstream):
    height_bits = preencher(binario_lista(image.shape[0]), 16)
    bitstream.write_bits(height_bits)
    width_bits = preencher(binario_lista(image.shape[1]), 16)
    bitstream.write_bits(width_bits)

def salvar_size(size, bitstream):
    height_bits = preencher(binario_lista(size[0]), 16)
    bitstream.write_bits(height_bits)
    width_bits = preencher(binario_lista(size[1]), 16)
    bitstream.write_bits(width_bits)

def codificar_arvore(tree, bitstream):
    if type(tree) == tuple:
        bitstream.write_bit(0)
        codificar_arvore(tree[0], bitstream)
        codificar_arvore(tree[1], bitstream)
    else:
        bitstream.write_bit(1)
        symbol_bits = preencher(binario_lista(tree), 16)
        bitstream.write_bits(symbol_bits)

def codificar_pixels(image, codes, bitstream):
    pixels = image.flatten()
    for value in pixels:
        bitstream.write_bits(codes[value])

def compressed_size(counts, codes):
    header_size = 2 * 16

    tree_size = len(counts) * (1 + 16)
    if tree_size % 8 > 0:
        tree_size += 8 - (tree_size % 8)

    pixels_size = sum([count * len(codes[symbol]) for symbol, count in counts])
    if pixels_size % 8 > 0:
        pixels_size += 8 - (pixels_size % 8)

    return (header_size + tree_size + pixels_size) / 8

def compress_array(array, out_file_name,size):
    counts = contar_numeros(array)
    tree = construir_arvore(counts)
    trimmed_tree = podar(tree)
    codes = criar_dicionario(trimmed_tree)
    stream = OutputBitStream(out_file_name)
    salvar_size(size,stream)
    codificar_cabecalho(array, stream)
    stream.flush()
    codificar_arvore(trimmed_tree, stream)
    stream.flush()
    codificar_pixels(array, codes, stream)
    stream.close()

# Ler bits de um arquivo
class InputBitStream(object):
    def __init__(self, file_name):
        self.file_name = file_name
        self.file = open(self.file_name, 'rb')
        self.bytes_read = 0
        self.buffer = []

    def read_bit(self):
        return self.read_bits(1)[0]

    def read_bits(self, count):
        while len(self.buffer) < count:
            self._load_byte()
        result = self.buffer[:count]
        self.buffer[:] = self.buffer[count:]
        return result

    def flush(self):
        assert(not any(self.buffer))
        self.buffer[:] = []

    def _load_byte(self):
        value = ord(self.file.read(1))
        self.buffer += preencher(binario_lista(value), 8)
        self.bytes_read += 1

    def close(self):
        self.file.close()

def decodificar_cabecalho(bitstream):
    height = lista_binario(bitstream.read_bits(16))
    width = lista_binario(bitstream.read_bits(16))
    return (height, width)

def decodificar_size(bitstream):
    height = lista_binario(bitstream.read_bits(16))
    width = lista_binario(bitstream.read_bits(16))
    return (height, width)

def decodificar_arvore(bitstream):
    flag = bitstream.read_bits(1)[0]
    if flag == 1:
        return np.uint16(lista_binario(bitstream.read_bits(16)))
    left = decodificar_arvore(bitstream)
    right = decodificar_arvore(bitstream)
    return (left, right)

def decodificar_valor(tree, bitstream):
    bit = bitstream.read_bits(1)[0]
    node = tree[bit]
    if type(node) == tuple:
        return decodificar_valor(node, bitstream)
    return np.uint16(node)

def decodificar_pixels(height, width, tree, bitstream):
    pixels = np.empty((height, width, 3), dtype=np.uint16)
    for i in range(height):
        for j in range(width):
            for channel in range(3):
                pixels[i, j, channel] = decodificar_valor(tree, bitstream)
    return pixels

def decompress_image(in_file_name):
    stream = InputBitStream(in_file_name)
    size = decodificar_size(stream)
    height, width = decodificar_cabecalho(stream)
    stream.flush()
    trimmed_tree = decodificar_arvore(stream)
    stream.flush()
    pixels = decodificar_pixels(height, width, trimmed_tree, stream)
    stream.close()
    return pixels,size


import bpy
import math

from dataclasses import dataclass
from ..util import console_out, bad_mesh
from .model_assets import model_util, armature, mesh, materials

class Model:
    def __init__(self, nn, file_path, settings):
        self.file_path = file_path
        self.model = nn.model
        self.settings = settings
        self.format = settings.format
        self.bone_groups = [bone.group for bone in self.model.bones]
        self.bone_names = nn.bones
        self.model_name = nn.name
        self.model_name_strip = self.model_name[:-4]
        self.texture_names = nn.textures
        self.armature = None
        self.material_list_blender = []
        self.group_names = []
        self.mat_names = []
        self.mesh_names = []

    def execute(self):
        print("Making a Model------------------------------------")
        message = "Making" + " " + self.model_name
        print(message + " " * (50 - len(message)) + "|")

        console_out("Making Armature...", armature.make_armature, self)
        console_out("Generating Names...", model_util.make_names, self)
        if self.settings.keep_bones_accurate:
            console_out("Making Accurate Bones...", armature.make_bones_accurate, self)
        else:
            console_out("Making Pretty Bones...", armature.make_bones_pretty, self)

        bpy.ops.object.mode_set(mode="POSE")  # pose bone stuff here
        console_out("Making Bone Groups...", armature.make_bone_groups, self)
        if self.settings.hide_null_bones:
            console_out("Hiding Null Bones...", armature.hide_null_bones)

        bpy.ops.object.mode_set(mode="OBJECT")  # return to normal
        if self.settings.simple_materials:
            console_out("Making Simple Materials...", materials.material_simple, self)
        else:
            console_out("Making Accurate Materials...", materials.material_complex, self)

        console_out("Making Meshes...", mesh.make_mesh, self)

@dataclass
class ModelData:
    name: str
    center: tuple
    radius: float
    bones: list
    materials: list
    meshes: tuple
    geometry: tuple
    bone_depth: int
    bone_used: list

@dataclass
class MeshTypes:
    simple_opaque: list
    complex_opaque: list
    simple_alpha: list
    complex_alpha: list

class ModelInfo:
    def __init__(self, settings, arma):
        self.settings = settings
        self.format = settings.format
        self.armature = arma
        self.name = ""
        self.mesh_list = []
        self.center = (0, 0, 0)
        self.radius = 0.0
        self.bone = []
        self.bone_depth = 0
        self.bone_used = []
        self.material = []
        self.meshes = []

    def generic(self):
        arma = self.armature
        name = arma.name
        mesh_list = [a for a in arma.children if a.type == "MESH" and len(a.data.polygons) > 0]
        self.mesh_list = mesh_list

        if name.endswith("." + self.format[-1].lower() + "no"):
            pass
        else:
            name = name + "." + self.format[-1].lower() + "no"
        self.name = name

        print("Getting Model Data--------------------------------")
        message = "Making" + " " + name

        print(message + " " * (50 - len(message)) + "|")

    def get_empty_rig(self):
        bone, bone_depth, bone_used = console_out("Getting Bone Info...", armature.get_bones, self)
        material = console_out("Getting Material Info...", materials.get_materials, self)
        meshes = MeshTypes([], [], [], [])
        meshes, geometry = console_out("Generating Geometry...", mesh.get_geometry, (meshes, self.settings, self))
        return ModelData(self.name, (0, 0, 0), 0, bone, material, meshes, geometry, bone_depth, bone_used)

    def get_generic(self):
        self.center, self.radius = console_out("Generating Bounds...", armature.get_render_data, self.mesh_list)
        self.bone, self.bone_depth, self.bone_used = console_out("Getting Bone Info...", armature.get_bones, self)
        self.material = console_out("Getting Material Info...", materials.get_materials, self)
        self.meshes = console_out("Getting Mesh Info...", mesh.get_meshes, self.mesh_list)

    def alpha_fix(self):
        material = self.material
        meshes = self.meshes
        mat_name_list = [a.name for a in material.material_list]
        for m in meshes:
            mat_index = mat_name_list.index(m.material_name)
            mat = material.material_list[mat_index]
            m.material_name = mat_index
            if m.bpy_obj.data.vertex_colors:
                mesh_v_alpha = [0, 0, 0, 0] * len(m.bpy_obj.data.vertex_colors[0].data)
                m.bpy_obj.data.vertex_colors[0].data.foreach_get("color", mesh_v_alpha)
                mesh_v_alpha = set(mesh_v_alpha[3::4])
                if len(mesh_v_alpha) > 1 or 1 > list(mesh_v_alpha)[0]:
                    m.opaque = False
                    continue
            for tex in mat.texture_list:
                img_alpha = set(tex.name.image.pixels[::][3::4])
                # sometimes bpy.data.images[mat.image].pixels[3::4] as a slice issue (warning it's not an int?)
                if len(img_alpha) > 1 or (list(img_alpha) and 1 > list(img_alpha)[0]):
                    # check if the texture has pixels (if texture path was valid but files were moved)
                    m.opaque = False
                    continue
            if 1 > mat.alpha:
                m.opaque = False

    def build_mesh_list(self):
        simple_opaque = []
        complex_opaque = []
        simple_alpha = []
        complex_alpha = []

        for m in self.meshes:
            if m.opaque:
                if len(m.bone_names) > 1:
                    complex_opaque.append(m)
                else:
                    simple_opaque.append(m)
            else:
                if len(m.bone_names) > 1:
                    complex_alpha.append(m)
                else:
                    simple_alpha.append(m)

        self.meshes = MeshTypes(simple_opaque, complex_opaque, simple_alpha, complex_alpha)

    def model(self):
        self.generic()

        name = self.name
        mesh_list = self.mesh_list

        if not mesh_list:
            return self.get_empty_rig()

        quad_count = console_out("Checking Faces...", model_util.check_meshes, mesh_list)
        if quad_count:
            bad_mesh("NN Model Exporter")
            return False
        self.get_generic()

        self.alpha_fix()

        self.build_mesh_list()

        meshes, geometry = console_out("Generating Geometry...", mesh.get_geometry, (self.meshes, self.settings, self))

        if self.format[-1] == "G":
            for me, geo in zip([meshes.simple_opaque, meshes.complex_opaque, meshes.simple_alpha, meshes.complex_alpha],
                               geometry):
                if me:  # first level is complex_opaque / simple_opaque etc.
                    for m, g in zip(me, geo.faces):
                        has_col = g.colours_type
                        if has_col:
                            self.material.material_list[m.material_name].v_col = True
        else:
            for me, geo in zip([meshes.simple_opaque, meshes.complex_opaque, meshes.simple_alpha, meshes.complex_alpha],
                               geometry):
                if me:  # first level is complex_opaque / simple_opaque etc.
                    for m, g in zip(me, geo.faces):
                        has_col = g.colours
                        if has_col:
                            self.material.material_list[m.material_name].v_col = True

        return ModelData(
            name, self.center, self.radius, self.bone, self.material, meshes, geometry, self.bone_depth, self.bone_used)

    def execute(self):
        return self.model()


import os
import subprocess
import sys
import filecmp
import shlex

class bcolors:
    SUCCESS = '\033[0;32m'
    NORMAL = '\033[0m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'

def print_results(tests):
    for test in tests:
        name = tests[test][0]
        if tests[test][1]:
            print("{}[SUCCESS]{} {} ".format(bcolors.SUCCESS, bcolors.NORMAL, name))
        else:
            print("{}[FAILED]{} {} ".format(bcolors.FAIL, bcolors.NORMAL, name))

def compare_results(output, expected):
    try:
        return filecmp.cmp(output, expected)
    except FileNotFoundError as e:
        print(e)
        sys.exit(1)

def run_test(path_to_test_dir, program, cwd, args):
    # path_to_test_dir = os.path.join(cwd, 'test')
    # test_files = os.path.join(path_to_test_dir, 'in')
    test_files = find_test(os.path.join(path_to_test_dir, 'in'))

    args.insert(0, program)
    args[0] = './' + args[0]

    if not os.path.exists(os.path.join(path_to_test_dir, 'out')):
        os.makedirs(os.path.join(path_to_test_dir, 'out'))
    if not os.path.exists(os.path.join(path_to_test_dir, 'err')):
        os.makedirs(os.path.join(path_to_test_dir, 'err'))

    for test in test_files:
        name = test_files[test][0]

        input_file_path = os.path.join(path_to_test_dir, "in/" + name + '.in')
        output_file_path = os.path.join(path_to_test_dir, "out/" + name + '.out')
        expected_output_file_path = os.path.join(path_to_test_dir, "valid/" + name + '.out')
        error_file_path = os.path.join(path_to_test_dir, "err/" + name + '.err')

        error_out = None
        try:
            input_file = open(input_file_path, 'r')
            output_file = open(output_file_path, 'w+')
            error_file = open(error_file_path, "w+")
        except Exception as e:
            print(e)
            sys.exit(1)

        process = subprocess.Popen(args, shell=False, cwd=cwd, stdin=input_file, stdout=output_file, stderr=error_file)
        outs, err = process.communicate()
        # error = process.returncode

        process.kill()
        process.terminate()

        input_file.close()
        output_file.close()
        error_file.close()

        # if error != 0:
        #     error_file = open(error_file_path, "w+")
        #     error_file.write("{}".format(error))
        #     error_file.close()
        #     if error_out is not None:
        #         print(error_out)
        #     # return 0

        test_files[test][1] = compare_results(output_file_path, expected_output_file_path)
    print_results(test_files)

def find_test(test_dir):
    test_dic = {}
    for root, dirs, files in os.walk(test_dir):
        for file in files:
            if file[-2:] == 'in':
                test_dic[os.path.join(root, file)] = [file[:-3], False]
    return test_dic

if __name__ == '__main__':

    project_root = os.getcwd()
    path_to_program_from_root = 'dka-2-mka'

    print("----- Argument -t -----")
    path_to_test_dir = os.path.join(project_root, '../Done/test/arg_t')
    run_test(path_to_test_dir, path_to_program_from_root, project_root, shlex.split("-t"))

    print("----- Argument -i -----")
    path_to_test_dir = os.path.join(project_root, '../Done/test/arg_i')
    run_test(path_to_test_dir, path_to_program_from_root, project_root, shlex.split("-i"))


import os

# path = input('请输入文件路径(结尾加上/)：')
path = "dataset/val/front"

# 获取该目录下所有文件，存入列表中
files = os.listdir(path)

n = 0
for i in files:
    # 设置旧文件名（就是路径+文件名）
    oldname = path + os.sep + files[n]  # os.sep添加系统分隔符

    # 设置新文件名
    newname = path + os.sep + 'f-' + str(n + 1) + '.jpg'

    os.rename(oldname, newname)  # 用os模块中的rename方法对文件改名
    print(oldname, '======>', newname)

    n += 1


# Licensed under a 3-clause BSD style license - see LICENSE.rst

import numpy as np
import pytest

from sofia_redux.toolkit.fitting.polynomial \
    import Polyfit, linear_polyfit, gaussj_polyfit, nonlinear_polyfit

@pytest.fixture
def data():
    y, x = np.mgrid[:5, :5]
    z = 1.0 + x + (x * y) + (y ** 2)
    c = np.array([[1, 1, 0], [0, 1, 1]]).ravel()
    return x, y, z, c

def test_success(data):
    x, y, z, c = data
    poly = Polyfit(x, y, z, 2)
    assert np.allclose(poly.coefficients, c)
    assert np.allclose(poly(x, y), z)
    assert np.isclose(poly(1, 1), 4)
    r, c = poly(1, 1, dovar=True)
    assert np.allclose([r, c], [4, 0.11857142857])
    assert poly.covariance.shape == (6, 6)
    assert np.allclose(poly(x, y), z)
    assert np.isclose(poly.stats.chi2, 0)
    z[2, 2] += 1  # can't fit this exactly with 2nd order polynomial
    poly = Polyfit(x, y, z, 2)
    assert not np.isclose(poly.stats.chi2, 0)

def test_get_coefficients(data):
    x, y, z, _ = data
    poly = Polyfit(x, y, z, 2)
    c = poly.get_coefficients(covar=False)
    assert np.allclose(c, [[1, 1, 0],
                           [0, 1, 0],
                           [1, 0, 0]])
    _, c = poly.get_coefficients(covar=True)
    assert c.shape == (9, 9)
    assert np.allclose(c, c.T)
    u = np.unique(c)
    assert not np.allclose(u, u[0])

    poly = Polyfit(x, y, z, [1, 2])  # max exponent of x is 1, y is 2
    poly.get_coefficients(covar=False)

def test_robust(data):
    x, y, z, c = data
    # The fit should fail on perfect data since everything
    # will be flagged as an outlier with sufficiently low
    # rejection threshold
    poly = Polyfit(x, y, z, 2, robust=1e-6)
    assert not poly.success
    assert poly.termination == "insufficient samples remain"

    # add some noise
    rand = np.random.RandomState(42)
    noise = rand.normal(0, 1e-3, z.shape)
    z += noise

    # should only require 1 iteration
    poly = Polyfit(x, y, z, 2, robust=5)
    assert poly.termination == "delta_rms = 0"

    poly = Polyfit(x, y, z, 2, robust=-1)
    assert poly._iteration == 1

    poly = Polyfit([1, 2], [1, 2], 1, robust=-1)
    poly._iterate()
    assert poly.stats.rchi2 is np.inf
    assert np.isnan(poly.stats.q)
    assert poly.stats.dof == 0

def test_parameters_string(data):
    x, y, z, c = data
    m = Polyfit(x, y, z, 2)
    s = m._parameters_string()
    assert "(1, 1) : 1.000000 +/- 0.100000" in s
    del m.stats.sigma
    s = m._parameters_string()
    assert "+/-" not in s
    assert "(1, 1) : 1.000000" in s

def test_parse_model_args(data):
    x, y, z, c = data
    m = Polyfit(x, y, z, 2)

    with pytest.raises(ValueError) as err:
        Polyfit(x, y, z, np.ones(1))
    assert "order size does not match" in str(err.value).lower()

    with pytest.raises(ValueError) as err:
        Polyfit(x, y, z, np.ones(1), set_exponents=True)
    assert "order must have 2 features" in str(err.value).lower()

    with pytest.raises(ValueError) as err:
        Polyfit(x, y, z, np.ones((4, 3)), set_exponents=True)
    assert "dimension 1 of order does not" in str(err.value).lower()

    m = Polyfit(x, y, z, np.ones((3, 2)), set_exponents=True)
    assert m._order == -1

    with pytest.raises(ValueError) as err:
        Polyfit(x, y, z, 2, solver='foo')
    assert "unknown solver" in str(err.value).lower()

    m = Polyfit(x, y, z, 2, solver='gaussj')
    m._parse_model_args()
    assert m.fitter is gaussj_polyfit

    m = Polyfit(x, y, z, 2, solver='linear')
    m._parse_model_args()
    assert m.fitter is linear_polyfit

    m = Polyfit(x, y, z, 2, solver='nonlinear')
    m._parse_model_args()
    assert m.fitter is nonlinear_polyfit

def test_fast_error(data):
    x, y, z, c = data
    m = Polyfit(x, y, z, 2, error=np.ones_like(z))
    m._interpolated_error = None
    m._fast_error()
    assert m._interpolated_error.size == z.size
    assert np.allclose(m._interpolated_error, 1)

    m._interpolated_error = None
    m = Polyfit(x, y, z, 2, error=2.0)
    m._interpolated_error = None
    m._fast_error()
    assert m._interpolated_error.size == z.size
    assert np.allclose(m._interpolated_error, 2)

def test_refit_mask(data):
    x, y, z, c = data
    z[3:] = 1
    z[:3] = 2
    m = Polyfit(x, y, z, 1)
    m.refit_mask((z == 1).ravel(), covar=False)
    assert np.allclose(m.coefficients, [1, 0, 0])
    assert m.covariance is None
    m.refit_mask((z == 2).ravel(), covar=True)
    assert np.allclose(m.coefficients, [2, 0, 0])
    assert np.allclose(np.diag(m.covariance),
                       [3 / 10, 1 / 30, 1 / 10])

    m.refit_mask((z == 3).ravel(), covar=True)
    assert not m.success
    assert m.covariance is None

def test_refit(data):
    x, y, z, c = data
    m = Polyfit(x, y, z, 1)
    z[3:] = 1
    z[:3] = 2
    error = np.ones_like(z)
    error[z == 2] = 0
    m.refit_data(z.ravel(), error=error.ravel())
    assert np.allclose(m.coefficients, [1, 0, 0])

    m.refit_data(z.ravel(), mask=(z == 2).ravel(), error=np.ones(z.size))
    assert np.allclose(m.coefficients, [2, 0, 0])

    z.fill(3)
    m.refit_data(x, y, z, mask=np.full(z.size, True))
    assert np.allclose(m.coefficients, [3, 0, 0])


class Segmentation:

    def __init__(self, sr=8000):
        self.sr = sr

    def segment_dataset(self, dataset, labels):
        segments_dataset = []
        for waveform, (turns, speakers) in zip(dataset, labels):
            segments = self.segment_waveform(waveform, turns, speakers)
            segments_dataset.append(segments)
        return segments_dataset

    def segment_waveform(self, waveform, turns, speakers):
        segments = []

        # set custom speaker ID / index
        s1 = 0
        s2 = 1

        # at all times, these will point to the first next speaker turns for each speaker
        pointers = [0, 0]

        # get speaker of the first speaker turn
        if turns[s1][pointers[s1]][0] < turns[s2][pointers[s2]][0]:
            s = s1
        else:
            s = s2

        pointers[s] += 1

        # initialize first segment attributes
        segment_start, segment_end = turns[s][0]
        segment_speaker = speakers[s]
        segment_overlap = False

        # continue until both pointers reach the end of the list
        while pointers[s1] < len(turns[s1]) or pointers[s2] < len(turns[s2]):

            # check if both pointers haven't reached the end of the list yet
            if pointers[s1] < len(turns[s1]) and pointers[s2] < len(turns[s2]):
                # get the next first of the two speakers
                s = s2 if turns[s2][pointers[s2]][0] < turns[s1][pointers[s1]][0] else s1
            else:
                # if pointer 1 has reached the last turns list, we set s2 as speaker and vice versa
                if pointers[s1] >= len(turns[s1]):
                    s = s2
                if pointers[s2] >= len(turns[s2]):
                    s = s1

            # get speaker turn and increment pointer
            turn = turns[s][pointers[s]]
            pointers[s] += 1

            # variables to correctly set the speaker and time after a cutoff
            other_speaker_continues = False
            same_speaker_continues = False
            neither_speaker_continues = False
            prev_segment_end = segment_end

            # check if speaker turn overlaps with current segment
            has_overlap = segment_end > turn[0]
            if has_overlap:

                # calculate overlap time
                overlap_end = min(segment_end, turn[1])
                overlap = (turn[0], overlap_end)

                # check which speaker continues talking after this segment is cut off
                if segment_end < turn[1]:
                    other_speaker_continues = True
                elif segment_end > turn[1]:
                    same_speaker_continues = True
                elif segment_end == turn[1]:
                    neither_speaker_continues = True
                    pass

                # update segment attributes
                segment_end = min(segment_end, overlap_end)
                segment_overlap = overlap

            # create wav segment
            wav_segment = waveform[int(segment_start * self.sr):int(segment_end * self.sr)]

            # append segment
            segment = {
                'wav': wav_segment,
                'time': (segment_start, segment_end),
                'speaker': segment_speaker,
                'overlap': segment_overlap,
            }
            segments.append(segment)

            # correctly adjust segment attributes to continue at the end of the overlap
            if has_overlap:

                # check how the overlap has ended
                if same_speaker_continues:
                    segment_start = segment_end
                    segment_end = prev_segment_end

                elif other_speaker_continues:
                    segment_start = segment_end
                    segment_end = turn[1]

                    segment_speaker = speakers[0] if segment_speaker == speakers[1] else speakers[1]

                elif neither_speaker_continues:

                    # check if either pointer hasn't reached the end yet
                    if pointers[s1] >= len(turns[s1]) and pointers[s2] >= len(turns[s2]):
                        continue

                    # check if both pointers haven't reached the end of the list yet
                    if pointers[s1] < len(turns[s1]) and pointers[s2] < len(turns[s2]):
                        # get the next first of the two speakers
                        s = s2 if turns[s2][pointers[s2]][0] < turns[s1][pointers[s1]][0] else s1
                    else:
                        # if pointer 1 has reached the last turns list, we set s2 as speaker and vice versa
                        if pointers[s1] >= len(turns[s1]):
                            s = s2
                        if pointers[s2] >= len(turns[s2]):
                            s = s1

                    # get speaker turn and increment pointer
                    turn = turns[s][pointers[s]]
                    pointers[s] += 1

                    segment_start, segment_end = turn
                    segment_speaker = speakers[s]

            # correctly set segment attributes to continue with the new segment
            else:
                segment_speaker = speakers[s]
                segment_start, segment_end = turn

            segment_overlap = False

        return segments


"""
Split Beverage table into Beverage and BeverageScrape. Separates the scraping (temporal) from the actual beverage.
Beverage table will be renamed to BeverageScrape. Beverage table created with similar columns. Move all unique
BeverageScrapes to Beverages table. Then drop unnecessary columns from BeverageScrape.
"""

import argparse
import logging
import sys
import dateutil.parser
from web.models import MenuScrape, Beverage, Location, BeverageScrape, Brewery, DistinctBeer
from web import db

root_log = logging.getLogger()
root_log.setLevel(logging.INFO)

def link():
    distinct = DistinctBeer.query.all()
    for d in distinct:
        # Technically could have multiple, but pick the first
        beverage = Beverage.query.filter_by(untappd_id=d.untappd_bid).first()
        if beverage:
            d.beverage_id = beverage.id
            db.session.add(d)
    db.session.commit()

if __name__ == '__main__':
    # Setup logging
    sh = logging.StreamHandler(sys.stdout)
    sh.setLevel(logging.INFO)
    sh.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
    root_log.addHandler(sh)

    # Command line arguments
    parser = argparse.ArgumentParser(description='Split beverage into scrapes, beverages, and brewery.')

    link()


"""Obstacle Class

"""

import tkinter as tk
from tkinter import *
import random

class Obstacle(object):
    def __init__(self, canvas, size, x, y, road_array, road_distance):
        self.canvas = canvas
        self.size = size
        self.x = y
        self.y = x
        #self.y = y
        self.canvas = canvas
        self.obstacle = canvas.create_rectangle(self.x, self.y, self.x+size, self.y+size, width=size)
        self.element = 0

    def get_x_y_coords(self,road1_array, road_distance):
        rand_elem = random.randrange(len(road1_array))
        if rand_elem % 2 != 0 and rand_elem != len(road1_array):
            rand_elem + 1
        elif rand_elem % 2 != 0 and rand_elem != 0:
            rand_elem - 1
        y = rand_elem * 5
        x = random.randrange(road1_array[rand_elem], road1_array[rand_elem] + road_distance)
        self.element = rand_elem
        return x, y

    def obstacle_coords(self):
        """Return 2 arrays of lines to determine if car runs into either side of the road"""
        return self.x, self.element
        #return self.canvas.coords(self.obstacle)


cnt=0
N = int(input())

"""while True:
    cnt+=1
    if N < 10:
        test = N*10+N

    else:

        test = str(N)
        tmp = int(test[-1])+int(test[0])
        tmp = str(tmp)
        test = int(test[-1])*10+int(tmp[-1])

    if N==test:
        print(cnt)
        break"""

백준/반복문/1110.py


import os

class ReferenceHandler:
    title = ""
    author = ""
    date = ""
    link = ""
    isbn = ""
    page = ""
    basepath = ""
    markdown = ""
    found = False
    def __init__(self, title, author, date, link, isbn, page):
        self.title = title
        self.author = author
        self.date = date
        self.link = link
        self.isbn = isbn
        self.page = page.url
        self.basepath = os.getcwd().replace("\\", "/")
        self.markdown = self.basepath + "/content/" + self.page + ".md"
    def addReference(self):
        if self.title == "":
            return -1
        reference = self.title + "|" + self.author + "|" + self.date + "|" + self.link + "|" + self.isbn
        if self.page == "tYYtD7HJp6":
            return reference
        with open(self.markdown, "r") as markdown:
            data = markdown.readlines()
            markdown.close()
        index = 0
        for entry in data:
            if entry.startswith("references:"):
                data[index] = data[index].strip() + "; " + reference + "\n"
                self.found = True
                break
            index += 1
        index = 0
        if self.found == False:
            for entry in data:
                print(reference)
                if entry in ['\n', '\r\n']:
                    data[index] = "references: " + reference + "\n\n"
                    break
                index += 1
        with open(self.markdown, "r+") as markdown:
            markdown.writelines(data)


import torch.nn as nn
import torch.nn.functional as F

class BasicBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_channels)

        self.shortcut = nn.Sequential()
        if stride != 1 or in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(out_channels)
            )

    def forward(self, x):
        residual = x

        out = F.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))

        out += self.shortcut(residual)
        out = F.relu(out)

        return out

class ResNet18(nn.Module):
    def __init__(self, num_classes=141):
        super().__init__()
        self.in_channels = 64

        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        #Chuyen 64 channel

        self.layer1 = self._make_layer(64, 2, stride=1)
        #Chuyen 128 channel
        self.layer2 = self._make_layer(128, 2, stride=2)
        self.layer3 = self._make_layer(256, 2, stride=2)
        self.layer4 = self._make_layer(512, 2, stride=2)

        # self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(338, num_classes)

    def _make_layer(self, out_channels, num_blocks, stride):
        layers = []
        layers.append(BasicBlock(self.in_channels, out_channels, stride))
        self.in_channels = out_channels
        for _ in range(num_blocks - 1):
            layers.append(BasicBlock(self.in_channels, out_channels))
            self.in_channels = out_channels
        return nn.Sequential(*layers)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))

        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        # print("preavgpool")
        #batch x channel out x dai x rong neu de padding = 1 thi shape dai rong giu nguyen
        # print(out.shape)
        # out = self.avgpool(out)
        # print("after")
        # print(out.shape)
        # print(out.shape)
        out = out.view(256, out.size(0), -1)
        # print(out.shape)
        out = self.fc(out)

        return out


import turtle

reduction = {"A": "DAAB", "B": "CBBA", "C": "BCCD", "D": "ADDC"}

steps = {"A": "URD", "B": "LDR", "C": "DLU", "D": "RUL"}

def step(s, length):
    turtle.setheading({"U": 90, "L": 180, "R": 0, "D": 270}[s])
    turtle.forward(length)

def hilbert(move="C", level=10):
    if (level <= 1):
        for s in steps[move]:
            step(s, 2**(level))
    else:
        red = reduction[move]
        s = steps[move]
        hilbert(red[0], level - 1)
        step(s[0], 2)
        hilbert(red[1], level - 1)
        step(s[1], 2)
        hilbert(red[2], level - 1)
        step(s[2], 2)
        hilbert(red[3], level - 1)

turtle.speed(10000)

hilbert(level=5)

turtle.Screen().mainloop()


def abs_sobel_thresh(img, orient='x', thresh_min=0, thresh_max=255):

    # Apply the following steps to img
    # 1) Convert to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 2) Take the derivative in x or y given orient = 'x' or 'y'
    if orient == 'x':
        sobel = cv2.Sobel(gray, cv2.CV_64F, 1, 0)
    elif orient == 'y':
        sobel = cv2.Sobel(gray, cv2.CV_64F, 0, 1)
    else:
        raise ValueError('orient must be x or y')
    # 3) Take the absolute value of the derivative or gradient
    sobel = np.absolute(sobel)
    # 4) Scale to 8-bit (0 - 255) then convert to type = np.uint8
    sobel = (sobel * 255 / sobel.max()).astype(np.uint8)
    # 5) Create a mask of 1's where the scaled gradient magnitude
            # is > thresh_min and < thresh_max
    binout = np.zeros_like(sobel)
    binout[(sobel >= thresh_min) & (sobel <= thresh_max)] = 1
    # 6) Return this mask as your binary_output image
    return binout

def mag_thresh(img, sobel_kernel=3, mag_thresh=(0, 255)):

    # Apply the following steps to img
    # 1) Convert to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 2) Take the gradient in x and y separately
    sx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
    sy = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
    # 3) Calculate the magnitude
    s = np.sqrt(sx**2 + sy**2)
    # 4) Scale to 8-bit (0 - 255) and convert to type = np.uint8
    s = (s * 255 / s.max()).astype(np.uint8)
    # 5) Create a binary mask where mag thresholds are met
    binout = np.zeros_like(s)
    binout[(s >= mag_thresh[0]) & (s <= mag_thresh[1])] = 1
    # 6) Return this mask as your binary_output image
    return binout

def dir_threshold(img, sobel_kernel=3, thresh=(0, np.pi/2)):

    # Apply the following steps to img
    # 1) Convert to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 2) Take the gradient in x and y separately
    sx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
    sy = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
    # 3) Take the absolute value of the x and y gradients
    sx = np.absolute(sx)
    sy = np.absolute(sy)
    # 4) Use np.arctan2(abs_sobely, abs_sobelx) to calculate the direction of the gradient
    s = np.arctan2(sy, sx)
    # 5) Create a binary mask where direction thresholds are met
    binout = np.zeros_like(s)
    binout[(s >= thresh[0]) & (s <= thresh[-1])] = 1
    # 6) Return this mask as your binary_output image
    return binout

def hls_select(img, thresh=(0, 255)):
    # 1) Convert to HLS color space
    ihls = cv2.cvtColor(img, cv2.COLOR_BGR2HLS)
    # 2) Apply a threshold to the S channel
    bin_output = np.zeros(img.shape[:-1], dtype=np.uint8)
    bin_output[(ihls[...,2] > thresh[0]) & (ihls[...,2] <= thresh[-1])] = 1
    # 3) Return a binary image of threshold result
    return bin_output


# import datetime

# currentYear = datetime.datetime.now().year

# class Car(object):
#     def __init__(self, color, model, make, price, year):
#         self.color = color
#         self.model = model
#         self.make = make
#         self.price = price
#         self.year = year

#     def service(self):
#         if(currentYear - self.year > 4):
#             print("You Need To Service Your Vehicle!!")
#         else:
#             print("You Vehicle's Condition Is Good!!")

# car = Car('red', 'A', 'ABC', 2634675, 2020)

# car.service()

class Mobile(object):
    def __init__(self, color, model, company, screensize, memory, battery):
        self.color = color
        self.model = model
        self.company = company
        self.screensize = screensize
        self.memory = memory
        self.battery = battery

    def checkbattery(self) :
        if(self.battery < 20):
            print("Charge Your Phone!!")

    def checkmemory(self):
        if(self.memory > 125):
            print("Your Phone Is High On Space!!")
        elif(self.memory > 80 and self.memory < 125):
            print("You Have A Little Space Use It Wisely!!")
        else:
            print("Your Phone Has A Lot Of Space!!")

    def checkscreensize(self):
        if(self.screensize > 6):
            print("Your Phone Size Is Too Huge!!")
        elif(self.screensize > 5.5 and self.screensize < 6):
            print("Your Phone Size Is Just Alright!!")
        else:
            print("Your Phone Is Too Small!!")

mobile = Mobile("blue", 'iPhone6', 'Apple', 7, 120, 10)
mobile.checkbattery()
mobile.checkmemory()
mobile.checkscreensize()


import asyncio
import logging
from dataclasses import dataclass
from http import HTTPStatus
from typing import Awaitable, Callable, Iterable, List

from .collector import ServiceCollector, Severity

@dataclass
class Component:
    """Атрибуты внешнего компонента по стандарту ДП."""

    name: str
    type: str
    severity: Severity
    checker: Callable[[], Awaitable[bool]]

class ExternalComponentsChecker:
    """Проверяет доступность внешних компонентов."""

    def __init__(
        self,
        components: Iterable[Component] = (),
        callbacks: Iterable[Callable[[Component, asyncio.Task], None]] = (),
    ):
        """Зависимости."""
        self._callbacks = callbacks
        self._minor_components: List[Component] = []
        self._major_components: List[Component] = []
        self.add_components(components)

    def add_component(self, external_component: Component):
        """Добавить компонент."""
        if external_component.severity == Severity.MINOR:
            components_container = self._minor_components
        elif external_component.severity == Severity.MAJOR:
            components_container = self._major_components
        else:
            raise ValueError('Unsupported component severity.')
        components_container.append(external_component)

    def add_components(self, external_components: Iterable[Component]):
        """Добавить список компонентов."""
        for component in external_components:
            self.add_component(component)

    async def major_components_status(self) -> bool:
        """Проверка MAJOR компонентов сервиса и запись метрик доступности.

        :return: готовность всех внешних компонентов.
        """
        return await self._check_component_statuses(self._major_components)

    async def minor_components_status(self) -> bool:
        """Проверка MINOR компонентов сервиса и запись метрик доступности.

        :return: готовность всех внешних компонентов.
        """
        return await self._check_component_statuses(self._minor_components)

    async def _check_component_statuses(self, components) -> bool:
        tasks = {
            asyncio.get_event_loop().create_task(component.checker()): component
            for component in components
        }
        component_statuses = await asyncio.gather(
            *tasks.keys(),
            return_exceptions=True,
        )
        for task_res, component in tasks.items():
            for callback in self._callbacks:
                callback(component, task_res)
        return all(res is True for res in component_statuses)

def collect_component_metrics(
    collector: ServiceCollector,
    component: Component,
    finished_check: asyncio.Task,
):
    res = finished_check.exception() or finished_check.result()
    collector.write_ready_component_status(
        HTTPStatus.OK.value if res is True else HTTPStatus.SERVICE_UNAVAILABLE.value,
        component=component.name,
        component_type=component.type,
        severity=component.severity,
    )

def log_check_exception(
    component: Component,
    finished_check: asyncio.Task,
):
    res = finished_check.exception() or finished_check.result()
    if isinstance(res, Exception) or res is False:
        logging.exception(
            '{severity} external {ctype} "{component}" unavailable'.format(
                severity=component.severity.name,
                ctype=component.type,
                component=component.name,
            ),
            exc_info=res,
        )


import logging
import sys
import numpy as np
# import cv2 as cv

np.random.seed(951105)

# logging.basicConfig(level=logging.DEBUG,
#                     filename='logs/CodeCraft-2019.log',
#                     format='[%(asctime)s] %(levelname)s [%(funcName)s: %(filename)s, %(lineno)d] %(message)s',
#                     datefmt='%Y-%m-%d %H:%M:%S',
#                     filemode='a')

TIME = [0]
duche = [0]
CARDISTRIBUTION = [0, 0, 0]
CARNAMESPACE, ROADNAMESPACE, CROSSNAMESPACE = [], [], []
CROSSDICT, CARDICT, ROADDICT ={}, {}, {}

class CAR(object):
    def __init__(self,id_,from_,to_,speed_,planTime_):
        # **** statistic parameters ****#
        self.id_, self.from_, self.to_, self.speed_, self.planTime_ = id_, from_, to_, speed_, -1
        self.carColor = [int(value) for value in np.random.random_integers(0, 255, [3])]
        # **** dynamic parameters ****#
        self.state,self.x,self.y = 0,0,0
        self.presentRoad, self.nextCrossId = None,self.from_
        self.deltaX,self.deltaY=0,0
        self.wait = False
        self.route,self.routeIndex = None,None
        # **** self defined paraments ****#
        self.routeclose = []
        self.routemap = []
        self.realtime = planTime_
    #
    # simulate initialization
    #
    def simulateInit(self,planTime,route):
        self.planTime_,self.route,self.routeIndex = planTime,route,0
    #
    # dynamic param update
    #
    def updateDynamic(self,state,x=None,y=None,presentRoad=None,roadSpeed=None,nextCrossId=None):
        # car not in carport of car is ready to go
        if self.state != 0 or presentRoad is not None:
            self.state = state
        if presentRoad is not None and self.state != 0 and self.routeIndex < self.route.__len__():
            self.routeIndex += 1
        self.x = x if x is not None else self.x
        self.y = y if y is not None else self.y
        self.presentRoad = presentRoad if presentRoad is not None else self.presentRoad
        if nextCrossId is not None:
            self.nextCrossId = nextCrossId
            toX, toY = CROSSDICT[self.to_].__loc__()
            nextCrossX, nextCrossY = CROSSDICT[nextCrossId].__loc__()
            self.deltaX, self.deltaY = toX - nextCrossX, toY - nextCrossY
    # show statistic parameters
    def __id__(self):
        return self.id_
    def __from__(self):
        return self.from_
    def __to__(self):
        return self.to_
    def __speed__(self):
        return  self.speed_
    def __planTime__(self):
        return self.planTime_
    def __carColor__(self):
        return self.carColor
    #
    # show dynamic parameters
    #
    def __state__(self):
        return self.state
    def __x__(self):
        return self.x
    def __y__(self):
        return self.y
    def __presentRoad__(self):
        return self.presentRoad
    def __nextCrossId__(self):
        return self.nextCrossId
    def __deltaX__(self):
        return self.deltaX
    def __deltaY__(self):
        return self.deltaY
    def __wait__(self):
        return self.wait
    def __route__(self):
        return self.route
    def __routeIndex__(self):
        return self.routeIndex
    #
    # show some important info
    #
    def __v__(self):
        return min(self.speed_,ROADDICT[self.presentRoad].__speed__())
    def __distance__(self):
        return abs(self.deltaX)+abs(self.deltaY)
    def __nextRoad__(self):
        try:
            return self.route[self.routeIndex]
        except:
            return -1

class ROAD(object):
    def __init__(self,id_, length_, speed_, channel_, from_, to_, isDuplex_):
        # **** statistic parameters ****#
        self.id_, self.length_, self.speed_, self.channel_, self.from_, self.to_, self.isDuplex_ = \
            id_, length_, speed_, channel_, from_, to_, isDuplex_
        self.carCapcity = self.channel_ * self.length_
        # **** dynamic parameters ****#
        # absolute bucket
        self.forwardBucket = [[None for j in range(self.channel_)] for i in range(self.length_)]
        self.backwardBucket = [[None for j in range(self.channel_)] for i in range(self.length_)] if self.isDuplex_ else None
        self.fx, self.fy, self.bx, self.by, self.forwardNum, self.backwardNum = [0], [0], [0], [0], [0], [0]
        self.forwardDone, self.backwardDone = [False], [False]
        # relative bucket
        self.provideBucket, self.receiveBucket = None, None
        self.px, self.py, self.provideNum, self.receiveNum = None, None, None, None
        self.provideDone = None
    #
    # determine relative bucket
    #
    def chooseAbsoluteBucket(self,crossId,pr):
        if crossId == self.from_ and pr == 'provide':
            return 'backward'
        elif crossId == self.from_ and pr == 'receive':
            return 'forward'
        elif crossId == self.to_ and pr == 'provide':
            return 'forward'
        elif crossId == self.to_ and pr == 'receive':
            return 'backward'
        else:
            print("Keywords mistake in CAR.chooseAbsoluteBucket()")
    def setBucket(self,crossId):
        bucket = self.chooseAbsoluteBucket(crossId, 'provide')
        if bucket == 'forward':
            self.provideBucket, self.px, self.py, self.provideDone, self.provideNum = \
                [self.forwardBucket, self.fx, self.fy, self.forwardDone, self.forwardNum]
            if self.isDuplex_:
                self.receiveBucket, self.receiveNum = \
                    self.backwardBucket, self.backwardNum
            else:
                self.receiveBucket, self.receiveNum = None, None
        else:
            self.receiveBucket, self.receiveNum = \
                self.forwardBucket, self.forwardNum
            if self.isDuplex_:
                self.provideBucket, self.px, self.py, self.provideDone, self.provideNum = \
                    self.backwardBucket, self.bx, self.by, self.backwardDone, self.backwardNum
            else:
                self.provideBucket, self.px, self.py, self.provideDone, self.provideNum = \
                    None, None, None, None, None
    #
    # stepInitial
    #
    def stepInit(self):
        # dynamic param initialization
        self.fx, self.fy, self.bx, self.by = [0], [0], [0], [0]
        self.forwardDone, self.backwardDone = [False], [False]
        self.provideBucket, self.receiveBucket = None, None
        self.px, self.py, self.provideNum, self.receiveNum = None, None, None, None
        self.provideDone = None
        # car state initialization
        for i in range(self.length_):
            for j in range(self.channel_):
                if self.forwardBucket[i][j] is not None:
                    car = CARDICT[self.forwardBucket[i][j]]
                    car.updateDynamic(state=1)
                if self.isDuplex_:
                    if self.backwardBucket[i][j] is not None:
                        car = CARDICT[self.backwardBucket[i][j]]
                        car.updateDynamic(state=1)
        # first step
        for channel in range(self.channel_):
            self.moveInChannel(self.forwardBucket, channel)
            if self.isDuplex_:
                self.moveInChannel(self.backwardBucket, channel)
    #
    # function for bucket action
    #
    def moveInChannel(self,bucket,channel):
        # car state: 0,1,2,3 in carport,waiting,finishing,end
        # set guard
        previousCar, previousState = -1, 1
        for i in range(self.length_):
            if bucket[i][channel] is not None:
                car = CARDICT[bucket[i][channel]]
                v = min(car.__speed__(),self.speed_)
                if car.__state__() == 2:
                    previousCar, previousState = i, 2
                    continue
                elif i - v > previousCar:
                    bucket[i - v][channel] = bucket[i][channel]
                    bucket[i][channel] = None
                    previousCar, previousState = i - v, 2
                    car.updateDynamic(state=2, x=previousCar)
                elif previousState == 2:
                    if previousCar + 1 != i:
                        bucket[previousCar + 1][channel] = bucket[i][channel]
                        bucket[i][channel] = None
                    previousCar, previousState = previousCar + 1, 2
                    car.updateDynamic(state=2, x=previousCar)
                else:
                    previousCar, previousState = i, 1
    def findCar(self,st,end,channel,bucket):
        # find car backward
        for i in range(end, st, -1):
            if bucket[i][channel] is not None:
                return i
        return -1
    #
    # provide car
    #
    def firstPriorityCar(self):
        if self.provideBucket is None:
            print("Please do CAR.setBucket() first!")
        while self.px[0] <  self.length_:
            carId = self.provideBucket[self.px[0]][self.py[0]]
            if carId is not None and CARDICT[carId].__state__() != 2:
                car = CARDICT[carId]
                left = min(car.__speed__(),self.__speed__())
                # speed enough and no front car
                if left > self.px[0] and self.findCar(-1, self.px[0] - 1, self.py[0], self.provideBucket) == -1:
                    return self.provideBucket[self.px[0]][self.py[0]]
            if self.py[0] == self.channel_ - 1:
                self.px[0], self.py[0] = self.px[0] + 1, 0
            else:
                self.py[0] += 1
        self.provideDone[0] = True
        return -1
    def firstPriorityCarAct(self,action):
        if self.provideBucket is None:
            print("Please do CAR.setBucket() first!")
        if action == 0:
            self.provideBucket[self.px[0]][self.py[0]] = None
            self.provideNum[0] -= 1
        elif action == 1:
            carId = self.provideBucket[self.px[0]][self.py[0]]
            self.provideBucket[self.px[0]][self.py[0]] = None
            self.provideBucket[0][self.py[0]] = carId
        self.moveInChannel(self.provideBucket, self.py[0])
    #
    # receive car
    #
    def receiveCar(self,carId):
        if self.receiveBucket is None:
            print("Please do CAR.setBucket() first!")
        car = CARDICT[carId]
        leftX = min(self.speed_, car.__speed__()) - car.__x__()
        nextCrossId = self.from_ if car.__nextCrossId__() != self.from_ else self.to_
        if leftX <= 0:
            car.updateDynamic(state=2,x=0)
            return 1
        #find front car
        for i in range(self.channel_):
            frontCarLoc = self.findCar(self.length_ - leftX - 1, self.length_ - 1, i, self.receiveBucket)
            # if no front car
            if frontCarLoc == -1:
                self.receiveBucket[self.length_ - leftX][i] = carId
                self.receiveNum[0] += 1
                car.updateDynamic(state=2, x=self.length_ - leftX, y=i, presentRoad=self.id_, roadSpeed=self.speed_,
                           nextCrossId=nextCrossId)
                return 0
            frontCar = CARDICT[self.receiveBucket[frontCarLoc][i]]
            # if frontCar.state == waiting
            if frontCar.__state__() == 1:
                return 2
            # if frontCar.state == finish and frontCar.x != road.__length__()-1
            elif frontCarLoc != self.length_ - 1:
                self.receiveBucket[frontCarLoc + 1][i] = carId
                self.receiveNum[0] += 1
                car.updateDynamic(state=2, x=frontCarLoc + 1, y=i, presentRoad=self.id_, roadSpeed=self.speed_,
                           nextCrossId=nextCrossId)
                return 0
            # if frontCar.state == finish and frontCar.x == road.__length__()-1
            else:
                continue
        # if road is full
        car.updateDynamic(state=2, x=0)
        return 1
    #
    # show statistic parameters
    #
    def __id__(self):
        return self.id_
    def __length__(self):
        return self.length_
    def __speed__(self):
        return self.speed_
    def __channel__(self):
        return self.channel_
    def __from__(self):
        return self.from_
    def __to__(self):
        return self.to_
    def __isDuplex__(self):
        return self.isDuplex_
    def __carCapcity__(self):
        return self.carCapcity
    #
    # show statistic parameters
    #
    def __forwardBucket__(self):
        return self.forwardBucket
    def __backwardBucket__(self):
        return self.backwardBucket
    def __fx__(self):
        return self.fx[0]
    def __fy__(self):
        return self.fy[0]
    def __bx__(self):
        return self.bx[0]
    def __by__(self):
        return self.by[0]
    def __forwardNum__(self):
        return self.forwardNum[0]
    def __backwardNum__(self):
        return self.backwardNum[0]
    def __forwardDone__(self):
        return self.forwardDone[0]
    def __backwardDone__(self):
        return self.backwardDone[0]
    def __provideBucket__(self):
        return self.provideBucket
    def __receiveBucket__(self):
        return self.receiveBucket
    def __px__(self):
        return self.px[0]
    def __py__(self):
        return self.py[0]
    def __provideNum__(self):
        return self.provideNum[0]
    def __receiveNum__(self):
        return self.receiveNum[0]
    def __provideDone__(self):
        return self.provideDone[0]

class CROSS(object):
    def __init__(self, id_, north_, east_, south_, west_):
        # **** statistic parameters ****#
        self.id_ = id_
        self.roadIds = [north_, east_, south_, west_]
        self.carport = {}
        self.left=[]
        # absolute loc
        self.x, self.y = 0, 0
        self.mapX,self.mapY = 0,0
        # priorityMap
        self.directionMap = {north_: {east_: 1, south_: 2, west_: -1}, \
                             east_: {south_: 1, west_: 2, north_: -1}, \
                             south_: {west_: 1, north_: 2, east_: -1}, \
                             west_: {north_: 1, east_: 2, south_: -1}}
        # relationship with roads
        self.providerDirection, self.receiverDirection, self.validRoadDirecction = [], [], []
        for index, roadId in enumerate(self.roadIds):
            road = ROADDICT[roadId] if roadId != -1 else None
            if road is not None and (road.__isDuplex__() or road.__to__() == self.id_):
                self.providerDirection.append(index)
            if road is not None and (road.__isDuplex__() or road.__from__() == self.id_):
                self.receiverDirection.append(index)
            if road is not None:
                self.validRoadDirecction.append(index)
        self.provider = [[direction, self.roadIds[direction]] for direction in self.providerDirection]
        self.receiver = [self.roadIds[direction] for direction in self.receiverDirection]
        self.validRoad = [self.roadIds[direction] for direction in self.validRoadDirecction]
        self.provider.sort(key=takeSecond)
        self.providerDirection = [self.provider[i][0] for i in range(self.provider.__len__())]
        self.provider = [self.provider[i][1] for i in range(self.provider.__len__())]
        # **** dynamic parameters ****#
        self.readyCars = []
        self.carportCarNum = 0
        self.finishCarNum = 0
        # **** flag ****#
        self.done = False
        self.update = False
    # main functions
    def step(self):
        self.update = False
        for roadId in self.validRoad:
            ROADDICT[roadId].setBucket(self.id_)
        # data preapre
        nextCarId,nextCar,nextRoad,nextDirection =[],[],[],[]
        #
        # 0,1,2,3 denote north,east,south,west
        #
        for index in range(self.provider.__len__()):
            nextCarId.append(ROADDICT[self.provider[index]].firstPriorityCar())
            # if first priority car exists
            if nextCarId[index]!=-1:
                nextCar.append(CARDICT[nextCarId[index]])
                nextRoad.append(nextCar[index].__nextRoad__())
                # nextRoad == -1 => terminal
                if nextRoad[index]==-1:
                    nextDirection.append(2)
                else:
                    nextDirection.append(self.direction(self.provider[index],nextRoad[index]))
            else:
                nextCar.append(-1)
                nextRoad.append(-1)
                nextDirection.append(-1)
        # loop
        for presentRoadIndex in range(self.provider.__len__()):
            conflict = False
            while nextCar[presentRoadIndex]!=-1:
                # same next road and high priority lead to conflict
                provider = ROADDICT[self.provider[presentRoadIndex]]
                for otherRoadIndex in range(self.provider.__len__()):
                    if nextCar[otherRoadIndex] != -1 and \
                            self.isConflict(self.providerDirection[presentRoadIndex], nextDirection[presentRoadIndex],
                                            self.providerDirection[otherRoadIndex], nextDirection[otherRoadIndex]):
                        conflict = True
                        break
                # conflict
                # first priority car exists at road self.provider[otherRoadIndex]
                if conflict:
                    break
                if nextRoad[presentRoadIndex] == -1:
                    provider.firstPriorityCarAct(0)
                    CARDISTRIBUTION[1] -= 1
                    CARDISTRIBUTION[2] += 1
                    self.finishCarNum += 1
                    self.update = True
                else:
                    nextroad_ = ROADDICT[nextRoad[presentRoadIndex]]
                    action = nextroad_.receiveCar(nextCar[presentRoadIndex].__id__())
                    if action == 2:
                        # waiting conflict
                        break
                    self.update = True
                    provider.firstPriorityCarAct(action)
                nextCarId[presentRoadIndex] = provider.firstPriorityCar()
                if nextCarId[presentRoadIndex] != -1:
                    nextCar[presentRoadIndex] = CARDICT[nextCarId[presentRoadIndex]]
                    nextRoad[presentRoadIndex] = nextCar[presentRoadIndex].__nextRoad__()
                    # nextRoad == -1 => terminal
                    if nextRoad[presentRoadIndex] == -1:
                        nextDirection[presentRoadIndex] = 2
                    else:
                        nextDirection[presentRoadIndex]= self.direction(self.provider[presentRoadIndex], nextRoad[presentRoadIndex])
                else:
                    nextCar[presentRoadIndex] = -1
                    nextRoad[presentRoadIndex]= -1
                    nextDirection[presentRoadIndex] = -1
        done = True
        for fromA in range(self.provider.__len__()):
            if nextCar[fromA] != -1:
                done = False
        self.done = done
    def outOfCarport(self):
        self.readyCars = self.left
        self.left=[]
        if TIME[0] in self.carport.keys():
            self.carport[TIME[0]].sort()
            self.readyCars.extend(self.carport[TIME[0]])
        if self.readyCars.__len__() == 0:
            return
        self.readyCars.sort()
        for roadId in self.receiver:
            ROADDICT[roadId].setBucket(self.id_)
        for i in range(self.readyCars.__len__()):
            carId = self.readyCars[i]
            roadId = CARDICT[carId].__nextRoad__()
            road = ROADDICT[roadId]
            if roadId not in self.receiver:
                print("Car(%d).Road(%d) not in cross(%d).function:class.outOfCarport"%(carId,roadId,self.id_))

            # **** 如果车的出口车超过了0.5 那么就调度初始时间+1 ****#
            # b = 0
            # for j in range(road.receiveBucket.__len__()):
            #     b += road.receiveBucket[j].count(None)
            # b = min(road.carCapcity, b)
            # bili = (road.carCapcity - b) / road.carCapcity
            # if bili >= 0.5:
            #     CARDICT[carId].realtime += 1
            #     # CROSSDICT[CARDICT[carId].__from__()].carportInitial(CARDICT[carId].realtime, carId)
            #     if CARDICT[carId].realtime not in self.carport.keys():
            #         self.carport[CARDICT[carId].realtime] = [carId]
            #     else:
            #         self.carport[CARDICT[carId].realtime].append(carId)
            #     duche[0] += 1
            #     continue
            # **** 如果车的出口车超过了80 那么就调度初始时间+1 ****#

            act = road.receiveCar(carId)
            if act!=0:
                self.left=self.readyCars[i:]
                break

            #assert act==0, print("Time(%d),Cross(%d),Road(%d),Car(%d) can't pull away from carport"%(TIME[0],self.id_,roadId,carId))
            self.carportCarNum -= 1
            CARDISTRIBUTION[0] -= 1
            CARDISTRIBUTION[1] += 1
    #
    # other functions
    #
    def isConflict(self,fromA,directionA,fromB,directionB):
        # -1,0,1,2,3,4,5 => guard_w,n,e,s,w,guard_n,guard_e
        # -1 ,1, 2 => right left, straight
        # reason why:
        # direction:-1,1,2
        # 0-1=-1=>3=>west,0+1=1=>east,0+2=>2=>south
        # 1-1=0=>north,1+2=2=>south,1+2=3=>west
        # and so...
        #       0
        #   3       1
        #       2
        #
        if (fromA + directionA)%4 == (fromB + directionB)%4 and directionA < directionB:
            return True
        else:
            return False
    def direction(self,providerId,receiverId):
        return self.directionMap[providerId][receiverId]
    def setDone(self,bool):
        self.done = bool
    def setLoc(self,x,y):
        self.x,self.y = x,y
    def setMapLoc(self,mapX,mapY):
        self.mapX,self.mapY = mapX,mapY
    def roadDirection(self,roadId):
        if self.roadIds[0]==roadId:
            return 0
        elif self.roadIds[1]==roadId:
            return 1
        elif self.roadIds[2]==roadId:
            return 2
        elif self.roadIds[3]==roadId:
            return 3
        else:
            return -1
    def carportInitial(self, timePlan, carId):
        if timePlan not in self.carport.keys():
            self.carport[timePlan] = [carId]
        else:
            self.carport[timePlan].append(carId)
        self.carportCarNum += 1
    #
    # show statistic parameters
    #
    def __id__(self):
        return self.id_
    def __roadIds__(self):
        return self.roadIds
    def __providerDirection__(self):
        return self.providerDirection
    def __receiverDirection__(self):
        return self.receiverDirection
    def __validRoadDirection__(self):
        return self.validRoadDirection
    def __provider__(self):
        return self.provider
    def __receiver__(self):
        return self.receiver
    def __validRoad__(self):
        return self.validRoad
    def __x__(self):
        return self.x
    def __y__(self):
        return self.y
    def __mapX__(self):
        return self.mapX
    def __mapY__(self):
        return self.mapY
    def __done__(self):
        return self.done
    #
    # show dynamic parameters
    #
    def __carportCarNum__(self):
        return self.carportCarNum
    def __finishCarNum__(self):
        return self.finishCarNum
    def __update__(self):
        return self.update
    #
    # show some important info
    #
    def __loc__(self):
        return self.x,self.y
    def __mapLoc__(self):
        return self.mapX,self.mapY

class visualization(object):
    def __init__(self):
        self.maxX,self.maxY = 0,0
        self.savePath = '../../../simulatePictures'
        # ** cross param **#
        self.crossRadius = 14
        self.crossDistance = 150
        self.crossColor = [25,200,0]
        # ** road param **#
        self.roadColor = [0,0,0] #black
        self.roadLineType = 4
        self.channelWidth = 5
        self.channelDistance = 3
        self.lineWidth = 2
        self.time = 0
    #
    # cross location gen
    #
    def crossLocGen(self):
        #**** relative location ****#
        # denote the first cross as the origin of coordinates
        for crossId in CROSSNAMESPACE:
            CROSSDICT[crossId].setDone(False)
        crossList = [CROSSNAMESPACE[0]]
        minX,minY = 0,0
        while(crossList.__len__()>0):
            nextCrossList = []
            for crossId in crossList:
                presentX,presntY = CROSSDICT[crossId].__loc__()
                validRoad = CROSSDICT[crossId].__validRoad__()
                for roadId in validRoad:
                    #next cross id
                    nextCrossId = ROADDICT[roadId].__from__() if ROADDICT[roadId].__from__() != crossId \
                                                            else ROADDICT[roadId].__to__()
                    # if next cross is visited
                    if not CROSSDICT[nextCrossId].__done__():
                        # visit sets true
                        CROSSDICT[nextCrossId].setDone(True)
                        # relative location of nextcross
                        nextX,nextY = self.crossRelativeLoc(presentX,presntY,crossId,roadId)
                        # update location
                        CROSSDICT[nextCrossId].setLoc(nextX,nextY)
                        minX,minY,self.maxX,self.maxY=\
                                    min(nextX,minX),min(nextY,minY),max(nextX,self.maxX),max(nextY,self.maxY)
                        nextCrossList.append(nextCrossId)
            crossList = nextCrossList
        self.maxX,self.maxY = (self.maxX-minX+2)*self.crossDistance,(self.maxY-minY+2)*self.crossDistance
        for crossId in CROSSNAMESPACE:
            x,y = CROSSDICT[crossId].__loc__()
            CROSSDICT[crossId].setLoc(x-minX,y-minY)
            CROSSDICT[crossId].setMapLoc((x - minX+1)*self.crossDistance, (y - minY+1)*self.crossDistance)
    def crossRelativeLoc(self,x,y,crossId,roadId):
        roadDirection = CROSSDICT[crossId].roadDirection(roadId)
        if roadDirection==0:
            return x,y-1
        elif roadDirection==1:
            return x+1,y
        elif roadDirection==2:
            return x,y+1
        elif roadDirection==3:
            return x-1,y
        else:
            print("Cross(%d) don't interact with road(%d)"%(self.id_,roadId))
    #
    # draw functions
    #
    # def drawMap(self):
    #     img = np.ones((self.maxY,self.maxX,3),np.uint8)*255
    #     #draw road
    #     for roadId in ROADNAMESPACE:
    #         self.plotRoad(roadId,img)
    #     # draw cross
    #     for crossId in CROSSNAMESPACE:
    #         self.plotCross(crossId,img)
    #     # plot info
    #     self.plotInfo(img)
    #     cv.imwrite(self.savePath+'/%d.jpg'%TIME[0],img)
    # def plotCross(self,crossId,img):
    #     x, y = CROSSDICT[crossId].__mapLoc__()
    #     cv.circle(img,(x,y),self.crossRadius,color=self.crossColor,thickness=-1,lineType=-1)
    #     if crossId>=10:
    #         xx, yy = int(x - 4*self.crossRadius/5), int(y + self.crossRadius / 2)
    #     else:
    #         xx, yy = int(x- self.crossRadius/2), int(y + self.crossRadius / 2)
    #     cv.putText(img,str(crossId),(xx,yy ),cv.FONT_HERSHEY_SIMPLEX,0.6,[0,0,255],2)
    # def plotRoad(self,roadId,img):
    #     # get road info
    #     road = ROADDICT[roadId]
    #     fromX, fromY = CROSSDICT[road.__from__()].__mapLoc__()
    #     toX, toY = CROSSDICT[road.__to__()].__mapLoc__()
    #     # plot line
    #     cv.line(img,(fromX, fromY),(toX, toY),color=self.roadColor,thickness=2)
    #     # plot bucket
    #     self.drawBucket(road,'forward',img)
    #     if road.__isDuplex__():
    #         self.drawBucket(road,'backward',img)
    # def drawBucket(self,road,lane,img):
    #     bucket = road.__forwardBucket__() if lane !='backward' else road.__backwardBucket__()
    #     length = road.__length__()
    #     channel = road.__channel__()
    #     fromX, fromY = CROSSDICT[road.__from__()].__mapLoc__()
    #     toX, toY = CROSSDICT[road.__to__()].__mapLoc__()
    #     XY, intervalXY, rectangleSize, channel2XY, length2XY = self.bucketDrawInitial(fromX,fromY,toX,toY,lane,length)
    #     for i in range(length):
    #         for j in range(channel):
    #             xRD,yRD = int(XY[0]+rectangleSize[0]),int(XY[1]+rectangleSize[1])
    #             if bucket[i][j] is  None:
    #                 cv.rectangle(img,(int(XY[0]),int(XY[1])),(xRD,yRD),(0,0,0),1)
    #             else:
    #                 color = CARDICT[bucket[i][j]].__carColor__()
    #                 cv.rectangle(img, (int(XY[0]), int(XY[1])),(xRD, yRD),color=color,thickness=-1)
    #             XY[channel2XY] = XY[channel2XY] + intervalXY[channel2XY]
    #         XY[channel2XY] = XY[channel2XY] - intervalXY[channel2XY]*channel
    #         XY[length2XY] = XY[length2XY] + intervalXY[length2XY]
    # def bucketDrawInitial(self,fromX,fromY,toX,toY,lane,length):
    #     direction = self.bucketDirection(fromX,fromY,toX,toY,lane)
    #     unitLength = (self.crossDistance - self.crossRadius * 4) / length
    #     if lane=='backward':
    #         toY=fromY
    #         toX=fromX
    #     if direction == 'north':
    #         XY = [fromX + self.channelDistance,toY + self.crossRadius * 2]
    #         intervalXY = self.channelDistance  + self.channelWidth , unitLength
    #         rectangleSize = self.channelWidth , unitLength
    #         channel2XY, length2XY = 0, 1
    #     elif direction == 'south':
    #         XY = [fromX - self.channelDistance - self.channelWidth,toY - self.crossRadius * 2 - unitLength]
    #         intervalXY = -(self.channelDistance  + self.channelWidth ), -unitLength
    #         rectangleSize = self.channelWidth , unitLength
    #         channel2XY, length2XY = 0, 1
    #     elif direction == 'east':
    #         XY = [toX - self.crossRadius * 2 - unitLength,fromY + self.channelDistance]
    #         intervalXY = -unitLength, self.channelDistance + self.channelWidth
    #         rectangleSize = unitLength, self.channelWidth
    #         channel2XY, length2XY = 1, 0
    #     elif direction == 'west':
    #         XY = [toX + self.crossRadius * 2, fromY - self.channelDistance - self.channelWidth]
    #         intervalXY = unitLength, -(self.channelDistance + self.channelWidth)
    #         rectangleSize = unitLength, self.channelWidth
    #         channel2XY, length2XY = 1, 0
    #     return XY,intervalXY,rectangleSize,channel2XY,length2XY
    # def bucketDirection(self,fromX,fromY,toX,toY,lane):
    #     if fromY > toY:
    #         direction = 'north' if lane=='forward' else 'south'
    #     elif fromY < toY:
    #         direction = 'south' if lane == 'forward' else 'north'
    #     elif fromX < toX:
    #         direction = 'east' if lane == 'forward' else 'west'
    #     else:
    #         direction = 'west' if lane == 'forward' else 'east'
    #     return direction
    # def plotInfo(self,img):
    #     for crossId in CROSSNAMESPACE:
    #         cross = CROSSDICT[crossId]
    #         x,y = cross.__mapLoc__()
    #         cn,fn = cross.__carportCarNum__(),cross.__finishCarNum__()
    #         cv.putText(img,"%d,%d"%(cn,fn),(int(x),int(y-1.1*self.crossRadius)),\
    #                    cv.FONT_HERSHEY_SIMPLEX,0.4,[0,0,255],1)
    #     cv.putText(img, "in the carport:%d,on the road:%d,end of the trip:%d" % (CARDISTRIBUTION[0],CARDISTRIBUTION[1],CARDISTRIBUTION[2]),(30,30), \
    #                cv.FONT_HERSHEY_SIMPLEX, 0.6, [0, 0, 255], 2)

class Astar(object):
    def __init__(self, ):
        self.cost = {}
        self.open = []
        self.F = [0, 0, 0, 0]
        self.G = []
        self.H = []

    def Astar_run(self):
        # fp = open('../config/answer.txt', 'w')
        count_num_car = 0
        for carname in CARNAMESPACE[0:]:
            count_num_car += 1
            CARDICT[carname].routeclose.append(CARDICT[carname].__from__())
            # fp.write('(%s, %s' % (carname, CARDICT[carname].__planTime__()))
            # print('(%s, %s' % (carname, CARDICT[carname].__planTime__()), sep='', end='')
            continue_tmp = True
            node = CARDICT[carname].__from__()
            road_temp = 1
            changeroad = False
            while continue_tmp:
                node_x_H, node_y_H, changeroad = Astar.findFvalue(self, carname, node, road_temp, changeroad)
                self.G = []
                ###### 找到最小值F所在的road 并且判断它是否是单向的 能否通行 ######
                Astar.checktoolong(self, node_x_H, node_y_H, carname)
                road_temp, changeroad = Astar.checkoneroad(self, carname, changeroad)
                continue1_tmp = True
                while continue1_tmp:
                    if ROADDICT[road_temp].isDuplex_ == 1:
                        if ROADDICT[road_temp].from_ == node:
                            # fp.write(', %s' % road_temp)
                            # print(', %s' % road_temp, sep='', end='')
                            node = ROADDICT[road_temp].to_
                            continue1_tmp = False
                        elif ROADDICT[road_temp].to_ == node:
                            # fp.write(', %s' % road_temp)
                            # print(', %s' % road_temp, sep='', end='')
                            node = ROADDICT[road_temp].from_
                            continue1_tmp = False
                    else:
                        if ROADDICT[road_temp].from_ == node:
                            # fp.write(', %s' % road_temp)
                            # print(', %s' % road_temp, sep='', end='')
                            node = ROADDICT[road_temp].to_
                            continue1_tmp = False
                        else:
                            del CARDICT[carname].routemap[-1]
                            self.F[self.F.index(min(self.F))] = max(self.F)
                            road_temp = self.open[self.F.index(min(self.F))]
                            CARDICT[carname].routemap.append(road_temp)
                CARDICT[carname].routeclose.append(node)
                ###### 如果车辆到达了最终的cross 推出循环 ######
                if node == CARDICT[carname].__to__():
                    # fp.write(')\n')
                    # print(')\n', sep='', end='')
                    continue_tmp = False
        return count_num_car
        # fp.close()

    def findFvalue(self, carname, node, road_temp, changeroad):
        self.open = CROSSDICT[node].roadIds[:] #找到与路口相连的四条路的信息
        ###### 已经走过的路标记为-1 第一次除外######
        if road_temp != 1:
            self.open[self.open.index(road_temp)] = -1
        Astar.findGvalue(self, carname)
        node_x_H, node_y_H = Astar.findHvalue(self, carname, node)
        for i in range(4):
            self.F[i] = self.G[i] + self.H[i]
        if changeroad:
            self.F[self.F.index(min(self.F))] += 10
            changeroad = False
        return node_x_H, node_y_H, changeroad

    def findGvalue(self, carname):
        ######  顺时针搜索 ######
        for i in range(4):
            if self.open[i] == -1:
                self.G.append(1)
            else:
                self.G.append(ROADDICT[self.open[i]].carCapcity * min(CARDICT[carname].__speed__(), ROADDICT[self.open[i]].__speed__()))
        max_G = max(self.G)
        for x in range(4):
            self.G[x] = max_G/self.G[x]

    def findHvalue(self, carname, node):
        # if node % 10 == 0:
        #     current_x_H = node // 10 - 1
        #     current_y_H = 10
        # else:
        #     current_x_H = node // 10
        #     current_y_H = node % 10
        # if CARDICT[carname].__to__() % 10 == 0:
        #     destination_x_H = CARDICT[carname].__to__() // 10 - 1
        #     destination_y_H = 10
        # else:
        #     destination_x_H = CARDICT[carname].__to__() // 10
        #     destination_y_H = CARDICT[carname].__to__() % 10
        node_x_H = CROSSDICT[CARDICT[carname].__to__()].x - CROSSDICT[node].x
        node_y_H = CROSSDICT[CARDICT[carname].__to__()].y - CROSSDICT[node].y
        node_H = abs(node_x_H) + abs(node_y_H)
        if (node_x_H > 0) & (node_y_H > 0):
            self.H[:] = [node_H + 1, node_H - 1, node_H - 1, node_H + 1]
        elif (node_x_H > 0) & (node_y_H < 0):
            self.H[:] = [node_H - 1, node_H - 1, node_H + 1, node_H + 1]
        elif (node_x_H < 0) & (node_y_H < 0):
            self.H[:] = [node_H - 1, node_H + 1, node_H + 1, node_H - 1]
        elif (node_x_H < 0) & (node_y_H > 0):
            self.H[:] = [node_H + 1, node_H + 1, node_H - 1, node_H - 1]
        elif (node_x_H == 0) & (node_y_H > 0):
            self.H[:] = [node_H + 1, node_H + 1, node_H - 1, node_H + 1]
        elif (node_x_H == 0) & (node_y_H < 0):
            self.H[:] = [node_H - 1, node_H + 1, node_H + 1, node_H + 1]
        elif (node_x_H > 0) & (node_y_H == 0):
            self.H[:] = [node_H + 1, node_H - 1, node_H + 1, node_H + 1]
        elif (node_x_H < 0) & (node_y_H == 0):
            self.H[:] = [node_H + 1, node_H + 1, node_H + 1, node_H - 1]
        return node_x_H, node_y_H

    def checktoolong(self, node_x_H, node_y_H, carname):
        if CARDICT[carname].routeclose.__len__() >= 1:
            if (node_x_H > 0) & (node_y_H > 0):
                self.F[0], self.F[1], self.F[2], self.F[3] = self.F[0] + 20, self.F[1] + max(np.random.randint(0, 2, 1)), self.F[2] + max(np.random.randint(0, 2, 1)), self.F[3] + 20
            elif (node_x_H > 0) & (node_y_H < 0):
                self.F[0], self.F[1], self.F[2], self.F[3] = self.F[0] + max(np.random.randint(0, 2, 1)), self.F[1] + max(np.random.randint(0, 2, 1)), self.F[2] + 20, self.F[3] + 20
            elif (node_x_H < 0) & (node_y_H < 0):
                self.F[0], self.F[1], self.F[2], self.F[3] = self.F[0] + max(np.random.randint(0, 2, 1)), self.F[1] + 20, self.F[2] + 20, self.F[3] + max(np.random.randint(0, 2, 1))
            elif (node_x_H < 0) & (node_y_H > 0):
                self.F[0], self.F[1], self.F[2], self.F[3] = self.F[0] + 20, self.F[1] + 20, self.F[2] + max(np.random.randint(0, 2, 1)), self.F[3] + max(np.random.randint(0, 2, 1))
            elif (node_x_H == 0) & (node_y_H > 0):
                self.F[0], self.F[1], self.F[3] = self.F[0] + 20, self.F[1] + 6 + max(np.random.randint(1, 4, 1)), self.F[3] + 6 + max(np.random.randint(1, 4, 1))
            elif (node_x_H == 0) & (node_y_H < 0):
                self.F[1], self.F[2], self.F[3] = self.F[1] + 6 + max(np.random.randint(1, 4, 1)), self.F[2] + 20, self.F[3] + 6 + max(np.random.randint(1, 4, 1))
            elif (node_x_H > 0) & (node_y_H == 0):
                self.F[0], self.F[2], self.F[3] = self.F[0] + 6 + max(np.random.randint(1, 4, 1)), self.F[2] + 6 + max(np.random.randint(1, 4, 1)), self.F[3] + 20
            elif (node_x_H < 0) & (node_y_H == 0):
                self.F[0], self.F[1], self.F[2] = self.F[0] + 6 + max(np.random.randint(1, 4, 1)), self.F[1] + 20, self.F[2] + 6 + max(np.random.randint(1, 4, 1))

    def checkoneroad(self, carname, changeroad):
        ######  如果这条路宽度只有1 并且速度小于等于4 那么把这条路的F变大 不选择他 概率可调  ######
        if (ROADDICT[self.open[self.F.index(min(self.F))]].__channel__() == 1) & (ROADDICT[self.open[self.F.index(min(self.F))]].__speed__() <= 4):
            if max(np.random.randint(0, 4, 1)) == 1:
                self.F[self.F.index(min(self.F))] = max(self.F)
        if self.open.count(-1) == 3:
            road_temp = max(self.open)
        else:
            road_temp = self.open[self.F.index(min(self.F))]
        CARDICT[carname].routemap.append(road_temp)
        if CARDICT[carname].routemap.count(road_temp) == 2:
            changeroad = True
        return road_temp, changeroad

class simulation(object):
    def __init__(self):
        self.dead = False
    def step(self):
        print("time:%d  %d  %d  %d" % (TIME[0], CARDISTRIBUTION[0], CARDISTRIBUTION[1], CARDISTRIBUTION[2]))
        for crossId in CROSSNAMESPACE:
            CROSSDICT[crossId].setDone(False)
        for road in ROADNAMESPACE:
            ROADDICT[road].stepInit()
        unfinishedCross = CROSSNAMESPACE
        while unfinishedCross.__len__() > 0:
            self.dead = True
            nextCross = []
            for crossId in unfinishedCross:
                cross = CROSSDICT[crossId]
                cross.step()
                if not cross.__done__():
                    nextCross.append(crossId)
                if cross.__update__() or cross.__done__():
                    self.dead = False
            unfinishedCross = nextCross
            assert self.dead is False, print("dead lock in", unfinishedCross)
        for i in range(CROSSNAMESPACE.__len__()):
            crossId = CROSSNAMESPACE[i]
            for roadId in CROSSDICT[crossId].__validRoad__():
                ROADDICT[roadId].setBucket(crossId)
            CROSSDICT[crossId].outOfCarport()
        # print(CARDISTRIBUTION,sum(CARDISTRIBUTION))
    def simulate(self):
        # visualize = visualization()
        # visualize.crossLocGen()
        while True:
            self.step()
            # visualize.drawMap()
            if CARDISTRIBUTION[2]==CARNAMESPACE.__len__():
                print(CARDISTRIBUTION[2])
                break
            if self.dead:
                break
            TIME[0] +=1

def takeSecond(elem):
    return elem[1]

def main():
#     if len(sys.argv) != 5:
#         logging.info('please input args: car_path, road_path, cross_path, answerPath')
#         exit(1)
#
#     car_path = sys.argv[1]
#     road_path = sys.argv[2]
#     cross_path = sys.argv[3]
#     answer_path = sys.argv[4]
#
#     logging.info("car_path is %s" % (car_path))
#     logging.info("road_path is %s" % (road_path))
#     logging.info("cross_path is %s" % (cross_path))
#     logging.info("answer_path is %s" % (answer_path))
# #
# # # to read input file
#     carInfo = open(car_path, 'r').read().split('\n')[1:]
#     roadInfo = open(road_path, 'r').read().split('\n')[1:]
#     crossInfo = open(cross_path, 'r').read().split('\n')[1:]

    carInfo = open('config/car.txt', 'r').read().split('\n')[1:]
    roadInfo = open('config/road.txt', 'r').read().split('\n')[1:]
    crossInfo = open('config/cross.txt', 'r').read().split('\n')[1:]

    for line in carInfo:
        # print(line)
        id_, from_, to_, speed_, planTime_ = line.replace(' ', '').replace('\t', '')[1:-1].split(',')
        CARNAMESPACE.append(int(id_))
        CARDICT[int(id_)] = CAR(int(id_), int(from_), int(to_), int(speed_), int(planTime_))
    # create road objects
    # line = (id,length,speed,channel,from,to,isDuplex)
    for line in roadInfo:
        id_, length_, speed_, channel_, from_, to_, isDuplex_ = line.replace(' ', '').replace('\t', '')[1:-1].split(',')
        ROADNAMESPACE.append(int(id_))
        ROADDICT[int(id_)] = ROAD(int(id_), int(length_), int(speed_), int(channel_), int(from_), int(to_), int(isDuplex_))
    # create cross objects
    # line = (id,north,east,south,west)

# ××××××××××××××××××××××××××××××××××××××× #
    visitDone = {}
    for line in crossInfo:
        id_, north_, east_, south_, west_ = line.replace(' ', '').replace('\t', '')[1:-1].split(',')
        CROSSNAMESPACE.append(int(id_))
        visitDone[int(id_)] = False
        CROSSDICT[int(id_)] = [int(north_), int(east_), int(south_), int(west_)]

    #DP and DFS adjust directions
    def DFS(crossId,direction=None,preCrossId=None):
        if visitDone[crossId]:
            return
        visitDone[crossId] = True
        if preCrossId is not None:
            for i in range(4):
                roadId = CROSSDICT[crossId][i]
                if roadId!=-1:
                    pcId = ROADDICT[roadId].__from__() if ROADDICT[roadId].__from__()!= crossId else ROADDICT[roadId].__to__()
                    if pcId == preCrossId:
                        break
            shift=((i+2)%4-direction)%4
            for i in range(shift):
                CROSSDICT[crossId]=[CROSSDICT[crossId][1],CROSSDICT[crossId][2],CROSSDICT[crossId][3],CROSSDICT[crossId][0]]
        for i in range(4):
            roadId = CROSSDICT[crossId][i]
            if roadId!=-1:
                nextCrossId = ROADDICT[roadId].__from__() if ROADDICT[roadId].__from__()!= crossId else ROADDICT[roadId].__to__()
                DFS(nextCrossId,i,crossId)

    DFS(CROSSNAMESPACE[0])
    for crossId in CROSSNAMESPACE:
        north_,east_,south_,west_ = CROSSDICT[crossId]
        CROSSDICT[crossId] = CROSS(crossId,north_,east_,south_,west_)

    visualize = visualization()
    visualize.crossLocGen()

# process
    astar = Astar()
    count_num_car = astar.Astar_run()

    # simulate = simulation()
    # simulate.simulate()
    # fp = open(answer_path, 'w')
    type1, type2, type3, type4, type5, type6, type7= 0, 0, 0, 0, 0, 0, 0
    # for i in range(20):
    # 当时我还加上了两个地图不一样的参数
    for carname in CARNAMESPACE[:]:
        if (CARDICT[carname].routemap.__len__() > 18) & (CARDICT[carname].speed_ < 10):
            # type1 += 1
            CARDICT[carname].realtime += max(np.random.randint(0, 50, 1))
        elif (CARDICT[carname].routemap.__len__() <= 18) & (CARDICT[carname].routemap.__len__() > 15 ) & (CARDICT[carname].speed_ < 10):
            # type2 += 1
            CARDICT[carname].realtime += max(np.random.randint(150, 500, 1))
        elif (CARDICT[carname].routemap.__len__() <= 15) & (CARDICT[carname].routemap.__len__() > 13 ) & (CARDICT[carname].speed_ < 10):
            # type3 += 1
            CARDICT[carname].realtime += max(np.random.randint(500, 950, 1))
        elif (CARDICT[carname].routemap.__len__() >= 15) & (CARDICT[carname].speed_ >= 10):
            # type4 += 1
            CARDICT[carname].realtime += max(np.random.randint(1000, 2000, 1))
        elif (CARDICT[carname].routemap.__len__() <= 13) & (CARDICT[carname].speed_ <= 10):
            # type5 += 1
            CARDICT[carname].realtime += max(np.random.randint(2000, 2500, 1))
        elif (CARDICT[carname].routemap.__len__() > 13) & (CARDICT[carname].routemap.__len__() <= 15) & (CARDICT[carname].speed_ >= 10):
            # type6 += 1
            CARDICT[carname].realtime += max(np.random.randint(2500, 2800, 1))
        elif (CARDICT[carname].routemap.__len__() <= 13) & (CARDICT[carname].speed_ >= 10):
            # type7 += 1
            CARDICT[carname].realtime += max(np.random.randint(2850, 3000, 1))
    # print(type1, type2, type3, type4, type5, type6, type7, type1+type2+type3+type4+type5+type6+type7)
        # type1, type2, type3, type4, type5, type6, type7 = 0, 0, 0, 0, 0, 0, 0

    count = 0
    for carname in CARNAMESPACE[:]:
        # line = line.strip()[1:-1].split(',')
        carId = carname
        planTime_ = CARDICT[carname].realtime
        route = CARDICT[carname].routemap[:]
        CARDICT[carId].simulateInit(planTime_, route)
        count += 1
    print("There are %d cars' route preinstalled" % count)
    CARDISTRIBUTION[0] = CARNAMESPACE.__len__()
    # **** cross initialization ****#
    for carId in CARNAMESPACE:
        CROSSDICT[CARDICT[carId].__from__()].carportInitial(CARDICT[carId].__planTime__(), carId)
    # ****Initialization ****#
    CARNAMESPACE.sort()
    CROSSNAMESPACE.sort()

    simulate = simulation()
    simulate.simulate()

# to write output file

    fp = open('config/answer.txt', 'w')
    for carname in CARNAMESPACE[:]:
        fp.write('(%s, %s' % (carname, CARDICT[carname].realtime))
        for value in CARDICT[carname].routemap[:]:
            fp.write(', %s' % value)
        fp.write(')\n')
    fp.close()

if __name__ == "__main__":
    main()


class LyricTagService:
    def __init__(self,lyric_tag_dao):
        self.dao = lyric_tag_dao

    def create_new_lyric_tag(self,tag_name):
        new_lyric_tag_id = self.dao.insert_lyric_tag(tag_name)
        return new_lyric_tag_id

    def create_new_map(self,tag_id,song_id):
        check = self.dao.insert_map(tag_id,song_id)
        return check

    def song_list_of_lyric_tag(self,lyric_tag_id):
        res = self.dao.get_song_list_of_lyric_tag(lyric_tag_id)
        if res == []:
            res = [{
                "title":"dummy",
                "artist":"dummy",
                "e_label":2,
                "v_label": 3,
                "mood_tag": "test_mood_tag",
                "id": 1
            }]
            return res
        return res

    def lyric_tags_of_song(self,song_id):
        tags = self.dao.get_lyric_tags_of_song(song_id)
        if tags == []:
            tags = [{
                "id":1,"tag":"드라이브"
            },{
                "id":2,"tag":"한강"
            }]
            return tags
        return tags

    def lyric_tags_with_query(self,query):
        res = self.dao.get_lyric_tags_with_query(query)
        if res == []:
            res = [{
                "id":1,"tag":"운동"
            },{"id":2,"tag":"운동광"}]
            return res
        return res


import random

if __name__ == "__main__":
    while True:
        min = input('Select a minimal value : ')
        max = input('Select a maximal value : ')
        if(not min.isdigit() or not max.isdigit()):
            print('Please enter digits only')
            continue
        else:
            secret = random.randint(int(min),int(max))
            while True:
                value = input('Select a number : ')
                if(value.isdigit()):
                    value = int(value)
                else:
                    print('Please enter digits only')
                    continue
                if(value == secret):
                    answer = input("GG, you found the secret number, want to play again ? (y/n)")
                    if answer == 'y':
                        break
                    else:
                        exit()
                elif(value > secret):
                    print("Secret is Lower")
                elif(value < secret):
                    print("Secret is Higher")