import numpy as np
from sklearn.metrics.pairwise import rbf_kernel

# def linearKernel_dist (in1, in2):
#     dist = in1-in2
#     return np.dot(dist,np.transpose(dist))

def distance(x1, x2, y1, y2, idx1, idx2, C, kernel, gamma=None):
    dist = 0
    if(idx1 != idx2):
        if (kernel == 'linear'):
            dist_vec = y1*x1 - y2*x2
            dist = 2*(1+1/C-y1*y2) + np.dot(dist_vec, np.transpose(dist_vec))
        elif (kernel == 'rbf'):
            dist_vec = x1-x2
            dist = 2 * (2+1/C - y1*y2*(np.exp(-gamma*np.dot(dist_vec, np.transpose(dist_vec)))+1))
    else:
        dist = 0

    return dist

def inner_product(x1, x2, y1, y2, idx1, idx2, C, kernel, gamma=None):
    prod = 0
    delta = 0
    if(idx1 != idx2):
        delta = 0
    else:
        delta = 1

    if (kernel == 'linear'):
        prod = y1*y2*np.dot(x1, np.transpose(x2))+y1*y2+delta/C
    elif (kernel == 'rbf'):
        prod = y1*y2*np.exp(-gamma * np.dot(x1, np.transpose(x2)))+y1*y2+delta/C

    return prod

def MEB (core_set, y_core, core_size, epsilon, C, kernel, gamma=None):

    first_index = np.random.randint(0, core_size, 1)[0]

    dist_list = np.zeros(core_size)

    bias_term = np.zeros(core_size)

    dist_max = 0

    p = core_set[first_index]
    py = y_core[first_index]

    bias_term[first_index] = bias_term[first_index] + 1/C

    far_list = []
    far_y_list = []
    far_index_list = []
    far_list.append(p)
    far_y_list.append(py)
    far_index_list.append(first_index)

    kernel_contant = np.ones(core_size) * (4+2/C)

    # initialize farthest point p away from the center c
    core_rbf = rbf_kernel(np.array(far_list), core_set, gamma) + 1
    core_rbf_sum = np.multiply(np.dot(np.array(far_y_list).reshape(-1), core_rbf), y_core) + bias_term
    dist_list = kernel_contant - core_rbf_sum * 2
    index = np.argmax(dist_list).reshape(-1)[0]

    p = core_set[index]
    py = y_core[index]

    bias_term[index] = bias_term[index] + 1 / C

    far_list.append(p)
    far_y_list.append(py)
    far_index_list.append(index)

    # iteration for constructing the core-set
    for cnt in range(int(2/epsilon)):
        core_rbf = np.multiply(rbf_kernel([p], core_set, gamma) + 1, y_core) * py
        core_rbf_sum = core_rbf_sum + core_rbf[0]
        core_rbf_sum[index] = core_rbf_sum[index] + 1 / C
        dist_list = kernel_contant - core_rbf_sum * 2 / (cnt+1)
        index = np.argmax(dist_list).reshape(-1)[0]

        p = core_set[index]
        py = y_core[index]

        bias_term[index] = bias_term[index] + 1 / C

        far_list.append(p)
        far_y_list.append(py)
        far_index_list.append(index)

    dist_max = dist_list[index]

    far_index_list = np.unique(far_index_list)

    return dist_max, dist_list, far_index_list

if __name__ == "__main__":
    dim = 10
    theta = 0.1
    data_size = 1000
    inp = np.random.rand(data_size,dim)
    y_core = np.ones(data_size)

    inp_re = np.random.rand(0,dim)
    y_re = np.ones(0)

    # R, dist_re, dist_core = MEB(inp, y_core, inp_re, y_re, data_size, 0, theta, 1.0, 'linear')
    # R, dist_re, dist_core = MEB(inp, y_core, inp_re, y_re, data_size, 0, theta, 1.0, 'rbf', 0.5)
    #
    # print('Smallest R is '+ str(R))
    # print ('dist_core is ' + str(dist_core))
    # print ('dist_re is ' + str(len(dist_re)))


import re
price = 0.0
quantity = 0
spent_money = 0
pattern = '>>([A-Za-z]+)<<(\d+\.?\d*)!(\d+)'
furniture_list = []
is_buying = True

while is_buying:
    data = input()
    if data == "Purchase":
        is_buying = False
        break
    result = re.match(pattern, data)
    if result is not None:
        spent_money += float(result[2])*int(result[3])
        furniture_list.append(result[1])

print(f'Bought furniture:')
for item in furniture_list:
    print(item)
print(f'Total money spend: {spent_money:.2f}')


from django.shortcuts import render,get_object_or_404,redirect, render_to_response
from jocs.models import Joc
from .forms import JocForm
from django.forms import modelform_factory
from django.contrib import messages
from django.conf import settings
from django.contrib.auth.decorators import login_required
# Create your views here.

def index(request):
    jocs= Joc.objects.all();
    ctx={'llista_jocs': jocs}
    return render(request, "jocs/index.html",ctx)

def joc(request,id_joc):
    joc = get_object_or_404(Joc,pk=id_joc)
    ctx={'joc': joc}
    return render(request,"jocs/joc.html",ctx)

@login_required (login_url='jocs:index')
def crear_joc(request):
    if request.method == 'POST':
        form = JocForm(request.POST,request.FILES)

        if form.is_valid():
           nom= form.cleaned_data['nom']
           preuE=form.cleaned_data['preuE']
           preuG=form.cleaned_data['preuG']
           descripcio=form.cleaned_data['descripcio']
           imatge=form.cleaned_data['imatge']
           #creem l'objecte Joc amb les dades rebudes
           Joc.objects.create( nom=nom,
                                        preuE=preuE,
                                        preuG=preuG,
                                        descripcio=descripcio,
                                        imatge=imatge,)
           messages.info(request,"joc pujat correctament")
           return redirect("usuaris:menu_usuari")
    else:
        nova_id=Joc.objects.latest('id'); #Haig de sumar un, o baixar el contador general
        nova_id.id += 1
        form= JocForm()

    for f in form.fields:
        form.fields[f].widget.attrs['class'] = 'formulari'

    return render (request, 'jocs/crear_joc.html', {'form': form, "nova_id":nova_id} )

@login_required (login_url='jocs:index')
def editar_joc(request, id_joc):
    EditForm = modelform_factory(Joc, fields=('nom','preuE','preuG','imatge','descripcio'))
    unEdit = Joc()

    #comprovem que existeix l'oferta_disc
    if id_joc:
        unEdit = get_object_or_404(Joc, pk=id_joc)

    if request.method == 'POST':
        form = EditForm (request.POST,request.FILES, instance= unEdit)
        if form.is_valid():
           form.save()
           messages.info(request,"Joc canviat correctament")
           ctx={'joc': unEdit}
           return render(request,"jocs/joc.html",ctx)
    else:
        form= EditForm (instance = unEdit)

    for f in form.fields:
        form.fields[f].widget.attrs['class'] = 'formulari'

    form.fields['nom'].widget.attrs['placeholder']="Nom"
    form.fields['descripcio'].widget.attrs['placeholder']="Descripcio"
    form.fields['preuE'].widget.attrs['placeholder']="PreuE"
    form.fields['preuG'].widget.attrs['placeholder']="PreuG"

    return render (request, 'jocs/editar_joc.html', {'form': form} )

@login_required (login_url='jocs:index')
def eliminar_joc(request,id_joc=None):

    if request.method == 'POST':
        joc = get_object_or_404(Joc, pk=id_joc);
        if (id_joc):
            joc.delete()
            return redirect('usuaris:menu_usuari')
    else:
        return render(request, 'jocs/eliminar_joc.html', {'Joc': Joc.objects.get(pk=id_joc)})

from django.db.models import Q

def search(request):
    query = request.GET.get('q', '')
    if query:
        qset = (
            Q(nom__icontains=query)
        )
        results = Joc.objects.filter(qset).distinct()
    else:
        results = []
    return render( request, "jocs/productes.html",
                                { "llista_jocs": results,
                                   "query": query }
                               )

from django.core.urlresolvers import reverse
from django.http import *
from django.contrib import messages
from django.core.management import call_command
import datetime
import sys

@login_required (login_url='jocs:index')
def fer_backups(request, id_backup):
    if (request.user.usuari.admin):
        objectiu = ''
        if id_backup == '1':
            objectiu = 'comandes'
        if id_backup == '2':
            objectiu = 'usuaris'
        if id_backup == '3':
            objectiu = 'jocs'
        sysout = sys.stdout
        nomFitxer = "backups/media/bdd-Backup" + str(datetime.datetime.now()).replace(" ","").replace(":","-")+".xml"
        sys.stdout = open (nomFitxer, 'w')
        call_command('dumpdata',objectiu,indent=2,format='xml')
        sys.stdout = sysout
        return HttpResponseRedirect(reverse('jocs:index'))
    else:
        return HttpResponseRedirect(reverse('jocs:productes'))


from __future__ import absolute_import

from collections import defaultdict
from flask_restful.reqparse import RequestParser
from itertools import groupby
from sqlalchemy.orm import contains_eager, joinedload, subqueryload_all
from typing import List
from uuid import UUID

from changes.api.base import APIView
from changes.api.serializer.models.testcase import TestCaseWithOriginCrumbler
from changes.config import db
from changes.constants import Result, Status
from changes.lib import build_type
from changes.models.build import Build, BuildPriority
from changes.models.buildseen import BuildSeen
from changes.models.event import Event
from changes.models.failurereason import FailureReason
from changes.models.job import Job
from changes.models.jobstep import JobStep
from changes.models.source import Source
from changes.models.test import TestCase
from changes.models.user import User

from changes.utils.originfinder import find_failure_origins

def find_changed_tests(current_build, previous_build, limit=25):
    current_job_ids = [j.id.hex for j in current_build.jobs]
    previous_job_ids = [j.id.hex for j in previous_build.jobs]

    if not (current_job_ids and previous_job_ids):
        return []

    current_job_clause = ', '.join(
        ':c_job_id_%s' % i for i in range(len(current_job_ids))
    )
    previous_job_clause = ', '.join(
        ':p_job_id_%s' % i for i in range(len(previous_job_ids))
    )

    params = {}
    for idx, job_id in enumerate(current_job_ids):
        params['c_job_id_%s' % idx] = job_id
    for idx, job_id in enumerate(previous_job_ids):
        params['p_job_id_%s' % idx] = job_id

    # find all tests that have appeared in one job but not the other
    # we have to build this query up manually as sqlalchemy doesnt support
    # the FULL OUTER JOIN clause
    query = """
        SELECT c.id AS c_id,
               p.id AS p_id
        FROM (
            SELECT label_sha, id
            FROM test
            WHERE job_id IN (%(current_job_clause)s)
        ) as c
        FULL OUTER JOIN (
            SELECT label_sha, id
            FROM test
            WHERE job_id IN (%(previous_job_clause)s)
        ) as p
        ON c.label_sha = p.label_sha
        WHERE (c.id IS NULL OR p.id IS NULL)
    """ % {
        'current_job_clause': current_job_clause,
        'previous_job_clause': previous_job_clause
    }

    total = db.session.query(
        'count'
    ).from_statement(
        'SELECT COUNT(*) FROM (%s) as a' % (query,)
    ).params(**params).scalar()

    if not total:
        return {
            'total': 0,
            'changes': [],
        }

    results = db.session.query(
        'c_id', 'p_id'
    ).from_statement(
        '%s LIMIT %d' % (query, limit)
    ).params(**params)

    all_test_ids = set()
    for c_id, p_id in results:
        if c_id:
            all_test_ids.add(c_id)
        else:
            all_test_ids.add(p_id)

    test_map = dict(
        (t.id, t) for t in TestCase.query.filter(
            TestCase.id.in_(all_test_ids),
        ).options(
            joinedload('job', innerjoin=True),
        )
    )

    diff = []
    for c_id, p_id in results:
        if p_id:
            diff.append(('-', test_map[UUID(p_id)]))
        else:
            diff.append(('+', test_map[UUID(c_id)]))

    return {
        'total': total,
        'changes': sorted(diff, key=lambda x: (x[1].package, x[1].name)),
    }

def get_failure_reasons(build):
    from changes.buildfailures import registry

    rows = FailureReason.query.join(
        JobStep, JobStep.id == FailureReason.step_id,
    ).filter(
        FailureReason.build_id == build.id,
        JobStep.replacement_id.is_(None),
    )

    failure_reasons = []
    for row in rows:
        failure_reasons.append({
            'id': row.reason,
            'reason': registry[row.reason].get_html_label(build),
            'step_id': row.step_id,
            'job_id': row.job_id,
            'data': dict(row.data or {}),
        })

    return failure_reasons

def get_parents_last_builds(build):
    # type: (Build) -> List[Build]
    # A patch have only one parent, while a revision can have more.
    if build.source.patch:
        parents = [build.source.patch.parent_revision_sha]
    elif build.source.revision:
        parents = build.source.revision.parents

    if parents:
        parent_builds = list(Build.query.filter(
            Build.project == build.project,
            Build.status == Status.finished,
            Build.id != build.id,
        ).join(
            Source, Build.source_id == Source.id,
        ).options(
            contains_eager('source').joinedload('revision'),
        ).filter(
            Source.revision_sha.in_(parents),
            *build_type.get_any_commit_build_filters()
        ).order_by(Build.date_created.desc()))
        if parent_builds:
            # This returns a list with the last build of each revision.
            return [
                list(builds)[0]
                for sha, builds in groupby(
                    parent_builds,
                    lambda rev: rev.source.revision_sha
                )
            ]
    return []

class BuildDetailsAPIView(APIView):
    post_parser = RequestParser()
    post_parser.add_argument('priority', choices=BuildPriority._member_names_)

    def get(self, build_id):
        build = Build.query.options(
            joinedload('project', innerjoin=True),
            joinedload('author'),
            joinedload('source').joinedload('revision'),
            subqueryload_all('stats'),
        ).get(build_id)
        if build is None:
            return '', 404

        try:
            most_recent_run = Build.query.filter(
                Build.project == build.project,
                Build.date_created < build.date_created,
                Build.status == Status.finished,
                Build.id != build.id,
            ).join(
                Source, Build.source_id == Source.id,
            ).filter(
                *build_type.get_any_commit_build_filters()
            ).options(
                contains_eager('source').joinedload('revision'),
                joinedload('author'),
            ).order_by(Build.date_created.desc())[0]
        except IndexError:
            most_recent_run = None

        jobs = list(Job.query.filter(
            Job.build_id == build.id,
        ))

        # identify failures
        if not jobs:
            # If we have no jobs, the query to find failures becomes very expensive due to `in_([])` being
            # handled poorly, but since we know the result, we can just set it.
            test_failures = []
            num_test_failures = 0
        else:
            test_failures = TestCase.query.options(
                joinedload('job', innerjoin=True),
            ).filter(
                TestCase.job_id.in_([j.id for j in jobs]),
                TestCase.result == Result.failed,
            ).order_by(TestCase.name.asc())
            num_test_failures = test_failures.count()
            test_failures = test_failures[:25]

        failures_by_job = defaultdict(list)
        for failure in test_failures:
            failures_by_job[failure.job].append(failure)

        failure_origins = find_failure_origins(
            build, test_failures)
        for test_failure in test_failures:
            test_failure.origin = failure_origins.get(test_failure)

        # identify added/removed tests
        if most_recent_run and build.status == Status.finished:
            changed_tests = find_changed_tests(build, most_recent_run)
        else:
            changed_tests = []

        seen_by = list(User.query.join(
            BuildSeen, BuildSeen.user_id == User.id,
        ).filter(
            BuildSeen.build_id == build.id,
        ))

        extended_serializers = {
            TestCase: TestCaseWithOriginCrumbler(),
        }

        event_list = list(Event.query.filter(
            Event.item_id == build.id,
        ).order_by(Event.date_created.desc()))

        context = self.serialize(build)
        context.update({
            'jobs': jobs,
            'seenBy': seen_by,
            'events': event_list,
            'failures': get_failure_reasons(build),
            'testFailures': {
                'total': num_test_failures,
                'tests': self.serialize(test_failures, extended_serializers),
            },
            'testChanges': self.serialize(changed_tests, extended_serializers),
            'parents': self.serialize(get_parents_last_builds(build)),
        })

        return self.respond(context)

    def post(self, build_id):
        build = Build.query.options(
            joinedload('project', innerjoin=True),
            joinedload('author'),
            joinedload('source').joinedload('revision'),
        ).get(build_id)
        if build is None:
            return '', 404

        args = self.post_parser.parse_args()
        if args.priority is not None:
            build.priority = BuildPriority[args.priority]

        db.session.add(build)

        context = self.serialize(build)

        return self.respond(context, serialize=False)


#List comprehensions 列表推导式
zCount = []
for zn in range(11):
    if zn%2 == 0:
        zCount.append(zn**2)
print(zCount)

squares = list(map(lambda x: x**2, range(11)))
print(squares)
#使用推导式
zCount = [zn**2 for zn in range(11) if zn%2==0]
print(zCount)


import tkinter as tk

# Crear una ventana
ventana = tk.Tk()

# Crear un botón
boton = tk.Button(ventana, text="Haz clic aquí")

# Configurar el comando del botón
def accion():
    print("¡Haz hecho clic en el botón!")
boton.config(command=accion)

# Empaquetar el botón en la ventana
boton.pack()

# Iniciar la ventana principal
ventana.mainloop()


import kivy

import utils

kivy.require('2.1.0')

from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.properties import StringProperty

class WelcomeWindow(Screen):
    """
    Welcome Window.
    This window will pop the first time the player starts to play and ask for the player's name.
    """
    WELCOME_NEW_PLAYER_TXT = StringProperty("ברוך הבא! מה שמך?"[::-1])
    CONTINUE_TXT = StringProperty("המשך"[::-1])

    def __init__(self, name):
        super().__init__()
        self.name = name

        self.trigger = True
        self.input_text = ''

    def on_pre_enter(self, *args):
        # Hide the hidden name input
        self.ids.name_input_hidden.size_hint_y = None
        self.ids.name_input_hidden.height = 0

        # Set size of the name input
        self.ids.name_txt_input.size_hint_y = None
        self.ids.name_txt_input.height = utils.get_str_pixel_height() * 2

        # Set pref name if exsists
        prefs = utils.get_prefrences()
        if 'player_name' in prefs:
            self.ids.name_input_hidden.text = prefs['player_name']

    def fix_string(self, txt):
        if not self.trigger:
            return

        self.trigger = False
        self.ids.name_txt_input.text = utils.fix_string(txt)
        self.trigger = True

    def redirect_focus(self):
        self.ids.name_input_hidden.focus = True

    def continue_to_game(self):
        App.get_running_app().player_name = self.ids.name_input_hidden.text
        utils.save_prefrences(player_name=self.ids.name_input_hidden.text)
        self.manager.current = 'main'


# python runpredict.py

from tensorflow.keras.preprocessing.image import img_to_array, load_img
from cnnbinary.main import get_data,ld_model

filename="./data/h5/model_c.h5"
batch_size=64
train_dir="./data/categorical/train/"
test_dir="./data/categorical/test/"
val_dir="./data/categorical/val/"

(train_generator,validation_generator,test_generator)=get_data(train_dir,test_dir,val_dir,batch_size)
model=ld_model(filename)

img = load_img("../Projekt/SkyCam/2018_07_01_0545.jpg")
img = img.resize((224, 224))
img = img_to_array(img)/255
print(type(img))
img = img.reshape((-1, 224, 224, 3))
res=model.predict(img)
print(res)
#model.predict(test_generator)


import cv2 as cv2
import numpy as np
import pandas as pd
from PIL import Image
import os
import SimpleITK as sitk
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from pathlib import Path
import argparse
import random
import numpy as np
import matplotlib.cm as cm
import glob

import re

import matplotlib.pyplot as plt
from matplotlib.cbook import get_sample_data
from skimage.transform import resize
import torch

def atoi(text):
    return int(text) if text.isdigit() else text

def natural_keys(text):
    '''
    alist.sort(key=natural_keys) sorts in human order
    http://nedbatchelder.com/blog/200712/human_sorting.html
    (See Toothy's implementation in the comments)
    '''
    return [ atoi(c) for c in re.split(r'(\d+)', text) ]

if __name__ == "__main__":
    # dataset = 2
    # bag_num = [1000, 200]
    dataset = 2
    bag_num = [1000, 200]
    bag_size = 8
    MIL = 1
    pos_ratio = 0.5

    bag_folder = '/Data3/GCA_Demo/Dataset%d_Bag_%d_%d_%d' % (dataset, bag_num[0],bag_size, MIL)

    data_folder = ['/Data3/GCA_Demo/Dataset%d_demo' % (dataset),'/Data3/GCA_Demo/Dataset%d_demo_val' % (dataset)]

    mode = ['Train','Val']
    r = np.random.RandomState(1)

    for mi in range(len(mode)):
        save_root = os.path.join(bag_folder, mode[mi])
        if not os.path.exists(save_root):
            os.makedirs(save_root)

        img_root = data_folder[mi]
        now_bag_num = int(bag_num[mi])

        for bi in range(now_bag_num):
            now_label = np.random.randint(0, 2, 1)[0]
            pos_list = glob.glob(os.path.join(img_root,'1','*size1024.png'))
            neg_list = glob.glob(os.path.join(img_root,'0','*size1024.png'))

            if now_label == 0:
                indices = torch.LongTensor(r.randint(0, len(neg_list), bag_size))

                if bag_size == 1:
                    now_images = [neg_list[indices]]
                else:
                    now_images = list(np.array(neg_list)[indices])

            else:
                if MIL:
                    pos_length = r.randint(1, int(pos_ratio * bag_size), 1)
                else:
                    pos_length = bag_size
                neg_length = bag_size - pos_length

                indices_pos = torch.LongTensor(r.randint(0, len(pos_list), pos_length))
                indices_neg = torch.LongTensor(r.randint(0, len(neg_list), neg_length))

                if len(indices_pos) == 1:
                    now_images_pos = [pos_list[indices_pos]]
                    now_images_neg = list(np.array(neg_list)[indices_neg])
                else:
                    now_images_pos = list(np.array(pos_list)[
                                              indices_pos])  # + list(np.array(self.image_list_class0)[indices_neg])   # self.image_list_class0[indices_neg]
                    now_images_neg = list(np.array(neg_list)[indices_neg])

                now_images = now_images_pos + now_images_neg
                random.shuffle(now_images)

            df = pd.DataFrame(columns = ['img_root', 'class'])
            for ki in range(len(now_images)):
                df.loc[ki] = [now_images[ki], now_label]

            df.to_csv(os.path.join(save_root, 'bag_%d.csv' % (bi)), index = False)


#Memory Mangement Unit: Best fit, Worst fit, First fit..
processSize = [212, 417, 112, 426]
memBlocksSizeInit = [100, 500, 200, 300, 600]

process = len(processSize)
blocks = len(memBlocksSizeInit)

def PrintProcess(allocation,memBlocksSize, a):
    print(a)
    for i in range(process):
        if(allocation[i] == -1):
            print("Process ", i+1,"of size",processSize[i],"assignment not possible")
        else:
            print("Process ", i+1,"of size",processSize[i], "MB assigned Block Number", allocation[i]+1)

def bestFit(memBlocksSize):
    allocation = [-1]*(len(processSize))

    for i in range(process):
        bestFitIndex = -1
        for j in range(blocks):

            if(memBlocksSize[j] >= processSize[i]):
                if(bestFitIndex == -1):
                    bestFitIndex = j
                elif(memBlocksSize[j] < memBlocksSize[bestFitIndex] ):
                    bestFitIndex = j

        if(bestFitIndex != -1):
            allocation[i] = bestFitIndex
            memBlocksSize[bestFitIndex] -= processSize[i]

    PrintProcess(allocation, memBlocksSize, "Best Fit")

def firstFit(memBlocksSize):
    allocation = [-1]*(len(processSize))

    for i in range(process):
        for j in range(blocks):
            if(memBlocksSize[j] >= processSize[i]):
                allocation[i] = j
                memBlocksSize[j] -= processSize[i]
                break

    PrintProcess(allocation,memBlocksSize, "First Fit")

def worstFit(memBlocksSize):
    allocation = [-1]*(len(processSize))
    #print(memBlocksSize)

    for i in range(process):
        worstFitIndex = -1
        for j in range(blocks):
            if(memBlocksSize[j] >= processSize[i]):
                if(worstFitIndex == -1):
                    worstFitIndex = j
                elif(memBlocksSize[j] > memBlocksSize[worstFitIndex] ):
                    worstFitIndex = j

        if(worstFitIndex != -1):
            allocation[i] = worstFitIndex
            #print(allocation[i])
            memBlocksSize[worstFitIndex] -= processSize[i]

    PrintProcess(allocation, memBlocksSize, "Worst Fit")

memBlocksSize = memBlocksSizeInit.copy()
bestFit(memBlocksSize)

memBlocksSize = memBlocksSizeInit.copy()
firstFit(memBlocksSize)

memBlocksSize = memBlocksSizeInit.copy()
worstFit(memBlocksSize)


class Star_Hall:
    hall_list = []

    def add_hall(self, obj):
        self.hall_list.append(obj)

class Hall(Star_Hall):
    def __init__(self, rows, cols, hall_no):
        self.__seats = {}
        self.__show_list = []
        self.__rows = rows
        self.__cols = cols
        self.__hall_no = hall_no

        super().add_hall(self)

    def entry_show(self, id, movie_name, time):
        self.__show_list.append((id, movie_name, time))
        self.__seats[id] = [[False for i in range(self.__cols)] for i in range(self.__rows)]

    def book_seats(self, customer_name, phone_number, show_id, seats_for_show):
        if self.__seats.get(show_id) is not None:
            for seat in seats_for_show:
                if (seat[0] > 0 and seat[0] <= self.__rows) and (seat[1] > 0 and seat[1] <= self.__cols):
                    if self.__seats[show_id][seat[0]-1][seat[1]-1] == False:
                        self.__seats[show_id][seat[0]-1][seat[1]-1] = True
                        print(f'Seat with row: {seat[0]}, column: {seat[1]} booked.')
                    else:
                        print(f'Seat with row: {seat[0]}, colum: {seat[1]} already booked.')
                else:
                    print(f"Seat with row: {seat[0]}, column: {seat[1]} is invalid")
        else:
            print('Invalid id of show')
            return

    def view_show_list(self):
        for i in self.__show_list:
            print(f"MOVIE NAME: {i[1]}\tSHOW ID: {i[0]}\tTIME: {i[2]}")

    def view_available_seats(self, show_id):
        if show_id in self.__seats.keys():
            for i in range(len(self.__seats[show_id])):
                for j in range(len(self.__seats[show_id][i])):
                    if self.__seats[show_id][i][j] == False:
                        print(f'{chr(65+i)}{j+1}', end="\t")
                    else:
                        print("XX", end="\t")
                print('\n')
        else:
            print("Invalid show id")

star = Hall(3, 3, 1)

star.entry_show('ae123', 'Black Adam', 'Oct 26 2022 10:00 AM')
star.entry_show('ae50', 'Spiderman', 'Oct 28 2022 8:00 PM')

while True:
    inp = input("1. VIEW ALL SHOWS TODAY\n2. VIEW AVAILABLE SEATS\n3. BOOK SEAT\n(Press 'q' to quit)\nEnter option: ")
    print(inp)
    if inp != 'q' and int(inp) in [1, 2, 3]:
        if int(inp) == 1:
            print("\n-------------------------------------------------------\n")
            star.view_show_list()
            print("\n-------------------------------------------------------\n")
        elif int(inp) == 2:
            id_inp = input("ENTER SHOW ID: ")
            print("\n-------------------------------------------------------\n")
            star.view_available_seats(id_inp)
            print("\n-------------------------------------------------------\n")
        elif int(inp) == 3:
            print("\n-------------------------------------------------------\n")
            name_inp = input("ENTER CUSTOMER NAME: ")
            phone_inp = input("ENTER CUSTOMER PHONE NUMBER: ")
            show_id_inp = input("ENTER SHOW ID: ")
            tickets_no = input("ENTER NUMBER OF TICKETS: ")
            tickets = []
            view_tickets = []
            for i in range(int(tickets_no)):
                seat_no = input("ENTER SEAT NO: ")
                view_tickets.append(seat_no)
                seat_row = ord(seat_no[0])-64
                seat_col = int(seat_no[1])
                tickets.append((seat_row, seat_col))
            star.book_seats(name_inp, phone_inp, show_id_inp, tickets)
            print("-------------------------------------------------------\n")
            print(f'CUSTOMER NAME: {name_inp}')
            print(f'PHONE NUMBER: {phone_inp}')
            print(f'SHOW ID: {show_id_inp}')
            print(f'TICKETS: {view_tickets}')
            print("\n-------------------------------------------------------\n")

    else:
        break


lis = [[0,-1],[0,-2],[0,-3],[1,-3],[2,-3],[3,-3],[3,-4],[3,-5],[4,-5],[5,-5],[5,-4],[5,-3],[6,-3],[7,-3],[7,-4],[7,-5],[7,-6],[7,-7],[6,-7],[5,-7],[4,-7],[3,-7],[2,-7],[1,-7],[0,-7],[-1,-7],[-1,-6]]
s = [-1,-5]

direction, steps = map(str, input().split())
steps = int(steps)

while direction != 'q' and steps != 0:
  found = False
  if direction == 'l':
    for i in range(steps):
      lis.append([s[0], s[1]])
      s[0] -= 1
      if s in lis:
        found = True

  elif direction == 'r':
    for i in range(steps):
      lis.append([s[0], s[1]])
      s[0] += 1
      if s in lis:
        found = True

  elif direction == 'd':
    for i in range(steps):
      lis.append([s[0], s[1]])
      s[1] -= 1
      if s in lis:
        found = True

  elif direction == 'u':
    for i in range(steps):
      lis.append([s[0], s[1]])
      s[1] += 1
      if s in lis:
        found = True

  if not found:
    print(s[0], s[1], 'safe')
  else:
    print(s[0], s[1], 'DANGER')
    break

  direction, steps = map(str, input().split())
  steps = int(steps)


#!/usr/bin/env python
import math
import sys
import time
import pybullet as p
from time import sleep

class Simulation:
    def __init__(self, directory):
        self.t = 0
        self.dt = 0.001

        # Instanciation de Bullet
        physicsClient = p.connect(p.GUI)
        p.setGravity(0, 0, -10)

        # Chargement du sol
        planeId = p.loadURDF(directory+'environment/plane.urdf')

        # Chargement du robot
        cubeStartPos = [0, 0, 0.0]
        cubeStartOrientation = p.getQuaternionFromEuler([0, 0, 0])
        self.robot = p.loadURDF(directory+"/robot.urdf",
                            cubeStartPos, cubeStartOrientation)

        # Engine parameters
        p.setPhysicsEngineParameter(fixedTimeStep=self.dt)
        p.setRealTimeSimulation(1)
        # p.setPhysicsEngineParameter(numSolverIterations=5)
        # p.setPhysicsEngineParameter(numSubSteps=1)

        # Retrieving joints and frames
        self.joints = {}
        self.frames = {}

        # Collecting the available joints
        for k in range(p.getNumJoints(self.robot)):
            jointInfo = p.getJointInfo(self.robot, k)
            name = jointInfo[1].decode('utf-8')
            if '_fixing' not in name:
                if '_frame' in name:
                    self.frames[name] = k
                else:
                    self.joints[name] = k

        print('* Found '+str(len(self.joints))+' DOFs')
        print('* Found '+str(len(self.frames))+' frames')

    def getFrames(self):
        frames = {}

        for name in self.frames.keys():
            jointState = p.getLinkState(self.robot, self.frames[name])
            pos = jointState[0]
            orientation = p.getEulerFromQuaternion(jointState[1])
            frames[name] = [pos, orientation]

        return frames

    def setJoints(self, joints):
        for name in joints.keys():
            if name in self.joints:
                p.setJointMotorControl2(
                    self.robot, self.joints[name], p.POSITION_CONTROL, joints[name])
            else:
                raise Exception("Can't find joint %s" % name)

    def getJoints(self):
        return self.joints.keys()

    def execute(self):
        while True:
            self.tick()

    def tick(self):
        self.t += self.dt
        p.stepSimulation()


"""utils.py

A few useful objects which do not naturally fit anywhere else.
"""
import ast
import difflib
import types
import uuid
from typing import Any, Dict, Iterable, List, Tuple

import pure_eval

from .tb_data import TracebackData  # purely for type checking

def unique_variable_name() -> str:
    """Creates a unique variable name. Useful when attempting to introduce
    a new token to see if it can fix specific cases of SyntaxError."""
    name = uuid.uuid4()
    return f"_{name.hex}"

def eval_expr(expr: str, frame: types.FrameType) -> Any:
    """Attempts to evaluate the expression 'expr' in a frame.
    Note that 'expr' might be a string containing leading spaces which need
    to be removed prior to being evaluated.

    This can raise some exceptions which are meant to be caught by the
    calling function.
    """
    node = ast.parse(expr.strip()).body[0].value  # type: ignore # noqa
    evaluator = pure_eval.Evaluator.from_frame(frame)
    return evaluator[node]  # can raise an exception

def get_similar_words(word_with_typo: str, words: Iterable[str]) -> List[str]:
    """Returns a list of similar words.

    The parameters we chose are based on experimenting with
    different values of the cutoff parameter for the difflib function
    get_close_matches.

    Suppose we have the following words:
    ['cos', 'cosh', 'acos', 'acosh']
    If we use a cutoff of 0.66, and ask for a maximum of 4 matches,
    all will be a match for 'cost'.  However, if we increase the cutoff
    to 0.67, 'acosh' will be dropped from the list, which seems sensible.

    However, this cutoff is "too generous" when dealing with long words.
    Using a cutoff up to 0.75 will result in both 'ascii_lowercase'
    and 'ascii_uppercase' matching 'ascii_lowecase'. Increasing the cutoff
    to 0.76 will drop ascii_uppercase as a match which also seems sensible.

    We thus use a heuristic cutoff based on length which ends up
    matching our expectation as to what a close match should be.

    We also do not return any matches for single character variables,
    nor do we consider single character variable potential matches.
    """
    if len(word_with_typo) == 1:
        return []
    words = set(words)  # removes duplicates
    words = sorted(list(words))  # get predictable order for tests

    if 2 <= len(word_with_typo) <= 4:
        words = [word for word in words if 2 <= len(word) <= 5]
        max_dist = 1
    elif 5 <= len(word_with_typo) <= 8:
        words = [word for word in words if 4 <= len(word) <= 10]
        max_dist = 2
    else:
        words = [word for word in words if len(word) >= 7]
        max_dist = 3

    similar_words: Dict[int, List[str]] = {}
    for word in words:
        distance = _leven(word_with_typo, word, max_dist + 1)
        if distance <= max_dist:
            if distance in similar_words:
                similar_words[distance].append(word)
            else:
                similar_words[distance] = [word]

    similar = []
    for distance in range(1, max_dist + 1):
        if distance in similar_words and similar_words[distance]:
            similar.extend(similar_words[distance])
    if not similar:  # example PI -> pi
        if word_with_typo.lower() in words:
            similar.append(word_with_typo.lower())
        elif word_with_typo.upper() in words:
            similar.append(word_with_typo.upper())
    return similar

# The following code, including comments, has been adapted from
# https://gist.github.com/giststhebearbear/4145811

def _leven(s1: str, s2: str, max_distance: int) -> int:
    #  get the smallest string so our rows are minimized
    s1, s2 = (s1, s2) if len(s1) <= len(s2) else (s2, s1)
    #  set lengths
    l1, l2 = len(s1), len(s2)

    #  We are simulating an NM matrix where n is the longer string
    #  and m is the shorter string. By doing this we can minimize
    #  memory usage to O(M).
    #  Since we are simulating the matrix we only maintain two rows
    #  at a time the current row and the previous rows.
    #  A move from the current cell looking at the cell before it indicates
    #  consideration of an insert operation.
    #  A move from the current cell looking at the cell above it indicates
    #  consideration of a deletion
    #  Both operations are cost 1
    #  A move from the current cell to the cell up and to the left indicates
    #  an edit operation of 0 cost for a matching character and a 1 cost for
    #  a non matching characters
    #  no row has been previously computed yet, set empty row
    #  Since this is also a Damerau-Levenshtein calculation transposition
    #  costs will be taken into account. These look back 2 characters to
    #  determine optimal cost based on a possible transposition
    #  example: aei -> aie with Levensthein has a cost of 2
    #  match a, change e->i change i->e => aie
    #  Damarau-Levenshtein has a cost of 1
    #  match a, transpose ei to ie => aie
    prev_row: List[int] = []

    #  build first leven matrix row
    #  The first row represents transformation from an empty string
    #  to the shorter string making it static [0-n]
    #  since this row is static we can set it as
    #  cur_row and start computation at the second row or index 1
    cur_row = [x for x in range(l1 + 1)]

    # use second length to loop through all the rows being built
    # we start at row one
    for row_num in range(1, l2 + 1):
        #  set transposition, previous, and current
        #  because the row_num always increments by one
        #  we can use row_num to set the value representing
        #  the first column which is indicative of transforming TO
        #  the empty string from our longer string
        #  transposition row maintains an extra row so that it is possible
        #  for us to apply Damarau's formula
        transposition_row, prev_row, cur_row = prev_row, cur_row, [row_num] + [0] * l1

        #  consider if we have passed the max distance if all paths through
        #  the transposition row are larger than the max we can stop calculating
        #  distance and return the last element in that row and return the max
        if transposition_row and all(
            cell_value > max_distance for cell_value in transposition_row
        ):
            return max_distance

        for col_num in range(1, l1 + 1):
            insertion_cost = cur_row[col_num - 1] + 1
            deletion_cost = prev_row[col_num] + 1
            change_cost = prev_row[col_num - 1] + (
                0 if s1[col_num - 1] == s2[row_num - 1] else 1
            )
            #  set the cell value - min distance to reach this
            #  position
            cur_row[col_num] = min(insertion_cost, deletion_cost, change_cost)

            #  test for a possible transposition optimization
            #  check to see if we have at least 2 characters
            if 1 < row_num <= col_num:  # sourcery skip
                #  test for possible transposition
                if (
                    s1[col_num - 1] == s2[col_num - 2]
                    and s2[col_num - 1] == s1[col_num - 2]
                ):
                    cur_row[col_num] = min(
                        cur_row[col_num], transposition_row[col_num - 2] + 1
                    )

    #  the last cell of the matrix is ALWAYS the shortest distance between the two strings
    return cur_row[-1]

def list_to_string(list_: Iterable[str], sep: str = ", ") -> str:
    """Transforms a list of names, like ['a', 'b', 'c'], into a single
    string of names, like "a, b, c"."""
    result = ["{c}".format(c=c.replace("'", "")) for c in list_]
    return sep.join(result)

def expected_in_result(expected: str, result: str) -> Tuple[bool, str]:
    """Used in tests. Intended to help more quickly identify
    differences between what was expected and what was found."""
    if expected in result:
        return True, "Test is satisfied: 'expected' is found in 'result'."
    result = result.strip(" ")
    lines = result.splitlines()
    best_ratio = 0.0
    best_line = ""
    for line in lines:
        line = line.strip(" ")
        ratio = difflib.SequenceMatcher(None, expected, line).ratio()
        if ratio > best_ratio:
            best_ratio = ratio
            best_line = line

    if result == best_line:
        return False, "Only differences are different white spaces at the ends."

    return False, "\n" + "\n".join(difflib.ndiff([expected], [best_line]))

def get_bad_statement(tb_data: TracebackData) -> str:
    """This function attempts to recover a complete statement
    even if it spans multiple lines."""
    try:
        ex = tb_data.records[-1].executing
        [statement] = ex.statements
        return ex.source.asttokens().get_text(statement)  # type: ignore
    except Exception:  # noqa
        if hasattr(tb_data, "original_bad_line"):
            return tb_data.original_bad_line
        elif hasattr(tb_data, "bad_line"):
            return tb_data.bad_line
        return ""

def to_code_block(code: str) -> str:
    """Takes some code and indent it with an added empty line at the top
    and bottom so that it is usable as a Markdown code block without
    showing the triple backquotes.
    """
    indent = " " * 4
    new_lines = ["\n"]
    lines = code.split("\n")
    new_lines.extend(f"{indent}{line}" for line in lines)
    new_lines.append("\n")
    return "\n".join(new_lines)

# The following is currently not used in friendly-traceback but
# is used by friendly.  It is kept here as it is part of
# a trio of functions, with one being used in friendly-traceback.
def get_highlighting_ranges(lines: List[str]) -> Dict[int, List[Tuple[int, int]]]:
    """Given a block of code highlighted primarily with carets (^),
    this function will identify the lines containing carets and break up
    that line into sub-ranges, showing at which indices the carets
    begin and end.

    It returns a dict whose index is the line number where the carets
    were found, and the content is a list of sub-ranges.
    """
    caret_set = set("^->")  # Some lines include --> to indicate that the
    # error continues on the next line
    error_lines = {}
    for index, line in enumerate(lines):
        if set(line.strip().replace(" ", "")).issubset(caret_set) and "^" in line:
            # Ensure the line contains only ^ and spaces
            line = line.replace("-", " ").replace(">", " ").rstrip("\n")
            # Then, add the amount of spaces corresponding to the number of
            # characters in the line to be highlighted
            line = line + " " * (len(lines[index - 1].rstrip("\n")) - len(line))
            error_lines[index] = get_single_line_highlighting_ranges(line)
            # includes the remaining range for the line to be highlighted
    return error_lines

def get_single_line_highlighting_ranges(line: str) -> List[Tuple[int, int]]:
    """Given a single line containing alternating sequences of consecutive
    spaces and carets (^), this function will compute the position of the
    beginning and end of each sequence of consecutive characters,
    recording them as tuples

    It returns a list corresponding containing these tuples alternating between
    regions where carets are not found and where carets are found.
    """
    caret_line = []
    scanning_carets = False
    char_index = begin = 0
    for char_index, char in enumerate(line):
        if not scanning_carets and char == "^":
            caret_line.append((begin, char_index))
            begin = char_index
            scanning_carets = True
        if scanning_carets and char == " ":
            caret_line.append((begin, char_index))
            begin = char_index
            scanning_carets = False
    # include the last subrange
    caret_line.append((begin, char_index + 1))
    return caret_line

def create_caret_highlighted(caret_line: List[Tuple[int, int]]) -> str:
    """Creates a line containing alternating sequences of spaces
    and carets, from a list containing a series of tuples denoting
    the range in which the carets are found.

    It is the inverse of get_single_line_highlighting_ranges().
    """
    line = []
    insert_caret = False
    for begin, end in caret_line:
        if insert_caret:
            line.append("^" * (end - begin))
        else:
            line.append(" " * (end - begin))
        insert_caret = not insert_caret
    return "".join(line)


import torch
import torch.nn as nn
from torch.utils.data import DataLoader, WeightedRandomSampler
from torch.optim.lr_scheduler import MultiStepLR
from torch.utils.tensorboard import SummaryWriter
import torchvision
import time
import matplotlib.pyplot as plt
import numpy as np
import random
import os

from loss import DGCLoss, MAPLoss, L1Loss
from utils import CosineSimilarityMatrix, cosine_similarity_matrix, ndcg, meanavep, CollateFn
from datasets import build as build_dataset

import pandas as pd
import seaborn as sns
import string

from options import get_args_parser

from models import PHOCNet, ResNet12, ResNet34, StringEmbedding
from logger import AverageMeter
from pretrain import pretrain_string
import Levenshtein
import pickle
import nltk
from nltk.corpus import stopwords
nltk.download('stopwords')

import multiprocessing
from joblib import Parallel, delayed

def train(img_model, str_model, device, train_loader, optim, lossf, loss_weights, similarity, epoch):
    img_model.train()
    str_model.train()

    stats = {
        'train_loss': AverageMeter(),
        'img_loss': AverageMeter(),
        'str_loss': AverageMeter(),
        'cross_loss': AverageMeter(),
    }

    start_time = time.time()
    for step, (data, targets, labels, _) in enumerate(train_loader):
        optim.zero_grad()

        data, targets = data.to(device), targets.to(device)

        # Batch size
        bz = len(labels)

        output_img = img_model(data)
        output_str = str_model(targets)

        # Similarity matrices
        ranking_img = similarity(output_img, output_img)
        ranking_str = similarity(output_str, output_str)
        ranking_cross = similarity(output_str, output_img)

        mask_diagonal = ~ torch.eye(ranking_img.shape[0]).bool()

        # Ground-truth Ranking function
        gt = torch.zeros((ranking_img.shape[0], ranking_img.shape[1]), device=ranking_img.device)
        for i, str1 in enumerate(labels):
            for j, str2 in enumerate(labels[i+1:], start=i+1):
                gt[i,j] = gt[j, i] = Levenshtein.distance(str1, str2)

        loss_img, loss_str, loss_cross = 0,0,0
        for k,loss_func in lossf.items():
            if k == 'l1_loss':
                # Regularization
                loss_cross += loss_weights[k]*loss_func(output_str, output_img)
                continue
            loss_img += loss_weights[k]*loss_func(ranking_img, gt, mask_diagonal=mask_diagonal)
            if k != 'map_loss':
                loss_str += loss_weights[k]*loss_func(ranking_str, gt, mask_diagonal=mask_diagonal)
            loss_cross += loss_weights[k]*loss_func(ranking_cross, gt)

        loss = loss_img + loss_str + loss_cross

        loss.backward()
        optim.step()

        stats['train_loss'].update(loss.item(), bz)
        stats['img_loss'].update(loss_img.item(), bz)
        if torch.is_tensor(loss_str):
            loss_str = loss_str.item()
        stats['str_loss'].update(loss_str, bz)
        stats['cross_loss'].update(loss_cross.item(), bz)

        if step % 1500 == 0:
            log_stats = [f'{k}: {v.avg:.4f}' for k,v in stats.items()]
            print(
                        f'EPOCH: {epoch}',
                        f'STEP: {step+1:0>{len(str(len(train_loader)))}}/{len(train_loader)}',
                        f'LOSS: {log_stats}',
            )

    log_stats = [f'{k}: {v.avg:.4f}' for k,v in stats.items()]
    print(
                f'EPOCH: {epoch}',
                f'STEP: {step+1:0>{len(str(len(train_loader)))}}/{len(train_loader)}',
                f'LOSS: {log_stats}',
    )
    end_time = time.time()
    print(f'TOTAL-TIME: {round(end_time-start_time)}', end='\n')

    return stats

# Define task for multiprocessing
def multiprocessing_levenshtein(str1, gallery_labels, i):
    out = torch.zeros(gallery_labels.shape)
    for j, str2 in enumerate(gallery_labels[i+1:], start=i+1):
        if str1 in string.punctuation or str2 in string.punctuation:
            out[j] = 15
            continue
        out[j] = Levenshtein.distance(str1, str2)
    return out

def test(img_model, str_model, device, test_loader, lossf, criterion):
    img_model.eval()
    str_model.eval()

    start_time = time.time()

    stats = {}
    for k, v in criterion.items():
        stats[k] = AverageMeter()
        stats[f'img_{k}'] = AverageMeter()
        if k != 'map':
            stats[f'str_{k}'] = AverageMeter()

    with torch.no_grad():
        queries, gallery, img_labels, img_id = [], [], [], []
        for step, (data, targets, labels, word_id) in enumerate(test_loader):
            data, targets = data.to(device), targets.to(device)

            output_img = img_model(data)
            output_str = str_model(targets)

            queries.append(output_str)
            gallery.append(output_img)
            img_labels.append(list(labels))
            img_id.append(list(word_id))
        gallery_labels = np.concatenate(img_labels)
        gallery = torch.cat(gallery)

        query_labels, idx_queries = np.unique(gallery_labels, return_index=True)
        queries = torch.cat(queries)
        queries = queries[idx_queries]

        # Ground-truth Ranking function
        n_processors = min(multiprocessing.cpu_count(), 8)
        gt_img = Parallel(n_jobs=n_processors)(delayed(multiprocessing_levenshtein)(str1, gallery_labels, i) for i, str1 in enumerate(gallery_labels))
        gt_img = torch.stack(gt_img)
        gt_img = gt_img + gt_img.t()

        gt_cross = gt_img[idx_queries]
        gt_str = gt_img[idx_queries][:, idx_queries]

        if test_loader.dataset._dataset == 'IAM':
            idx_without_stopwords = [i for i, w in enumerate(query_labels) if (w not in stopwords.words()) and (w not in string.punctuation)]
            query_labels = query_labels[idx_without_stopwords]
            queries = queries[idx_without_stopwords]
            gt_cross = gt_img[idx_without_stopwords]
            gt_str = gt_img[idx_without_stopwords][:, idx_without_stopwords]

            idx_without_stopwords = [i for i, w in enumerate(gallery_labels) if (w not in stopwords.words()) and (w not in string.punctuation)]
            query_gallery_labels = gallery_labels[idx_without_stopwords]
            query_gallery = gallery[idx_without_stopwords]
            gt_img = gt_img[idx_without_stopwords]
        else:
            query_gallery = gallery

        for k, criterion_func in criterion.items():
            stats[k].update(criterion_func(queries, gt_cross, gallery=gallery))
            stats[f'img_{k}'].update(criterion_func(query_gallery, gt_img, gallery, drop_first=True))
            if k != 'map':
                stats[f'str_{k}'].update(criterion_func(queries, gt_str))

        img_id = np.concatenate(img_id)

    stats_str = [f'{k}: {v.avg:.4f}' for k,v in stats.items()]
    print(f'\n* TEST set: {stats_str}')
    end_time = time.time()
    print(f'TOTAL-TEST-TIME: {round(end_time-start_time)}', end='\n')
    return stats, (queries, query_labels), (gallery, gallery_labels, img_id)

def main(args):
    torch.manual_seed(args.seed)
    np.random.seed(args.seed)
    random.seed(args.seed)

    device = torch.device('cpu')
    if torch.cuda.is_available():
        device = torch.device(args.device)
        torch.cuda.manual_seed(args.seed)

    train_file, val_file, test_file = build_dataset(args.dataset, args.data_path, partition=args.partition)

    train_sampler = WeightedRandomSampler(weights=train_file.balance_weigths(), num_samples=15000, replacement = True)

    collate = CollateFn(train_file.voc_size())
    train_loader = DataLoader(
        dataset=train_file,
        batch_size=args.batch_size,
        sampler=train_sampler,
        num_workers=args.num_workers,
        drop_last=True,
        collate_fn=collate.collate_fn,
        pin_memory=True
    )
    val_loader = DataLoader(
        dataset=val_file,
        batch_size=args.batch_size,
        shuffle=False,
        num_workers=args.num_workers,
        collate_fn=collate.collate_fn,
        pin_memory=True
    )
    test_loader = DataLoader(
        dataset=test_file,
        batch_size=args.batch_size,
        shuffle=False,
        num_workers=args.num_workers,
        collate_fn=collate.collate_fn,
        pin_memory=True
    )

    if args.arch == 'phoc':
        img_model = PHOCNet(args.out_dim, in_channels=train_file.in_channels).to(device)
    elif args.arch == 'resnet':
        img_model = ResNet12(args.out_dim, in_channels=train_file.in_channels).to(device)
    elif args.arch == 'resnet34':
        img_model = ResNet34(args.out_dim, in_channels=train_file.in_channels).to(device)
    else:
        raise ValueError(f'architecture {args.arch} not supported')

    str_model = StringEmbedding(args.out_dim, train_file.voc_size()).to(device)

    optim = torch.optim.Adam([
        {'params': img_model.parameters()},
        {'params': str_model.parameters()}
    ], args.learning_rate, weight_decay=0.0005)
    scheduler = MultiStepLR(optim, [25, 40], gamma=0.25, verbose=True)

    similarity = CosineSimilarityMatrix()

    lossf, loss_weights = {}, {}
    lossf['l1_loss'] = L1Loss()
    loss_weights['l1_loss'] = 0.5
    if args.loss == 'ndcg':
        lossf['ndcg_loss'] = DGCLoss(k=args.tau, penalize=args.penalize)
        loss_weights['ndcg_loss'] = 1
    elif args.loss == 'map':
        lossf['map_loss'] = MAPLoss(k=args.tau)
        loss_weights['map_loss'] = 1
    elif args.loss == 'combine':
        lossf['ndcg_loss'] = DGCLoss(k=args.tau, penalize=args.penalize)
        lossf['map_loss'] = MAPLoss(k=args.tau)
        loss_weights['ndcg_loss'] = 1
        loss_weights['map_loss'] = 1
    else:
        raise ValueError(f'loss {args.loss} not supported')

    criterion = {
        'ndcg' : ndcg,
        'map' : meanavep,
    }

    if args.save is not None and not args.test:
        writer = SummaryWriter(log_dir=args.save)
        # Test transforms
        for i in range(5):
            image, _, _, _ = train_file[0]
            writer.add_image('Train/Images', image, i)

            image, _, _, _ = test_file[0]
            writer.add_image('Test/Images', image, i)

    if (args.pretrain_path is not None) and not args.pretrain_str:
        print('Loading pretrained string embedder')
        checkpoint = torch.load(args.pretrain_path, map_location=device)
        str_model.load_state_dict(checkpoint['str_state_dict'])

    best_stats = {'ndcg': 0, 'map': 0}
    start_epoch = 1
    early_stop_counter = 0
    if args.load is not None:
        checkpoint = torch.load(args.load, map_location=device)
        img_model.load_state_dict(checkpoint['img_state_dict'])
        str_model.load_state_dict(checkpoint['str_state_dict'])
        optim.load_state_dict(checkpoint['optimizer'])
        best_stats = checkpoint['best_stats']
        start_epoch = checkpoint['epoch']

        print(f'Model load at epoch {start_epoch}\n\t* NDCG = {best_stats["ndcg"]}\n\t* MAP = {best_stats["map"]}\n')

    if not args.test:
        if args.pretrain_str and (args.dataset == 'iiit5k'):
            str_model = pretrain_string(str_model, device, args.data_path, similarity, train_file.char_to_idx)
            if args.pretrain_path is not None:
                torch.save({
                    'str_state_dict': str_model.state_dict(),
                    }, os.path.join(args.pretrain_path, 'checkpoint.pth'))

        for epoch in range(1, args.epochs+1):
            train_stats = train(img_model, str_model, device, train_loader, optim, lossf, loss_weights, similarity, epoch)
            val_stats, str_embedding, img_embedding = test(img_model, str_model, device, val_loader, lossf, criterion)

            scheduler.step()

            if args.save is not None:
                # Train
                writer.add_scalar('Loss/Global', train_stats['train_loss'].avg, epoch)
                writer.add_scalar('Loss/Image', train_stats['img_loss'].avg, epoch)
                writer.add_scalar('Loss/String', train_stats['str_loss'].avg, epoch)
                writer.add_scalar('Loss/Cross', train_stats['cross_loss'].avg, epoch)

                # Test
                writer.add_scalar('TestQbS/NDCG', val_stats['ndcg'].avg, epoch)
                writer.add_scalar('TestQbS/MAP', val_stats['map'].avg, epoch)

                writer.add_scalar('TestQbE/NDCG', val_stats['img_ndcg'].avg, epoch)
                writer.add_scalar('TestQbE/MAP', val_stats['img_map'].avg, epoch)

                writer.add_scalar('TestSED', val_stats['str_ndcg'].avg, epoch)

                # Confusion Matrix
                sed = torch.zeros((str_embedding[0].shape[0], img_embedding[0].shape[0]), device=str_embedding[0].device)
                for i, str1 in enumerate(str_embedding[1]):
                    for j, str2 in enumerate(img_embedding[1]):
                        sed[i,j] = Levenshtein.distance(str1, str2)
                distance = cosine_similarity_matrix(str_embedding[0],img_embedding[0])

                sed = sed.view(-1).tolist()
                distance = distance.view(-1).tolist()
                fig = plt.figure()
                plt.scatter(sed, distance)
                ax = plt.gca()
                ax.set_ylim(0,1)
                plt.xlabel('String Edit Distance')
                plt.ylabel('Learned Similarity')

                writer.add_figure('Correlation', fig, global_step = epoch)

                data = []
                sed, distance = np.array(sed), np.array(distance)
                for used in np.unique(sed):
                   data.append(distance[used == sed])

                fig = plt.figure()
                plt.boxplot(data)
                ax = plt.gca()
                ax.set_ylim(0,1)
                plt.xlabel('String Edit Distance')
                plt.ylabel('Learned Similarity')

                writer.add_figure('Box Plot', fig, global_step = epoch)

                # Learning rate
                writer.add_scalar('Learning Rate', optim.param_groups[0]['lr'], epoch)

                torch.save({
                    'epoch': epoch,
                    'img_state_dict': img_model.state_dict(),
                    'str_state_dict': str_model.state_dict(),
                    'best_stats': best_stats,
                    'optimizer': optim.state_dict(),
                    }, os.path.join(args.save, 'checkpoint.pth'))

    if args.save is not None and not args.test:
        checkpoint = torch.load(os.path.join(args.save, 'checkpoint.pth'), map_location=device)
        img_model.load_state_dict(checkpoint['img_state_dict'])
        str_model.load_state_dict(checkpoint['str_state_dict'])

    test_stats, str_embedding, img_embedding = test(img_model, str_model, device, test_loader, lossf, criterion)

    if args.save is not None:
        # Embedding
        header = str_embedding[1].shape[0]*['String/'] + img_embedding[1].shape[0]*['Image/']
        embedding = torch.cat((str_embedding[0], img_embedding[0]))
        metadata = np.concatenate((str_embedding[1], img_embedding[1]))
        metadata = np.core.defchararray.add(header, metadata)

        with open(os.path.join(args.save, 'str_embedding.pickle'), 'wb') as handle:
            pickle.dump(str_embedding, handle)
        with open(os.path.join(args.save, 'img_embedding.pickle'), 'wb') as handle:
            pickle.dump(img_embedding, handle)

        # Confusion Matrix
        sed = torch.zeros((str_embedding[0].shape[0], img_embedding[0].shape[0]), device=str_embedding[0].device)
        for i, str1 in enumerate(str_embedding[1]):
            for j, str2 in enumerate(img_embedding[1]):
                sed[i,j] = Levenshtein.distance(str1, str2)
        distance = cosine_similarity_matrix(str_embedding[0],img_embedding[0])

        sed = sed.view(-1).tolist()
        distance = distance.view(-1).tolist()

        data = []
        sed, distance = np.array(sed), np.array(distance)
        for used in np.unique(sed):
           data.append(distance[used == sed])

        fig = plt.figure()
        plt.boxplot(data)
        ax = plt.gca()
        ax.set_ylim(0,1)
        ax.set_xticklabels(list(range(0,int(max(sed))+1)))
        plt.xlabel('String Edit Distance')
        plt.ylabel('Learned Similarity')
        plt.savefig(os.path.join(args.save, 'boxplot_test.png'))

if __name__ == '__main__':
    import argparse
    args = get_args_parser()

    # Check Test and Load
    if args.test and args.load is None:
        raise Exception('Cannot test without loading a model.')

    if args.save is not None and not args.test:
        if not os.path.isdir(args.save):
            os.makedirs(args.save)

    main(args)


#!/usr/bin/env python
# coding=utf-8
'''
@Description:
@Author: Xuannan
@Date: 2019-12-18 20:47:10
@LastEditTime : 2020-01-13 14:01:15
@LastEditors  : Xuannan
'''

from app.utils.swagger_filed import IntegerQueryFiled, StringQueryFiled, IntegerPathFiled, StringPathFiled

name = StringQueryFiled(name='name',
						description="名称",
						default='',
						required=True).data
info = StringQueryFiled(name='info',
						description="描述",
						default='',
						required=True).data
rules = StringQueryFiled(name='rules',
						description="规则授权",
						default='',
						required=True).data
id = StringPathFiled(	name='id',
						description="id",
						default='',
						required=True).data
data_fields = {
						'name':{"type": "string",},
						'info':{"type": "string",},
						'rules':{"type": "string",},
						'id':{"type": "string",},
						}

lst = {
	"description": "列表",
	"parameters": [
	],
	"responses": {
		"200": {
			"description": "获取成功",
			"properties":{
				'data':{
					'properties':data_fields
				}
			}
		}
	}
}

get = {
	"description": "根据id获取信息",
	"parameters": [ id],
	"responses": {
		"200": {
			"description": "获取成功",
			"examples": {
			},
			"properties":{
				'data':{
					'properties':data_fields
				}
			}
		}
	}
}

delete = {
	"description": "删除",
	"parameters": [ id],
	"security": [
		{
			"Authorization": ''
		}
	],
	"responses": {
		"200": {
			"description": "删除成功",
			"properties":{
				'msg':{
					'type':'string'
				}
			}
		}
	}
}

put = {
	"description": "修改",
	"parameters": [ id,name,info],
	"security": [
		{
			"Authorization": ''
		}
	],
	"responses": {
		"200": {
			"description": "修改成功",
			"examples": {
				'msg':'修改成功'
			},
			"properties":{
				'msg':{
					"type": "string"
				}
			}
		}
	}
}

add = {
	"description": "添加",
	"parameters": [
		name,info
	],
	"security": [
		{
			"Authorization": ''
		}
	],
	"responses": {
		"201": {
			"description": "添加成功",
			"properties":{
				'data':{
					'properties':data_fields
				},
				'msg':{"type": "string"
					}
			}
		}
	}
}
auth = {
	"description": "角色授权",
	"parameters": [
		id,rules
	],
	"security": [
		{
			"Authorization": ''
		}
	],
	"responses": {
		"201": {
			"description": "设置成功",
			"properties":{
				'data':{
					'properties':data_fields
				},
				'msg':{"type": "string"
					}
			}
		}
	}
}


from __future__ import print_function

import datetime
import os
import time
import shutil
from itertools import chain
import dill

from arguments import get_args

if __name__ == '__main__':
    import torch
    import torch.multiprocessing as mp
    mp.set_start_method('spawn')

    import my_optim
    from envs import create_env
    from model import *
    from test import test
    from train_reward_module import train_rewards
    from common import *
    from train_dynamics_module import train_dynamics
    from train_online import train_online
    from eval_modules import eval_reward
    from tensorboardX import SummaryWriter

    os.environ['OMP_NUM_THREADS'] = '1'
    args = get_args()
    log(args)

    if not args.gpu:
        os.environ['CUDA_VISIBLE_DEVICES'] = ""

    torch.manual_seed(args.seed)

    args_param = vars(args)
    toprint = ['seed', 'lr', 'entropy_coef', 'value_loss_coef', 'num_steps',
               'dim']

    if args.planning:
        toprint += ['rollout']

    env_name = args.env_name
    if args.env_name.endswith("MazeEnv"):
        env_name += 'mazeid%slength%s' % (args.maze_id, args.maze_length)
        toprint += ['random_start', 'difficulty']
    if args.baseline:
        model_type = 'baseline'
        if args.neg_reward:
            model_type += '_neg_reward'
        if args.file_path:
            model_type += '_dynamics_transfer'
        toprint += ['algo', 'gae', 'num_processes']
    elif args.train_dynamics:
        model_type = 'dynamics_planning'
        toprint = ['lr', 'forward_loss_coef', 'dec_loss_coef', 'inv_loss_coef', 'rollout', 'dim',
                   'train_size']
        # env_name = os.path.basename(args.train_set.strip('/'))
        if args.single_env:
            data_args = torch.load(os.path.join(args.train_set, 'args.pt'))
            args.maze_structure = data_args.maze_structure
    elif args.train_reward:
        model_type = 'reward'
        if args.neg_reward:
            model_type += '_neg_reward'
        if args.file_path:
            model_type += '_dynamics_transfer'
        toprint += ['algo', 'gae']
        if args.planning:
            model_type += '_planning'
    elif args.train_online:
        model_type = 'online'
        toprint += ['lr', 'dec_loss_coef', 'inv_loss_coef', 'rollout', 'dim']
    if args.transfer:
        model_type += '_transfer'

    name = ''
    for arg in toprint:
        name += '_{}{}'.format(arg, args_param[arg])
    out_dir = os.path.join(args.out, env_name, model_type, name)
    args.out = out_dir

    dynamics_path = ''
    if args.dynamics_module is not None and not args.baseline:
        dynamics_path = args.dynamics_module.split('/')
        dynamics_path = dynamics_path[-4] + dynamics_path[-2] +\
            '_' + dynamics_path[-1].strip('.pt')
        args.out = os.path.join(out_dir, dynamics_path)
    os.makedirs(args.out, exist_ok=True)

    # create the tensorboard summary writer here
    tb_log_dir = os.path.join(args.log_dir, env_name, model_type, name,
        dynamics_path, 'tb_logs')
    print(tb_log_dir)
    print(args.out)

    if args.reset_dir:
        shutil.rmtree(tb_log_dir, ignore_errors=True)
    os.makedirs(tb_log_dir, exist_ok=True)
    tb_writer = SummaryWriter(log_dir=tb_log_dir)

    # dump all the arguments in the tb_log_dir
    print(args, file=open(os.path.join(tb_log_dir, "arguments"), "w"))

    env = create_env(args.env_name, framework=args.framework, args=args)
    if args.train_dynamics:
        train_dynamics(env, args, None) # tb_writer
    if args.train_reward:
        model_name = 'rewards_module'
        if args.from_checkpoint is not None:  # using curriculum
            model_name += 'curr'
        if args.single_env:
            model_name += '_single_env'
            args.maze_structure = env._env.MAZE_STRUCTURE
        args.model_name = model_name
        enc = None
        d_module = None
        assert args.dynamics_module is not None
        enc = load_encoder(env.observation_space.shape[0], args)
        if args.planning:
            d_module = load_d_module(env.action_space.shape[0], args)

        shared_model = R_Module(env.action_space.shape[0], args.dim,
                            discrete=args.discrete, baseline=args.baseline,
                            state_space=env.observation_space.shape[0])

        # shared reward module for everyone
        shared_model.share_memory()

        if args.no_shared:
            optimizer = None
        else:
            optimizer = my_optim.SharedAdam(shared_model.parameters(), lr=args.lr)
            optimizer.share_memory()

        processes = []

        train_agent_method = None

        total_args = args
        train_agent_method = train_rewards

        for rank in range(0, args.num_processes):
            if rank==0:
                p = mp.Process(target=train_agent_method, args=(
                    rank, total_args, shared_model, enc, optimizer, tb_log_dir,
                    d_module))
            else:
                p = mp.Process(target=train_agent_method, args=(
                    rank, total_args, shared_model, enc, optimizer, None, d_module))
            p.start()
            processes.append(p)

        for p in processes:
            p.join()

        torch.save((shared_model.state_dict(), args), os.path.join(
            args.out, model_name + '%s.pt' % args.num_episodes))

        print(os.path.join(args.out, model_name))
    if args.train_online:
        model_name = 'rewards_module'
        if args.from_checkpoint is not None:  # using curriculum
            model_name += 'curr'
        if args.single_env:
            model_name += '_single_env'
            args.maze_structure = env._env.MAZE_STRUCTURE
        args.model_name = model_name
        shared_enc = Encoder(env.observation_space.shape[0], args.dim,
                      use_conv=args.use_conv)
        shared_dec = Decoder(env.observation_space.shape[0], args.dim,
                      use_conv=args.use_conv)
        shared_d_module = D_Module(env.action_space.shape[0], args.dim,
                                   args.discrete)
        shared_r_module = R_Module(env.action_space.shape[0], args.dim,
                                discrete=args.discrete, baseline=args.baseline,
                                state_space=env.observation_space.shape[0])

        shared_enc = Encoder(env.observation_space.shape[0], args.dim,
                      use_conv=args.use_conv)
        shared_dec = Decoder(env.observation_space.shape[0], args.dim,
                      use_conv=args.use_conv)
        shared_d_module = D_Module(env.action_space.shape[0], args.dim,
                                   args.discrete)
        shared_r_module = R_Module(env.action_space.shape[0], args.dim,
                                discrete=args.discrete, baseline=args.baseline,
                                state_space=env.observation_space.shape[0])

        shared_enc.share_memory()
        shared_dec.share_memory()
        shared_d_module.share_memory()
        shared_r_module.share_memory()
        all_params = chain(shared_enc.parameters(), shared_dec.parameters(),
                           shared_d_module.parameters(),
                           shared_r_module.parameters())
        shared_model = [shared_enc, shared_dec, shared_d_module, shared_r_module]

        if args.single_env:
            model_name += '_single_env'
            args.maze_structure = env.MAZE_STRUCTURE

        if args.no_shared:
            optimizer = None
        else:
            optimizer = my_optim.SharedAdam(all_params, lr=args.lr)
            optimizer.share_memory()

        train_agent_method = train_online

        processes = []
        for rank in range(0, args.num_processes):
            if rank==0:
                p = mp.Process(target=train_agent_method, args=(
                    rank, args, shared_model, optimizer, tb_log_dir))
            else:
                p = mp.Process(target=train_agent_method, args=(
                    rank, args, shared_model, optimizer))
            p.start()
            processes.append(p)

        # start an eval process here
        eval_agent_method = eval_reward
        p = mp.Process(target=eval_agent_method, args=(
            args, shared_model, tb_log_dir))
        p.start()
        processes.append(p)

        for p in processes:
            p.join()
        results_dict = {'args': args}
        torch.save((shared_r_module.state_dict(), args), os.path.join(
            args.out, 'reward_module%s.pt' % args.num_episodes))
        results_dict['enc'] = shared_enc.state_dict()
        results_dict['dec'] = shared_dec.state_dict()
        results_dict['d_module'] = shared_d_module.state_dict()
        torch.save(results_dict,
            os.path.join(args.out, 'dynamics_module%s.pt' % args.num_episodes))
        log("Saved model %s" % os.path.join(args.out, model_name))


# -*- coding: utf-8 -*-
import typing

import streamlit as st
from kiara import Kiara
from kiara.data import Value
from kiara.data.registry import DataRegistry
from kiara.workflow.kiara_workflow import KiaraWorkflow
from streamlit.delta_generator import DeltaGenerator

if typing.TYPE_CHECKING:
    pass

IMPORT_OPTION = "-- import file --"

# mypy: ignore-errors

class KiaraComponentMixin(object):
    @classmethod
    def create_components_class(
        cls, name: str, *mixins: typing.Iterable[typing.Type["KiaraComponentMixin"]]
    ):

        cls = type(name, tuple(mixins), {})
        return cls

    def __init__(self, temp_dir: str, **kwargs):

        self._temp_dir: str = temp_dir
        self._kiara: typing.Optional[Kiara] = None

    @property
    def temp_dir(self):
        return self._temp_dir

    @property
    def kiara(self) -> Kiara:

        if self._kiara is None:
            raise Exception("Kiara object not set (yet).")
        return self._kiara

    @property
    def data_store(self) -> DataRegistry:
        return self.kiara.data_store

    @property
    def data_registry(self) -> DataRegistry:
        return self.kiara.data_registry

class KiaraBaseWidgetsMixin(KiaraComponentMixin):
    def value_data(self, value_id: str, container: DeltaGenerator = st):

        value: Value = self.data_store.get_value_obj(value_id, raise_exception=True)
        value_data = value.get_value_data()
        if value.type_name == "table":
            container.dataframe(value_data.to_pandas())
        else:
            container.write(value_data)

class KiaraWorkflowWidgetsMixin(KiaraComponentMixin):
    def workflow_status(self, workflow_alias: str, container: DeltaGenerator = st):

        workflow: KiaraWorkflow = self.get_workflow(workflow_alias)

        state = workflow.get_current_state()
        for step_id, status in state.step_states.items():
            container.markdown(f" - *{step_id}*: {status.name}")

    # def create_workflow_inputs_container(self, workflow_alias: str, container: DeltaGenerator=st):
    #
    #     workflow = self.get_workflow(workflow_alias=workflow_alias)
    #     self.create_input_fields(value_set=workflow.inputs, container=container)
    #
    # def create_steps_details(self, workflow_alias: str, container: DeltaGenerator=st):
    #
    #     workflow = self.get_workflow(workflow_alias=workflow_alias)
    #     for step_id, desc in workflow.steps.steps.items():
    #
    #         exp = container.expander(f"Step: {step_id}")
    #         exp.write(desc.step.module.module_instance_doc)
    #         inputs = workflow.pipeline.get_step_inputs(step_id)
    #         outputs = workflow.pipeline.get_step_outputs(step_id)
    #         exp.write("inputs")
    #         self.create_output_fields(inputs, container=exp)
    #         exp.write("outputs")
    #         self.create_output_fields(outputs, container=exp)
    #
    # def create_workflow_outputs_container(self, workflow_alias: str, container: DeltaGenerator=st):
    #
    #     workflow = self.get_workflow(workflow_alias)
    #     self.create_output_fields(workflow.outputs, container=container)

# class Other(object):
#     def create_data_selection(self, value_type: str, container: DeltaGenerator = str):
#         def transform(value_id: str):
#             if value_id == IMPORT_OPTION:
#                 return None
#             return self.data_store.get_value_obj(value_id)
#
#         import_value = container.checkbox(f"Import new {value_type}")
#         if not import_value:
#             all_files = self.data_store.find_all_values_of_type("file")
#             aliases = set()
#             for f in all_files.values():
#                 aliases.update(f.alias_names)
#
#             selected_data = container.selectbox(
#                 f"Select '{value_type}' dataset", sorted(aliases)
#             )
#
#             if selected_data:
#                 value_md = self.data_store.get_value_info(selected_data)
#                 _md = value_md.metadata.get(value_md.value_type, {}).get(
#                     "metadata_item", {}
#                 )
#                 md_str = "| key | value |\n| --- | --- |\n"
#                 for k, v in _md.items():
#                     md_str = md_str + f"| {k} | {v} |\n"
#                 exp = container.expander("Metadata")
#                 exp.markdown(md_str)
#                 select_button = container.button("Select")
#                 if select_button:
#                     new_data = selected_data
#                     return new_data, transform
#
#             return None
#
#         else:
#             with container.container():
#
#                 file_type = None
#                 multiple = False
#
#                 container.write("Import into kiara data-store")
#                 uploaded_files = st.file_uploader(
#                     "Add files", type=file_type, accept_multiple_files=multiple
#                 )
#                 value = ""
#                 if uploaded_files and not multiple:
#                     value = uploaded_files.name
#                 alias = container.text_input("Alias", value=value)
#                 import_button = container.button("Import")
#
#             if import_button:
#                 if not uploaded_files:
#                     container.warning("No files selected")
#                     return None
#
#                 if not alias:
#                     container.warning("No alias provided")
#                     return None
#
#                 value_id = self.onboard_file(uploaded_files, aliases=[alias])
#                 container.info(f"Value '{alias}' (value_id: {value_id}) imported.")
#
#     def create_input_field(
#         self, field_name: str, value: Value, container: DeltaGenerator = str
#     ):
#
#         func_name = f"create_input_field_{value.type_name}"
#         if not hasattr(self, func_name):
#             raise Exception(f"Value type '{value.type_name}' not supported for input.")
#
#         container.write(value.value_schema.doc)
#         func = getattr(self, func_name)
#         default = value.value_schema.default
#         if default in [SpecialValue.NO_VALUE, SpecialValue.NOT_SET]:
#             default = None
#         result = func(
#             field_name=field_name, value=value, default=default, container=container
#         )
#         if isinstance(result, tuple):
#             if len(result) == 1:
#                 new_data = result[0]
#                 callback = None
#             elif len(result) == 2:
#                 new_data = result[0]
#                 callback = result[1]
#             else:
#                 raise Exception(
#                     f"Invalid return value for method '{func_name}. This is a bug."
#                 )
#         else:
#             new_data = result
#             callback = None
#
#         if callback:
#             new_data = callback(new_data)
#
#         if isinstance(new_data, Value):
#             new_data = new_data.get_value_data()
#         try:
#             value.set_value_data(new_data)
#         except Exception as e:
#             print(e)
#
#     def create_input_fields(self, value_set: ValueSet, container: DeltaGenerator = st):
#
#         for idx, (field_name, value) in enumerate(value_set.items()):
#             self.create_input_field(
#                 field_name=field_name, value=value, container=container
#             )
#
#     def create_input_field_boolean(
#         self,
#         field_name: str,
#         value: Value,
#         default: typing.Any,
#         container: DeltaGenerator = st,
#     ):
#
#         new_data = container.checkbox(field_name, value=default)
#         return new_data
#
#     def create_input_field_string(
#         self,
#         field_name: str,
#         value: Value,
#         default: typing.Any,
#         container: DeltaGenerator = st,
#     ):
#
#         if default is None:
#             default = ""
#         new_data = container.text_input(field_name, value=default)
#         return new_data
#
#     def create_input_field_list(
#         self,
#         field_name: str,
#         value: Value,
#         default: typing.Any,
#         container: DeltaGenerator = st,
#     ):
#
#         if default is None:
#             default = []
#         new_data = container.text_area(field_name, value="\n".join(default))
#
#         def transform(text: str):
#             return text.split("\n")
#
#         return new_data, transform
#
#     def create_input_field_file(
#         self,
#         field_name,
#         value: Value,
#         default: typing.Any,
#         container: DeltaGenerator = st,
#     ):
#
#         selection, transform = self.create_data_selection(
#             value_type="file", container=container
#         )
#
#         if not selection:
#             return None
#
#         return selection, transform
#
#     def create_output_fields(self, value_set: ValueSet, container: DeltaGenerator = st):
#
#         # columns = container.columns(len(value_set))
#         for idx, (field_name, value) in enumerate(value_set.items()):
#             self.create_output_field(
#                 field_name=field_name, value=value, container=container
#             )
#
#     def create_output_field(
#         self, field_name: str, value: Value, container: DeltaGenerator = st
#     ):
#
#         func_name = f"create_output_field_{value.type_name}"
#         if not hasattr(self, func_name):
#             raise Exception(f"Value type '{value.type_name}' not supported for output.")
#
#         container.write(value.value_schema.doc)
#         func = getattr(self, func_name)
#         if not value.item_is_valid():
#             value = None
#         func(field_name=field_name, value=value, container=container)
#
#     def create_output_field_table(
#         self,
#         field_name: str,
#         value: typing.Optional[Value],
#         container: DeltaGenerator = st,
#     ):
#
#         if value is None:
#             table: pa.Table = pa.Table.from_pydict({})
#         else:
#             table = value.get_value_data()
#         container.dataframe(table.to_pandas())
#
#     def create_output_field_string(
#         self,
#         field_name: str,
#         value: typing.Optional[Value],
#         container: DeltaGenerator = st,
#     ):
#
#         if value is None:
#             text = ""
#         else:
#             text = value.get_value_data()
#         container.write(text)
#
#     def create_output_field_list(
#         self, field_name, value: typing.Optional[Value], container: DeltaGenerator = st
#     ):
#
#         if value is None:
#             list_value = []
#         else:
#             list_value = value.get_value_data()
#
#         container.write(list_value)
#
#     def create_output_field_dict(
#         self, field_name, value: typing.Optional[Value], container: DeltaGenerator = st
#     ):
#
#         if value is None:
#             dict_value = {}
#         else:
#             dict_value = value.get_value_data()
#
#         container.write(dict_value)
#
#     def create_output_field_file(
#         self, field_name, value: typing.Optional[Value], container: DeltaGenerator = st
#     ):
#
#         if value is None:
#             file_value = {}
#         else:
#             file_value = value.get_value_data().dict()
#
#         container.write(file_value)


'''Adversarial autoencoder

'''

from cortex.plugins import ModelPlugin, register_model
from cortex.built_ins.models.gan import (SimpleDiscriminator, GradientPenalty,
                                         generator_loss)
from cortex.built_ins.models.vae import ImageDecoder, ImageEncoder

class AdversarialAutoencoder(ModelPlugin):
    '''Adversarial Autoencoder

    Autoencoder with a GAN loss on the latent space.

    '''

    defaults = dict(
        data=dict(batch_size=dict(train=64, test=640),
                  inputs=dict(inputs='images')),
        optimizer=dict(optimizer='Adam', learning_rate=1e-4),
        train=dict(epochs=500, archive_every=10)
    )

    def __init__(self):
        super().__init__()
        encoder_contract = dict(kwargs=dict(dim_out='dim_z'))
        decoder_contract = dict(kwargs=dict(dim_in='dim_z'))
        disc_contract = dict(kwargs=dict(dim_in='dim_z'))
        penalty_contract = dict(nets=dict(network='discriminator'))

        self.encoder = ImageEncoder(contract=encoder_contract)
        self.decoder = ImageDecoder(contract=decoder_contract)
        self.discriminator = SimpleDiscriminator(contract=disc_contract)
        self.penalty = GradientPenalty(contract=penalty_contract)

    def build(self, noise_type='normal', dim_z=64):
        '''

        Args:
            noise_type: Prior noise distribution.
            dim_z: Dimensionality of latent space.

        '''

        self.add_noise('Z', dist=noise_type, size=dim_z)
        self.encoder.build()
        self.decoder.build()
        self.discriminator.build()

    def routine(self, inputs, Z, encoder_loss_type='non-saturating',
                measure=None, beta=1.0):
        '''

        Args:
            encoder_loss_type: Adversarial loss type for the encoder.
            beta: Amount of adversarial loss for the encoder.

        '''

        Z_Q = self.encoder.encode(inputs)
        self.decoder.routine(inputs, Z_Q)

        E_pos, E_neg, P_samples, Q_samples = self.discriminator.score(
            Z, Z_Q, measure)

        adversarial_loss = generator_loss(
            Q_samples, measure, loss_type=encoder_loss_type)

        self.losses.encoder = self.losses.decoder + beta * adversarial_loss
        self.results.adversarial_loss = adversarial_loss.item()

    def train_step(self, n_discriminator_updates=1):
        '''

        Args:
            n_discriminator_updates: Number of discriminator updates per step.

        '''
        for _ in range(n_discriminator_updates):
            self.data.next()
            inputs, Z = self.inputs('inputs', 'Z')
            Z_Q = self.encoder.encode(inputs)
            self.discriminator.routine(Z, Z_Q)
            self.optimizer_step()
            self.penalty.routine(Z)
            self.optimizer_step()

        self.routine(auto_input=True)
        self.optimizer_step()

    def eval_step(self):
        self.data.next()
        inputs, Z = self.inputs('inputs', 'Z')
        Z_Q = self.encoder.encode(inputs)
        self.discriminator.routine(Z, Z_Q)
        self.penalty.routine(Z)

        self.routine(auto_input=True)

    def visualize(self, inputs, Z, targets):
        self.decoder.visualize(Z)
        self.encoder.visualize(inputs, targets)

        Z_Q = self.encoder.encode(inputs)
        R = self.decoder.decode(Z_Q)
        self.add_image(inputs, name='ground truth')
        self.add_image(R, name='reconstructed')

register_model(AdversarialAutoencoder)


# Zadanie 7. (wydawanie monet) Mamy daną tablicę z nominałami monet stosowanych
# w pewnym dziwnym kraju, oraz kwotę T. Proszę podać algorytm, który oblicza
# minimalną ilość monet potrzebną do wydania kwoty T (algorytm zachłanny, wydający
# najpierw największą monetę, nie działa: dla monet 1, 5, 8 wyda kwotę 15 jako
# 8+5+1+1 zamiast 5+5+5).

def MinimumCoin(price, values):
    dp = [0] + [float('inf')] * price

    for val in range(1, price + 1):
        for coin in values:
            if val - coin >= 0:
                dp[val] = min(dp[val], dp[val - coin] + 1)
    return dp[price]

val = [1, 5, 8]
price = 15
print(MinimumCoin(15, val))


class Solution_997:
    def findJudge(self, N, trust):
        if not trust and N == 1:
            return 1
        cands = [0] * (N + 1)
        for elem1, elem2 in trust:
            cands[elem2] += 1
            cands[elem1] -= 1

        return cands.index(N - 1) if N - 1 in cands else -1


from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from opentelemetry.exporter.richconsole import RichConsoleExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.jinja2 import Jinja2Instrumentor
from opentelemetry.instrumentation.tortoiseorm import TortoiseORMInstrumentor
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.trace import get_current_span
from starlette.exceptions import HTTPException as StarletteHTTPException
from tortoise.contrib.fastapi import register_tortoise

from example_app.models import Settings

app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
settings = Settings(_env_file=".env")
templates = Jinja2Templates(directory="templates")
tracer = TracerProvider(resource=Resource({SERVICE_NAME: "FastAPI"}))

import example_app.routes  # NOQA

@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
    span_context = get_current_span().get_span_context()
    return JSONResponse(
        {
            "message": str(exc.detail),
            "trace_id": span_context.trace_id,
            "span_id": span_context.span_id,
        },
        status_code=exc.status_code,
    )

@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception):
    span = get_current_span()
    assert span.is_recording
    span_context = span.get_span_context()
    return JSONResponse(
        {
            "message": "Server Error",
            "trace_id": span_context.trace_id,
            "span_id": span_context.span_id,
        },
        status_code=500,
    )

@app.on_event("startup")
def startup_event():
    if settings.verbose_tracing:
        tracer.add_span_processor(BatchSpanProcessor(RichConsoleExporter()))

    from azure.monitor.opentelemetry.exporter import AzureMonitorTraceExporter

    exporter = AzureMonitorTraceExporter.from_connection_string(
        settings.app_insights_connection_string
    )
    tracer.add_span_processor(BatchSpanProcessor(exporter))

    FastAPIInstrumentor.instrument_app(app, tracer_provider=tracer)
    TortoiseORMInstrumentor().instrument(tracer_provider=tracer)
    Jinja2Instrumentor().instrument(tracer_provider=tracer)
    register_tortoise(
        app,
        db_url=settings.db_url,
        modules={"models": ["example_app.db_models"]},
        generate_schemas=True,
        add_exception_handlers=True,
    )


import pandas as pd

def league_links(page_content):
    leagues = page_content.findAll('area', {'shape': 'rect'})
    countries, links = [], []
    for league in leagues:
        countries.append(league['title'])
        links.append(league['href'])
    return pd.DataFrame(dict(Country=countries, Link=links))

def top_tier_leagues_links(page_content):
    all_tiers = page_content.findAll('table', {'class': 'inline-table'})[0]
    return all_tiers.find_all(href=True)[1].get('href')