import lzma
import os
import sys
import shutil
import subprocess
import pickle
import hashlib
import tarfile, zipfile
import tempfile
from glob import glob
from mesonbuild.environment import detect_ninja
from mesonbuild.mesonlib import windows_proof_rmtree
from mesonbuild import mlog

def create_hash(fname):
    hashname = fname + '.sha256sum'
    m = hashlib.sha256()
    m.update(open(fname, 'rb').read())
    with open(hashname, 'w') as f:
        f.write('%s %s\n' % (m.hexdigest(), os.path.basename(fname)))

def create_zip(zipfilename, packaging_dir):
    prefix = os.path.dirname(packaging_dir)
    removelen = len(prefix) + 1
    with zipfile.ZipFile(zipfilename,
                         'w',
                         compression=zipfile.ZIP_DEFLATED,
                         allowZip64=True) as zf:
        zf.write(packaging_dir, packaging_dir[removelen:])
        for root, dirs, files in os.walk(packaging_dir):
            for d in dirs:
                dname = os.path.join(root, d)
                zf.write(dname, dname[removelen:])
            for f in files:
                fname = os.path.join(root, f)
                zf.write(fname, fname[removelen:])

def del_gitfiles(dirname):
    for f in glob(os.path.join(dirname, '.git*')):
        if os.path.isdir(f) and not os.path.islink(f):
            windows_proof_rmtree(f)
        else:
            os.unlink(f)

def process_submodules(dirname):
    module_file = os.path.join(dirname, '.gitmodules')
    if not os.path.exists(module_file):
        return
    subprocess.check_call(['git', 'submodule', 'update', '--init'], cwd=dirname)
    for line in open(module_file):
        line = line.strip()
        if '=' not in line:
            continue
        k, v = line.split('=', 1)
        k = k.strip()
        v = v.strip()
        if k != 'path':
            continue
        del_gitfiles(os.path.join(dirname, v))

def run_dist_scripts(dist_root, dist_scripts):
    assert(os.path.isabs(dist_root))
    env = os.environ.copy()
    env['MESON_DIST_ROOT'] = dist_root
    for d in dist_scripts:
        script = d['exe']
        args = d['args']
        name = ' '.join(script + args)
        print('Running custom dist script {!r}'.format(name))
        try:
            rc = subprocess.call(script + args, env=env)
            if rc != 0:
                sys.exit('Dist script errored out')
        except OSError:
            print('Failed to run dist script {!r}'.format(name))
            sys.exit(1)

def git_have_dirty_index(src_root):
    '''Check whether there are uncommitted changes in git'''
    ret = subprocess.call(['git', '-C', src_root, 'diff-index', '--quiet', 'HEAD'])
    return ret == 1

def create_dist_git(dist_name, src_root, bld_root, dist_sub, dist_scripts):
    if git_have_dirty_index(src_root):
        mlog.warning('Repository has uncommitted changes that will not be included in the dist tarball')
    distdir = os.path.join(dist_sub, dist_name)
    if os.path.exists(distdir):
        shutil.rmtree(distdir)
    os.makedirs(distdir)
    subprocess.check_call(['git', 'clone', '--shared', src_root, distdir])
    process_submodules(distdir)
    del_gitfiles(distdir)
    run_dist_scripts(distdir, dist_scripts)
    xzname = distdir + '.tar.xz'
    # Should use shutil but it got xz support only in 3.5.
    with tarfile.open(xzname, 'w:xz') as tf:
        tf.add(distdir, dist_name)
    # Create only .tar.xz for now.
    # zipname = distdir + '.zip'
    # create_zip(zipname, distdir)
    shutil.rmtree(distdir)
    return (xzname, )

def hg_have_dirty_index(src_root):
    '''Check whether there are uncommitted changes in hg'''
    out = subprocess.check_output(['hg', '-R', src_root, 'summary'])
    return b'commit: (clean)' not in out

def create_dist_hg(dist_name, src_root, bld_root, dist_sub, dist_scripts):
    if hg_have_dirty_index(src_root):
        mlog.warning('Repository has uncommitted changes that will not be included in the dist tarball')

    os.makedirs(dist_sub, exist_ok=True)
    tarname = os.path.join(dist_sub, dist_name + '.tar')
    xzname = tarname + '.xz'
    subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'tar', tarname])
    if len(dist_scripts) > 0:
        mlog.warning('dist scripts are not supported in Mercurial projects')
    with lzma.open(xzname, 'wb') as xf, open(tarname, 'rb') as tf:
        shutil.copyfileobj(tf, xf)
    os.unlink(tarname)
    # Create only .tar.xz for now.
    # zipname = os.path.join(dist_sub, dist_name + '.zip')
    # subprocess.check_call(['hg', 'archive', '-R', src_root, '-S', '-t', 'zip', zipname])
    return (xzname, )

def check_dist(packagename, meson_command):
    print('Testing distribution package %s' % packagename)
    unpackdir = tempfile.mkdtemp()
    builddir = tempfile.mkdtemp()
    installdir = tempfile.mkdtemp()
    ninja_bin = detect_ninja()
    try:
        tf = tarfile.open(packagename)
        tf.extractall(unpackdir)
        srcdir = glob(os.path.join(unpackdir, '*'))[0]
        if subprocess.call(meson_command + ['--backend=ninja', srcdir, builddir]) != 0:
            print('Running Meson on distribution package failed')
            return 1
        if subprocess.call([ninja_bin], cwd=builddir) != 0:
            print('Compiling the distribution package failed')
            return 1
        if subprocess.call([ninja_bin, 'test'], cwd=builddir) != 0:
            print('Running unit tests on the distribution package failed')
            return 1
        myenv = os.environ.copy()
        myenv['DESTDIR'] = installdir
        if subprocess.call([ninja_bin, 'install'], cwd=builddir, env=myenv) != 0:
            print('Installing the distribution package failed')
            return 1
    finally:
        shutil.rmtree(unpackdir)
        shutil.rmtree(builddir)
        shutil.rmtree(installdir)
    print('Distribution package %s tested' % packagename)
    return 0

def run(args):
    src_root = args[0]
    bld_root = args[1]
    meson_command = args[2:]
    priv_dir = os.path.join(bld_root, 'meson-private')
    dist_sub = os.path.join(bld_root, 'meson-dist')

    buildfile = os.path.join(priv_dir, 'build.dat')

    build = pickle.load(open(buildfile, 'rb'))

    dist_name = build.project_name + '-' + build.project_version

    _git = os.path.join(src_root, '.git')
    if os.path.isdir(_git) or os.path.isfile(_git):
        names = create_dist_git(dist_name, src_root, bld_root, dist_sub, build.dist_scripts)
    elif os.path.isdir(os.path.join(src_root, '.hg')):
        names = create_dist_hg(dist_name, src_root, bld_root, dist_sub, build.dist_scripts)
    else:
        print('Dist currently only works with Git or Mercurial repos')
        return 1
    if names is None:
        return 1
    error_count = 0
    for name in names:
        rc = check_dist(name, meson_command) # Check only one.
        if rc == 0:
            create_hash(name)
        error_count += rc
    return 1 if error_count else 0


import torch
import numpy as np
import dgl
from dgl.nn.pytorch import GraphConv

# 生成20个城市点的坐标，范围为0-100
n = 20  # 城市数量
coords = np.random.randint(0, 100, size=(n, 2))

# 计算每两个城市之间的距离矩阵
dist_matrix = np.zeros((n, n))
for i in range(n):
    for j in range(n):
        dist_matrix[i][j] = np.sqrt(np.sum((coords[i] - coords[j]) ** 2))

# 构建完全图，每条边的权重为对应城市之间的距离
g = dgl.complete_graph(n)  # 完全图有n*(n-1)/2条边
g.edata['w'] = torch.from_numpy(dist_matrix[g.edges()[0], g.edges()[1]]).float()  # 边权重

# 定义GNN模型，使用GraphConv层
class GNN(torch.nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(GNN, self).__init__()
        self.conv1 = GraphConv(input_dim, hidden_dim)
        self.conv2 = GraphConv(hidden_dim, output_dim)

    def forward(self, g, x):
        h = self.conv1(g, x)
        h = torch.relu(h)
        h = self.conv2(g, h)
        return h

# 实例化模型，输入维度为2（坐标），隐藏维度为16，输出维度为1（得分）
model = GNN(2, 16, 1)

# 定义优化器和损失函数，使用Adam优化器和负对数似然损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
criterion = torch.nn.NLLLoss()

# 将坐标转换为张量作为节点特征
x = torch.from_numpy(coords).float()

# 训练模型，迭代次数为1000
epochs = 1000
for epoch in range(epochs):
    # 前向传播，得到每个节点的得分
    logits = model(g, x).squeeze()

    # 将得分归一化为概率分布，使用gumbel softmax采样一个路径作为预测值
    probs = torch.softmax(logits / 0.2, dim=0)  # 温度参数设为0.2
    pred_path = torch.argmax(torch.nn.functional.gumbel_softmax(probs.log(), tau=0.2), dim=0)

    # 计算预测路径的总距离作为损失值，并反向传播更新参数
    pred_dist = g.edata['w'][g.edge_id(pred_path[:-1], pred_path[1:])].sum()
    loss = pred_dist
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    # 每100次迭代打印一次损失值和预测路径
    if (epoch + 1) % 100 == 0:
        print(f"Epoch {epoch + 1}, Loss {loss.item():.4f}")
        print(f"Predicted path: {pred_path.tolist()}")

# bing 写的代码


# 알파벳 대문자와 숫자(0 ~9) 로만 구성된 문자열이 주어집니다. 이때 모든 알파벳을 오름차순으로 정렬하여 이어서 출력한 뒤에,
# 그 뒤에 모든 숫자를 더한 값을 이어서 출력합니다.

# 예를 들어, K1KA5CB7 이라는 값이 들어오면 ABCKK13 출력합니다.

data = list(input())

alpha = []
value = 0

for x in data:

    if x.isalpha():
        alpha.append(x)

    else :
        value += int(x)

alpha.sort()

if value != 0 :

    alpha.append(str(value))

print(''.join(alpha))


import numpy as np

def input_MatVec():
    CorrectMatrix = False
    while True:
        Size = int(input('Enter Size of Matrix/Vector: '))
        A = np.zeros((Size,Size),dtype=float)
        print('Enter Matrix:')
        for i in range(Size):
            A[i,:] = list(map(int,input(f"\nEnter Values in Row {i} : ").strip().split()))[:Size]
        print('Printing Resulting Matrix...')
        for i in range(Size):
            print(A[i,:])

        CorrectMatrix = str(input('Is this Matrix Correct? (Y/N) '))
        if CorrectMatrix == 'y' or CorrectMatrix == 'Y':
            break
        else:
            print('Retrying...')
            print()

    print()
    CorrectMatrix = False
    while True:
        b = np.zeros((Size),dtype=float)
        print('Enter Vector:')
        b[:] = list(map(int,input(f"\nEnter Values : ").strip().split()))[:Size]
        print('Printing Resulting Vector...')
        print(b[:])

        CorrectMatrix = str(input('Is this Vector Correct? (Y/N) '))
        if CorrectMatrix == 'y' or CorrectMatrix == 'Y':
            break
        else:
            print('Retrying...')
            print()

    return A, b

def gauss_seidel(A, b, x0, max_its, tol):
    n = len(A)
    x = x0.copy()

    #Gauss-Seidel Method
    for its in range(max_its):
        x_new = np.zeros(n)
        for j in range(n):
            s1 = np.dot(A[j, :j], x_new[:j])
            s2 = np.dot(A[j, j + 1:], x[j + 1:])
            x_new[j] = (b[j] - s1 - s2) / A[j, j]
        if np.allclose(x, x_new, rtol=tol):
            return x_new
        x = x_new
    return its, x

A, b = input_MatVec()
x0 = np.ones(np.size(b),dtype=float)
its = 0

its, x = gauss_seidel(A, b, x0)

print('Required Iterations:', its)
print('Solution:', x)
#Calculate Error on Solve
print('Calculated Error:',np.sum(np.matmul(A,x)-b))


# Given a list of signed integers, return true if the sum of any two integers is 0

# Brute force would to be look at each pair of integer elements and see if sum is 0 but the complexity is O(n^2)

# def sum2(arr):
#     # Looping through arrary with index and the value
#     for i_index, i in enumerate(arr):
#         for j_index, j in enumerate(arr):
#             if i + j == 0 and i_index != j_index:
#                 return True
#     return False

# We loop through the array. For each elemenet, we put in the numbers hashmap with the index being the number we want to see that would sum to 0 and the value is True.
def sum2(arr):
    numbers = {}
    for i in arr:
        if i in numbers:
            return True
        numbers[-i] = True
    return False

# php equivalent of line 26 is $numbers = [];
def sum2_bert(arr):
    numbers = {}
    for i in arr:
        if -i in numbers:
            return True
        numbers[i] = True
    return False

assert(sum2_bert([1, 2, -1, 0, 3]) == True)
assert(sum2_bert([1, 2, 3, -4, 0]) == False)
assert(sum2_bert([1, 2, 0, 0, -3]) == True)
assert(sum2_bert([]) == False)
assert(sum2_bert([0]) == False)

# Given a two list of letters, check if they are anagrams

# Runtime complexity is O(nlogn)
def anagram_check(arr1, arr2):
    arr1.sort()
    arr2.sort()
    return arr1 == arr2

assert(anagram_check(["b", "a"], ["a", "b"]) == True)
assert(anagram_check(["b", "a", "a"], ["a", "b", "a"]) == True)
assert(anagram_check(["a", "b", "a"], ["a", "b", "a", "c"]) == False)

# Runtime complexity is O(min(n + m)) where n is length of arr1 and m is length of arr2
# Space complexity is O(1)
def anagram_check_hashmap(arr1, arr2):
    return len(arr1) != len(arr2)
    map1 = {}
    map2 = {}
    for letter in arr1:
        if letter in map1:
            map1[letter] += 1
        else:
            map1[letter] = 0
    for letter in arr2:
        if letter in map2:
            map2[letter] += 1
        else:
            map2[letter] = 0
    return map1 == map2

# Given a two list of letters, check if they are anagrams
assert(anagram_check_hashmap(["b", "a"], ["a", "b"]) == True)
assert(anagram_check_hashmap(["b", "a", "a"], ["a", "b", "a"]) == True)
assert(anagram_check_hashmap(["a", "b", "a"], ["a", "b", "a", "c"]) == False)


import streamlit as st
from langchain import LLMChain
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (ChatPromptTemplate,
                                    HumanMessagePromptTemplate,
                                    SystemMessagePromptTemplate)
from langchain.document_loaders import *
from langchain.chains.summarize import load_summarize_chain
import tempfile
from langchain.docstore.document import Document
import csv
from io import StringIO
import pandas as pd
import openai
import os
import random

openai.api_key = st.secrets["OPENAI_API_KEY"]

st.sidebar.title('Flash cards')

style = """

"""

JOB_DESCRIPTIONS = {
    'Life coach': 'dÃ©velopper ses compÃ©tences de coach professionnel dans la vie de tous les jours',
    'Business coach': 'dÃ©velopper ses compÃ©tences de coach pour faire croÃ®tre son entreprise'
}

st.markdown(style, unsafe_allow_html=True)

def get_taxonomy_instruction(rua):
    if rua == "Remember":
        return random.choice(["Formattez la question sous forme de choix multiples avec une liste Ã  puces, pour tester la mÃ©moire directe de l'Ã©tudiant.",
                "CrÃ©ez une question Vrai ou Faux pour tester la capacitÃ© de l'Ã©tudiant Ã  identifier des informations exactes.",
                "CrÃ©ez une question Ã  trou, oÃ¹ l'Ã©tudiant doit remplir le blanc avec le terme ou le concept appropriÃ©, centrÃ©e sur un concept clÃ©."])
    elif rua == "Understand":
        return random.choice([
            "CrÃ©ez une question qui guide l'Ã©tudiant Ã  interprÃ©ter des informations ou des idÃ©es, dÃ©montrant leur comprÃ©hension.",
            "RÃ©digez une question qui guide l'Ã©tudiant Ã  rÃ©sumer des informations ou des idÃ©es principales.",
            "Ã‰laborez une question qui amÃ¨ne l'Ã©tudiant Ã  infÃ©rer ou faire des dÃ©ductions, basÃ©es sur des informations donnÃ©es.",
            "Concevez une question qui requiert que l'Ã©tudiant explique des concepts, des idÃ©es, des procÃ©dures, ou des phÃ©nomÃ¨nes."
        ])
    elif rua == "Apply":
        return random.choice([
            "Formulez une question qui demande Ã  l'Ã©tudiant d'exÃ©cuter une procÃ©dure ou une mÃ©thode dans une situation donnÃ©e.",
            "Concevez une question qui guide l'Ã©tudiant Ã  mettre en Å“uvre ou appliquer des concepts ou des idÃ©es Ã  une nouvelle situation.",
            "CrÃ©ez une question qui encourage l'Ã©tudiant Ã  rÃ©soudre un problÃ¨me, en appliquant des connaissances et des compÃ©tences acquises.",
            "Ã‰laborez une question qui amÃ¨ne l'Ã©tudiant Ã  dÃ©montrer comment appliquer un concept ou une thÃ©orie dans un contexte pratique.",
            "RÃ©digez une question qui incite l'Ã©tudiant Ã  utiliser des informations pour accomplir une tÃ¢che ou rÃ©soudre un problÃ¨me concret.",
            "Formulez une question qui demande Ã  l'Ã©tudiant de montrer comment un concept ou une idÃ©e peut Ãªtre utilisÃ© dans un contexte rÃ©el."
        ])
    else:
        return ""

def questionGenerator(prompt, job, difficulty, personal=None):
    chat = ChatOpenAI(
        model="gpt-4",
        temperature=0.5
    )
    taxonomy_instruction = get_taxonomy_instruction(rua)
    if personal:
        system_template = f"""
        Vous Ãªtes un expert en coaching et en enseignement du dÃ©veloppement personnel.
        Votre tÃ¢che consiste Ã  crÃ©er une question courte et concise basÃ©e sur le document : "{prompt}"
        pour un Ã©tudiant visant Ã  {job_description}.
        La situation personnelle de l'Ã©tudiant est la suivante : '{personal}'.
        Ne formulez pas de questions complexes, composÃ©es, ni au mode subjonctif. Formatez la question en Markdown, en plusieurs lignes si nÃ©cessaire, et sans gras.
        {taxonomy_instruction}.
        DifficultÃ©: {difficulty}.
        """
    else:
        system_template = f"""
        Vous Ãªtes un expert en coaching et en enseignement du dÃ©veloppement personnel.
        Votre tÃ¢che consiste Ã  crÃ©er une question courte et concise basÃ©e sur le document : "{prompt}"
        pour un Ã©tudiant visant Ã  {job_description}.
        Ne formulez pas de questions complexes, composÃ©es, ni au mode subjonctif. Formatez la question en Markdown, en plusieurs lignes si nÃ©cessaire, et sans gras.
        {taxonomy_instruction}.
        DifficultÃ©: {difficulty}.
        """
    system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)
    human_template = """BasÃ© sur le document: '{prompt}', formulez une question pertinente, courte et concise."""
    human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
    chat_prompt = ChatPromptTemplate.from_messages(
        [system_message_prompt, human_message_prompt]
    )
    chain = LLMChain(llm=chat, prompt=chat_prompt)
    result = chain.run(prompt=prompt)
    return result

def bulletPointAnswer(front, prompt):
    chat = ChatOpenAI(
        model="gpt-4",
        temperature=0.5
    )
    system_template = """
    Vous Ãªtes un expert en coaching et en dÃ©veloppement personnel.
    Votre tÃ¢che consiste Ã  rÃ©pondre Ã  une question de maniÃ¨re claire et concise, en vous basant sur '{prompt}'.
    - Si la question est de type 'choix multiples', 'vrai ou faux' ou 'remplissez les blancs', identifiez et prÃ©sentez clairement la rÃ©ponse correcte.
    - Si la question est un texte Ã  trous, identifiez et prÃ©sentez clairement le mot manquant.
    - Vous pouvez formater votre rÃ©ponse en trois points clefs, chacun ne dÃ©passant pas 30 mots.
    - Commencez votre rÃ©ponse par une synthÃ¨se en gras, en moins de 25 mots.
    - Vos rÃ©ponses doivent Ãªtre formulÃ©es comme des vÃ©ritÃ©s gÃ©nÃ©rales et doivent strictement rÃ©pondre Ã  la question posÃ©e. Ã‰vitez tout contenu superflu ou hors sujet.

    """

    system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)

    human_template = """
    La question est: '{front}'. Veuillez fournir une rÃ©ponse basÃ©e sur '{prompt}', en suivant strictement le format et les directives fournies.
    """
    human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
    chat_prompt = ChatPromptTemplate.from_messages(
        [system_message_prompt, human_message_prompt]
    )
    chain = LLMChain(llm=chat, prompt=chat_prompt)
    result = chain.run(front=front, prompt=prompt)
    return result

def getFeedback(front, user_input, back):
    chat = ChatOpenAI(
        model="gpt-4",
        temperature=0.2
    )
    system_template = """Vous Ãªtes un expert en coaching et en enseignement du dÃ©veloppement personnel, et devez adresser un feedback concis Ã  l'Ã©tudiant qui a rÃ©pondu Ã  la question: '{front}'
    La rÃ©ponse attendue est : '{back}'.
    - Si la rÃ©ponse fournie par l'Ã©tudiant est correcte, rÃ©pondez 'Bravo! RÃ©ponse correcte.' et ignorez les Ã©tapes suivantes.
    - Si la rÃ©ponse fournie par l'Ã©tudiant est partiellement correcte, identifiez les Ã©lÃ©ments manquants ou hors-sujet dans la rÃ©ponse.
    Structurez la rÃ©ponse avec des points-clefs si nÃ©cessaire.
    La rÃ©ponse ne doit pas dÃ©passer 75 mots.
    Restez toujours dans une dÃ©marche bienveillante et pÃ©dagogue.
    """
    system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)
    human_template = """Donnez un feedback Ã  l'Ã©tudiant qui a rÃ©pondu '{user_input}'."""
    human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
    chat_prompt = ChatPromptTemplate.from_messages(
        [system_message_prompt, human_message_prompt]
    )
    chain = LLMChain(llm=chat, prompt=chat_prompt)
    result = chain.run(front=front, user_input=user_input, back=back)
    return result

def getExample(front, prompt, example_situation, back):
    chat = ChatOpenAI(
        model="gpt-4",
        temperature=0.2
    )
    system_template = """Vous Ãªtes un expert en coaching et en enseignement du dÃ©veloppement personnel, et devez illustrer d'un exemple la rÃ©ponse '{back}' Ã  la question: '{front}'.
    Vous devez vous servir de '{prompt}'. CrÃ©ez un scÃ©nario fictif. La rÃ©ponse ne doit pas dÃ©passer 90 mots. Vous pouvez la formuler en liste Ã  puces.
    Restez toujours dans une dÃ©marche bienveillante et pÃ©dagogue.
    """
    system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)
    human_template = """Illustrer la rÃ©ponse '{back}' Ã  la question {front}. Personnalisez la rÃ©ponse Ã  l'Ã©tudiant: '{example_situation}'"""
    human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)
    chat_prompt = ChatPromptTemplate.from_messages(
        [system_message_prompt, human_message_prompt]
    )
    chain = LLMChain(llm=chat, prompt=chat_prompt)
    result = chain.run(front=front, prompt=prompt, example_situation=example_situation, back=back)
    return result

def display_front(front):
    """"Displays the question, and an input box to gather user_input"""
    st.markdown(f"
{front}
", unsafe_allow_html=True)
    st.session_state.user_input = st.text_input("Your Answer:")

def display_back(front_content, back_content, user_input):
    """Displays the question, the Answer, the user_input, and the Je le savais dÃ©jÃ /Je ne le savais pas buttons"""
    st.markdown(f"
Question:\n\n{front_content}
", unsafe_allow_html=True)
    if back_content:
        st.markdown(f"
Answer:\n\n{back_content}
", unsafe_allow_html=True)
    st.markdown(f"
Your Answer:\n\n{user_input}
", unsafe_allow_html=True)
    feedback_placeholder = st.empty()
    example_placeholder = st.empty()
    with st.container():
        col1, col2, col3, col4, col5 = st.columns(5)
        with col1:
            if st.button('Voir la question'):
                st.session_state.side = 'front'
        with col2:
            st.button("â›” Difficile â›”")
        with col3:
            st.button("ðŸŸ  Moyen ðŸŸ ")
        with col4:
            st.button("âœ… Facile âœ…")
        with col5:
            if st.button("Obtenir du feedback"):
                feedback = getFeedback(st.session_state.front_content, st.session_state.user_input, st.session_state.back_content)
                feedback_placeholder.markdown(f"
{feedback}
", unsafe_allow_html=True)
    with st.container():
        colA, colB = st.columns(2)
        with colA:
            example_situation = st.text_input("Illustrez l'exemple")
        with colB:
            if st.button("Obtenir un exemple"):
                example = getExample(st.session_state.front_content, prompt, example_situation, st.session_state.back_content)
                example_placeholder.markdown(f"
{example}
", unsafe_allow_html=True)

def load_flashcards_from_csv(uploaded_file):
    """Upload a CSV of flashcards into the session_state"""
    flashcards = []
    decoded_file = uploaded_file.read().decode('utf-8')
    file_as_string = StringIO(decoded_file)
    reader = csv.reader(file_as_string, delimiter=',')
    next(reader)
    next(reader)
    for row in reader:
        params, front, back  = row
        job, difficulty = params.split('_')
        flashcards.append({
            'front': front,
            'back': back,
            'job': job,
            'difficulty': difficulty,
            'taxonomy': rua
        })
    return flashcards

def export_flashcards_to_csv(flashcards, title="Flashcards"):
    output = StringIO()
    writer = csv.writer(output)
    writer.writerow([title, "", ""])  # CSV title row
    writer.writerow(["Params", "Question", "Answer"])  # header
    for card in flashcards:
        params = f"{card['job']}_{card['difficulty']}_{card['taxonomy']}"
        writer.writerow([params, card['front'], card['back']])

    # Get the content of the output and return it
    content = output.getvalue()
    output.close()
    return content

# Initialize session_states
if 'user_input' not in st.session_state:
    st.session_state.user_input = ""

if 'flashcards' not in st.session_state:
    st.session_state.flashcards = []

if 'side' not in st.session_state:
    st.session_state.side = 'front'

if 'txt_content' not in st.session_state:
    st.session_state.txt_content = None

if 'front_content' not in st.session_state:
    st.session_state.front_content = None

if 'back_content' not in st.session_state:
    st.session_state.back_content = None

if 'current_flashcard_index' not in st.session_state:
    st.session_state.current_flashcard_index = 0

# ------------ Settings ------------
st.sidebar.header("Commencez ici ðŸ‘‡")

if 'txt_content' not in st.session_state:
    prompt = st.sidebar.text_input('Entrez un prompt (ou chargez un fichier .txt ci-dessous)')
else:
    prompt = st.session_state.txt_content

# File
#uploaded_file = st.sidebar.file_uploader('Upload a .txt file', type=["txt"])
#if uploaded_file:
#    txt_content = uploaded_file.read().decode("utf-8")
#    st.session_state.txt_content = txt_content
#    prompt = txt_content

template_dir = 'Fiches pÃ©dagogiques'
try:
    file_names = sorted([file[:-4] for file in os.listdir(template_dir) if file.endswith('.txt')])
except FileNotFoundError:
    st.sidebar.write(f"Folder {template_dir} not found.")
    file_names = []
file_names.insert(0, "Chargez votre fichier")
selected_file = st.sidebar.selectbox('Choisissez un fichier modÃ¨le ou chargez le vÃ´tre', file_names)
if selected_file == "Chargez votre fichier":
    uploaded_file = st.sidebar.file_uploader('Chargez votre fichier .txt', type=["txt"])
    if uploaded_file:
        txt_content = uploaded_file.read().decode("utf-8")
        st.session_state.txt_content = txt_content
        prompt = txt_content
else:
    try:
        with open(os.path.join(template_dir, selected_file + '.txt'), 'r', encoding='utf-8') as file:
            txt_content = file.read()
            st.session_state.txt_content = txt_content
            prompt = txt_content
    except FileNotFoundError:
        st.sidebar.write(f"Fichier {selected_file}.txt non trouvÃ© dans {template_dir}.")

# Params
personal = None

job = st.sidebar.selectbox('Choississez votre voie', ['Life coach', 'Business coach'])
job_description = JOB_DESCRIPTIONS.get(job, job)
difficulty = st.sidebar.selectbox('Choississez la difficultÃ©', ['DÃ©butant', 'AvancÃ©'])
rua = st.sidebar.selectbox('Choississez le type de carte', ['Remember','Understand','Apply'],index=1)
st.sidebar.header("Optionnel (WIP)")
personal = st.sidebar.text_input("Qu'est ce qui vous motive Ã  devenir coach?")
go_button = st.sidebar.button("Let's go!")
if go_button:
    with st.spinner('GÃ©nÃ©ration en cours...'):
        if prompt:
            st.session_state.front_content = questionGenerator(prompt, job, difficulty, personal)
            st.session_state.back_content = bulletPointAnswer(st.session_state.front_content, prompt)
            st.session_state.flashcards.append({
                'front': st.session_state.front_content,
                'back': st.session_state.back_content,
                'job': job,
                'difficulty': difficulty,
                'taxonomy': rua
            })
            st.session_state.side = 'front'
            st.session_state.current_flashcard_index = len(st.session_state.flashcards) - 1

# Display the front and back content of the flashcard
if st.session_state.get('front_content') and st.session_state.side == 'front':
    display_front(st.session_state.front_content)
    col_flip1, col_flip2 = st.columns(2)
    with col_flip1:
        if st.button('Voir la rÃ©ponse'):
            st.session_state.side = 'back'
elif st.session_state.get('front_content') and st.session_state.side == 'back':
    display_back(st.session_state.front_content, st.session_state.back_content, st.session_state.user_input)
else:
    if not go_button:
        st.write('Veuillez indiquer vos paramÃ¨tres et cliquer "Let\'s go!".')

# Select a flashcard from the list
flashcard_options = [f"Flashcard {i+1} ({card['job']}_{card['difficulty']}_{card['taxonomy']})" for i, card in enumerate(st.session_state.flashcards)]
if not flashcard_options:
    st.sidebar.write("Lorsque vous aurez gÃ©nÃ©rÃ© des cartes, elles apparaÃ®tront ici.")
if flashcard_options:
    selected_flashcard = st.sidebar.selectbox("Choose a flashcard:", flashcard_options, index=st.session_state.current_flashcard_index or 0)
    if selected_flashcard and st.session_state.current_flashcard_index != flashcard_options.index(selected_flashcard):
        st.session_state.current_flashcard_index = flashcard_options.index(selected_flashcard)
        st.session_state.front_content = st.session_state.flashcards[st.session_state.current_flashcard_index]['front']
        st.session_state.back_content = st.session_state.flashcards[st.session_state.current_flashcard_index]['back']
        st.session_state.side = 'front'

else:
    selected_flashcard = None

# ------------ Export ------------
if flashcard_options:
    if st.sidebar.download_button(
            label="TÃ©lecharger les Flashcards",
            data=export_flashcards_to_csv(st.session_state.flashcards, title='Flashcards'),
            file_name='flashcards.csv',
            mime='text/csv'
        ):
        st.sidebar.write(f'Flashcards tÃ©lÃ©chargÃ©es: flashcards.csv!')


def caeser_cipher(txt):
    txt2 = ''
    alphabet = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','a','b','c']
    alphaM = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C']
    for i in range(0, len(txt), 1):
        for j in range(0, len(alphabet)-3,1):
            if(txt[i] == alphabet[j]):
                txt2 += alphabet[j+3]
            elif(txt[i] == alphaM[j]):
                txt2 += alphaM[j+3]
    return txt2

def deco_caeser_cipher(txt):
    txt2 = ''
    alphabet = ['x','y','z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    alphaM = ['X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
    for i in range(0, len(txt), 1):
        for j in range(0, len(alphabet)-3,1):
            if(txt[i] == alphabet[j]):
                txt2 += alphabet[j-3]
            elif(txt[i] == alphaM[j]):
                txt2 += alphaM[j-3]
    return txt2

x = int(input('Se você deseja encriptar a mensagem digite 1, se deseja descriptar digite 0: '))
t = str(input('Digite o texto: '))
if(x == 1):
    print(caeser_cipher(t))
elif(x == 0):
    print(deco_caeser_cipher(t))
else:
    print('Digite 1 ou 0')


import rpyc

proxy = rpyc.connect('localhost', 18861, config={'allow_public_attrs': True})

op = input(' 1 - Cadastrar usuário\n 2 - Listar Quantidade\n 3 - Listar códigos cadastrados \n 4 - Listar Codigos da sala\n\n')
list_cod = []
while(op!= '5'):
    if (op == '1'):
        cod = input("Digite o código\n")
        list_cod = (str(proxy.root.listar_usuarios()))
        if cod in list_cod:
            print('Código já está Cadastrado\n')
        else:
            proxy.root.cadastrar_cod(str(cod))
            print("Código Cadastrado\n")
    if (op == '2'):
        print(proxy.root.listar_quantidade())
    if (op == '3'):
        print(proxy.root.listar_usuarios())
    if (op == '4'):
        print(proxy.root.listar_cod_sala())
    op = input(' 1 - Cadastrar usuário\n 2 - Listar Quantidade\n 3 - Listar códigos cadastrados \n 4 - Listar Codigos da sala\n\n')


def printGrid(grid):
	printOut = ""
	for row in grid:
		for num in row:
			if num == "":
				printOut += "_ "
			else:
				printOut += str(num) + " "
		printOut += "\n"
	print(printOut)

def is_legal(curr_pos, new_pos, grid, grid_size):
	# out of bounds
	if new_pos[0] not in range(0, grid_size):
		return False
	if new_pos[1] not in range(0, grid_size):
		return False
	# wrong direction
	if new_pos[0] < curr_pos[0]:
		return False
	if new_pos[1] < curr_pos[1]:
		return False
	# illegal path
	illegal_move = grid[curr_pos[1]][curr_pos[0]]
	if move_south(curr_pos,"")[0] == new_pos:
		if illegal_move == "S":
			return False
	if move_east(curr_pos,"")[0] == new_pos:
		if illegal_move == "E":
			return False
	return True

def move_south(curr_pos, my_path):
	new_pos = [curr_pos[0], curr_pos[1]+1]
	new_path = my_path + "S"
	return [new_pos, new_path]

def move_east(curr_pos, my_path):
	new_pos = [curr_pos[0]+1, curr_pos[1]]
	new_path = my_path + "E"
	return [new_pos, new_path]

def reached_finish(pos, grid_size):
	if pos == [grid_size-1, grid_size-1]:
		return True
	return False

def create_grid(path, grid_size):
	grid = [[""] * grid_size for i in range(grid_size)]
	x = 0
	y = 0
	for move in path:
		if move == "S":
			grid[y][x] = "S"
			y += 1
		elif move == "E":
			grid[y][x] = "E"
			x += 1
		else:
			print("SOMETHING WENT WRONG")
			return
	return grid

cases = int(input())
for case in range(1, cases + 1):
    grid_size = int(input())
    illegal_path = str(input())
    grid = create_grid(illegal_path, grid_size)
    my_path = ""
    my_curr_pos = [0,0]

    while not reached_finish(my_curr_pos, grid_size):
        if is_legal(my_curr_pos, move_south(my_curr_pos, my_path)[0], grid, grid_size):
            my_curr_pos, my_path = move_south(my_curr_pos, my_path)
        if is_legal(my_curr_pos, move_east(my_curr_pos, my_path)[0], grid, grid_size):
            my_curr_pos, my_path = move_east(my_curr_pos, my_path)

    print("Case #{}: {}".format(case, my_path))


from typing import TypeVar, List, Callable, Type

import msgspec
from memproxy import ItemCodec, Item, new_multi_get_filler

from init_cache import get_pipeline, add_item_stats

T = TypeVar('T')
K = TypeVar('K')

def new_codec(cls: Type[T]) -> ItemCodec[T]:
    encoder = msgspec.msgpack.Encoder()
    decoder = msgspec.msgpack.Decoder(cls)
    return ItemCodec(
        encode=encoder.encode,
        decode=decoder.decode,
    )

def new_cache_item(
        cls: Type[T],
        fill_func: Callable[[List[K]], List[T]],
        get_key: Callable[[T], K],
        default: Callable[[], T],
        key_name: Callable[[K], str],
) -> Callable[[], Item[T, K]]:
    codec = new_codec(cls)

    def new_func() -> Item[T, K]:
        filler = new_multi_get_filler(
            fill_func=fill_func, get_key_func=get_key,
            default=default(),
        )
        it = Item(
            pipe=get_pipeline(),
            key_fn=key_name,
            filler=filler,
            codec=codec
        )
        add_item_stats(cls.__name__, it)
        return it

    return new_func


# Use frequency analysis to find the key to ciphertext.txt, and then
# decode it.
import string
letters = string.ascii_uppercase

f = open('ciphertext.txt', 'r')
text = f.read()
f.close()

def crack_it(text):
	counts = {}
	frequency = ["E", "T", "A", "O", "H", "N", "R", "I", "S", "D", "L", "W", "U", "G", "F", "B", "M", "Y", "C", "P", "K", "V", "Q", "J", "X", "Z"]

	for char in text.upper():
		if char in letters:
			if counts.get(char):
				counts[char] += 1
			else:
				counts[char] = 1

	counts_list = list(counts.items())
	counts_list = sorted(counts_list, key=lambda a : a[1], reverse=True)
	text_frequency = [a[0] for a in counts_list]

	cypher = {}

	for i, char in enumerate(text_frequency):
		if char in letters:
			cypher[char] = frequency[i]

	decoded = []

	for char in text.upper():
		if char in letters:
			decoded.append(cypher[char])
		else:
			decoded.append(char)

	return "".join(decoded)

print(crack_it(text))


# – Species should be one of the following values: setosa, versicolor or virginica.
import numpy as np
def checkSpecies(data):
  arr1=np.array(data['Species'].value_counts().index)
  count=0
  for i in arr1:
    if i not in ['setosa','versicolor','virginica']:
       count+=1
  return count,'ruleset 1'

# – All measured numerical properties of an iris should be positive.
def check_num(data):
    count=0
    for i in data.columns:
        if data[i].dtypes == "float64":
            if data[data[i]<0].shape[0]>0:
                count=count+1
    return count, "ruleset 2"
# – The petal length of an iris is at least 2 times its petal width.
def checkPetalLength(data):
    count=0
    for i in range(len(data)):
     if(data.loc[i]['Petal.Length']< 2*(data.loc[i]['Petal.Width'])):
      count+=1
    return count,'ruleset 3'

# – The sepal length of an iris cannot exceed 30 cm.
def checkSepalLength(data):
 count=(data['Sepal.Length']>30).sum()
 return count,'ruleset 4'

# – The sepals of an iris are longer than its petals.
def checkSepals(data):
    count=((data['Sepal.Length']+data['Sepal.Width'])<(data['Petal.Length']+data['Petal.Width'])).sum()
    return count,'ruleset 5'


import telegram
from telegram.ext import Updater

# Create a bot object using your bot token
bot = telegram.Bot(token='YOUR_BOT_TOKEN')

# Create an updater object to handle updates from the bot
updater = Updater(token='YOUR_BOT_TOKEN')

# Define a function to restrict a user's actions in the channel
def prevent_reports(update, context):
    # Get the chat ID and user ID from the update object
    chat_id = update.message.chat_id
    user_id = update.message.from_user.id

    # Use the restrictChatMember method to prevent the user from reporting messages
    bot.restrict_chat_member(chat_id=chat_id, user_id=user_id, can_report_messages=False)

# Register the prevent_reports function with the updater object
updater.dispatcher.add_handler(telegram.ext.MessageHandler(telegram.ext.Filters.all, prevent_reports))

# Start the bot
updater.start_polling()

FREE


"""
Docstring:
In order to use this function, n always has to have positive values, otherwise you get an infinite recursion.
"""

def recurse(n,s):
    if n == 0:
        print(s)
    else:
        recurse(n-1, n+s)


# this sql program helps me get accustomed to how sql datatypes work

# importing sqlite3 to use it
import sqlite3

# creating the sqlite3 connection and cursor
con = sqlite3.connect('data.db')

# creating an exam hall table
con.execute('''CREATE TABLE exhall(NAME TEXT, PIN INTEGER, OCCUPANCY REAL);''')

# inserting data (tuples) into TABLE
con.execute('''INSERT INTO exhall VALUES('hall_a', 8967, 94.2)''')
con.execute('''INSERT INTO exhall VALUES(NULL, 12134, 1.10)''')

# reads out both of the rows that were previously created, as well as their types of data
cur = con.execute('''SELECT * FROM exhall;''')
for i in cur:
    print(str(i[0])+" "+str(i[1])+" "+str(i[2]))
    print(str(type(i[0]))+" "+str(type(i[1]))+" " + str(type(i[2])))


from django.conf.urls import url
from django.urls import include
from rest_framework.routers import SimpleRouter
from rest_framework_nested import routers

from members.views import UserModelViewSet, ProfileModelViewSet
from posts.views import PostModelViewSet, CommentModelViewSet, PostLikeModelViewSet, CommentLikeModelViewSet

router = SimpleRouter(trailing_slash=False)
router.register(r'users', UserModelViewSet)
router.register(r'posts', PostModelViewSet)

users_router = routers.NestedSimpleRouter(router, r'users')
post_like_router = routers.NestedSimpleRouter(router, r'posts')
post_like_router.register('like', PostLikeModelViewSet)
post_like_router.register('comments', CommentModelViewSet)

comment_like_router = routers.NestedSimpleRouter(post_like_router, r'comments')
comment_like_router.register('like', CommentLikeModelViewSet)

users_router.register(r'posts', PostModelViewSet)
users_router.register(r'profile', ProfileModelViewSet)

posts_router = routers.NestedSimpleRouter(users_router, 'posts')
posts_router.register('comments', CommentModelViewSet)

urlpatterns = [
    url('', include(router.urls)),
    url('', include(users_router.urls)),
    url('', include(post_like_router.urls)),
    url(r'', include(posts_router.urls)),
    url(r'', include(comment_like_router.urls)),
]


class_count = int(input())
score_list = [[0] for _ in range(class_count)]
student_num_list = [0 for _ in range(class_count)]
class_avg = [0 for _ in range(class_count)]

def get_all_avg():

    for i in range(len(score_list)):
        class_avg[i] = sum(score_list[i]) / student_num_list[i]

    return

def compare():
    bad_student = 0

    for i in range(len(score_list)):
        for j in range(len(score_list[i])):
            if(class_avg[i] < score_list[i][j]):
                bad_student += 1
        rate = (bad_student / student_num_list[i]) * 100
        print("{:.3f}%".format(rate))
        bad_student = 0

    return

for i in range(class_count):
    student_num_list[i], *score_list[i] = list(map(int, input().split()))

get_all_avg()
compare()


import math
import cmath

a90 = math.pi/2
def walk(instructions):
    angle = a90
    pos = complex(0, 0)
    visitedPositions = []
    firstVisitedTwice = None
    for instruction in instructions.split(', '):
        turn = instruction[0]
        if turn == 'L':
            angle += a90
        elif turn == 'R':
            angle -= a90
        length = int(instruction[1:])
        delta = cmath.rect(1, angle)
        for i in range(0, length):
            pos += delta
            if pos in visitedPositions:
                firstVisitedTwice = pos
                break
            visitedPositions.append(pos)
        if firstVisitedTwice:
            break

    blocksAway = abs(pos.real) + abs(pos.imag)
    print('Blocks away: ' + str(blocksAway) + ' ' + str(pos))

walk('R8, R4, R4, R8')
walk('R3, L2, L2, R4, L1, R2, R3, R4, L2, R4, L2, L5, L1, R5, R2, R2, L1, R4, R1, L5, L3, R4, R3, R1, L1, L5, L4, L2, R5, L3, L4, R3, R1, L3, R1, L3, R3, L4, R2, R5, L190, R2, L3, R47, R4, L3, R78, L1, R3, R190, R4, L3, R4, R2, R5, R3, R4, R3, L1, L4, R3, L4, R1, L4, L5, R3, L3, L4, R1, R2, L4, L3, R3, R3, L2, L5, R1, L4, L1, R5, L5, R1, R5, L4, R2, L2, R1, L5, L4, R4, R4, R3, R2, R3, L1, R4, R5, L2, L5, L4, L1, R4, L4, R4, L4, R1, R5, L1, R1, L5, R5, R1, R1, L3, L1, R4, L1, L4, L4, L3, R1, R4, R1, R1, R2, L5, L2, R4, L1, R3, L5, L2, R5, L4, R5, L5, R3, R4, L3, L3, L2, R2, L5, L5, R3, R4, R3, R4, R3, R1')


import typing
import os

def returnEvenLinesOfStream(text:typing.TextIO) -> typing.List[str]:
    lineCollection = []
    oddLine = True
    for line in text:
        if not oddLine:
            lineCollection.append(line.strip())
        oddLine = not oddLine
    #lineCollection.append(42)
    return lineCollection

def rejoinLines(lineCollection:typing.List[str]) -> str:
    #lineCollection = [str(item) for item in lineCollection]
    rejoined = "\n".join(lineCollection)
    return rejoined

def getFileStream(path:str) -> typing.TextIO:
    if not os.path.isfile(path):
        raise FileNotFoundError("Unable to find file at %s" %path)
    return open(path, 'r')

if __name__ == "__main__":
    fileName = "rosalind_ini5 (1).txt"
    stream = getFileStream(fileName)
    evenLines = returnEvenLinesOfStream(stream)
    stream.close()
    rejoined = rejoinLines(evenLines)
    print(rejoined)


import logging
from stockmarket.models import StockNameCodeMap

from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render
from django.utils.translation import ugettext_lazy as _
from django.views.generic import TemplateView

from investors.models import StockFollowing, TradeStrategy
from stockmarket.utils import get_stocknames

class KanpanView(LoginRequiredMixin, TemplateView):
    # template_name属性用于指定使用哪个模板进行渲染
    template_name = 'investors/kanpan.html'
    # context_object_name属性用于给上下文变量取名（在模板中使用该名字）
    context_object_name = 'kanpan'

    def get(self, request, *args, **kwargs):
        req_user = request.user
        if req_user is not None:
            stocks_following = StockFollowing.objects.filter(
                trader=req_user.id,)
            queryset = {
                'followings': stocks_following,
            }
            return render(request, self.template_name, {self.context_object_name: queryset})

class LinechartView(LoginRequiredMixin, TemplateView):
    # template_name属性用于指定使用哪个模板进行渲染
    template_name = 'investors/linechart.html'
    # context_object_name属性用于给上下文变量取名（在模板中使用该名字）
    context_object_name = 'linechart'

    def get(self, request, *args, **kwargs):
        req_user = request.user
        if req_user is not None:
            return render(request, self.template_name)

# Create your views here.
@login_required
def follow_stock(request, symbol):
    if request.method == 'POST':
        # data = request.POST.copy()
        name = get_stocknames([symbol])[symbol]  # data.get('name')
        investor = request.user
        try:
            stk_basic = StockNameCodeMap.objects.get(ts_code=symbol)
            new_follow = StockFollowing(trader=investor, stock_code=symbol.split('.')[0], stock_name=name, industry=stk_basic.industry,
                                        area=stk_basic.area, fullname=stk_basic.fullname, ts_code=stk_basic.ts_code)
            new_follow.save()
            return JsonResponse({'code': 'aok', 'message': _('添加成功')}, safe=False)
        except Exception as err:
            return JsonResponse({'code': 'error', 'message': _('添加失败')}, safe=False)

@login_required
def unfollow_stock(request, symbol):
    if request.method == 'DELETE':
        investor = request.user
        following = StockFollowing.objects.filter(
            trader=investor, ts_code=symbol)
        following.delete()
        return JsonResponse({'code': 'dok', 'message': _('删除成功')}, safe=False)
    return JsonResponse({'code': 'error', 'message': _('删除失败')}, safe=False)

@login_required
def stocks_following(request):
    if request.method == 'GET':
        try:
            stock_list = []
            investor = request.user
            following = StockFollowing.objects.filter(trader=investor)
            if following is not None and len(following) > 0:
                for stock in following:
                    stock_list.append(stock.stock_code)
                return JsonResponse({'results': stock_list}, safe=False)
            else:
                return HttpResponse(status=404)
        except Exception as e:
            print(e)
            return HttpResponse(status=500)

@login_required
def get_trade_account(request):
    if request.method == 'GET':
        try:
            stock_list = []
            investor = request.user
            following = StockFollowing.objects.filter(trader=investor)
            if following is not None and len(following) > 0:
                for stock in following:
                    stock_list.append(stock.stock_code)
                return JsonResponse({'results': stock_list}, safe=False)
            else:
                return HttpResponse(status=404)
        except Exception as e:
            print(e)
            return HttpResponse(status=500)


import random
from model.group import Group

def test_quick_delete_group(app, db):
    if app.group.count() == 0:
        app.group.create(Group(name="del_name"))

    old_groups = db.get_group_list()
    group = random.choice(old_groups)
    app.group.delete_group_by_id(group.id)
    new_groups = db.get_group_list()
    old_groups.remove(group)
    assert old_groups == new_groups


import cv2
import numpy as np

class Matcher:
    def __init__(self):
        self.surf = cv2.xfeatures2d.SURF_create()
        index_params = dict(algorithm=0, trees=5)
        search_params = dict(checks=50)
        self.flann = cv2.FlannBasedMatcher(index_params, search_params)

    def match(self, i1, i2):
        image_set_1 = self.get_SURF_features(i1)
        image_set_2 = self.get_SURF_features(i2)
        matches = self.flann.knnMatch(image_set_2["des"], image_set_1["des"], k=2)
        good = []
        for i, (m, n) in enumerate(matches):
            if m.distance < 0.7 * n.distance:
                good.append((m.trainIdx, m.queryIdx))

        if len(good) > 4:
            points_current = image_set_2["kp"]
            points_previous = image_set_1["kp"]

            matched_points_current = np.float32(
                [points_current[i].pt for (__, i) in good]
            )
            matched_points_prev = np.float32(
                [points_previous[i].pt for (i, __) in good]
            )

            H, _ = cv2.findHomography(
                matched_points_current, matched_points_prev, cv2.RANSAC, 4
            )
            return H
        return None

    def get_SURF_features(self, im):
        gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
        kp, des = self.surf.detectAndCompute(gray, None)
        return {"kp": kp, "des": des}


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Definition for stringly-linked list.
class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):

    """
    Given two non-empty linked lists representing two non-negative integers.
    The digits are stored in reverse order and each of their nodes contain
    a single digit. Add the two numbers and return it as a linked list.
    """

    def addTwoNumbers(self, l1, l2):
        """

        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode

        """
        ret = None
        retHead = ret
        addOn = 0
        while l1 is not None:
            v1 = l1.val
            if l2 is None:
                v2 = 0
            else:
                v2 = l2.val
            output = (v1 + v2 + addOn) % 10
            addOn = (v1 + v2 + addOn) / 10

            if retHead is None:
                retHead = ListNode(output)
                ret = retHead
            else:
                ret.next = ListNode(output)
                ret = ret.next
            l1 = l1.next
            if l2 is not None:
                l2 = l2.next
        while l2 is not None:
            v1 = 0
            v2 = l2.val
            output = (v1 + v2 + addOn) % 10
            addOn = (v1 + v2 + addOn) / 10

            ret.next = ListNode(output)
            ret = ret.next
            l2 = l2.next
        if addOn == 1:
            ret.next = ListNode(1)
        return retHead


boolean = 1
for i in range(0, 5):
    print("Informe o peso da","{}ª pessoa: ".format(i+1), end ='')
    x = float(input())
    if(boolean):
        maior = x
        menor = x
        boolean = 0
    else:
        if(x > maior):
            maior = x
        if(x < menor):
            menor = x
print('A pessoa mais pesada tem ',maior,'kg\n','A pessoa mais leve tem',menor,'kg')


from nonebot import on_command, on_regex
from nonebot.params import CommandArg
from nonebot.adapters import Event
from nonebot.adapters.onebot.v11 import Message, MessageSegment
from nonebot.exception import FinishedException

from src.libraries.image import *
from src.libraries.chuni_music import *
from src.libraries.tool import hash
from src.libraries.image import *

import re

chuni_music_jp = get_chuni_json()

chuni_b40 = on_command('cb30', priority=10, block=True)
@chuni_b40.handle()
async def _(event: Event, message: Message = CommandArg()):
    username = str(message).strip()
    if username == "":
        payload = {'qq': str(event.get_user_id())}
    else:
        payload = {'username': username}
    img, success = await generate_chuni40(payload)
    if success == 400:
        await chuni_b40.finish("未找到此玩家，请确登陆https://www.diving-fish.com/maimaidx/prober/录入分数，并正确填写用户名与QQ号。")
    elif success == 403:
        await chuni_b40.finish("该用户禁止了其他人获取数据。")
    else:
        await chuni_b40.finish(MessageSegment.image(f"base64://{str(image_to_base64(img), encoding='utf-8')}"))

cover_dir = 'src/static/chunithm/cover/'

def song_txt(music: Music):
    return MessageSegment.text(f"{music.id}. {music.title}\n") + \
        MessageSegment.image(f"base64://{str(image_to_base64(get_chuni_cover(music.id)), encoding='utf-8')}") + \
        MessageSegment.text(f"\n定数:{'/'.join(str(ds) for ds in music['ds'])}\n") + \
        MessageSegment.text(f"艺术家: {music['basic_info']['artist']}\n") + \
        MessageSegment.text(f"分类: {music['basic_info']['genre']}\n") + \
        MessageSegment.text(f"BPM: {music['basic_info']['bpm']}\n") + \
        MessageSegment.text(f"版本: {music['basic_info']['from']}\n")

def song_txt_r(music: dict):
    lev_list = []
    lev_keys = ["lev_bas", "lev_adv", "lev_exp", "lev_mas", "lev_ult"]
    for key in lev_keys:
        if music[key] != "":
            lev_list.append(music[key])
        else:
            lev_list.append("-")
    return MessageSegment.text(f"{music['id']}. {music['title']}\n") + \
        MessageSegment.image(f"base64://{str(image_to_base64(get_chuni_cover(music['id'])), encoding='utf-8')}") + \
        MessageSegment.text(f"\n等级:{'/'.join(lev_list)}\n") + \
        MessageSegment.text(f"艺术家: {music['artist']}\n") + \
        MessageSegment.text(f"分类: {music['catname']}\n") + \
        MessageSegment.text(f"注音: {music['reading']}\n")

def inner_level_q(ds1, ds2=None):
    result_set = []
    diff_label = ['Bas', 'Adv', 'Exp', 'Mst', 'ReM']
    if ds2 is not None:
        music_data = total_list.filter(ds=(ds1, ds2))
    else:
        music_data = total_list.filter(ds=ds1)
    for music in sorted(music_data, key=lambda i: int(i['id'])):
        for i in music.diff:
            result_set.append(
                (music['id'], music['title'], music['ds'][i], diff_label[i], music['level'][i]))
    return result_set

inner_level = on_command('cinner_level ', aliases={'c定数查歌 '}, priority=10, block=True)
@inner_level.handle()
async def _(event: Event, message: Message = CommandArg()):
    argv = str(message).strip().split(" ")
    if len(argv) > 2 or len(argv) == 0:
        await inner_level.finish("命令格式为\nc定数查歌 <定数>\nc定数查歌 <定数下限> <定数上限>")
    if len(argv) == 1:
        result_set = inner_level_q(float(argv[0]))
    else:
        result_set = inner_level_q(float(argv[0]), float(argv[1]))
    if len(result_set) > 300:
        await inner_level.finish(f"结果过多（{len(result_set)} 条），请缩小搜索范围。")
    s = """ 结果如下：

 """
    for elem in result_set:
        s += f"""{elem[0]}. {elem[1]} {elem[3]} {elem[4]}({elem[2]})
 """
    await inner_level.finish(MessageSegment.image(f"base64://{str(image_to_base64(text_to_image(s)), encoding='utf-8')}"))

spec_rand = on_regex(r"^c随个(?:dx|sd|标准)?[绿黄红紫白]?[0-9]+\+?", priority=10, block=True)
@spec_rand.handle()
async def _(event: Event):
    # level_labels = ['绿', '黄', '红', '紫', '白']
    regex = "c随个((?:dx|sd|标准))?([绿黄红紫白]?)([0-9]+\+?)"
    res = re.match(regex, str(event.get_message()).lower())
    level = res.groups()[2]
    if res.groups()[1] == "":
        music_data = total_list.filter(level=level)
    else:
        music_data = total_list.filter(
            level=level, diff=['绿黄红紫白'.index(res.groups()[1])])
    if len(music_data) == 0:
        rand_result = "没有这样的乐曲哦。"
    else:
        rand_result = song_txt(music_data.random())
    await spec_rand.finish(rand_result)

mr = on_regex(r".*中二.*什么", priority=10, block=True)
@mr.handle()
async def _():
    await mr.finish(song_txt(total_list.random()))

search_music = on_regex(r"^c查歌.+",priority=10, block=True)
@search_music.handle()
async def _(event: Event):
    regex = "c查歌(.+)"
    name = re.match(regex, str(event.get_message())).groups()[0].strip()
    if name == "":
        return
    res = total_list.filter(title_search=name)
    if len(res) == 0:
        await search_music.finish("没有找到这样的乐曲。")
    elif len(res) == 1:
        await search_music.finish(song_txt(res[0]))
    elif len(res) < 30:
        search_result = ""
        for music in sorted(res, key=lambda i: int(i['id'])):
            search_result += f"{music['id']}. {music['title']}\n"
        await search_music.finish(search_result.strip())
    else:
        await search_music.finish(f"结果过多（{len(res)} 条），请缩小查询范围。")

crsearch_music = on_regex(r"^cr查歌.+",priority=10, block=True)
@crsearch_music.handle()
async def _(event: Event):
    regex = "cr查歌(.+)"
    name = re.match(regex, str(event.get_message())).groups()[0].strip()
    if name == "":
        return
    res = []
    for music in chuni_music_jp:
        if name.lower() in music['title'].lower():
            res.append(music)
    if len(res) == 0:
        await crsearch_music.finish("没有找到这样的乐曲。")
    elif len(res) == 1:
        await crsearch_music.finish(song_txt_r(res[0]))
    elif len(res) < 50:
        search_result = ""
        for music in sorted(res, key=lambda i: int(i['id'])):
            search_result += f"{music['id']}. {music['title']}\n"
        await crsearch_music.finish(search_result.strip())
    else:
        await crsearch_music.finish(f"结果过多（{len(res)} 条），请缩小查询范围。")

crid = on_regex(r"^crid ?([0-9]+)", priority=10, block=True)
@crid.handle()
async def _(event: Event):
    regex = "crid ?([0-9]+)"
    id = re.match(regex, str(event.get_message())).groups()[0].strip()
    for music in chuni_music_jp:
        if music['id'] == id:
            await crid.finish(song_txt_r(music))
    await crid.finish("没有找到这样的乐曲。")

query_chart = on_regex(r"^c([绿黄红紫白]?)id ?([0-9]+)", priority=10, block=True)
@query_chart.handle()
async def _(event: Event):
    regex = "c([绿黄红紫白]?)id ?([0-9]+)"
    groups = re.match(regex, str(event.get_message())).groups()
    level_labels = ['绿', '黄', '红', '紫', '白']
    if groups[0] != "":
            level_index = level_labels.index(groups[0])
            level_name = ['Basic', 'Advanced',
                          'Expert', 'Master', 'Re: MASTER']
            name = groups[1].strip()
            music = total_list.by_id(name)

            if music is None:
                await query_chart.finish("没有找到这样的乐曲。")
            if len(music['charts']) < level_index:
                await query_chart.finish("没有这个难度。")

            chart = music['charts'][level_index]
            ds = music['ds'][level_index]
            level = music['level'][level_index]
            img = get_chuni_cover(music.id)
            msg = f"{level_name[level_index]} {level}({ds})\n谱师: {chart['charter']}\nCombo: {chart['combo']}"
            await query_chart.finish(MessageSegment.text(f"{music['id']}. {music['title']}\n") +
                                     MessageSegment.image(f"base64://{str(image_to_base64(img), encoding='utf-8')}") +
                                     MessageSegment.text(msg))
    else:
        name = groups[1].strip()
        music = total_list.by_id(name)
        await query_chart.finish(song_txt(music))

wm_list = ['推分', '越级', '下埋', '夜勤', '练底力','练手法', '打SUN', '干饭', '抓大J', '收歌', '扭头去打mai']
jrzhe = on_command('今日中二', aliases={'今日chuni'}, priority=10, block=True)

@jrzhe.handle()
async def _(event: Event, message: Message = CommandArg()):
    qq = int(event.get_user_id())
    h = hash(qq)
    rp = h % 100
    wm_value = []
    for i in range(11):
        wm_value.append(h & 3)
        h >>= 2
    s = f"今日人品值：{rp}\n"
    for i in range(11):
        if wm_value[i] == 3:
            s += f'宜 {wm_list[i]}\n'
        elif wm_value[i] == 0:
            s += f'忌 {wm_list[i]}\n'
    s += "然哥提醒您：打几把中二快去学习\n"
    music = total_list[h % len(total_list)]
    await jrzhe.finish(MessageSegment.text(s) + song_txt(music))

"""-----------谱师查歌&曲师查歌&新歌查歌&BPM查歌&版本查歌-----------"""
hardlist = ['Basic', 'Advance', 'Expert', 'Master', 'Re:Master']

ccharter_search = on_command('c谱师查歌', priority=10, block=True)
@ccharter_search.handle()
async def _(event: Event, message: Message = CommandArg()):
    charter = str(message).strip()
    k = 0
    s = """ 结果如下

 """
    for i in range(0, len(music_data)):
        for j in range(3, len(music_data[i]['charts'])):
            if charter.lower() in music_data[i]['charts'][j]['charter'].lower():
                k += 1
                s += ('No.' + str(k) + ' ' + music_data[i]['charts'][j]['charter'] + ' ' + '[' + str(music_data[i]['id']) + ']' + '. ' + hardlist[j] + ' ' + music_data[i]['title'])
                s += """
 """
    if k > 350:
        await ccharter_search.finish(f"结果过多（{k} 条），请缩小搜索范围。")
    elif k == 0:
        await ccharter_search.finish(f"没有找到结果，请检查搜索条件。")
    await ccharter_search.finish(MessageSegment.image(f"base64://{str(image_to_base64(text_to_image(s)), encoding='utf-8')}"))

cartist_search = on_command('c曲师查歌', priority=10, block=True)
@cartist_search.handle()
async def _(event: Event, message: Message = CommandArg()):
    artist = str(message).strip()
    k = 0
    s = """ 结果如下

 """
    for i in range(0, len(music_data)):
        if artist.lower() in music_data[i]['basic_info']['artist'].lower():
            k += 1
            s += ('No.' + str(k) + ' ' + music_data[i]['basic_info']['artist'] +
                  ' ' + '[' + str(music_data[i]['id']) + ']' + '. ' + music_data[i]['title'])
            s += """
 """
    if k > 300:
        await cartist_search.finish(f"结果过多（{k} 条），请缩小搜索范围。")
    elif k == 0:
        await cartist_search.finish(f"没有找到结果，请检查搜索条件。")
    await cartist_search.finish(MessageSegment.image(f"base64://{str(image_to_base64(text_to_image(s)), encoding='utf-8')}"))

cversion_search = on_command('c版本查歌', priority=10, block=True)
@cversion_search.handle()
async def _(event: Event, message: Message = CommandArg()):
    artist = str(message).strip()
    k = 0
    s = """ 结果如下

 """
    for i in range(0, len(music_data)):
        if artist.lower() in music_data[i]['basic_info']['from'].lower():
            k += 1
            s += ('No.' + str(k) + ' ' + music_data[i]['basic_info']['from'] +
                  ' ' + '[' + str(music_data[i]['id']) + ']' + '. ' + music_data[i]['title'])
            s += """
 """
    if k > 300:
        await cversion_search.finish(f"结果过多（{k} 条），请缩小搜索范围。")
    elif k == 0:
        await cversion_search.finish(f"没有找到结果，请检查搜索条件。")
    await cversion_search.finish(MessageSegment.image(f"base64://{str(image_to_base64(text_to_image(s)), encoding='utf-8')}"))

cbpm_search = on_command('cbpm查歌', aliases={"cBPM查歌", "cBpm查歌"}, priority=10, block=True)
@cbpm_search.handle()
async def _(event: Event, message: Message = CommandArg()):
    argv = str(message).strip().split(" ")
    if len(argv) == 2:
        k = 0
        s = """ 结果如下

 """
        for i in range(0, len(music_data)):
            if (float(argv[0]) <= music_data[i]['basic_info']['bpm'] <= float(argv[1])):
                k += 1
                s += ('No.' + str(k) + ' BPM:' + str(music_data[i]['basic_info']['bpm']) +
                      ' ' + '[' + str(music_data[i]['id']) + ']' + '. ' + music_data[i]['title'])
                s += """
 """
    elif len(argv) == 1:
        k = 0
        s = """ 结果如下
 """
        for i in range(0, len(music_data)):
            if (float(argv[0]) == music_data[i]['basic_info']['bpm']):
                k += 1
                s += ('No.' + str(k) + ' BPM:' + str(music_data[i]['basic_info']['bpm']) +
                      ' ' + '[' + str(music_data[i]['id']) + ']' + '. ' + music_data[i]['title'])
                s += """
 """
    else:
        await cbpm_search.finish("命令格式为\nbpm查歌 <bpm>\nbpm查歌 <bpm下限> <bpm上限>")
    if k > 300:
        await cbpm_search.finish(f"结果过多（{k} 条），请缩小搜索范围。")
    elif k == 0:
        await cbpm_search.finish(f"没有找到结果，请检查搜索条件。")
    await cbpm_search.finish(MessageSegment.image(f"base64://{str(image_to_base64(text_to_image(s)), encoding='utf-8')}"))


import os
import sys
import torch
import torch.nn as nn
import pickle

import numpy as np
from gensim.models import KeyedVectors
import spacy

nlp = spacy.load('en_core_web_sm')

cur_dir = os.path.dirname(os.path.abspath(__file__))

class TextTokenizer(nn.Module):
    def __init__(
            self,
            word2vec_model_path='filtered_f30k_word2vec.model',
            max_length_tokens=16,
    ):
        super().__init__()
        self.gensim_model = KeyedVectors.load(word2vec_model_path)

        self.max_length_tokens = max_length_tokens

    @property
    def word2vec_embd_dim(self):
        return self.word_embd.embedding_dim

    def _zero_pad_tensor_token(self, tensor, size):
        if len(tensor) >= size:
            return tensor[:size]
        else:
            zero = torch.zeros(size - len(tensor)).long()
            return torch.cat((tensor, zero), dim=0)

    def _words_to_token_ids(self, x):
        def _get_lemma(token):
            if not token.is_punct and not token.is_space:
                lower_lemma = token.lemma_.lower()
                return lower_lemma

        tokens = []
        for sent in x:
            sent_tokens = []
            for token in nlp(sent):
                try:
                    sent_tokens.append(self.gensim_model.get_index(_get_lemma(token)))
                except KeyError as ex:
                    continue
            tokens.append(self._zero_pad_tensor_token(
                torch.LongTensor(sent_tokens), self.max_length_tokens))
        return torch.stack(tokens, dim=0)

    def forward(self, x):
        return self._words_to_token_ids(x)

class TextEncoder(nn.Module):
    def __init__(
            self,
            gensim_model_vector_weights,
            embd_dim=512,
            output_dim=2048,
    ):
        super().__init__()
        self.word_embd = nn.Embedding.from_pretrained(gensim_model_vector_weights, freeze=False)
        self.fc1 = nn.Linear(self.word_embd.embedding_dim, output_dim)
        self.relu = nn.ReLU(inplace=True)
        self.fc2 = nn.Linear(output_dim, embd_dim)

    def forward(self, x):
        x = self.word_embd(x)
        x = self.relu(self.fc1(x))
        # x is of shape (batch_size, tokens, output_dim)
        x = torch.max(x, dim=1).values
        # it is reduced in the number of tokens. For each dim in output_dim it takes the maximum value for each of the words,
        # so x is of the shape (batch_dim, output_dim)
        x = self.fc2(x)
        result = torch.nn.functional.normalize(x, p=2, dim=1)
        return result

def get_word2vec_for_vocabulary(countvectorizer_path: str = 'coco_vectorizer.pkl',
                                original_word2vec: str = 'word2vec-google-news-300',
                                output_model_path: str = 'filtered_f30k_word2vec.model'):
    """
    Given a DataLoader loading only captions fit into a CountVectorizer to obtain the TextEncoder model to use for training
    """

    import gensim.downloader as api

    original_model = api.load(original_word2vec)
    with open(countvectorizer_path, 'rb') as f:
        vectorizer = pickle.load(f)
    new_vectors = []
    new_vocab = {}
    new_index2entity = []
    new_model = original_model
    words_to_keep = list(vectorizer.vocabulary_.keys())

    for word, index in original_model.key_to_index.items():
        if word in words_to_keep:
            new_vocab[word] = len(new_index2entity)
            new_vectors.append(original_model.get_vector(word))
            new_index2entity.append(word)

    new_model.key_to_index = new_vocab
    new_model.vectors = np.array(new_vectors)
    new_model.index_to_key = np.array(new_index2entity)
    new_model.save(output_model_path)

if __name__ == '__main__':
    countvectorizer_path = sys.argv[1] if len(sys.argv) > 1 else f'coco_vectorizer_with_stop_words.pkl'
    original_word2vec = sys.argv[2] if len(sys.argv) > 2 else f'word2vec-google-news-300'
    output_model_path = sys.argv[3] if len(sys.argv) > 3 else f'filtered_coco_word2vec_with_stop_words.model'
    get_word2vec_for_vocabulary(countvectorizer_path, original_word2vec, output_model_path)


from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
from dash import dcc
from app import app
import home
import macroeconomic
import feedback

navbar = dbc.NavbarSimple(children=[
    dbc.NavItem(dbc.NavLink("Home", href="/home")),
    dbc.NavItem(dbc.NavLink("Macroeconomic", href="/macroeconomic")),
    dbc.NavItem(dbc.NavLink("Feedback", href="/feedback")), ],
    color="grey",)

app.layout = html.Div([
    dcc.Location(id='url', refresh=False),
    navbar,
    html.Div(id='page-content')
])

@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/macroeconomic':
        return macroeconomic.layout
    elif pathname == '/feedback':
        return feedback.layout
    else:
        return home.layout

if __name__ == '__main__':
    app.run_server(debug=False)


#!/usr/bin/python3
# -*- coding: utf-8 -*-

# how to
import heapq

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0

    def push(self, item, priority):
        heapq.heappush(self._queue, (priority, self._index, item))
        self._index += 1

    def pop(self):
        return heapq.heappop(self._queue)

q = PriorityQueue()
q.push('a', 3)
q.push('b', 5)
q.push('c', 2)
q.push('d', 6)
for i in range(4):
    print(q.pop())


from typing import List
import torch
import torch.nn as nn
from torch.nn.modules import activation, conv, padding
from config import configurable
from shape_spec import ShapeSpec
from typing import List
from model import Conv2d, get_norm
import numpy as np
import fvcore.nn.weight_init as weight_init

class FastRCNNConvFCHead(nn.Sequential):
    @configurable
    def __init__(self, input_shape:ShapeSpec, *, conv_dims:List[int], fc_dims:List[int], conv_norm='' ):
        super().__init__()
        assert len(conv_dims) + len(fc_dims) > 0

        self._output_size = (input_shape.channels, input_shape.height, input_shape.width)

        self.conv_norm_relus = []
        for k, conv_dim in enumerate(conv_dims):
            conv = Conv2d(
                self._output_size[0],
                conv_dim,
                kernel_size = 3,
                padding = 1,
                bias = not conv_norm,
                norm = get_norm(conv_norm, conv_dim),
                activation = nn.ReLU(),
            )
            self.add_module('conv{}'.format(k+1), conv)
            self.conv_norm_relus.append(conv)
            self._output_size = (conv_dim, self._output_size[1], self._output_size[2])

        self.fcs = []
        for k, fc_dim in enumerate(fc_dims):
            if k == 0:
                self.add_module('flatten', nn.Flatten())
            fc = nn.Linear(int(np.prod(self._output_size)), fc_dim)
            self.add_module('fc{}'.format(k+1), fc)
            self.add_module('fc_relu{}'.format(k+1), nn.ReLU())
            self.fcs.append(fc)
            self._output_size = fc_dim
        for layer in self.conv_norm_relus:
            weight_init.c2_msra_fill(layer)
        for layer in self.fcs:
            weight_init.c2_xavier_fill(layer)

    @classmethod
    def from_config(self, cfg, input_shape:ShapeSpec):
        num_conv = cfg.MODEL.ROI_BOX_HEAD.NUM_CONV
        conv__dim = cfg.MODEL.ROI_BOX_HEAD.CONV_DIM
        num_fc = cfg.MODEL.ROI_BOX_HEAD.NUM_FC
        fc_dim = cfg.MODEL.ROI_BOX_HEAD.FC_DIM
        return {
            'input_shape': input_shape,
            'conv_dims': [conv__dim] * num_conv,
            'fc_dims': [fc_dim] * num_fc,
            'conv_norm': cfg.MODEL.ROI_BOX_HEAD.NORM
        }

    def forward(self, x):
        for layer in self:
            x = layer(x)
        return x

    @property
    def output_shape(self):
        o = self._output_size
        if isinstance(o, int):
            return ShapeSpec(channels=o)
        else:
            return ShapeSpec(channels=o[0], height=o[1], width=o[2])

def build_box_head(cfg, input_shape):
    name = cfg.MODEL.ROI_BOX_HEAD.NAME
    return FastRCNNConvFCHead(cfg, input_shape)


from flask import Flask, render_template, Response, request, send_file, jsonify
import cv2
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
import numpy as np
import pandas as pd
import json
import requests
from pathlib import Path
from posixpath import join

from utils.faiss_processing import MyFaiss
from utils.submit import write_csv, show_csv
from utils.bert_processing import BERTSearch
from utils.ocr_processing import fill_ocr_results, fill_ocr_df
from utils.sequence_search_processing import get_sequence_frame_order
from utils.object_processing import filter_by_objects

# http://0.0.0.0:5001/thumbnailimg?index=0

# app = Flask(__name__, template_folder='templates', static_folder='static')
app = Flask(__name__, template_folder='templates/front-end')

# Faiss
bin_file= 'dataset/clip-features-vit-b32/clip-features-vit-b32/'

json_path = 'dict/keyframes_id.json'
json_id2img_path = 'dict/dict_id2img_path.json'
json_img2id_path = 'dict/dict_img2id_path.json'
json_keyframe2id = 'dict/keyframe_path2id.json'

json_object_thr01 = 'dict/object_all_s_thr01.json'
json_object_thr02 = 'dict/object_all_s_thr02.json'
json_object_thr03 = 'dict/object_all_s_thr03.json'
json_object_thr05 = 'dict/object_all_s_thr05.json'
json_object_thr005 = 'dict/object_all_s_thr005.json'

# with open("dict/info_ocr.txt", "r", encoding="utf8") as fi:
#     ListOcrResults = list(map(lambda x: x.replace("\n",""), fi.readlines()))

# with open("dict/info_asr.txt", "r", encoding="utf8") as fi:
#     ListASRResults = list(map(lambda x: x.replace("\n",""), fi.readlines()))
# df_asr = pd.read_csv("dict/info_asr.txt", delimiter=",", header=None)
# df_asr.columns = ["video_id", "frame_id", "asr"]

with open(json_id2img_path, 'r') as f:
    DictId2Img = json.loads(f.read())

with open(json_img2id_path, 'r') as f:
    DictImg2Id = json.loads(f.read())

with open(json_keyframe2id, 'r') as f:
    DictKeyframe2Id = json.loads(f.read())

with open(json_path, 'r') as f:
    DictGlobalId2Path = json.loads(f.read())

# with open(json_object_thr01, 'r') as f:
#     Dict_Img2Objs_thr01 = json.loads(f.read())

thresholds = {}

with open(json_object_thr05, 'r') as f:
    thresholds['0.5'] = json.loads(f.read())

with open(json_object_thr03, 'r') as f:
    thresholds['0.3'] = json.loads(f.read())

with open(json_object_thr02, 'r') as f:
    thresholds['0.2'] = json.loads(f.read())

with open(json_object_thr01, 'r') as f:
    thresholds['0.1'] = json.loads(f.read())

with open(json_object_thr005, 'r') as f:
    thresholds['0.05'] = json.loads(f.read())

CosineFaiss = MyFaiss('Database', bin_file, json_path)
DictImagePath = CosineFaiss.id2img_fps
LenDictPath = len(CosineFaiss.id2img_fps)
print("LenDictPath: ", LenDictPath)
# CosineFaiss.id2img_fps

# BERT
# MyBert = BERTSearch(dict_bert_search='dict/keyframes_id_bert.json', bin_file='dict/faiss_bert.bin', mode='search')

@app.route('/thumbnailimg')
def thumbnailimg():
    print("load_iddoc")

    # remove old file submit
    submit_path = join("submission", "submit.csv")
    old_submit_path = Path(submit_path)
    if old_submit_path.is_file():
        os.remove(submit_path)
        # open(submit_path, 'w').close()

    pagefile = []
    index = int(request.args.get('index'))
    if index == None:
        index = 0

    imgperindex = 100

    # imgpath = request.args.get('imgpath') + "/"
    pagefile = []

    page_filelist = []
    list_idx = []

    if LenDictPath-1 > index+imgperindex:
        first_index = index * imgperindex
        last_index = index*imgperindex + imgperindex

        tmp_index = first_index
        while tmp_index < last_index:
            page_filelist.append(DictImagePath[tmp_index]["image_path"])
            list_idx.append(tmp_index)
            tmp_index += 1
    else:
        first_index = index * imgperindex
        last_index = LenDictPath

        tmp_index = first_index
        while tmp_index < last_index:
            page_filelist.append(DictImagePath[tmp_index]["image_path"])
            list_idx.append(tmp_index)
            tmp_index += 1

    for imgpath, id in zip(page_filelist, list_idx):
        pagefile.append({'imgpath': imgpath, 'id': id})

    data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile}

    return render_template('index_thumb.html', data=data)

@app.route('/imgsearch')
def image_search():
    print("image search")
    k = int(request.args.get('k_value'))

    pagefile = []
    id_query = int(request.args.get('imgid'))
    _, list_ids, _, list_image_paths = CosineFaiss.image_search(id_query, k=k)

    imgperindex = 100

    for imgpath, id in zip(list_image_paths, list_ids):
        pagefile.append({'imgpath': imgpath, 'id': int(id)})

    data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile}

    return render_template('index_thumb.html', data=data)

@app.route('/textsearch')
def text_search():
    print("text search")
    k = int(request.args.get('k_value'))
    pagefile = []
    text_query = request.args.get('textquery')
    _, list_ids, _, list_image_paths = CosineFaiss.text_search(text_query, k=k)

    print('text_query: ', text_query)

    imgperindex = 100

    for imgpath, id in zip(list_image_paths, list_ids):
        # print(imgpath)
        if (int(imgpath[41:-4]) == 1): continue
        pagefile.append({'imgpath': imgpath, 'id': int(id)})
        # print(imgpath)
# dataset/Keyframes_L19/keyframes/L19_V046/
    # data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile, 'mode': "Text", 'query': text_query}
    data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile, 'mode': "Text", 'query': text_query.replace(' ','_')}

    return render_template('index_thumb.html', data=data)

@app.route('/sequencesearch')
def sequence_search():
    print ('sequence search')
    print(request.args.get('k_value'))
    k = int(request.args.get('k_value'))
    pagefile = []
    images_start = []
    images_next = []

    text_query_start = request.args.get('text_start')
    text_query_next = request.args.get('text_nextframes')

    # list_ids_start
    scores_start, _, _, list_image_paths_start = CosineFaiss.text_search(text_query_start, k=k)
    scores_end, _, _, list_image_paths_next = CosineFaiss.text_search(text_query_next, k=k)

    # print('scores_start: ', scores_start)

    imgperindex = 100

    for imgpath in list_image_paths_start:
        images_start.append(imgpath[32:-4])
    for imgpath in list_image_paths_next:
        images_next.append(imgpath[32:-4])

    frames = get_sequence_frame_order(images_start, images_next, scores_start[0], scores_end[0])

    for i in frames:
        imgpath = f'dataset/Keyframes_{i[:3]}/keyframes/{i}.jpg'
        id = DictKeyframe2Id[imgpath]
        pagefile.append({'imgpath': imgpath, 'id': int(id)})

    data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile, 'mode': 'Sequence', 'query1': text_query_start.replace(' ','_'), 'query2': text_query_next.replace(' ','_')}

    return render_template('index_thumb.html', data=data)

    ################################################ brute force ################################################
    # pairs, weak_pairs, frames_in_both = get_sequence_frame(images_start, images_next)

    # for i in pairs + weak_pairs:
    #     tmp_imgpath_first = f'dataset/Keyframes_{i[0][:3]}/keyframes/{i[0]}.jpg'
    #     tmp_imgpath_last = f'dataset/Keyframes_{i[1][:3]}/keyframes/{i[1]}.jpg'

    #     tmp_id_first = DictKeyframe2Id[tmp_imgpath_first]
    #     tmp_id_last = DictKeyframe2Id[tmp_imgpath_last]

    #     tmp_imgpath_mids = []
    #     tmp_id_mids = []
    #     for midid in range(int(tmp_id_first), int(tmp_id_last)):
    #         midid = str(midid)
    #         tmp_id_mids.append(midid)
    #         tmp_imgpath_mids.append(DictGlobalId2Path[midid]["image_path"])

    #     for imgpath, id in zip([tmp_imgpath_first] + tmp_imgpath_mids + [tmp_imgpath_last], [tmp_id_first] + tmp_id_mids + [tmp_id_last]):
    #         pagefile.append({'imgpath': imgpath, 'id': int(id)})

    # for i in frames_in_both:
    #     imgpath = f'dataset/Keyframes_{i[:3]}/keyframes/{i}.jpg'
    #     id = DictKeyframe2Id[imgpath]
    #     pagefile.append({'imgpath': imgpath, 'id': int(id)})

    # data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile}

    # return render_template('index_thumb.html', data=data)
    ################################################ brute force ################################################

@app.route('/objectfilter')
def object_filter():
    print ('object filter')
    pagefile = []
    k = int(request.args.get('k_value'))
    images = []
    imgperindex = 100

    text_query = request.args.get('textquery')
    obj_filter = list(map(lambda x: x.lower(), request.args.get('objects').split(',')))
    threshold = request.args.get('threshold')
    mode_search = request.args.get('operator')
    # threshold = 0.3
    dict_obj_thr = thresholds[threshold]

    _, _, _, list_image_paths = CosineFaiss.text_search(text_query, k=k)
    for imgpath in list_image_paths:
        if (int(imgpath[41:-4]) == 1): continue
        images.append(imgpath[32:-4])

    images_filtered = filter_by_objects(images, obj_filter, dict_obj_thr,  mode_search = mode_search)
    print('obj want to filter: ', obj_filter)

    for i in images_filtered:
        imgpath = f'dataset/Keyframes_{i[:3]}/keyframes/{i}.jpg'
        id = DictKeyframe2Id[imgpath]
        pagefile.append({'imgpath': imgpath, 'id': int(id)})

    data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile}

    return render_template('index_thumb.html', data=data)

# @app.route('/asrsearch')
# def asrsearch():
#     print("asr search")
#      # remove old file submit

#     pagefile = []
#     text_query = request.args.get('text_asr')
#     _, list_ids, _, list_image_paths = MyBert.bert_search(text_query, k=100)

#     imgperindex = 100

#     for imgpath, id in zip(list_image_paths, list_ids):
#         imgpath = imgpath.replace("\\","/")
#         pagefile.append({'imgpath': imgpath, 'id': int(DictKeyframe2Id[imgpath])})

#     data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile}

#     return render_template('index_thumb.html', data=data)

# @app.route('/ocrfilter')
# def ocrfilter():
#     print("ocr search")

#     pagefile = []
#     text_query = request.args.get('text_ocr')

#     list_all = fill_ocr_results(text_query, ListOcrResults)
#     list_all.extend(fill_ocr_results(text_query, ListASRResults))

#     # list_all = fill_ocr_df(text_query, df_ocr)
#     # list_all = np.vstack((list_all, fill_ocr_df(text_query, df_ocr)))

#     print("list results of ocr + asr: ", list_all)

#     imgperindex = 100

#     for frame in list_all:
#         list_frame_name = frame.split("/")
#         keyframe_dir = list_frame_name[0][:7]
#         video_dir = list_frame_name[0]
#         new_frame_name = list_frame_name[-1]
#         frame_in_video_path =  join("Database", "KeyFrames"+keyframe_dir, video_dir, new_frame_name)
#         frame_in_video_path =  frame_in_video_path.replace("\\","/")
#         # print("frame_in_video_path: ", frame_in_video_path)
#         if frame_in_video_path in DictKeyframe2Id:
#             print("frame_in_video_path: ", frame_in_video_path)
#             frame_id_in_video_path = DictKeyframe2Id[frame_in_video_path]
#             pagefile.append({'imgpath': frame_in_video_path, 'id': int(frame_id_in_video_path)})

#     data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile}

#     return render_template('index_thumb.html', data=data)

@app.route('/showsegment')
def show_segment():
    print("showsegment")
    id_query = int(request.args.get('imgid'))
    img_path = DictGlobalId2Path[str(id_query)]["image_path"][32:-4]
    print(img_path)

    return(search_image_path(img_path))

    # pagefile = []

    # list_shot_path = DictImagePath[id_query]['list_shot_path']

    # imgperindex = 100
    # for shot_info in list_shot_path:
    #     pagefile.append({'imgpath': shot_info['shot_path'], 'id': int(DictKeyframe2Id[shot_info['shot_path']])})

    # # show  around 200 key image
    # frame_path = DictImagePath[id_query]["image_path"]
    # list_split = frame_path.split("/")
    # keyframe_dir = list_split[1][-7:]
    # video_dir = list_split[2]
    # image_name = list_split[3]

    # total_image_in_video = int(DictImg2Id[keyframe_dir][video_dir]["total_image"])
    # number_image_id_in_video = int(DictImg2Id[keyframe_dir][video_dir][image_name])

    # first_index_in_video = number_image_id_in_video-40 if number_image_id_in_video-40>0 else 0
    # last_index_in_video = number_image_id_in_video+40 if number_image_id_in_video+40<total_image_in_video else total_image_in_video
    # frame_index = first_index_in_video
    # while frame_index < last_index_in_video:
    #     new_frame_name = DictId2Img[keyframe_dir][video_dir][str(frame_index)]
    #     frame_in_video_path =  join("Database", "KeyFrames"+keyframe_dir, video_dir, new_frame_name)
    #     frame_in_video_path =  frame_in_video_path.replace("\\","/")
    #     if frame_in_video_path in DictKeyframe2Id:
    #         frame_id_in_video_path = DictKeyframe2Id[frame_in_video_path]
    #         pagefile.append({'imgpath': frame_in_video_path, 'id': int(frame_id_in_video_path)})

    #     frame_index += 1

    # data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile}

    # return render_template('index_thumb.html', data=data)

@app.route('/writecsv')
def submit():
    print("writecsv")
    info_key = request.args.get('info_key')
    mode_write_csv = request.args.get('mode')
    print("info_key", info_key)
    print("mode: ", mode_write_csv)
    info_key = info_key.split(",")

    id_query = int(info_key[0])
    selected_image = info_key[1]

    number_line, list_frame_id = write_csv(DictImagePath, mode_write_csv, selected_image, id_query, "submission")

    str_fname = ",".join(list_frame_id[:])
    # str_fname += " #### number csv line: {}".format(number_line)

    info = {
        "str_fname": str_fname,
        "number_line": str(number_line)
    }

    return jsonify(info)

@app.route('/get_img')
def get_img():
    # print("get_img")
    fpath = request.args.get('fpath')
    # fpath = fpath
    list_image_name = fpath.split("/")
    image_name = "/".join(list_image_name[-2:])

    if os.path.exists(fpath):
        img = cv2.imread(fpath)
    else:
        print("load 404.jph")
        img = cv2.imread("./static/images/404.jpg")

    img = cv2.resize(img, (1280,720))

    # print(img.shape)
    img = cv2.putText(img, image_name, (30, 80), cv2.FONT_HERSHEY_SIMPLEX,
                   3, (255, 0, 0), 4, cv2.LINE_AA)

    ret, jpeg = cv2.imencode('.jpg', img)
    return  Response((b'--frame\r\n'
                     b'Content-Type: image/jpeg\r\n\r\n' + jpeg.tobytes() + b'\r\n\r\n'),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/dowload_submit_file', methods=['GET'])
def dowload_submit_file():
    print("dowload_submit_file")
    filename = request.args.get('filename')
    fpath = join("submission", filename)
    print("fpath", fpath)

    return send_file(fpath, as_attachment=True)

@app.route('/get_first_row')
def getFirstRowOfCsv():
    csv_path = "submission/submit.csv"
    result = {
        'video_id':"None",
        'frame_id':"None"
    }
    if os.path.exists(csv_path):
        lst_frame = show_csv(csv_path)[0]
        video_id, frame_id = lst_frame.split("/")[-2:]
        result["video_id"] = video_id
        result["frame_id"] = int(frame_id[:-4])

    return result

@app.route('/visualize')
def visualize():
    number_of_query = int(request.args.get('number_of_query'))
    csv_path = join("submission", "query-{}.csv".format(number_of_query))

    query_path = join("query","query-{}.txt".format(number_of_query))
    if os.path.exists(query_path):
        with open(query_path, "rb") as fi:
            query_content = fi.read().decode("utf-8").replace(" ","_")

    pagefile = []
    lst_frame = show_csv(csv_path)
    for frame_path in lst_frame:
        frame_id = DictKeyframe2Id[frame_path]
        pagefile.append({'imgpath': frame_path, 'id': int(frame_id)})
    if query_content is not None:
        data = {'num_page': 1, 'pagefile': pagefile, 'query': query_content}
    else:
        data = {'num_page': 1, 'pagefile': pagefile}

    return render_template('index_thumb.html', data=data)

@app.route('/search_image_path')
def search_image_path(frame_path = None):
    pagefile = []
    frame_path = request.args.get('frame_path') if not(frame_path) else frame_path
    query = frame_path
    if (len (frame_path) <= 9):

        pass
    else:
        frame_path_origin = frame_path

        list_frame_split = frame_path.split("/")

        video_dir = list_frame_split[0]
        image_name = list_frame_split[1] + ".jpg"
        keyframe_dir = video_dir[:-2]

        frame_path = join("dataset", "Keyframes"+ "_" + keyframe_dir.split("_")[0],"keyframes", video_dir, image_name)
        frame_path = frame_path.replace("\\","/")
        frame_id = DictKeyframe2Id[frame_path]
        print("frame_id: ", frame_id)

        imgperindex = 100
        pagefile.append({'imgpath': frame_path, 'id': int(frame_id)})
        # print(pagefile)
        # print (frame_path)

        # pass

        # TODO Show img_padding before and after
        img_padding = 40

        list_split = frame_path.split("/")
        keyframe_dir = list_split[1]
        video_dir = list_split[-2]
        image_name = list_split[-1]

        # total_image_in_video = int(DictImg2Id[keyframe_dir][video_dir]["total_image"])
        # frame_ids = [i for i in range(max(1, int(list_frame_split[1]) - img_padding), min(int(list_frame_split[1]) + img_padding + 1, total_image_in_video))]
        # tmp_append = [{'imgpath': frame_path[:-8] + DictId2Img[keyframe_dir][video_dir][str(i)], 'id': int(DictKeyframe2Id[frame_path[:-8] + DictId2Img[keyframe_dir][video_dir][str(i)]])} for i in frame_ids]

        frame_ids = [i for i in range(max(1, int(frame_id) - img_padding), min(int(frame_id) + img_padding + 1, 328829))]
        tmp_append = [{'imgpath': DictGlobalId2Path[str(i)]['image_path'], 'id': i} for i in frame_ids]

        # print(keyframe_dir)
        # print (image_name)
        # print (tmp_append)

        pagefile += tmp_append

        # dataset/Keyframes_L01/L01_V001/0001.jpg
        # dataset/Keyframes_L01/keyframes/L01_V001/0001.jpg

        # # show  around 30 key image
        # total_image_in_video = int(DictImg2Id[keyframe_dir][video_dir]["total_image"])
        # number_image_id_in_video = int(DictImg2Id[keyframe_dir][video_dir][image_name])

        # # print(DictKeyframe2Id)

        # first_index_in_video = number_image_id_in_video-40 if number_image_id_in_video-40>0 else 0
        # last_index_in_video = number_image_id_in_video+40 if number_image_id_in_video+40<total_image_in_video else total_image_in_video

        # frame_index = first_index_in_video
        # while frame_index < last_index_in_video:
        #     new_frame_name = DictId2Img[keyframe_dir][video_dir][str(frame_index)]
        #     frame_in_video_path =  join("Database", "KeyFrames"+keyframe_dir, video_dir, new_frame_name)
        #     frame_in_video_path = frame_in_video_path.replace("\\","/")
        #     if frame_in_video_path in DictKeyframe2Id:
        #         frame_id_in_video_path = DictKeyframe2Id[frame_in_video_path]
        #         pagefile.append({'imgpath': frame_in_video_path, 'id': int(frame_id_in_video_path)})

        id_query = video_dir
        # id_query = frame_path_origin
        #     frame_index += 1
        print('query =', query)
        link, keyframe = get_url(query)
        print(link)
        print(keyframe)
        data = {'num_page': int(LenDictPath/imgperindex)+1, 'pagefile': pagefile, 'youtube_url': link, 'keyframe_id': int(keyframe), 'mode': 'Image' , 'query': query}

    return render_template('index_thumb.html', data=data)

def get_url(query):
    # to do after
    print(query)
    folder, id = query.split('/')
    print(folder)
    id = int(id)
    print(id)
    path = folder.split('_')[0]
    csv_path = f'map_frame_id/MapKeyframe_{path}/{folder}.csv'
    json_path = f'dataset/New_Metadata/{folder}.json'

    if not os.path.exists(csv_path) or not os.path.exists(json_path):
        print("CSV/json file does not exist.")
        print(csv_path)
        print(json_path)
        return

    df = pd.read_csv(csv_path)
    df.set_index('n', inplace=True)

    try:
        output = df.at[id, 'frame_idx']
        pts_time = df.at[id, 'pts_time']
    except KeyError:
        print('except key error')
        return

    with open(json_path, 'r', encoding="utf8") as json_file:
        json_data = json.load(json_file)
    watch_url = json_data.get('watch_url', '')

    minutes = int(pts_time // 60)  # Get the whole minutes
    seconds = int(pts_time % 60)  # Get the remaining seconds

    link = f"{watch_url}&t={minutes}m{seconds}s"

    return link, output

@app.route('/submit_img')
def submit_img(session = "node0daps0nu1p57w1xda7c5bybauu3047"):
    id = request.args.get('id')
    item = id.split("/")[0]
    frame = request.args.get('frame')
    url = f"https://eventretrieval.one/api/v1/submit?item={item}&frame={frame}&session={session}"
    print(url)
    r = requests.get(url=url)
    response_data = r.json()  # Get the JSON content from the response
    return jsonify(response_data)

if __name__ == '__main__':
    submit_dir = "submission"
    if not os.path.exists(submit_dir):
        os.mkdir(submit_dir)

    app.run(debug=True, host="0.0.0.0", port=5001)


from django.urls import path, include
from api_v2.views import ArticleView, Operation

app_name = 'api_v2'

article_urls = [
    path('', ArticleView.as_view(), name='articles'),
    path('<int:pk>/operation', Operation.as_view(), name='detail_articles'),

]

urlpatterns = [
    path('articles/', include(article_urls)),
]