# coding: utf-8

from yabadaba import load_query

from test_Query import BaseTestQuery
import pandas as pd

class TestStrContainsQuery(BaseTestQuery):

    @property
    def style(self) -> str:
        return 'list_contains'

    def test_mongo(self):
        """Tests mongo query"""

        # Test setting path when loading
        query = load_query(self.style, path='root.element')
        assert query.path == 'root.element'

        # Test None value
        querylist = []
        query.mongo(querylist, None)
        assert len(querylist) == 0

        # Check single value
        querylist = []
        query.mongo(querylist, 'value')
        querydict = querylist[0]
        querydict = querylist[0]
        assert len(querydict['$and']) == 1
        assert querydict['$and'][0]['root.element'] == 'value'

        # Check multiple values
        querylist = []
        query.mongo(querylist, ['value1', 'value2'])
        querydict = querylist[0]
        querydict = querylist[0]
        assert len(querydict['$and']) == 2
        assert querydict['$and'][0]['root.element'] == 'value1'
        assert querydict['$and'][1]['root.element'] == 'value2'

        # Check single value with prefix
        querylist = []
        query.mongo(querylist, 'value', prefix='content.')
        querydict = querylist[0]
        querydict = querylist[0]
        assert len(querydict['$and']) == 1
        assert querydict['$and'][0]['content.root.element'] == 'value'

    @property
    def df(self) -> pd.DataFrame:
        """pd.Dataframe: demo data for filter testing"""

        return pd.DataFrame([
            {
                'name': 'first',
                'thisguy': ['value1'],
                'parent': [
                    {
                        'thisguy': ['pop', 'goes', 'the', 'weasel']
                    },
                    {
                        'thisguy': ['zoot', 'suit', 'riot']
                    }
                ],
            },
            {
                'name': 'second',
                'thisguy': ['value1', 'value2'],
                'parent': [
                    {
                        'thisguy': ['live', 'and', 'let', 'die']
                    },
                    {
                        'thisguy': ['flying', 'microtonal', 'banana']
                    }
                ],
            },
            {
                'name': 'third',
                'thisguy': ['value3', 'value4'],
                'parent': [
                    {
                        'thisguy': ['funk', '#49']
                    },
                    {
                        'thisguy': ['wheels', 'on', 'the', 'bus']
                    }
                ],
            },
        ])

    def test_pandas(self):
        """Tests pandas filter without a parent element"""

        df = self.df

        # Test setting path when loading
        query = load_query(self.style, name='thisguy')
        assert query.name == 'thisguy'

        # Test None value
        df2 = df[query.pandas(df, None)]
        assert len(df2) == 3

        # Test single missing value
        df2 = df[query.pandas(df, 'NOT THERE')]
        assert len(df2) == 0

        # Test single value
        df2 = df[query.pandas(df, 'value1')]
        assert len(df2) == 2
        assert df2.name.tolist()[0] == 'first'
        assert df2.name.tolist()[1] == 'second'

        # Test multiple values
        df2 = df[query.pandas(df, ['value1', 'value2'])]
        assert len(df2) == 1
        assert df2.name.tolist()[0] == 'second'

    def test_pandas_parent(self):
        """Tests pandas filter with a parent element"""

        df = self.df

        # Test setting parent when loading
        query = load_query(self.style, name='thisguy', parent='parent')
        assert query.name == 'thisguy'
        assert query.parent == 'parent'

        # Test directly setting parent
        query.parent = None
        assert query.parent is None
        query.parent = 'parent'
        assert query.parent == 'parent'

        # Test None value
        df2 = df[query.pandas(df, None)]
        assert len(df2) == 3

        # Test single missing value
        df2 = df[query.pandas(df, 'NOT THERE')]
        assert len(df2) == 0

        # Test single value
        df2 = df[query.pandas(df, 'the')]
        assert len(df2) == 2
        assert df2.name.tolist()[0] == 'first'
        assert df2.name.tolist()[1] == 'third'

        # Test multiple values
        df2 = df[query.pandas(df, ['the', 'bus'])]
        assert len(df2) == 1
        assert df2.name.tolist()[0] == 'third'

    def test_inline(self):
        """This tests the old non-class version of the queries"""

        # Test mongo
        querylist = []
        load_query('list_contains', path='root.element').mongo(querylist, ['value1', 'value2'])
        querydict = querylist[0]
        assert len(querydict['$and']) == 2
        assert querydict['$and'][0]['root.element'] == 'value1'
        assert querydict['$and'][1]['root.element'] == 'value2'

        # Test pandas
        df = self.df
        df2 = df[load_query('list_contains', name='thisguy', parent='parent').pandas(df, ['the', 'bus'])]
        assert len(df2) == 1
        assert df2.name.tolist()[0] == 'third'


#Código de prueba para publicar usando la librería paho.mqtt.client
import ssl, sys, socket
import paho.mqtt.client as mqtt
import xbox
from time import time
#Inicializo mando xbox
joy = xbox.Joystick()
#Velocidad máxima
Nmax = 100
k_giro = 0.4
#Que solo tenga 2 decimales los valores del joystick
#def fmtFloat(n):
#    return '{:6.2f}'.format(n)

keep_going = True
def manejador_de_senal(signum, frame):
    global keep_going
    # Si entramos en el manejador por una llamada CTRL-C, ponemos el flag a False
    keep_going = False

#Ejecuta cuando se ha conectado con éxito
def on_connect(client, userdata, flags, rc):
	print('connected (%s)' % client._client_id)
	client.subscribe(topic = 'prueba', qos = 2) #qos = 0 para que no se produzca mucho lag

#Ejecuta cuando recibe el mensaje
def on_publish(client,userdata,result):             #create function for callback
    print(Nd,Ni,B)
    pass
Host_raspberry = socket.gethostbyname('chemipi.local') #Puede ser otro, cambiar de forma manual
#Inicializo el publicador de MQTT
client = mqtt.Client(client_id='Josemi_pub', clean_session=False)
client.on_connect = on_connect
#client.on_message = on_message
client.on_publish = on_publish
client.connect(host = Host_raspberry, port=1883)
t2 = time()
cont = 0
#Bucle infinito de envio de mensajes
while keep_going:
    #Código:
    t1 = time()
    if (t1 - t2) > 0.2:
        N_recto = joy.rightY()
        N_giro = joy.rightX()
        Nd = round(Nmax*(N_recto - k_giro*N_giro), 2)
        Ni = round(Nmax*(N_recto + k_giro*N_giro), 2)
        B = joy.Back()
        dato_envio = '{},{},{}'.format(Nd, Ni, B)
        #dato_envio = 'ON'
        client.publish('prueba', dato_envio)
        #print(Nd,Ni)
        t2 = t1
        if B == 1:
            cont = cont + 1
            if cont == 4:
                break
#Terminamos cerrando el mando
client.loop_stop()
joy.close()


import tkinter as tk
from tkinter import simpledialog, messagebox
import os
import requests

class DesktopNoteApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Desktop Note App")
        self.notes = {}
        self.load_notes()

        self.text = tk.Text(self.root, height=20, width=50)
        self.text.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        # Create a frame at the bottom for the buttons
        bottom_frame = tk.Frame(self.root)
        bottom_frame.pack(side=tk.BOTTOM, pady=10)

        self.listbox = tk.Listbox(self.root)
        self.listbox.pack(side=tk.BOTTOM, fill=tk.X)
        self.refresh_note_list()

        # Place the Backup Notes button in the bottom frame, aligned to the left
        backup_button = tk.Button(bottom_frame, text="Backup / Restore Notes", command=self.backup_or_restore_notes)
        backup_button.pack(side=tk.LEFT, padx=5)

        save_button = tk.Button(self.root, text="Save Note", command=self.save_note)
        save_button.pack(side=tk.LEFT)

        load_button = tk.Button(self.root, text="Load Note", command=self.load_note)
        load_button.pack(side=tk.LEFT)

        delete_button = tk.Button(self.root, text="Delete Note", command=self.delete_note)
        delete_button.pack(side=tk.LEFT)

    def save_note(self):
        note_title = simpledialog.askstring("Note Title", "Enter a title for your note:")
        note_text = self.text.get("1.0", tk.END).strip()
        if note_title and note_text:
            self.notes[note_title] = note_text
            self.refresh_note_list()
            self.text.delete("1.0", tk.END)
            messagebox.showinfo("Success", "Note saved successfully!")
        elif not note_text:
            messagebox.showerror("Error", "Note text cannot be empty.")

    def load_note(self):
        try:
            note_title = self.listbox.get(self.listbox.curselection())
            self.text.delete("1.0", tk.END)
            self.text.insert(tk.END, self.notes[note_title])
        except tk.TclError:
            messagebox.showerror("Error", "Please select a note to load.")

    def delete_note(self):
        try:
            note_title = self.listbox.get(self.listbox.curselection())
            # Confirmation dialog before deleting a note
            if messagebox.askyesno("Confirm Delete", f"Are you sure you want to delete '{note_title}'?"):
                del self.notes[note_title]
                self.refresh_note_list()
                messagebox.showinfo("Success", "Note deleted successfully!")
        except tk.TclError:
            messagebox.showerror("Error", "Please select a note to delete.")

    def refresh_note_list(self):
        self.listbox.delete(0, tk.END)
        for title in self.notes.keys():
            self.listbox.insert(tk.END, title)

    def load_notes(self):
        if os.path.exists("notes.dat"):
            with open("notes.dat", "r") as file:
                self.notes = eval(file.read())

    def save_notes_to_file(self):
        with open("notes.dat", "w") as file:
            file.write(str(self.notes))
        self.root.destroy()

    def backup_or_restore_notes(self):
        # Create a Toplevel window
        popup = tk.Toplevel(self.root)
        popup.title("Backup or Restore")
        popup.geometry("300x100")  # Width x Height

        # Add a label
        label = tk.Label(popup, text="Choose an action:")
        label.pack(pady=10)

        # Add a Backup button
        backup_button = tk.Button(popup, text="Backup", command=lambda: [self.backup_notes(), popup.destroy()])
        backup_button.pack(side=tk.LEFT, padx=(20, 10), pady=10)

        # Add a Restore button
        restore_button = tk.Button(popup, text="Restore", command=lambda: [self.restore_notes_from_backup(), popup.destroy()])
        restore_button.pack(side=tk.RIGHT, padx=(10, 20), pady=10)

    def backup_notes(self):
        try:
            response = requests.post('http://localhost:5001/backup', json=self.notes)
            if response.status_code == 200:
                messagebox.showinfo("Backup", "Notes backed up successfully.")
            else:
                messagebox.showerror("Backup", "Failed to back up notes.")
        except requests.exceptions.ConnectionError:
            messagebox.showerror("Backup", "Backup service is not running.")

    def restore_notes_from_backup(self):
        try:
            response = requests.get('http://localhost:5001/restore')
            if response.status_code == 200:
                self.notes = response.json()
                self.refresh_note_list()
                messagebox.showinfo("Restore", "Notes restored successfully from backup.")
            else:
                messagebox.showerror("Restore", "Failed to restore notes from backup.")
        except requests.exceptions.ConnectionError:
            messagebox.showerror("Restore", "Restore service is not running.")

    def create_search_bar(self, frame):
        # Create a label for the search bar
        search_label = tk.Label(frame, text="Search Notes:")
        search_label.pack(side=tk.LEFT, padx=(0, 5))

        # Create an entry widget for the search bar
        self.search_var = tk.StringVar()
        search_entry = tk.Entry(frame, textvariable=self.search_var)
        search_entry.pack(side=tk.LEFT, expand=True, fill=tk.X, padx=(0, 5))

        # Create a search button
        search_button = tk.Button(frame, text="Search", command=self.search_notes)
        search_button.pack(side=tk.LEFT, padx=(5, 0))

    def run(self):
        self.root.protocol("WM_DELETE_WINDOW", self.save_notes_to_file)

        self.root.mainloop()

if __name__ == "__main__":
    root = tk.Tk()
    app = DesktopNoteApp(root)
    app.run()


#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @author : liuhefei
# @Time : 2019/7/7 1:14
# @desc: 常胜将军

if __name__ == "__main__":
    spare = 21  # 21根火柴
    print("--------你不能战胜我，不信试试--------")
    print("开始游戏: ")
    while 1:
        print("--------目前还有火柴 %d 根--------" %spare)
        people = int(input("人取火柴："))   # 人取火柴
        if people < 1 or people > 4 or people > spare:
            print("你违规了，你取的火柴数有问题！")
            continue
        spare = spare - people   # 人取后，剩余的火柴数
        if spare == 0:   # 人取后，剩余的火柴数为0， 则计算机获胜，跳出循环
            print("计算机获胜，游戏结束！")
            break
        computer = 5 - people   # 计算机取火柴
        spare = spare - computer
        print("计算机取火柴：%d" %computer)
        # 计算机取后，剩余的火柴数为0， 则人获胜，跳出循环
        if spare == 0:
            print("人获胜，游戏结束！")
            break


import gosling as gos
import streamlit as st
import streamlit_gosling as st_gos
import pandas as pd

from GoslingEnhancers import get_enhancer_track
from GoslingPromoters import get_promoter_track
from GoslingGenes import get_gene_overlay
from BigWigTrack import get_bigwig_track
from ChipMerge import get_merge_track
import StreamlitFunctions
import ContrastOptions
import Contrasts

import importlib

importlib.reload(Contrasts)
#@st.cache TODO separate functions into what can be cached and what doesnt need to be cached
def main(container_width:int,
        chromosome_selection,
        interval:list,
        chip_height:int,
        gene_height:int,
        enhancer_height:int,
        promoter_height:int,
        datasets:Contrasts.datasets,
        MergedChip:bool,
        EnableContrasts:bool,
        contrasts:Contrasts.contrasts):
    """
    Make an ideagram with Enhancers AND Promoters
    """

    ######~~~~~~~~~~~
    #Create Domain of Selection
    ######~~~~~~~~~~~

    domain = gos.GenomicDomain(chromosome=chromosome_selection, interval=interval)
    # ChromFilter = gos.IncludeFilter(field='chromosome', include=mydomain, type=mydomain)

    ######~~~~~~~~~~~
    #Enhancer Track
    ######~~~~~~~~~~~
    enhancer_track = get_enhancer_track(enhancer_height=20)

    ######~~~~~~~~~~~
    #Promoter Track
    ######~~~~~~~~~~~
    promoter_track = get_promoter_track(promoter_height=20)

    ######~~~~~~~~~~~
    # Genes Overlay
    ######~~~~~~~~~~~

    gene_overlay = get_gene_overlay(gene_height=gene_height)

    ######~~~~~~~~~~~
    # If Contrasts are Disabled...
    ######~~~~~~~~~~~

    if not EnableContrasts:

        chipseq_tracks = []

        for dataset in datasets.lod:
            track = get_bigwig_track(bigwig_file= dataset.url,
                                        chip_height = chip_height,
                                        name = dataset.name,
                                        color = dataset.color).properties(
                                                            width=container_width)

            chipseq_tracks.append(track)

        chip_vert = gos.vertical(*chipseq_tracks).properties(
                    spacing = 0,
                    linkingId = "vert")

        ######~~~~~~~~~~~
        # If Merged view is Disabled...
        ######~~~~~~~~~~~

        vis = gos.stack(gene_overlay, enhancer_track, promoter_track).properties(
                    spacing = 0, width=container_width, linkingId = "vert")

        vis = gos.vertical(vis, chip_vert).properties(spacing = 30,
                    xDomain=domain, linkingId = "vert")

        ######~~~~~~~~~~~
        # If Merged view is Enabled...
        ######~~~~~~~~~~~
        if MergedChip:
            if len(st.session_state['datasets'].lod) == 0:
                return vis

            urls =[dataset.url for dataset in st.session_state['datasets'].lod]
            print(f'URLS {urls}')

            merged_track = get_merge_track(chip_height=chip_height*5,
                                                chip_data_files=[dataset.url for dataset in st.session_state['datasets'].lod],
                                                colors = [dataset.color for dataset in st.session_state['datasets'].lod]).properties(
                    spacing = 0, width=container_width, linkingId = "vert")

            vis = gos.vertical(vis, merged_track).properties(
                                xDomain=domain, spacing = 40, linkingId = "vert")

        return vis

    if EnableContrasts:
        #chipseq_stacks: A List of stacks. Each stack corresponds to a contrast's chipseq profiles
        chipseq_stacks_l = []
        for contrast in contrasts.loc:
            #chipseq_tracks: A List of tracks. Each track is from a dataset in the current contrast
            chipseq_tracks = []

            for dataset in contrast.datasets.lod:
                track = get_bigwig_track(bigwig_file= dataset.url, chip_height = chip_height, name = dataset.name, color = dataset.color)
                chipseq_tracks.append(track)
                #Each dataset has its own track.

            #Make 1 stack that corresponds to all of the tracks in the current contrast
            # NB: A chipseq stack is of type "view"

            chipseq_stack = gos.stack(*chipseq_tracks).properties(
                    xDomain=domain, spacing = 0, width=container_width)

            # Append new stack.
            chipseq_stacks_l.append(chipseq_stack)

            #add int for background color reasons

        # Combine all Chipseq Stacks into one stack
        # We cannot do this because we don't have a "view"?
        #contrast_stack = gos.stack(*chipseq_stacks_l)
        chipseq_vertical = gos.vertical(*chipseq_stacks_l, spacing = 32)

        # NB a Vertical is a "View" type
        print(f'Chipseq_vertical {type(chipseq_vertical)}')

        vis = gos.stack(gene_overlay, enhancer_track, promoter_track).properties(
                    xDomain=domain, spacing = 0, width=container_width)
        print(f'Enhancer {type(enhancer_track)}')
        print(f'Promoter {type(promoter_track)}')
        print(f'Gene_Overlay {type(gene_overlay)}')

        #vis is a view
        print(f'Vis {type(vis)}')

        # I think you can add two views together easily right?
        vis2 = gos.vertical(vis, chipseq_vertical,  spacing = 37).properties(
            linkingId = "-",
            xDomain = domain)

        contrast_names = st.session_state['contrasts'].get_names()
        print(contrast_names)

        if MergedChip:

            if contrasts.get_num_datasets() == 0:
                return vis2

            merged_tracks = []

            for contrast in contrasts.loc:
                if contrast.get_len_datasets() == 0:
                    continue

                dataset_urls = contrast.get_datasets_urls()
                dataset_colors = contrast.get_datasets_colors()

                print(f'URLS {dataset_urls}')
                print(f'COLORS {dataset_colors}')

                #SOMETHING IS WRONG WITH MERGED_TRACK
                merged_track = get_merge_track(chip_height = 75,
                                                chip_data_files = dataset_urls,
                                                colors = dataset_colors).properties(
                                                    width=container_width)
                print(type(merged_track))

                merged_tracks.append(merged_track)

            merged_vis = gos.vertical(*merged_tracks, spacing = 0)
            vis2 = gos.vertical(vis2, merged_vis, spacing = 50).properties(
                linkingId = "-",
                xDomain = domain
                )

        return vis2

    # return full_vis

######## Page Config
#This must Be the first "st" script you call
#Makes sure stuff loads on the left, not the middle
st.set_page_config(layout='wide')

############### Add Search box for selection method

if 'datasets' not in st.session_state.keys():
    datasets = Contrasts.datasets(lod=[])
    st.session_state['datasets'] = datasets
else:
    datasets = st.session_state['datasets']

if 'contrasts' not in st.session_state.keys():
    contrasts = Contrasts.contrasts(loc = [])
    st.session_state['contrasts'] = contrasts
else:
    contrasts = st.session_state['contrasts']

if 'EnableContrasts' not in st.session_state.keys():
    st.session_state['EnableContrasts'] = False
EnableContrasts = st.session_state['EnableContrasts']

if not EnableContrasts:
    ChromosomeSelection, IntervalSelection = ContrastOptions.display_no_contrast_options(datasets)
else:
    ChromosomeSelection, IntervalSelection = ContrastOptions.display_yes_contrast_options(contrasts)

with st.sidebar:
    #multiple_contrasts=st.checkbox(label = "Enable Multiple Contrasts", help="Enabling Multiple Contrasts allows you to compare ChIPseq, and ATACseq of multiple categorical contrasts at once. For example: several time series, or several cell types")
    EnableContrasts=StreamlitFunctions.display_enablecontrast_check_box()

with st.sidebar:
    MergedChip=StreamlitFunctions.display_merged_checkbox()

if st.session_state['EnableContrasts'] == False:
    st.markdown("""## SingleChIPViewer""")
    st.markdown("""###### mm10 Construct | Scroll and Zoom to Explore Data""" )
elif st.session_state['EnableContrasts'] == True:
    st.markdown("""## MultiChIPViewer""")
    st.markdown("""###### mm10 Construct | Scroll and Zoom to Explore Data""")

col1, col2 = st.columns([1,15], gap = 'medium')

with col1:

    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')
    st.text('')

    contrasts = st.session_state['contrasts']

    #num_datasets has the number of datasets for each ocntrast indexed
    num_datasets = []
    for contrast in contrasts.loc:
        num_datasets.append(contrast.get_len_datasets())

    #Only look at 1 onwards for contrasts because first contrast name is always placed in the same place
    for i,contrast in enumerate(contrasts.loc):

        if i == 0:

            st.markdown("""<p> </p>""", unsafe_allow_html=True)
            st.markdown("""<p> </p>""", unsafe_allow_html=True)

            name = str(contrast.name)
            st.subheader(name)

        elif num_datasets[i] == 0:
            continue

        else:

            prev_num = num_datasets[i-1]

            spacing_dic = {0:0, 1:0, 2:2, 3:4, 4:7, 5:9, 6:11, 7:13, 8:15, 9:17}

            req_spaces = spacing_dic[prev_num]

            for i in range(req_spaces):
                st.text('')

            name = str(contrast.name)
            st.subheader(name)

    if MergedChip:

        st.text('')
        st.text('')
        st.text('')
        st.text('')
        st.text('')

        for i,contrast in enumerate(contrasts.loc):

            if i == 0:

                st.markdown("""<p> </p>""", unsafe_allow_html=True)
                st.markdown("""<p> </p>""", unsafe_allow_html=True)

                name = str(contrast.name)
                st.subheader(name)

            else:

                spacing = 2

                name = str(contrast.name)
                st.subheader(name)

with col2:

    result=st_gos.from_gos(
        spec=main(container_width=1550,
                    chip_height=36,
                    gene_height=100,
                    promoter_height = 40,
                    enhancer_height = 40,
                    chromosome_selection=ChromosomeSelection,
                    interval=IntervalSelection,
                    datasets = datasets,
                    MergedChip=MergedChip,
                    EnableContrasts=EnableContrasts,
                    contrasts=contrasts),
        id='id1',
        #This height changes the height of the streamlit container
        height = 5000)


import sys
class Solution:
    """
    @param prices: Given an integer array
    @return: Maximum profit
    """
    def maxProfit(self, prices):
        res = 0
        low, high = sys.maxint, sys.maxint
        for p in prices:
            if p > high:
                high = p
            else:
                res += (high - low)
                high, low = p, p
        return res + (high - low)


from __future__ import absolute_import
from __future__ import print_function

import torch
from bisect import bisect_right

AVAI_SCH = ['single_step', 'multi_step', 'cosine', 'warmup_multi_step', 'warmup_cosine']

def build_lr_schedulers(optimizers, *args):

    lr_schedulers = []
    for i, optimizer in enumerate(optimizers):
        if args[i].get('lr_scheduler') is None:
            lr_schedulers.append(None)
        else:
            lr_schedulers.append(build_lr_scheduler(optimizer, **args[i]))
    return lr_schedulers

def build_lr_scheduler(optimizer, lr_scheduler='single_step', step_size=1, gamma=0.1, max_epoch=1, warmup_factor=0.01, warmup_method="linear", warmup_epoch=10):
    """A function wrapper for building a learning rate scheduler.

    Args:
        optimizer (Optimizer): an Optimizer.
        lr_scheduler (str, optional): learning rate scheduler method. Default is single_step.
        step_size (int or list, optional): step size to decay learning rate. When ``lr_scheduler``
            is "single_step", ``step_size`` should be an integer. When ``lr_scheduler`` is
            "multi_step", ``step_size`` is a list. Default is 1.
        gamma (float, optional): decay rate. Default is 0.1.
        max_epoch (int, optional): maximum epoch (for cosine annealing). Default is 1.

    Examples::
        >>> # Decay learning rate by every 20 epochs.
        >>> scheduler = torchreid.optim.build_lr_scheduler(
        >>>     optimizer, lr_scheduler='single_step', step_size=20
        >>> )
        >>> # Decay learning rate at 30, 50 and 55 epochs.
        >>> scheduler = torchreid.optim.build_lr_scheduler(
        >>>     optimizer, lr_scheduler='multi_step', step_size=[30, 50, 55]
        >>> )
    """
    if lr_scheduler not in AVAI_SCH:
        raise ValueError('Unsupported scheduler: {}. Must be one of {}'.format(lr_scheduler, AVAI_SCH))

    if lr_scheduler == 'single_step':
        if isinstance(step_size, list):
            step_size = step_size[-1]

        if not isinstance(step_size, int):
            raise TypeError(
                'For single_step lr_scheduler, step_size must '
                'be an integer, but got {}'.format(type(step_size))
            )

        scheduler = torch.optim.lr_scheduler.StepLR(
            optimizer, step_size=step_size, gamma=gamma
        )

    elif lr_scheduler == 'multi_step':
        if not isinstance(step_size, list):
            raise TypeError(
                'For multi_step lr_scheduler, step_size must '
                'be a list, but got {}'.format(type(step_size))
            )

        scheduler = torch.optim.lr_scheduler.MultiStepLR(
            optimizer, milestones=step_size, gamma=gamma
        )

    elif lr_scheduler == 'cosine':
        scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
            optimizer, float(max_epoch)
        )
    elif lr_scheduler == 'warmup_multi_step':
        scheduler = WarmupMultiStepLR(optimizer, milestones=step_size, gamma=gamma, warmup_factor=warmup_factor, warmup_epoch=warmup_epoch, warmup_method=warmup_method)

    elif lr_scheduler == 'warmup_cosine':
        scheduler = WarmupCosineAnnealingLR(optimizer, float(
            max_epoch), warmup_factor=warmup_factor, warmup_epoch=warmup_epoch, warmup_method=warmup_method)

    return scheduler

class WarmupMultiStepLR(torch.optim.lr_scheduler._LRScheduler):
    def __init__(
        self,
        optimizer,
        milestones,
        gamma=0.1,
        warmup_factor=0.1,
        warmup_epoch=10,
        warmup_method="linear",
        last_epoch=-1,
    ):
        if not list(milestones) == sorted(milestones):
            raise ValueError(
                "Milestones should be a list of" " increasing integers. Got {}",
                milestones,
            )

        if warmup_method not in ("constant", "linear"):
            raise ValueError(
                "Only 'constant' or 'linear' warmup_method accepted"
                "got {}".format(warmup_method)
            )
        self.milestones = milestones
        self.gamma = gamma
        self.warmup_factor = warmup_factor
        self.warmup_epoch = warmup_epoch
        self.warmup_method = warmup_method
        super(WarmupMultiStepLR, self).__init__(optimizer, last_epoch)

    def get_lr(self):
        warmup_factor = 1
        if self.last_epoch < self.warmup_epoch:
            if self.warmup_method == "constant":
                warmup_factor = self.warmup_factor
            elif self.warmup_method == "linear":
                alpha = self.last_epoch / self.warmup_epoch
                warmup_factor = self.warmup_factor * (1 - alpha) + alpha
        return [
            base_lr
            * warmup_factor
            * self.gamma ** bisect_right(self.milestones, self.last_epoch)
            for base_lr in self.base_lrs
        ]

class WarmupCosineAnnealingLR(torch.optim.lr_scheduler._LRScheduler):

    def __init__(
        self,
        optimizer,
        T_max,
        eta_min=0,
        warmup_factor=0.1,
        warmup_epoch=10,
        warmup_method="linear",
        last_epoch=-1,
    ):

        self.T_max = T_max
        self.eta_min = eta_min
        self.warmup_factor = warmup_factor
        self.warmup_epoch = warmup_epoch
        self.warmup_method = warmup_method
        super(WarmupMultiStepLR, self).__init__(optimizer, last_epoch)

    def get_lr(self):
        warmup_factor = 1
        if self.last_epoch < self.warmup_epoch:
            if self.warmup_method == "constant":
                warmup_factor = self.warmup_factor
            elif self.warmup_method == "linear":
                alpha = self.last_epoch / self.warmup_epoch
                warmup_factor = self.warmup_factor * (1 - alpha) + alpha

        return [warmup_factor * (self.eta_min + (base_lr - self.eta_min) * (1 + math.cos(math.pi * self.last_epoch / self.T_max)) / 2) for base_lr in self.base_lrs]


'''
使用一个最大堆 maxSet 与最小堆 minSet（ maxSet 用 multiset 的反向遍历代替）。maxSet 存的是到目前为止较小的那一半数，minSet 存的是到目前为止较大的那一半数，这样中位数只有可能是 maxSet 的堆顶元素（本题中）或者是两个堆顶元素的均值。
minSet与maxSet交替使用，保证两个堆的大小之差不超过1。
当插入一个新数时，若新数大于 minSet 的堆顶元素，说明新数在所有数的下半部分，此时将新数插入 minSet，取出 minSet 堆顶元素并插入至 maxSet ；否则，说明新数在所有数的上半部分，将新数插入 maxSet
当插入一个新数时，若新数小于 maxSet 的堆顶元素，说明新数在所有数的上半部分，此时将新数插入 maxSet，取出 maxSet 堆顶元素并插入至 minSet ；否则，说明新数在所有数的下半部分，将新数插入 minSet
将 maxSet 堆顶元素存入返回值数组，但不取出堆顶元素
'''
import heapq

class Solution:
    minH, maxH = [], []
    number = 0
    """
    @param nums: A list of integers
    @return: the median of numbers
    """

    def medianII(self, nums):
        res = []
        for num in nums:
            self.add(num)
            res.append(self.getM())
        return res

    def getM(self):
        return -self.maxH[0]

    def add(self, num):
        if self.number & 1:
            heapq.heappush(self.minH, num)
        else:
            heapq.heappush(self.maxH, -num)
        self.number += 1
        if len(self.maxH) == 0 or len(self.minH) == 0:
            return
        if -self.maxH[0] > self.minH[0]:
            maxs = -self.maxH[0]
            mins = self.minH[0]
            heapq.heapreplace(self.maxH, -mins)
            heapq.heapreplace(self.minH, maxs)


import tennisTools
import ranking
import prizeMoney
import manualInput
import sys
import sortLists
import menuFunctions

#Set saved data files to default(Does not delete results files)
menuFunctions.dataWipe()
#########################
#START MAIN PROGRAM LOOP#
#########################
while True:

    #Populate list of Male Players
    listOfMalePlayers = []
    tennisTools.fillPlayerList('MALE_PLAYER_LIST.CSV', listOfMalePlayers)

    #Populate list of female players
    listOfFemalePlayers = []
    tennisTools.fillPlayerList('FEMALE_PLAYER_LIST.CSV', listOfFemalePlayers)

    #Tornement select
    tornement = menuFunctions.tornementSelector()

    #Simple string to complete nameOfFile
    fileType = '.csv'

    #Gender select
    selectGender= menuFunctions.genderSelector()

    #Check if previous tornement of this type ended properly
    checkPrevious = tennisTools.checkIfPreviousComplete(tornement, selectGender)

    #IF PREVIOUS TORNEMENT OF THIS TYPE COMPLETED, RUN AS NORMAL
    if checkPrevious == 'TRUE':
        #Manual imput option
        manualSelect = menuFunctions.manualSelector()

        playRound = 0
        #Play next round
        playRound = menuFunctions.playNextRound(playRound)
        print('Round: ',  playRound)

        #Determine list of players to use
        if selectGender == 'f':
            gender = '_WOMEN'
            if manualSelect == 'n':
                listSelect = listOfFemalePlayers
        elif selectGender == 'm':
            gender = '_MEN'
            if manualSelect == 'n':
                listSelect = listOfMalePlayers

        #Recieve manual input if requested, else ignore
        if manualSelect == 'y':
            listSelect = manualInput.userInputStack(selectGender, str(playRound))
        else:
            pass

        #Name of Round File to be generated
        nameOfFile = tornement + str(playRound) + gender + fileType

        ######################################
        #START ROUND 1 (INITIALIZE TORNEMENT)#
        ######################################

        #Set fixtures, generate scores, write to file.
        if manualSelect == 'n':
            tennisTools.setFixtures(nameOfFile,listSelect, selectGender)
        else:
            tennisTools.setFixturesFromManual(nameOfFile,listSelect, selectGender)

        #Determine winners by reading file created in previous step. Display Results
        tennisTools.runRound(nameOfFile)

        #Update Ranking points, both per round and overall
        ranking.updateRankPoints(tornement, str(playRound), selectGender)
        ranking.updatePointsCurrentTornement(tornement, str(playRound), selectGender)

        #Determine money owed to each player
        prizeMoney.calculatePrizeMoney(tornement, str(playRound), selectGender)

        #Record tornement as complete, or not.
        tennisTools.writePreviousComplete(tornement, selectGender, playRound)

        #Enable sorted lists
        cantSee = False

    #IF PREVIOUS ROUND OF THIS TORNEMENT TYPE DID NOT FINISH, RE-RUN ROUND PRIOR TO SHUTDOWN
    elif checkPrevious == 'FALSE':
        if selectGender == 'f':
            gender = '_WOMEN'
        elif selectGender == 'm':
            gender = '_MEN'
        #Get number of round to restart from (i.e. round played just before tornement finished prematurely)
        playRound = tennisTools.restartRound

        #Name of previous round
        nameOfFile = tornement + str(playRound) + gender + fileType
        #Re-run round, but don't update anything as those points already added
        tennisTools.runRound(nameOfFile)

        #Don't display option to view sorted list if re-running un-finished tornement
        cantSee = True
        manualSelect = 'n'

    #end check#

    ################################
    #LOOP THROUGH SUBSEQUENT ROUNDS#
    ################################

    while int(playRound) != 5:
        if cantSee == False:
            #check players' earnings
            menuFunctions.checkPrizeMoney(selectGender)
            #Check leader board for round
            menuFunctions.checkPointsFromRound()
            #check overall leader bourd
            menuFunctions.checkOverallRankPoints()
        else:
            pass

        #Enable sorted lists
        cantSee = False

        #Confirm play next round and add players to list for next round
        if manualSelect == 'y':
            playRound = menuFunctions.playNextRound(playRound)
            listSelect = manualInput.userInputStack(selectGender, str(playRound))
        else:
            playRound = menuFunctions.playNextRound(playRound)
            listSelect = tennisTools.currentWinners

        #Display round number
        print('Round: ', playRound)

        #select file depending on round
        nameOfFile = tornement + str(playRound) + gender + fileType

        #Set fixtures, generate scores, write to file.
        if manualSelect == 'y':
            tennisTools.setFixturesFromManual(nameOfFile,listSelect, selectGender)
        else:
            tennisTools.setFixtures(nameOfFile,listSelect, selectGender)

        #Clear curent winners list, so a new list of winners can be made from this round
        tennisTools.currentWinners.clear()

        #Determine winners by reading file created in previous step. Display Results
        tennisTools.runRound(nameOfFile)

        #Update Ranking points, both per round and overall
        ranking.updateRankPoints(tornement, str(playRound), selectGender)
        ranking.updatePointsCurrentTornement(tornement, str(playRound), selectGender)

        #Determine money owed to each player
        prizeMoney.calculatePrizeMoney(tornement, str(playRound), selectGender)

        #Record tornement as complete, or not.
        tennisTools.writePreviousComplete(tornement, selectGender, str(playRound))

    #Clear temporary points file, as tornement finished
    ranking.clearTempFileForPastTornement(selectGender)

    #Commit Prize money to file
    prizeMoney.commitPrizeMoney(selectGender)

    #Clear temporary prize money file, as tornement finished
    prizeMoney.clearTemporaryRoundFile(selectGender)

    #empty current Winners list, so winner doesn't spill into next tornement
    tennisTools.currentWinners.clear()

    #check players' earnings
    menuFunctions.checkPrizeMoney(selectGender)
    #Check leader board for round
    menuFunctions.checkPointsFromRound()
    #check overall leader bourd
    menuFunctions.checkOverallRankPoints()

    #Exit System?
    #exitSystem = input('Exit Program: Y/N').upper()
    exitSystem = menuFunctions.exitSelector()
    if exitSystem == 'Y':
        sys.exit(0)
    else:
        pass

#######################
#END MAIN PROGRAM LOOP#
#######################


import logging
from flask_restplus import Api
from werkzeug.exceptions import NotFound

log = logging.getLogger(__name__)

api = Api(
    #version=settings.get("API_VERSION","1.0"),
    #title=settings.get("API_TITLE","data Engine API"),
    #description=settings.get("API_DESC","data"),
    #authorizations=authorizations,
    #decorators=decorators
    )

@api.errorhandler
def default_error_handler(e):
    """Default Error Handles

    Args:
        e (Exception): Any exeption generated

    Returns:
        json: A proper json message
    """
    message = 'An unhandled exception occurred.'
    log.exception(message)
    print(type(message))

    return {'message': message, 'message': message.specific}, 500
    #return {'message': message}, 500

@api.errorhandler(NotFound)
def handle_no_result_exception(error):
    '''Return a custom not found error message and 404 status code'''
    return {'message': error.specific}, 404


#! /usr/bin/env python3
import atheris
import sys
import fuzz_helpers

with atheris.instrument_imports(include=['vermin']):
  import vermin

def TestOneInput(data):
    fdp = fuzz_helpers.EnhancedFuzzedDataProvider(data)
    try:
      if fdp.ConsumeBool():
        vermin.version_strings(vermin.detect(fdp.ConsumeRemainingString()))
      else:
        vermin.visit(fdp.ConsumeRemainingString())
    except (vermin.InvalidVersionException, UnicodeDecodeError, SyntaxError):
      return -1
    except ValueError as e:
      if 'null bytes' in str(e):
        return -1
      raise e

def main():
    atheris.Setup(sys.argv, TestOneInput)
    atheris.Fuzz()

if __name__ == "__main__":
    main()


#!/usr/bin/env python3
# -*-encoding: utf-8-*-

# created: 11.12.18
# by David Zashkolny
# 2 course, comp math
# Taras Shevchenko National University of Kyiv
# email: davendiy@gmail.com

from collections import deque

WALL_CELL = 'R'
START1 = 'g'
START2 = 'l'
END = 'e'

def readMazesFromFile(filename):
    tmp = ''
    with open(filename, 'r') as file:
        n = int(file.readline())
        for test in range(n):
            maze = []  # Створення порожньої матриці для задавання лабіринту
            while not tmp:
                tmp = file.readline()

            n1, m1 = map(int, tmp.split())
            start1 = (1, 1)
            start2 = (1, 1)
            end = (1, 1)
            i = 1
            while True:
                str_row = file.readline()
                if not str_row:
                    str_row = file.readline()
                if not str_row or str_row[0].isdigit():
                    tmp = str_row
                    break
                row = list(str_row.strip())
                if len(row) == 0:  # Захист від зайвих рядків у кінці файлу
                    break

                # додавання лівої та правої "стіни" лабіринту
                row.insert(0, WALL_CELL)
                row.append(WALL_CELL)

                if START1 in row:
                    start1 = (i, row.index(START1))
                if START2 in row:
                    start2 = (i, row.index(START2))
                if END in row:
                    end = (i, row.index(END))

                maze.append(row)  # додавання рядка до лабіринту

            rowLast = [WALL_CELL] * (n1 + 2)  # останній рядок матриці, що визначає нижню стіну
            maze.append(rowLast)
            yield maze, start1, start2, end

def task_wave(maze, start1, start2, end):
    """ Функція побудови хвильової матриці для лібіринту
    P4 зі стартовою точкою start
    wall_cell - символ, що позначає стіну лабіринта або непрохідну його клітину
    """
    dx = [-1, 0, 1, 0]
    dy = [0, -1, 0, 1]

    n = len(maze)  # кількість рядків у матриці P4
    m = len(maze[0])  # кількість стовпчиків у матриці P4

    # створення та ініціалізація хвильової матриці
    # такої ж розмірності, що і матриця лабіринту
    waveMatrix1 = [[-1 for i in range(m)] for i in range(n)]
    waveMatrix2 = [[-1 for i in range(m)] for i in range(n)]

    q = deque()  # Створюємо чергу
    q.appendleft((start2, 2))
    q.appendleft((start1, 1))  # Додаємо у чергу координати стартової клітини

    waveMatrix1[start1[0]][start1[1]] = 0  # Відстань від стартової клітини до себе нуль
    waveMatrix2[start2[0]][start2[1]] = 0
    while q:
        current = q.pop()  # Беремо перший елемент з черги
        i = current[0][0]  # координата поточного рядка матриці
        j = current[0][1]  # координата поточного стовчика матриці
        side = current[1]
        # Додаємо в чергу всі сусідні клітини
        for k in range(len(dx)):

            i1 = i + dy[k]  # координата рядка сусідньої клітини
            j1 = j + dx[k]  # координата стовпчика сусідньої клітини

            # які ще не були відвідані та у які можна пересуватися

            if waveMatrix1[i1][j1] == -1 and maze[i1][j1] != WALL_CELL and side == 1 and waveMatrix2[i1][j1] == -1:
                q.appendleft(((i1, j1), 1))
                # Встановлюємо відстань на одиницю більшу ніж для поточної
                waveMatrix1[i1][j1] = waveMatrix1[i][j] + 1

            if waveMatrix2[i1][j1] == -1 and maze[i1][j1] != WALL_CELL and side == 2 and maze[i1][j1] != END:
                q.appendleft(((i1, j1), 2))
                waveMatrix2[i1][j1] = waveMatrix2[i][j] + 1

    # print('\n-----------')
    # for row in waveMatrix1:
    #     tmp = ' '.join(map(str, row))
    #     print(tmp.replace('-1', '_'))
    # print()
    # for row in waveMatrix2:
    #     tmp = ' '.join(map(str, row))
    #     print(tmp.replace('-1', '_'))
    return waveMatrix1[end[0]][end[1]] != -1

if __name__ == '__main__':
    with open('output88.txt', 'w') as outfile:
        for tmp_maze, tmp_start1, tmp_start2, tmp_end in readMazesFromFile('input88.txt'):
            res = task_wave(tmp_maze, tmp_start1, tmp_start2, tmp_end)
            if res:
                outfile.write('YES\n')
            else:
                outfile.write('NO\n')


from ecoalert.earthquakes.selectors import get_earth_quakes_features
from ecoalert.weatherwarnings.selectors import get_warnings

from .types import County, EarthQuake, EventType, Warning

async def get_weather_warnings(
    county: County | None = None,
    event: EventType | None = None,
) -> list[Warning]:
    items = await get_warnings(
        county=county.value if county else None,
        event=event.value if event else None,
    )
    return [Warning.from_basemodel(item) for item in items]

async def get_earthquakes() -> list[EarthQuake]:
    features = await get_earth_quakes_features()
    return [EarthQuake.from_basemodel(feature) for feature in features]


import  tensorflow as tf
from tensorflow.keras import datasets, layers, Sequential, callbacks, models
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.utils import to_categorical
from datetime import datetime
from matplotlib import pyplot
from numpy import mean, std, expand_dims

def create_model():
    model = Sequential([
        layers.Flatten(input_shape=(28,28,1)),
        layers.Dense(512, activation='relu'),
        layers.Dense(128, activation='relu'),
        layers.Dense(32, activation='relu'),
        layers.Dense(10, activation='softmax')
    ])

    model.compile(
        optimizer='adam',
        loss='sparse_categorical_crossentropy',
        metrics=['accuracy'])

    return model

def evaluate_model(model, epochs, steps_per_epoch, batch_size):
    logdir='logs\\' + datetime.now().strftime("%Y%m%d-%H%M%S")
    tensorboard_callback = callbacks.TensorBoard(log_dir=logdir, update_freq='batch', profile_batch = 3)

    gen = ImageDataGenerator(
        rescale=1./255,
        data_format="channels_last",
        zoom_range=0.4,
        shear_range=0.2,
        rotation_range=45,
        width_shift_range=3,
        height_shift_range=3)

    training_it = gen.flow_from_directory(
        "./images/training",
        target_size=(28, 28),
        color_mode='grayscale',
        class_mode='binary',
        batch_size=batch_size,
        # save_to_dir="./images/training_augmented",
        # save_format='png',
        interpolation='nearest')

    validation_it = gen.flow_from_directory(
        "./images/training",
        target_size=(28, 28),
        color_mode='grayscale',
        class_mode='binary',
        batch_size=batch_size,
        interpolation='nearest')

    model.fit_generator(training_it,
        steps_per_epoch=steps_per_epoch,
        epochs=epochs,
        callbacks=[tensorboard_callback],
        validation_data=validation_it,
        validation_freq=1)

def preprocess(path):
    pil = image.load_img(path, color_mode="grayscale")
    array = image.img_to_array(pil, data_format="channels_last")
    reshaped = array.reshape(1, pil.width, pil.height, 1)
    resized = tf.image.resize(reshaped, size=[28,28], method='gaussian')
    return resized/255


from urllib import response
import pandas as pd
import requests
import json
# from bs4 import BeautifulSoup
# from selenium import webdriver
# from selenium.webdriver.firefox.options import Options

# Grab content from URL
strain_origin_url = "https://consumer-api.leafly.com/api/strain_playlists/v2?"
strain_page_per_take = 18
strain_page_num = 342
# strains list to excel

strainList_name=[]
strainList_url=[]
strainList_category=[]
strainList_thc=[]
strainList_cbd=[]
strainList_rating=[]

def scrapStrain():

    for x in range(strain_page_num):
        strain_get_url = strain_origin_url + "&skip={}&take={}"
        response = requests.get(strain_get_url.format(x, strain_page_per_take))
        strains = json.loads(response.text)['hits']['strain']
        for y in range(strain_page_per_take):
            strainList_name.append(strains[y]['name'])
            strainList_url.append(strains[y]['nugImage'])
            strainList_category.append(strains[y]['category'])
            strainList_thc.append(strains[y]['cannabinoids']['thc']['percentile50'])
            strainList_cbd.append(strains[y]['cannabinoids']['cbd']['percentile50'])
            strainList_rating.append(strains[y]['averageRating'])
    df = pd.DataFrame({
        'name' : strainList_name,
        'url':strainList_url,
        'category':strainList_category,
        'thc':strainList_thc,
        'cbd':strainList_cbd,
        'rating':strainList_rating
    })
    df.to_excel('names.xlsx', index=False, encoding='utf-8')

scrapStrain()


import sys
import os
import codecs

sys.path.append(".")
old_dir = os.getcwd()
os.chdir("../")

from TrendAnalyser import TrendAnalyser

TA = TrendAnalyser(load_api=False)
os.chdir(old_dir)

positive = open("positive-words.txt", "r")

for line in positive:
    fixed = line.rstrip("\n").decode("iso-8859-1")
    if fixed == "":
        continue
    elif fixed[0] == ";":
        continue

    #print fixed
    TA.db.insert("words_positive", {"word": fixed})

negative = open("negative-words.txt", "r")

for line in negative:
    fixed = line.rstrip("\n").decode("iso-8859-1")
    if fixed == "":
        continue
    elif fixed[0] == ";":
        continue

    #print fixed
    TA.db.insert("words_negative", {"word": fixed})


import geopandas as gpd
import pandas as pd

def areal(source, target, cols = [None], suffix = ''):
    """
    The areal weighting method interpolates data into target polygons by using the ratio of
    intersected area to source area. It accepts two DataFrames – a source and target, a list of columns to be interpolated,
    and an optional suffix for the new name of the interpolated column in the target DataFrame. In the function,
    the source polygons are reindexed for summing later, and the areas of the source polygons are calculated.
    The source and target are intersected, and the area of the intersected polygons is calculated.
    Each intersected area is divided by the source area that encapsulates it for its areal weight.
    The function then iterates through the selected columns and multiplies each value by the areal weight.
    The target DataFrame is returned with the interpolated columns.

    :param source: DataFrame with values for interpolation.
    :type source: DataFrame
    :param target: DataFrame with polygons obtaining interpolated values.
    :type target: DataFrame
    :param cols: Column(s) from source to be interpolated.
    :type cols: list
    :param suffix: New name for interpolated columns. The default is ''
    :type suffix: str, optional

    :returns: Target DataFrame with interpolated columns added
    :rtype: DataFrame
    """

    #reindex for sum of interpolated results to merge later
    target['_index'] = target.index

    #calculate source areas
    source['source_area'] = source.geometry.area

    #intersect source and target
    joined1 = gpd.overlay(source, target, how = 'intersection')

    #calculate intersected areas
    joined1['intersect_area'] = joined1.geometry.area

    #calculate areal weight per intersected polygon
    joined1["AREAL_WT"] = joined1['intersect_area'] / joined1['source_area']

    #interpolate designated columns, create list to include in target dataframe
    new_cols = []
    for col in cols:
        new_col = col + suffix
        new_cols.append(new_col)
        joined1[new_col] = joined1["AREAL_WT"] * joined1[col]

    #merge interpolated results to target dataframe
    results = joined1.groupby('_index').sum()
    final = pd.merge(target, results[new_cols], on='_index')
    del final['_index']
    return final


"""
出席管理画面
"""
import sys
import os
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
from ic_reader import ICReader
# from attendance_management import AttendanceManagement,AttendIdent
from attendance_management2 import AttendanceManagement
from shadow_effect import ShadowEffect
from widget.totalization_widget import TotalizationWidget
from widget.clock_widget import ClockWidget
from widget.syuketu_widget import SyussekiWidget
from widget.start_widget import StartWidget
import resource

# ラズパイ公式7インチタッチパネル 800 x 480 60fps

# メインウィンドウ
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('出席管理')
        self.initUI()

    def initUI(self):
        # self.setStyleSheet('background-color:white;')
        self.setObjectName('MainWindow')
        self.status = QStatusBar()
        self.setStatusBar(self.status)
        self.start_widget = StartWidget()
        #self.common = TestWidget()
        self.setCentralWidget(self.start_widget)
        self.start_widget.clicked_signal.connect(lambda x,y:self.change(x,y))
        #self.setCentralWidget(self.common)
        # self.start_widget.changeWidget.connect(lambda x,y:self.change(x,y))
        statuslabel = QLabel()
        statuslabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
        statuslabel.setOpenExternalLinks(True)
        hrefurl = os.path.join(os.path.dirname(__file__),'table.html').replace('\\','/') # windowsだとpathがバックスラッシュになってhrefだと認識しない
        statuslabel.setText('科目ID，科目名対応表')
        self.status.addWidget(statuslabel)
        self.resize(800,500)
        # self.start_widget.setFixedSize(800,500)
        # self.start_widget.setGraphicsEffect(ShadowEffect(self))

    def resizeEvent(self, event):
        super(MainWindow, self).resizeEvent(event)
        # self.start_widget.setFixedSize(self.width(),self.height())
        print(self.height(),self.width())

    # 出席状況表示用ウィジェットに切り替え
    @Slot(str,int)
    def change(self,kamoku,kaisu):
        print('科目ID',kamoku,'授業回数',kaisu)
        tmp = AttendanceManagement(kamoku,kaisu)
        try:
            if not tmp.is_ready():
                pass
            if not tmp.is_existed_file()[0]:
                if 0 in tmp.is_existed_file()[1]:
                    QMessageBox.warning(self,'NotFoundError','履修者ファイルがありません')
                elif 1 in tmp.is_existed_file()[1]:
                    QMessageBox.warning(self,'NotFoundError','規則データがありません')
                return
            self.main = MainWidget(kamoku,kaisu)
            self.main.returnSignal.connect(self.return_toppage)
            self.setCentralWidget(self.main)
            self.resize(800,480)
        except:
            import traceback
            traceback.print_exc()

    # トップページに戻る
    @Slot()
    def return_toppage(self):
        self.main = ''
        self.start_widget = StartWidget()
        self.start_widget.clicked_signal.connect(self.change)
        self.setCentralWidget(self.start_widget)

# 起動時の画面
class MainWidget(QWidget):
    changeWidget = Signal(str,int)
    returnSignal = Signal()
    readSignal = Signal(str,str)
    def __init__(self,kamoku,kaisu):
        super().__init__()
        # self.setFixedSize(800,480)
        self.attendace_management = AttendanceManagement(kamoku,int(kaisu))
        self.attendace_management.on_connect(self.update_text2)
        self.attendace_management.on_connect(lambda x,y:self.readSignal.emit(x,y))
        self.readSignal.connect(lambda x,y:self.update_text2(x,y))
        self.attendace_management.set_kisoku()
        self.attendace_management.set_attendance_list()
        self.attendace_management.start()
        self.uketuke = True
        self.initUI()
        self.initSlot()
        self.setStyle(QStyleFactory.create('WindowsXP'))

    def __del__(self):
        print("削除")
        self.attendace_management.__del__()

    def initUI(self):
        # 上段
        # タイトルラベル
        self.label = QLabel("出席管理 ")
        self.label.setFont(QFont('メイリオ',30))
        self.label.setAlignment(Qt.AlignCenter|Qt.AlignVCenter)
        self.label.setObjectName('TitleLabel')
        # self.label.setStyleSheet("border-radius:40%;color:black;background-color: white;")
        self.label.setGraphicsEffect(ShadowEffect(self))
        self.label.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
        # 時計
        self.clock = ClockWidget(20)
        self.clock.start()

        # 中層
        # なまえラベル
        self.name_label = QLabel('待機中')
        self.name_label.setFont(QFont('メイリオ',30))
        self.name_label.setAlignment(Qt.AlignCenter)
        self.name_label.setObjectName('NameLabel')
        # self.name_label.setStyleSheet("border-radius:40%;color:black;background-color: white;")
        self.name_label.setGraphicsEffect(ShadowEffect(self))
        self.name_label.setMargin(20)
        self.name_label.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
        self.name_label.setWordWrap(True)
        # self.name_label.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
        # 出席ラベル
        self.syusseki_label = SyussekiWidget()
        self.syusseki_label.setText('')

        # 戻るボタン
        self.return_btn = QPushButton("戻る")
        self.return_btn.setIcon(QPixmap(":images/images/return.png"))
        self.return_btn.setIconSize(QSize(60,60))
        self.return_btn.setGraphicsEffect(ShadowEffect(self))
        self.return_btn.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
        self.return_btn.setObjectName('ReturnBtn')
        # self.return_btn.setStyleSheet("border-radius:30%;color:black;background-color: white;")
        self.return_btn.setFont(QFont("メイリオ",20))
        # 終了ボタン
        self.exit_btn = QPushButton("終了")
        self.exit_btn.setGraphicsEffect(ShadowEffect(self))
        self.exit_btn.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
        self.exit_btn.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
        self.exit_btn.setObjectName('ExitBtn')
        # self.exit_btn.setStyleSheet("border-radius:30%;color:white;background-color: black;")
        self.exit_btn.setFont(QFont("メイリオ",20))
        # self.exit_btn.clicked.connect(lambda :(self.name_label.setText("スズキイチロウタロ\nウジロウ"),self.syusseki_label.setText("欠席")))
        # 集計
        self.syukei = TotalizationWidget()
        self.syukei.setGraphicsEffect(ShadowEffect(self))

        # layout
        self.main_layout = QVBoxLayout() # 全体のレイアウト
        self.headerLayout = QGridLayout() # 上段部分レイアウト
        self.middleLayout = QGridLayout() # 中段部分レイアウト
        self.footerLayout = QGridLayout() # 下段部分レイアウト
        self.clockLayout = QVBoxLayout() # 時計部分レイアウト

        # レイアウトの設定
        self.main_layout.setSpacing((self.height()+self.width())/20)
        self.main_layout.setMargin((self.height()+self.width())/20)
        self.main_layout.setSpacing(30)
        self.main_layout.setMargin(30)
        self.headerLayout.setContentsMargins(0,0,20,0)
        self.middleLayout.setContentsMargins(25,0,25,0)
        self.footerLayout.setContentsMargins(10,0,10,0)
        # 上段
        self.clockLayout.addWidget(self.clock)
        self.clockLayout.addWidget(QWidget())
        # self.clockLayout.addStretch(1)
        # self.headerLayout.setColumnStretch(0,1)
        self.headerLayout.addWidget(QWidget(),0,0) # stretchの使い方がわからないので無理やり
        self.headerLayout.addWidget(self.label,0,1,1,3)
        # self.headerLayout.setColumnStretch(4,1)
        self.headerLayout.addLayout(self.clockLayout,0,5)
        # self.main_layout.addWidget(self.label)
        self.main_layout.addLayout(self.headerLayout)
        # self.main_layout.addStretch(1)
        # self.main_layout.addLayout(self.combo_layout)
        # self.main_layout.addStretch(1)
        # self.main_layout.addLayout(self.btn_layout)

        # middle
        # self.middleLayout.setMargin(100)
        # self.middleLayout.setSpacing(100)
        self.middleLayout.addWidget(self.name_label,0,0,1,2)
        self.middleLayout.addWidget(self.syusseki_label,0,2,1,1)

        # self.main_layout.addStretch(1)
        # 最下段
        self.footerLayout.addWidget(self.return_btn,1,0)
        # self.footerLayout.addWidget(QWidget(),1,1)
        self.footerLayout.addWidget(self.syukei,0,2,2,1)
        # self.footerLayout.addWidget(QWidget(),1,3)
        self.footerLayout.addWidget(self.exit_btn,1,4)

        self.main_layout.addLayout(self.middleLayout)
        # self.main_layout.addStretch(1)
        self.main_layout.addLayout(self.footerLayout)

        self.setLayout(self.main_layout)
        # self.setGraphicsEffect(ShadowEffect(self))

    # 最初の画面に戻る
    @Slot()
    def return_window(self):
        res = QMessageBox.question(self, '終了します', '出席管理を終わりまする．')
        if res == QMessageBox.Yes:
            self.returnSignal.emit()
            self.close()

    # スロット設定
    def initSlot(self):
        # self.return_btn.clicked.connect(self.update_text)
        self.return_btn.clicked.connect(lambda :self.return_window())
        self.exit_btn.clicked.connect(lambda :self.exit_window())

    # 初期テキスト
    def init_text(self):
        self.name_label.setText('待機中')
        self.name_label.setFont(QFont('メイリオ',30))
        self.syusseki_label.setText('')
        self.uketuke = True
        QCoreApplication.processEvents()
        print('init_text')

    # 画面を落とす
    @Slot()
    def exit_window(self):
        res = QMessageBox.question(self, '終了します', '出席管理を終わりまする．')
        if res == QMessageBox.Yes:
            self.close()
            QCoreApplication.quit()

    # 科目と回数を引数にシグナルを発火
    @Slot()
    def emit_clicked(self):
        print(self.kaisu_combo.currentText())
        self.changeWidget.emit(str(self.kamoku_combo.currentText()),int(self.kaisu_combo.currentText()))

    @Slot(str,str)
    def update_text2(self,name,syusseki):
        print(syusseki)
        if self.uketuke:
            self.uketuke = False
            if syusseki == '登録済':
                self.name_label.setText(name)
                self.syusseki_label.setText(syusseki)
            elif syusseki == 'not':
                self.name_label.setFont(QFont('メイリオ', 15))
                self.name_label.setText('履修者として登録されていません')
                self.syusseki_label.setText('エラー')
            else:
                self.name_label.setText(name)
                self.syusseki_label.setText(syusseki)
                if syusseki == '出席':
                    self.syukei.set_attend()
                elif syusseki == '遅刻':
                    self.syukei.set_late()
                elif syusseki == '欠席':
                    self.syukei.set_absence()
        QCoreApplication.processEvents()
        QTimer.singleShot(2000, self.init_text) # 二秒後に行う処理を書く
        print("並列処理再開 on MainWidget.update_text")
        QTimer.singleShot(2000,self.attendace_management.event.set)

    # ラベルとかその他とかをアップデート
    @Slot()
    def update_text(self):
        # syukketu = self.attendance_management.check_attendance(idm)
        # 2秒間だけ表示して元のテキストに戻す
        # 表示中にスキャンできないようにフラグを用意する
        if self.uketuke:
            self.uketuke = False
            self.name_label.setFont(QFont('メイリオ',15))
            self.name_label.setText('履修者として登録されていません')
            self.syusseki_label.setText('エラー')
            # self.name_label.setFont(QFont('メイリオ',30))
            # time.sleep(2)
            QTimer.singleShot(2000, self.init_text) # 二秒後に行う処理を書く
            # self.init_text()
            print("並列処理再開 on GamelikeWidget.update_text")
            # QTimer.singleShot(2000, self.reader.event.set)

# ポケモン風UI -> ボツ
class GamelikeWidget(QWidget):
    readidm:Signal = Signal(str) # idmを読み取ったときのsignal
    returnsignal:Signal = Signal() # 画面をトップページに戻したいときのsignal
    def __init__(self,kamoku,kaisu,parent=None):
        super(GamelikeWidget,self).__init__(parent)
        # ラズパイ公式7インチタッチパネル 800 x 480 60fps
        self._height = 480
        self._width = 800
        self.reader = ICReader(self)
        self.reader.on_connect(self.readidm.emit) # 読み取り部分に関数登録
        self.reader.start() # 読み取り開始
        self.attendance_management = AttendanceManagement(kamoku,kaisu)
        self.attendance_management.get_risyu_list('D:\work\systemproject\\test.csv')
        self.risyusya_number = self.attendance_management.risyu_number # 履修者の数
        self.enemyHP = self.attendance_management.risyu_number # HP上限は履修者の数
        self.myHP = self.attendance_management.risyu_number # HP上限は履修者の数
        self.initUI()

    def initUI(self):
        self.setFixedSize(self._width,self._height)
        # バックグラウンド(ポケモン風画像)
        self.background = QLabel(self)
        self.background.setFixedSize(self._width,self._height)
        self.background.setPixmap(QPixmap('C:\\Users\\user\\Downloads\\pokemonlike.png'))
        # 敵HP
        self.enemyHPbar = QProgressBar(self)
        self.enemyHPbar.setFixedSize(240,20)
        self.enemyHPbar.setMaximum(self.risyusya_number)
        self.enemyHPbar.setValue(self.enemyHP)
        self.enemyHPbar.setFormat('%v/'+str(self.risyusya_number))
        self.enemyHPinfo = QLabel(self)
        self.enemyHPinfo.setText(str(self.enemyHP)+'  /  '+str(self.risyusya_number))
        self.enemyHPinfo.setFont(QFont("メイリオ",25))
        self.enemyHPinfo.setFixedSize(300,35)
        # 自分HP
        self.myHPbar = QProgressBar(self)
        self.myHPbar.setFixedSize(240,20)
        self.myHPbar.setMaximum(self.risyusya_number)
        self.myHPbar.setValue(self.myHP)
        self.myHPbar.setFormat('%v/'+str(self.risyusya_number))
        self.myHPinfo = QLabel(self)
        self.myHPinfo.setFont(QFont("メイリオ",25))
        self.myHPinfo.setText(str(self.myHP)+'  /  '+str(self.risyusya_number))
        self.myHPinfo.setFixedSize(300,35)
        # テキスト欄
        self.text = QLabel(self)
        self.text.setFixedSize(900,200)
        # self.text.setStyleSheet('background-color: red;')
        self.text.setFont(QFont("メイリオ",40))
        self.init_text()

        #終了，戻るボタン
        self.exitBtn = QPushButton(self)
        self.exitBtn.setText("終了")
        self.exitBtn.setFixedSize(100,50)
        self.exitBtn.clicked.connect(self.exitWindow)
        self.exitBtn.setShortcut('q')
        self.returnBtn = QPushButton(self)
        self.returnBtn.setText("戻る")
        self.returnBtn.setFixedSize(100,50)
        self.returnBtn.clicked.connect(self.returnWindow)
        self.returnBtn.setShortcut('r')

        # 配置
        self.background.move(0,0)
        self.enemyHPbar.move(50,50)
        self.enemyHPinfo.move(50,80)
        self.myHPbar.move(500,240)
        self.myHPinfo.move(500,270)
        self.text.move(20,330)
        self.exitBtn.move(700,380)
        self.returnBtn.move(700,420)
        self.readidm.connect(lambda idm: self.update_text(idm))

    # 待機画面のラベルに遷移
    def init_text(self):
        self.text.setText("ICカードをかざすがよい")
        self.update()
        QCoreApplication.processEvents()

    # テキストの内容を割り当てる
    def assign_text(self,syukketu,idm):
        # 出席時には敵のHPが減る
        if syukketu == AttendIdent.Attendance:
            self.enemyHP = self.enemyHP-1
            if self.enemyHP < 0:
                self.enemyHP = 0
            self.enemyHPbar.setValue(self.enemyHP)
            self.enemyHPinfo.setText(str(self.enemyHP)+'  /  '+str(self.risyusya_number))
            #syukketu_table = ['出席','遅刻','欠席']
            self.text.setText(idm+'は出席することができました')
        # 欠席，遅刻時には自分のHPが減る
        elif syukketu == AttendIdent.Late or syukketu == AttendIdent.Absence:
            self.myHP = self.myHP-1
            if self.myHP < 0:
                self.myHP = 0
            self.myHPbar.setValue(self.myHP)
            self.myHPinfo.setText(str(self.myHP)+'  /  '+str(self.risyusya_number))
            #syukketu_table = ['出席','遅刻','欠席']
            if syukketu == AttendIdent.Late:
                self.text.setText(idm+'は遅刻することができました')
            else:
                self.text.setText(idm+'は欠席することができました')
        elif syukketu == AttendIdent.Already:
            self.text.setText(idm+'はすでにかざしてらっしゃる')
        else:
            self.text.setText(idm+'は履修者ではありません')
        self.update()
        QCoreApplication.processEvents()

    # ラベルとかその他とかをアップデート
    @Slot(str)
    def update_text(self,idm):
        syukketu = self.attendance_management.check_attendance(idm)
        self.assign_text(syukketu,idm)
        # 2秒間だけ表示して元のテキストに戻す
        # time.sleep(2)
        QTimer.singleShot(2000,self.init_text)
        # self.init_text()
        print("並列処理再開 on GamelikeWidget.update_text")
        QTimer.singleShot(2000,self.reader.event.set)

    @Slot()
    def exitWindow(self):
        res = QMessageBox.question(self, '終了します', '出席管理を終わりまする．')
        if res == QMessageBox.Yes:
            self.close()
            QCoreApplication.quit()

    @Slot()
    def returnWindow(self):
        res = QMessageBox.question(self, '終了します', '出席管理を終わりまする．')
        if res == QMessageBox.Yes:
            self.returnsignal.emit()
        self.reader.raise_exception()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle(QStyleFactory.create('Fusion'))
    print(QStyleFactory.keys())
    ex = MainWindow()
    try:
        csspath = os.path.join(os.path.dirname(__file__),'css/main.css')
        with open(csspath, 'r', encoding='utf-8') as f:
            css = f.read()
            app.setStyleSheet(css)
    except:
        print('css open error')
    #ex = GamelikeWidget()
    ex.show()
    #reader = ICReader(ex)
    #reader.start_read()
    sys.exit(app.exec_())


# coding: utf-8
from pdb import lasti2lineno
import tkinter as tk

version = "v1.0"

class Window(tk.Frame):
    def __init__(self,master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.menu()

    def menu(self):
        self.start_menu = tk.Frame(self)
        self.start_menu.pack()

        self.startbutton = tk.Button(self.start_menu,text="起動",command=lambda:self.guzai_setting())
        self.startbutton.pack()

        self.endbutton = tk.Button(self.start_menu,text="終了",command=lambda:self.master.destroy())
        self.endbutton.pack()

    def guzai_setting(self):
        self.reset(self.start_menu)

        self.setting_frame = tk.Frame(self)
        self.setting_frame.pack(side=tk.LEFT)

        label = tk.Label(self.setting_frame,text="具材を入力してください")
        label.pack()

        self.t = tk.StringVar()

        self.entrybox = tk.Entry(self.setting_frame,textvariable=self.t)
        self.entrybox.bind("<Return>",lambda event:self.add_guzai())
        self.entrybox.pack()

        add_button = tk.Button(self.setting_frame,text="具材追加",command=lambda:self.add_guzai())
        add_button.pack()

        decide_button = tk.Button(self.setting_frame,text="具材の確定",command=lambda:self.get_list())
        decide_button.pack()

        self.guzai_list = tk.Listbox(self.setting_frame)
        self.guzai_list.bind("<<ListboxSelect>>",lambda event:self.guzai_list.delete(self.guzai_list.curselection()))
        self.guzai_list.pack()

        self.num_frame = tk.Frame(self)
        self.num_frame.pack(side=tk.LEFT)

    def add_guzai(self):
        self.guzai_list.insert(tk.END,self.entrybox.get())
        self.t.set("")

    def get_list(self):
        l = self.guzai_list.get(0,tk.END)
        self.add_label(self.num_frame,l)

    def add_label(self,frame,guzai_list):
        dic = {}
        num_dic = {}
        num = {}
        i = 0

        for guzai in guzai_list:
            dic[i] = tk.Label(frame,text=guzai)
            dic[i].pack()

            num[i] = tk.StringVar()
            num_dic[i] = tk.Spinbox(frame,state="readonly",textvariable=num[i],values=[x+1 for x in range(9)])
            num_dic[i].pack()

            i += 1

    def reset(self,frame):
        widgets = frame.winfo_children()
        for widget in widgets:
            widget.destroy()

class App:
    def run(self):
        root = tk.Tk()
        root.title("取り分チェッカー {}".format(version))
        root.geometry("1000x800+300+100")
        Window(root)
        root.mainloop()

if __name__ == "__main__":
    app = App()
    app.run()