import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import traceback

import functions as fn
import algorithms as alg
import numpy as np
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
from mpl_toolkits.mplot3d import Axes3D  # This import HAS to stay here !!!

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.initialized = False
        self.master = master
        self.initVars()
        self.createWorkspace()

    def initVars(self):
        # Default padding for GUI elements
        self.defPad = 2

        self.maxIterations = tk.IntVar()
        self.maxIterations.set(100)

        # Selection boxes
        self.functions = ['Sphere', 'Schwefel', 'Rosenbrock', 'Rastrigin', 'Griewank', 'Levy', 'Michalewicz',
                          'Zakharov', 'Ackley']
        self.selectedFunction = tk.StringVar()
        self.selectedFunction.set(self.functions[0])

        self.defaultNotebookFrameWidth = 200
        self.defaultNotebookFrameHeight = 200

        self.renderDelay = tk.DoubleVar()
        self.renderDelay.set(0.05)

    def createWorkspace(self):
        # Frames
        mainFrame = ttk.Frame(self.master)
        mainFrame.grid(row=0, column=0, padx=self.defPad, pady=self.defPad)

        mainConfigFrame = ttk.LabelFrame(mainFrame, text="Config")
        mainConfigFrame.grid(row=0, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.NW + tk.NE)

        commonConfigFrame = ttk.LabelFrame(mainConfigFrame, text="Common")
        commonConfigFrame.grid(row=0, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.NW + tk.NE)

        algoConfigFrame = ttk.LabelFrame(mainConfigFrame, text="Algorithms")
        algoConfigFrame.grid(row=1, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.NW + tk.NE)

        controlsConfigFrame = ttk.LabelFrame(mainConfigFrame, text="Control")
        controlsConfigFrame.grid(row=2, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.NW + tk.NE)

        #
        # Common config
        #

        functionLabel = ttk.Label(commonConfigFrame, text="Function")
        functionLabel.grid(row=0, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.E)

        functionOption = ttk.OptionMenu(commonConfigFrame, self.selectedFunction, None, *self.functions)
        functionOption.grid(row=0, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.W)

        functionOption.bind("<Configure>", self.onSelectFunction)

        iterationLabel = ttk.Label(commonConfigFrame, text="Iterations")
        iterationLabel.grid(row=1, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.E)

        iterationEntry = ttk.Entry(commonConfigFrame, textvariable=self.maxIterations)
        iterationEntry.grid(row=1, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.W)

        renderDelayLabel = ttk.Label(commonConfigFrame, text="Render delay")
        renderDelayLabel.grid(row=2, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.E)

        renderDelaySlider = ttk.Scale(commonConfigFrame, from_=0.0, to=5.0, variable=self.renderDelay)
        renderDelaySlider.grid(row=2, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.W + tk.E)

        renderDelayEntry = ttk.Entry(commonConfigFrame, textvariable=self.renderDelay)
        renderDelayEntry.grid(row=3, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.W + tk.E)

        # style = ttk.Style(root)
        # style.configure('lefttab.TNotebook', tabposition='wn')

        # self.tabsFrame = ttk.Notebook(algoConfigFrame, style='lefttab.TNotebook')
        self.tabsFrame = ttk.Notebook(algoConfigFrame)

        blindFrame = self.createBlindFrame(self.tabsFrame)
        hillClimbFrame = self.createHillClimbFrame(self.tabsFrame)
        annealingFrame = self.createAnnealingFrame(self.tabsFrame)
        tspFrame = self.createTSPFrame(self.tabsFrame)
        dgaFrame = self.createDGAFrame(self.tabsFrame)
        somaFrame = self.createSomaFrame(self.tabsFrame)
        antFrame = self.createAntFrame(self.tabsFrame)
        fireflyFrame = self.createFireflyFrame(self.tabsFrame)
        tlbaFrame = self.createTLBAFrame(self.tabsFrame)

        self.tabsFrame.add(blindFrame, text='Blind')
        self.tabsFrame.add(hillClimbFrame, text='Hill Climb')
        self.tabsFrame.add(annealingFrame, text='Annealing')
        self.tabsFrame.add(tspFrame, text='TSP')
        self.tabsFrame.add(dgaFrame, text='Differential GA')
        self.tabsFrame.add(somaFrame, text='SOMA')
        self.tabsFrame.add(antFrame, text='Ants')
        self.tabsFrame.add(fireflyFrame, text='Firefly')
        self.tabsFrame.add(tlbaFrame, text='TLBA')

        self.tabsFrame.grid(row=0, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.NW + tk.NE)

        runButton = ttk.Button(controlsConfigFrame, text="Run", command=self.run)
        runButton.grid(row=0, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.E)

        graph3dFrame = ttk.LabelFrame(mainFrame, text="3D plot")
        graph3dFrame.grid(row=0, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.NW + tk.NE)

        self.fig3D = Figure(figsize=(5, 4), dpi=100)
        self.canvas3D = FigureCanvasTkAgg(self.fig3D, master=graph3dFrame)
        # self.canvas3D.draw()

        self.graph3Dax = self.fig3D.gca(projection="3d")

        t = np.arange(0, 3, .01)
        self.graph3Dax.plot(t, 2 * np.sin(2 * np.pi * t))

        self.canvas3D.get_tk_widget().grid()

        graph2dFrame = ttk.LabelFrame(mainFrame, text="Fitness history")
        graph2dFrame.grid(row=0, column=2, padx=self.defPad, pady=self.defPad, sticky=tk.NW + tk.NE)

        # self.onSelectFunction(None)
        self.initialized = True

    def onSelectFunction(self, evt):
        if self.initialized is False:
            return
        try:
            func = fn.functionsMap[self.selectedFunction.get()]
            print(f"{func} selected")
            func.plot(axes=self.graph3Dax)
            self.canvas3D.draw()
            self.canvas3D.flush_events()
        except:
            print("Unable to update graph")
            traceback.print_exc()

    def quitApp(self):
        root.destroy()

    def createBlindFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)

        self.blindOptions = {
            "pointCloud": tk.IntVar()
        }
        self.blindOptions["pointCloud"].set(60)

        self.getFrameWithEntry(frame, text="Point cloud size", variable=self.blindOptions["pointCloud"]).grid(row=0,
                                                                                column=0,
                                                                                columnspan=2,
                                                                                sticky=tk.E)

        return frame

    def createHillClimbFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)

        self.hillClimbOptions = {
            "pointCloud": tk.IntVar(),
            "sigma": tk.DoubleVar()
        }
        self.hillClimbOptions["pointCloud"].set(60)
        self.hillClimbOptions["sigma"].set(0.05)

        self.getFrameWithEntry(
            master=frame,
            text="Point cloud size",
            variable=self.hillClimbOptions["pointCloud"]
        ).grid(row=0, column=0, columnspan=2, sticky=tk.E)
        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Sigma",
            variable=self.hillClimbOptions["sigma"],
            from_=0,
            to=1
        ).grid(row=1, column=0, columnspan=2, sticky=tk.E)

        return frame

    def createAnnealingFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)

        self.annealingOptions = {
            "pointCloud": tk.IntVar(),
            "temp": tk.DoubleVar(),
            "tempMin": tk.DoubleVar(),
            "alpha": tk.DoubleVar(),
            "sigma": tk.DoubleVar(),
            "elitism": tk.IntVar(),
            "repeats": tk.IntVar(),
        }
        self.annealingOptions["pointCloud"].set(10)
        self.annealingOptions["temp"].set(5000)
        self.annealingOptions["tempMin"].set(0.1)
        self.annealingOptions["alpha"].set(0.99)
        self.annealingOptions["sigma"].set(0.1)
        self.annealingOptions["elitism"].set(True)
        self.annealingOptions["repeats"].set(5)

        self.getFrameWithEntry(
            master=frame,
            text="Point cloud size",
            variable=self.annealingOptions["pointCloud"]
        ).grid(row=0, column=0, columnspan=2, sticky=tk.E)
        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Sigma",
            variable=self.annealingOptions["sigma"],
            from_=0,
            to=1
        ).grid(row=1, column=0, columnspan=2, sticky=tk.E)
        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Temperature",
            variable=self.annealingOptions["temp"],
            from_=1,
            to=10000
        ).grid(row=2, column=0, columnspan=2, sticky=tk.E)
        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Min temperature",
            variable=self.annealingOptions["tempMin"],
            from_=0.0,
            to=1
        ).grid(row=3, column=0, columnspan=2, sticky=tk.E)
        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Alpha",
            variable=self.annealingOptions["alpha"],
            from_=0.01,
            to=0.99
        ).grid(row=4, column=0, columnspan=2, sticky=tk.E)
        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Repeats for T",
            variable=self.annealingOptions["repeats"],
            from_=0.0,
            to=100
        ).grid(row=5, column=0, columnspan=2, sticky=tk.E)
        return frame

    def createTSPFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)
        self.tspOptions = {
            'citiesCount': tk.IntVar(),
            'dimensions': tk.IntVar(),
            'populationSize': tk.IntVar(),
            'workspaceSize': [10000, 10000, 10000],
            'mutationChance': tk.DoubleVar(),
        }

        self.tspOptions['citiesCount'].set(20)
        self.tspOptions['dimensions'].set(3)
        self.tspOptions['populationSize'].set(20)
        self.tspOptions['mutationChance'].set(0.5)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Cities count",
            variable=self.tspOptions["citiesCount"],
            from_=4,
            to=100
        ).grid(row=0, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Population",
            variable=self.tspOptions["populationSize"],
            from_=1,
            to=100
        ).grid(row=1, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Mutation chance",
            variable=self.tspOptions["mutationChance"],
            from_=0,
            to=1
        ).grid(row=2, column=0, columnspan=2, sticky=tk.E)

        return frame

    def createDGAFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)
        self.dgaOptions = {
            'populationSize': tk.IntVar(),
            'dimensions': tk.IntVar(),
            'scalingFactorF': tk.DoubleVar(),
            'crossoverCR': tk.DoubleVar(),
        }

        self.dgaOptions['populationSize'].set(20)
        self.dgaOptions['dimensions'].set(3)
        self.dgaOptions['scalingFactorF'].set(0.7)
        self.dgaOptions['crossoverCR'].set(0.7)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Population size",
            variable=self.dgaOptions["populationSize"],
            from_=4,
            to=100
        ).grid(row=0, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Scaling factor F",
            variable=self.dgaOptions["scalingFactorF"],
            from_=0.1,
            to=1.1
        ).grid(row=1, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Crossover factor CR",
            variable=self.dgaOptions["crossoverCR"],
            from_=0.0,
            to=1.0
        ).grid(row=2, column=0, columnspan=2, sticky=tk.E)

        return frame

    def createSomaFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)
        self.somaOptions = {
            'populationSize': tk.IntVar(),
            'dimensions': tk.IntVar(),
            'pathLength': tk.DoubleVar(),
            'step': tk.DoubleVar(),
            'perturbation': tk.DoubleVar(),
            'minDiv': tk.DoubleVar(),
        }

        self.somaOptions['populationSize'].set(20)
        self.somaOptions['dimensions'].set(3)
        self.somaOptions['pathLength'].set(3)
        self.somaOptions['step'].set(0.11)
        self.somaOptions['perturbation'].set(0.1)
        self.somaOptions['minDiv'].set(-0.1)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Population size",
            variable=self.somaOptions["populationSize"],
            from_=10,
            to=100
        ).grid(row=0, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Path length",
            variable=self.somaOptions["pathLength"],
            from_=1.1,
            to=10
        ).grid(row=1, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Step",
            variable=self.somaOptions["step"],
            from_=0.11,
            to=self.somaOptions["pathLength"].get()
        ).grid(row=2, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Perturbation",
            variable=self.somaOptions["perturbation"],
            from_=0,
            to=1
        ).grid(row=3, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Min Div",
            variable=self.somaOptions["minDiv"],
            from_=1,
            to=100
        ).grid(row=4, column=0, columnspan=2, sticky=tk.E)

        return frame

    def createAntFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)
        self.antOptions = {
            'dimensions': tk.IntVar(),
            'citiesCount': tk.IntVar(),
            'evaporization': tk.DoubleVar(),
            'initialFeromone': tk.DoubleVar(),
            'alpha': tk.DoubleVar(),
            'beta': tk.DoubleVar(),
            'workspaceSize': [100, 100, 100],
        }

        self.antOptions['dimensions'].set(3)
        self.antOptions['citiesCount'].set(20)
        self.antOptions['evaporization'].set(0.5)
        self.antOptions['initialFeromone'].set(1)
        self.antOptions['alpha'].set(1)
        self.antOptions['beta'].set(2)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Cities count",
            variable=self.antOptions["citiesCount"],
            from_=4,
            to=100
        ).grid(row=0, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Evaporization",
            variable=self.antOptions["evaporization"],
            from_=0.001,
            to=0.99
        ).grid(row=1, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Initial pheromone",
            variable=self.antOptions["initialFeromone"],
            from_=0.1,
            to=10
        ).grid(row=2, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Pheromone importance",
            variable=self.antOptions["alpha"],
            from_=0,
            to=10
        ).grid(row=3, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Distance importance",
            variable=self.antOptions["beta"],
            from_=0,
            to=10
        ).grid(row=4, column=0, columnspan=2, sticky=tk.E)

        return frame

    def createFireflyFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)
        self.fireflyOptions = {
            'dimensions': tk.IntVar(),
            "populationSize": tk.IntVar(),
            'alpha': tk.DoubleVar(),
            'betaAtractivness': tk.DoubleVar(),
        }

        self.fireflyOptions['dimensions'].set(3)
        self.fireflyOptions['populationSize'].set(20)
        self.fireflyOptions['alpha'].set(0.6)
        self.fireflyOptions['betaAtractivness'].set(1.0)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Number of fireflies",
            variable=self.fireflyOptions["populationSize"],
            from_=4,
            to=100
        ).grid(row=0, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Random factor (alpha)",
            variable=self.fireflyOptions["alpha"],
            from_=0,
            to=1
        ).grid(row=1, column=0, columnspan=2, sticky=tk.E)

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Atractivness (beta)",
            variable=self.fireflyOptions["betaAtractivness"],
            from_=0,
            to=1
        ).grid(row=2, column=0, columnspan=2, sticky=tk.E)
        return frame

    def createTLBAFrame(self, master):
        frame = ttk.Frame(master, width=self.defaultNotebookFrameWidth, height=self.defaultNotebookFrameHeight)
        self.tlbaOptions = {
            'dimensions': tk.IntVar(value=3),
            "populationSize": tk.IntVar(value=20),
        }

        self.getFrameWithSliderAndEntry(
            master=frame,
            text="Population size",
            variable=self.tlbaOptions["populationSize"],
            from_=4,
            to=100
        ).grid(row=0, column=0, columnspan=2, sticky=tk.E)
        return frame

    def getFrameWithEntry(self, master, text, variable):
        frame = ttk.Frame(master)

        valLabel = ttk.Label(frame, text=text)
        valLabel.grid(row=0, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.E)
        valEntry = ttk.Entry(frame, textvariable=variable)
        valEntry.grid(row=0, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.W + tk.E)

        return frame

    def getFrameWithSliderAndEntry(self, master, text, variable, from_, to):
        frame = ttk.Frame(master)

        valLabel = ttk.Label(frame, text=text)
        valLabel.grid(row=0, column=0, padx=self.defPad, pady=self.defPad, sticky=tk.E)
        valSlider = ttk.Scale(frame, from_=from_, to=to, variable=variable)
        valSlider.grid(row=0, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.W + tk.E)
        valEntry = ttk.Entry(frame, textvariable=variable)
        valEntry.grid(row=1, column=1, padx=self.defPad, pady=self.defPad, sticky=tk.W + tk.E)

        return frame

    def getAlgorithm(self):
        currentTabIdx = self.tabsFrame.index("current")
        func = fn.functionsMap[self.selectedFunction.get()]
        func.clearDict()

        algo = {
            0: alg.BlindAlgorithm(function=func,
                                  pointCloudSize=self.blindOptions["pointCloud"].get()),
            1: alg.HillClimbAlgorithm(function=func,
                                      pointCloudSize=self.hillClimbOptions["pointCloud"].get(),
                                      sigma=self.hillClimbOptions["sigma"].get()),
            2: alg.AnnealingAlgorithm(function=func,
                                      options=self.annealingOptions),
            3: alg.TravelingSalesmanGeneticAlgorithm(options=self.tspOptions),
            4: alg.DifferentialGeneticAlgorithm(function=func, options=self.dgaOptions),
            5: alg.SelfOrganizingMigrationAlgorithm(function=func, options=self.somaOptions),
            6: alg.TravelingSalesmanAntColonyAlgorithm(options=self.antOptions),
            7: alg.FireflyAlgorithm(function=func, options=self.fireflyOptions),
            8: alg.TeachingLearningBasedAlgorithm(function=func, options=self.tlbaOptions),
        }.get(currentTabIdx, None)

        print(f"Func: {func}")
        print(f"Current index: {currentTabIdx}")
        print(f"Alg: {algo}")

        return algo

    def run(self):
        algo = self.getAlgorithm()
        algo.renderDelay = self.renderDelay.get()
        algo.solve(maxIterations=self.maxIterations.get(), ax3d=self.graph3Dax, canvas=self.canvas3D)
        tk.messagebox.showinfo("Done", f"Best found value: {algo.fitness}. For more info check console output.")
        algo.plotFitnessHistory()

if __name__ == '__main__':
    root = tk.Tk()
    root.title("BIA GUI")
    app = Application(master=root)
    root.resizable(False, False)
    app.mainloop()


"""
<FloydWarshall>
- 모든 정점에서 모든 정점으로의 최단거리를 구하는 알고리즘
- 거쳐가는 정점을 기준으로 최단거리를 구한다???
"""

from sys import *

# number of nodes (1 ~ 100)
N = int(stdin.readline().rstrip())

# Graph
graph = []

for _ in range(N):
    graph.append(list(stdin.readline().rstrip().split()))

# check all nodes
for i in range(N):
    for j in range(N):
        for k in range(N):
            # i : pass node
            if graph[j][k] == "0" and graph[j][i] == "1" and graph[i][k] == "1":
                graph[j][k] = "1"

for g in graph:
    print(" ".join(g))


from dash import Dash, CeleryManager
from flask_caching import Cache
import dash_bootstrap_components as dbc
from app_main import layout
from app_main.callbacks import register_callbacks
from celery import Celery

REDIS_URL = "redis://localhost:6379"
celery_app = Celery(__name__, broker=REDIS_URL, backend=REDIS_URL)
background_callback_manager = CeleryManager(celery_app)

DEBUG = False
if DEBUG:
    requests_pathname_prefix = None
else:
    requests_pathname_prefix = '/mangem/'

app = Dash(__name__, external_stylesheets=[dbc.icons.FONT_AWESOME], background_callback_manager=background_callback_manager,
           requests_pathname_prefix=requests_pathname_prefix)

app.title = 'MANGEM'
application = app.server

CACHE_CONFIG = {
    'CACHE_TYPE': 'FileSystemCache',
    'CACHE_DIR': 'cache_dir',
    'CACHE_THRESHOLD': 500,  # maximum number of items the cache will store
    'CACHE_DEFAULT_TIMEOUT': 172800  # Default timeout, seconds (3600 s/hr * 48 hr = 172800)
}
cache = Cache()
cache.init_app(application, config=CACHE_CONFIG)

app.layout = layout.get_layout()
register_callbacks(app, cache, background_callback_manager)

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


from matplotlib import pyplot as plt
import numpy as np
import itertools
import random
import dataset
import networkx as nx
import os
#import main

def time_lasted(t):
    if t <= 60:
        return f"{round(t, 3)}s"
    return f"{round(t / 60, 3)}min"

def make_random_graph(n_nodes):
    # Create nodes
    nodes = [str(i) for i in range(n_nodes)]

    # Create edges
    edges = list(itertools.combinations(range(n_nodes), 2))
    n_edges = len(edges)
    edge_weights = [random.randint(1,10) for _ in edges] # use random ints for edge weights for now, to be changed
    edge_list = [(edges[i][0], edges[i][1], edge_weights[i]) for i in range(n_edges)]

    # Add edges to the graph (also adds nodes)
    edge_labels = {}
    for i in range(len(edges)):
        key = edges[i]
        edge_labels[key] = edge_weights[i]

    graph = {
        "n_node": n_nodes,
        "n_edge": n_edges,
        "nodes": nodes,
        "edges": edge_list,
        "edge_labels": edge_labels
        }
    return graph

def updated_graph(nodes, edges):
    """
    Return a new graph based on given nodes and find corresponding edges.
    """
    n_nodes = len(nodes)
    new_edges = list(itertools.combinations(nodes, 2))
    n_edges = len(new_edges)

    edge_list = []
    edge_labels = {}
    for e in new_edges:
        edge_labels[e] = edges[e]
        edge_list.append((e[0], e[1], edges[e]))

    graph = {
        "n_node": n_nodes,
        "n_edge": n_edges,
        "nodes": nodes,
        "edges": edge_list,
        "edge_labels": edge_labels
        }
    return graph

def display_result(results):
    """
    Reform results into a list of dicts to be written into files.
    Input:
        results: list of course groups
    Return:
        list of dicts
    """
    final_result = []
    for i in range(len(results)):
        group = {f'Group {i+1}': results[i]}
        final_result.append(group)
    return final_result

def plot_log(logs, out_img, out_file):
    """
    Plot graph size vs run time.
    """
    ax = plt.subplots(figsize=(6, 6))[1]
    n_node = np.array([abs(int(i[0])) for i in logs], dtype=np.int8)
    run_time = np.array([i[1] for i in logs], dtype=np.float32)

    csv = dataset._CSV()
    result = [{"Number of Nodes": n_node, "Time (s)": run_time}]
    csv.write(result, out_file)

    ax.scatter(n_node, run_time)
    ax.set_title("Run Time vs Graph Size")
    ax.set_ylabel("Time (s)", fontsize=12)
    ax.set_xlabel("Number of Nodes", fontsize=12)
    plt.tight_layout()
    plt.show()
    plt.savefig(out_img, bbox_inches='tight')

def objective_value(result, nodes, edge_weights):
    """
    Calculate the final objective value optimized.

    Input:
        result: final result groups
        nodes: the nodes from the original graph
        edge_weights: a dictionary with the initial edge weights
    Return:
        Optimized final value and original total weights.
    """
    all_weights = sum([edge_weights[e] for e in edge_weights])
    final_value = all_weights
    for group in result:
        new_group = [nodes.index(i) for i in group]
        edges = list(itertools.combinations(new_group, 2))
        for e in edges:
            try:
                final_value -= edge_weights[e]
            except KeyError:
                final_value -= edge_weights[(e[1], e[0])]
    return all_weights, final_value

def plot_graph(graph, name, output_dir, color_list='0.1', g=None):
    edges = graph["edges"]
    #edge_labels = graph["edge_labels"]
    nodes = graph["nodes"]

    if g == None:
        g = nx.Graph()
        node_list = list(range(len(nodes)))
        g.add_nodes_from(node_list)
        g.add_weighted_edges_from(edges)

    plt.figure(figsize=(5,5))
    pos = nx.spring_layout(g)
    nx.draw_networkx_nodes(g, pos, node_size=15, node_color=color_list)
    nx.draw_networkx_edges(g, pos, alpha=0.05, edge_color='0.3')
    filename = f"{name}.png"
    out_name = os.path.join(output_dir, filename)
    print(f">>> The plot {filename} is saved to {out_name}")
    plt.savefig(out_name, bbox_inches='tight')

def plot_final_graph(groups, graph, output_dir, g=None):
    nodes = graph["nodes"]
    color_list = list(nodes)
    color_order = ["r", "c"]
    new_edges = []
    i = 0
    for group in groups:
        new_group = []
        #r, g, b = random.randint(1, 255), random.randint(1, 255), random.randint(1,255)
        for n in group:
            j = nodes.index(n)
            #color_list[j] = (r/255, g/255, b/255)
            color_list[j] = color_order[i]
            new_group.append(j)
        e = list(itertools.combinations(new_group, 2))
        new_edges += e
        i += 1

    edges = graph["edge_labels"]
    edge_list = []
    edge_labels = {}
    for e in new_edges:
        edge_labels[e] = edges[e]
        edge_list.append((e[0], e[1], edges[e]))

    new_graph = {
        "n_node": len(nodes),
        "n_edge": len(new_edges),
        "nodes": nodes,
        "edges": edge_list,
        "edge_labels": edge_labels
        }

    plot_graph(new_graph, "Output Graph", output_dir, color_list=color_list, g=g)
    return new_graph

def calc_mass(Pt1, Pt2, eta1, eta2, phi1, phi2):
    return np.sqrt(2*Pt1*Pt2*(np.cosh(eta1-eta2)-np.cos(phi1-phi2)))

def get_jet_info(event, idx):
    return [event.JetPt[idx], event.JetEta[idx], event.JetPhi[idx]]

def get_track_info(event, idx):
    return [event.TrackPt[idx], event.TrackEta[idx], event.TrackPhi[idx]]

def get_tower_info(event, idx):
    return [event.JetTowerEt[idx], event.JetTowerEta[idx], event.JetTowerPhi[idx]]

def cos_similarity(a, b):
    """
    Return the negative value of inner product.
    """
    return -np.dot(np.linalg.norm(a), np.linalg.norm(b))

def euclidean_distance(a, b):
    """
    Return root mean square error.
    """
    a, b = np.array(a), np.array(b)
    return np.linalg.norm(a - b)

def abe(a, b):
    """
    Return the absolute mean error.
    """
    a, b = np.array(a), np.array(b)
    return np.mean(np.abs(a - b))

def rename_file(file_path, overwrite=False):
    file_name = file_path[:-4]
    file_type = file_path[-4:]
    count = 0
    while os.path.exists(file_path) and not overwrite:
        file_path = f"{file_name}_copy{count}{file_type}"
        count += 1
    return file_path


from collections import deque

class Solution:
    def getFood(self, grid: [[str]]) -> int:
        """ O(n*m) time, O(n*m) space, worst case go through all points """
        # this is a typical BFS question, each time we try all the possible dirs by adding it to queue
        # iterate the element in curr level, add all next levels into the queue
        # the first time we met a food will be the shorted length by the nature of BFS
        # mark the visited sell so we don't need to go there again
        queue = deque()
        rows = len(grid)
        cols = len(grid[0])
        for row in range(rows):
            for col in range(cols):
                if grid[row][col] == '*':
                    queue.append([row, col])
                    break

        dirs = [(0, 1), (0, -1), (1, 0), (-1, 0)]
        # bfs to check all the neighboring cells, use "V" to indicate this cell has been visited
        curr_step = 0
        while queue:
            curr_step += 1
            for _ in range(len(queue)):
                row, col = queue.popleft()
                for d in dirs:
                    next_row = row + d[0]
                    next_col = col + d[1]
                    if 0 <= next_row < rows and 0 <= next_col < cols:
                        if grid[next_row][next_col] == '#':
                            return curr_step
                        if grid[next_row][next_col] == 'O':
                            grid[next_row][next_col] = 'V'
                            queue.append([next_row, next_col])
        return -1

s = Solution()
print(s.getFood(grid=[["X", "X", "X", "X", "X", "X"], ["X", "*", "O", "O", "O", "X"], ["X", "O", "O", "#", "O", "X"],
                      ["X", "X", "X", "X", "X", "X"]]))


# Флаги

#Ограничение времени	1 секунда
#Ограничение памяти	64Mb
#Ввод	стандартный ввод или input.txt
# Вывод	стандартный вывод или output.txt

#Для украшения улиц купили флаги разных цветов. Нужно составить гирлянду из некоторого количества флагов, в которой цвета идут подряд, а затем повторяются в том же порядке, пока не наберется нужное количество флагов.

#Формат ввода
#Вводится количество различных цветов флагов, затем сами цвета. Затем вводится количество флагов в гирлянде.

#Формат вывода
# Вывести цвета флагов, как они должны идти в гирлянде.

# __________________________________

#Пример
#Ввод	                    Вывод
#3                           red
#red                         green
#green                       blue
#blue                        red
#7                           green
                            #blue
                            #red
# ___________________________________

number_of_colors = int(input())
colors = []
for i in range(number_of_colors):
    colors.append(input())
number_of_repeats = int(input())
count = 0
while count != number_of_repeats:
    for color in colors:
        count += 1
        print(color)
        if count == number_of_repeats:
            break


from . import db
from .data_mapper import map_penalty_records, map_to_game_summary
from .models import UserEntity, GameEntity, GameStatus, PenaltyEntity, PenaltyRecordEntity, ParticipantStatus, ParticipantEntity, TotalFineEntity
from flask import Blueprint, render_template, request, flash, redirect, url_for, abort
from flask_login import login_required, current_user
import json

from .logger_config import setup_logger

DEBUG = True

class PlayerListError(ValueError):
    pass

logger = setup_logger()

views = Blueprint('views', __name__) # setup a blueprint for flask, can be named w.e. best practice to name same as file

# Display homepage endpoint
@views.route('/') # decorator
@login_required
def home():
    return render_template("home.html", user=current_user)

# Display user_management site
@views.route('/user_management', methods=['GET'])
@login_required
def user_management():
    participants = ParticipantEntity.query.filter_by(user_id=current_user.id, status = ParticipantStatus.active)
    return render_template("user_management.html", participants=participants, user=current_user)

# Display Game creation and loading site
@views.route('/create_or_load_game/', methods=['GET'])
@login_required
def create_or_load_game():
    participants = ParticipantEntity.query.filter_by(user_id=current_user.id, status = ParticipantStatus.active)
    all_saved_games = GameEntity.query.filter_by(user_id = current_user.id, status = GameStatus.active).all()
    len_all_saved_games = len(all_saved_games)
    logger.debug("Length of all saved_games for user {} is {}".format(current_user.email, len_all_saved_games))
    return render_template("create_or_load_game.html", game_participants=participants, user=current_user, all_saved_games = all_saved_games, len_all_saved_games=len_all_saved_games)

# Display certain game
@views.route('/view_game/<game_id>', methods=['GET'])
@login_required
def view_game(game_id):
    try:
        game = GameEntity.query.filter_by(id = game_id,user_id = current_user.id).one()
    except:
        flash("No game was found", category="error")
        return render_template("create_or_load_game.html",user=current_user)
    # game_participants is a json object storing all the player_ids as a string
    all_penalties = PenaltyEntity.query.filter_by(user_id=current_user.id).all()
    game_participants = game.game_participants
    if game_participants is None or game_participants == "":
        flash("invalid game", category="error")
        return render_template("create_or_load_game.html", user=current_user)
    logger.info("Game Status for user {} is {}".format(current_user.email,game.status))
    all_participant_ids = []
    if game.status == GameStatus.active:
        participants_data = []
        # Iterate through all participant ids
        # Get all their PenaltyRecordEntities from database
        # Get their TotalFine from database
        for player in json.loads(game_participants):
            all_participant_ids.append(int(player))
            participant_record = PenaltyRecordEntity.query.filter_by(game_id=game.id, participant_id=player).first()
            participant_fine_sum = TotalFineEntity.query.filter_by(game_id=game.id, participant_id=player).first()
            # Map the Database Entities to useful data_models, a single object that stores everything needed for the player
            # (name, quantity for each penalty, the total_finesum and more)
            # All stored in a list and given to the template
            participants_data.extend(map_penalty_records(participant_record, game_id,all_penalties, participant_fine_sum))
    if game.status == GameStatus.save:
        participants_data = []
        for player in json.loads(game_participants):
            all_participant_ids.append(player)
            participant_records = PenaltyRecordEntity.query.filter_by(game_id=game.id, participant_id=player).all()
            participant_fine_sum = TotalFineEntity.query.filter_by(game_id=game.id, participant_id=player).first()
            participants_data.append(map_to_game_summary(participant_records, participant_fine_sum))
        logger.debug("All participant_ids going into the game: ", all_participant_ids)
    return render_template("view_game.html",user=current_user, game=game, all_penalties=all_penalties, player_record_list = participants_data, all_participant_ids=all_participant_ids)

# Display finished game summary
@views.route('/game_summary/<game_id>', methods=['POST','GET'])
@login_required
def game_summary(game_id):
    if request.method != 'POST' and request.method !='GET':
        abort(405)
    # Create a game summary object and map everything so far obtained to it in the finish_game endpoint
    all_penalties = PenaltyEntity.query.filter_by(user_id = current_user.id).all()
    target_game = GameEntity.query.filter_by(id = game_id, user_id = current_user.id).first()
    if target_game and target_game.status == GameStatus.finish:
        game_participants = target_game.game_participants
        game_summary_objects = []
        for player in json.loads(game_participants):
            participant_records = PenaltyRecordEntity.query.filter_by(game_id=target_game.id, participant_id=player).all()
            participant_fine_sum = TotalFineEntity.query.filter_by(game_id=target_game.id, participant_id=player).first()
            game_summary_objects.append(map_to_game_summary(participant_records,participant_fine_sum))
        tier_list = retrieve_tier_list(game_summary_objects)
        penalty_sum = 1 + len(all_penalties)
        return render_template("game_summary.html", user= current_user, game = target_game, all_penalties = all_penalties, game_summary_objects = game_summary_objects, tier_list = tier_list, penalty_sum = penalty_sum)
    else:
        flash("This game has not been finished yet", category="error")

def retrieve_tier_list(PenaltyRecordList):
    max_quantities = {}
    for record in PenaltyRecordList:
        for penalty in record.penalties:
            if penalty.penalty_name not in max_quantities or max_quantities[penalty.penalty_name][1] < penalty.penalty_quantity:
                max_quantities[penalty.penalty_name] = (record.participant_name, penalty.penalty_quantity)
    return max_quantities

@views.route('/penalties', methods=['GET'])
@login_required
def penalties():
    penalties = PenaltyEntity.query.filter_by(user_id=current_user.id)
    return render_template("penalties.html", user=current_user, all_penalties = penalties)

@views.route('/view_archive', methods=['GET'])
@login_required
def view_archive():
    all_finished_games = GameEntity.query.filter_by(user_id = current_user.id, status = 'finish').all()
    return render_template("view_archive.html", user=current_user, all_finished_games = all_finished_games)


from typing import Dict
from lesson_20.decorator.hobby import Hobby

@Hobby("dancing")
class Human:
    def __init__(self, name: str, age: int) -> None:
        self.__name = name
        self.__age = age

    def __modify_key(self, key: str) -> str:
        return key.replace(f"_{self.__class__.__name__}__", "")

    def json(self) -> Dict[str, str]:
        data = {}

        for key, value in self.__dict__.items():
            data[self.__modify_key(key)] = value

        return data

if __name__ == "__main__":
    john = Human("John", 32)
    print(john.hobby)


""" Apply air quality modelling EPA functions and return statistics for NO2 specifically

Returns:
    [type]: [description]
"""

import pandas as pd

from .File_Utilties import _read_large_dataset, prepend_header_dataframe
import typing

def _compute_statistics(
    dataframe: pd.DataFrame, exceedances: float, percentile: float, window: float
) -> pd.DataFrame:
    outdf = pd.DataFrame(
        {
            "Max of Sensor": dataframe.max(),
            "Average of Sensor": dataframe.mean(),
            "Number of Exceedances": dataframe[dataframe > exceedances].count(),
            "Average Max Column": dataframe.max().mean(),
            "Max Value": dataframe.values.max(),
            f"{percentile * 100}th Percentile of Sensor": dataframe.quantile(
                percentile
            ),
            f"Max of {percentile * 100}th Percentile": dataframe.quantile(
                percentile
            ).max(),
            f"Average {window} Hour Rolling Average of Sensor": dataframe.rolling(
                window=window
            )
            .mean()
            .mean(),
            f"Max {window} Hour Rolling Average of Sensor": dataframe.rolling(
                window=window
            )
            .mean()
            .max(),
            # f"Max {window} Hour Rolling Average": dataframe.rolling(window=window)
            # .mean()
            # .max()
            # .max(),
        }
    )
    outdf.index.name = "Sensor ID"
    outdf.insert(0, "Sensor ID", outdf.index)
    return outdf

def process(
    header_length: int,
    initial: float,
    exceedance: float,
    background_name: str,
    input_data: str,
    ozone_column_name: str,
    fill_invalid_value: float,
    calc_without_background: bool,
    background_column_name: str,
    ozone_scale: float,
    percentile: float,
    window: int,
    top_header_length: int
) -> typing.Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame]:
    """ Apply EPA modelling functions for NO2 and generate statistics

    Args:
        header_length (int): Number of columns before data starts (eg 3 for year/month/day)
        initial (float): Initial percentage to work with (eg 0.1 = 10%)
        exceedance (float): How many exceedances to compute (eg, compare how many are greater than 246)
        background_name (str): File path to background NO2 data set
        input_data (str): Source data file path
        ozone_column_name (str): Column name of ozone data in background data set
        fill_invalid_value (float): Value to fill any missing values
        calc_without_background (bool): Whether to calculate the same statistics for the data set without the background summed
        background_column_name (str): Column name of background data in background data set (eg, Background NO2)
        ozone_scale (float): Number to scale the ozone values by (default 46/48)
        top_header_length (int): Number of rows to ignore before data begins

    Returns:
        typing.Tuple[pd.DataFrame, pd.DataFrame,pd.DataFrame]: Temporary computed data set, output statistics on computed data, output background statistics
    """

    print(f"Processing NO2 statistics for {input_data}")

    # Read Data
    background = _read_large_dataset(background_name)
    background.dropna(how='all', inplace=True)

    data = _read_large_dataset(input_data)

    data_header = data.iloc[:, :header_length]

    data = data.iloc[:, header_length:]

    data = data[top_header_length - 1:]

    # Multiply background data by provided scalar

    data["background_NO2"] = background[background_column_name]

    data["background_O3"] = background[ozone_column_name]

    print("25%")

    data = data.fillna(fill_invalid_value)

    def olmfunction(row: pd.Series) -> pd.Series:
        """ Compute OLM which is the recorded value multiplied by the initial amount, and add the minimum of (1-iniial)*value or the ozone)

        Args:
            row (pd.Series): Row to be computed where last column is the ozone data scaled

        Returns:
            pd.Series: Computed row
        """
        # Take the ozone value
        ozone_value = float(row.iloc[-1]) * ozone_scale
        background_value = float(row.iloc[-2])
        new_row = []

        # Skip header rows and ignore last 2 values
        for value in row[:-2]:
            value = (float(value) * initial) + min(((1 - initial) * float(value)), ozone_value) + background_value
            new_row.append(value)
        return pd.Series(new_row)

    def backfunction(row: pd.Series) -> pd.Series:
        """ Background function for computing sum of recorded value and background

        Args:
            row (pd.Series): Row to be computed where last column is the background data

        Returns:
            pd.Series: Computed row
        """
        # Take the background value
        background_value = float(row.iloc[-1])
        new_row = []
        for value in row[:-1]:
            value = value - background_value
            new_row.append(value)

        return pd.Series(new_row)

    olm_data = data.apply(olmfunction, axis=1)
    olm_data.columns = data.columns[:-2]
    olm_data_with_background = olm_data.copy()
    olm_data["background"] = list(background[background_column_name])
    olm_data_without_background = olm_data.apply(backfunction, axis=1)
    olm_data_without_background.columns = data.columns[:-2]

    print("50%")
    # Compute statistics
    outdf = _compute_statistics(
        olm_data_with_background, exceedance, percentile, window
    )
    print("75%")
    no_bg_outdf = pd.DataFrame
    if calc_without_background:
        # data["background"] = list(background[background_column_name])
        # bg_data = data.apply(backfunction, axis=1)
        no_bg_outdf = _compute_statistics(
            olm_data_without_background, exceedance, percentile, window
        )

    olm_data_with_background = prepend_header_dataframe(
        olm_data_with_background, data_header
    )
    olm_data_without_background = prepend_header_dataframe(
        olm_data_without_background, data_header
    )

    print("100%")

    return olm_data_with_background, olm_data_without_background, outdf, no_bg_outdf


'''
Estimate the SNR of seismic signals.

Autor: Peidong Shi
Contact: speedshi@hotmail.com  or  peidong.shi@sed.ethz.ch
Create time: 20221110
'''

from obspy import UTCDateTime
import numpy as np

def estimate_snr(trace, stime, noise_window, signal_window, method='maxamp'):
    # trace is one or three component seismic data recroded at a certain station; no gaps in traces;
    # 'stime' is the picked signal arrival-time (phase arrival-time) in datetime format, such as datetime.datetime(2022,2,3,15,21,30,345332).
    # 'noise_window' specify the time window in second relative to 'stime' for evaluating noise, such as [-4, -2].
    # 'signal_window' specify the time window in second relative to 'stime' for evaluating signal, such as [-0.4, 0.6].
    # 'method' specify how to calculate snr; 'maxamp': maximum amplitude (on an arbitrary channel) ratio;
    #                                        'maxeng': maximum energy ratio (need more than 2 channel);
    #                                         'std': standard deviation ratio;

    if trace.count() == 0:
        # no input seismic data
        return None
    else:
        assert(trace.count()<=3)

        # check traces are coming from the same station
        for itrace in trace:
            assert(itrace.stats.station == trace[0].stats.station)

        stime = UTCDateTime(stime)

        assert(len(noise_window)==2 and (noise_window[0]<=noise_window[1]))
        assert(len(signal_window)==2 and (signal_window[0]<=signal_window[1]))

        noise_start = stime + noise_window[0]
        noise_end = stime + noise_window[1]
        noises = (trace.copy()).trim(starttime=noise_start, endtime=noise_end, pad=True, fill_value=0)  # noise segments

        signal_start = stime + signal_window[0]
        signal_end = stime + signal_window[1]
        signals = (trace.copy()).trim(starttime=signal_start, endtime=signal_end, pad=True, fill_value=0)  # signal segments

        if method.lower() == 'maxeng':
            if noises.count() == 1:
                maxeng_noise = max(np.sqrt(noises[0].data*noises[0].data))
            elif noises.count() == 2:
                maxeng_noise = max(np.sqrt(noises[0].data*noises[0].data + noises[1].data*noises[1].data))
            elif noises.count() == 3:
                maxeng_noise = max(np.sqrt(noises[0].data*noises[0].data + noises[1].data*noises[1].data + noises[2].data*noises[2].data))
            else:
                raise ValueError

            if signals.count() == 1:
                maxeng_signal = max(np.sqrt(signals[0].data*signals[0].data))
            elif signals.count() == 2:
                maxeng_signal = max(np.sqrt(signals[0].data*signals[0].data + signals[1].data*signals[1].data))
            elif signals.count() == 3:
                maxeng_signal = max(np.sqrt(signals[0].data*signals[0].data + signals[1].data*signals[1].data + signals[2].data*signals[2].data))
            else:
                raise ValueError

            snr = maxeng_signal / maxeng_noise
        elif method.lower() == 'maxamp':
            maxamp_noise = np.amax(np.absolute(noises.max()))
            maxamp_signal = np.amax(np.absolute(signals.max()))
            snr = maxamp_signal / maxamp_noise
        elif method.lower() == 'std':
            std_noise = np.amax(noises.std())
            std_signal = np.amax(signals.std())
            snr = std_signal / std_noise
        else:
            raise ValueError("Unrecognized input for method: {method}.")

        del noises, signals
    return snr


from typing import List, Union

from dofbot.dofcalculator.dofconstants import DofConstants
from dofbot.dofcalculator.dofresult import DofResult
from dofbot.dofcalculator.hyperfocalresult import HyperFocalResult
from dofbot.htmlbuilder.htmlbuilder import HtmlBuilder
from dofbot.htmlbuilder.elements import Header, Hr, Table, Td, Th, Tr

class DofResultFormatter:
    def __init__(self, focal_length: int, fnumber: Union[float, None], focus_distance: Union[float, None],
                 dof_result: List[DofResult], hyperfocal_result: Union[HyperFocalResult, None]):
        self._focal_length = focal_length
        self._fnumber = fnumber
        self._focus_distance = focus_distance
        self._dof_result = dof_result
        self._hyper_focal_result = hyperfocal_result

    def format(self) -> str:
        bldr = HtmlBuilder()
        bldr.add_element(Header('Depth Of Field Calculation', 1))
        bldr.add_element(Header(f'Focal length = {self._focal_length}'))
        bldr.add_element(Header(f'F-number = {self._fnumber}'))
        bldr.add_element(Header(f'Focus distance = {self._focus_distance}'))
        if self._hyper_focal_result:
            bldr.add_element(Header(f'Hyper focal distance = {self._hyper_focal_result.hyperfocal}'))
        bldr.add_element(Hr())
        bldr.add_element(Header('Results', 1))

        op_code = f'{int(self._fnumber is not None)}{int(self._focus_distance is not None)}'
        {
            '00': self._format_by_focal_length,
            '01': self._format_by_focal_length_and_focus_distance,
            '10': self._format_by_focal_length_and_fnumber,
            '11': self._format_by_all
        }[op_code](bldr)

        return bldr.build()

    def _format_by_focal_length(self, bldr: HtmlBuilder) -> None:
        table = Table()
        self._add_common_header(table, len(DofConstants.FOCUS_DISTANCE_LIST))

        focus_distance_vals = Tr()
        for fd in DofConstants.FOCUS_DISTANCE_LIST:
            focus_distance_vals.add_element(Th(str(fd)))
        table.add_thead_element(focus_distance_vals)

        for i, fn in enumerate(DofConstants.FNUMBER_LIST):
            row = Tr()
            row.add_element(Th(str(fn)))

            slice_start = i * len(DofConstants.FOCUS_DISTANCE_LIST)
            slice_end = slice_start + len(DofConstants.FOCUS_DISTANCE_LIST)
            for v in self._dof_result[slice_start:slice_end]:
                row.add_element(Td(f'[{v.dof_near},{v.dof_far},{v.dof_depth}]'))

            table.add_tbody_element(row)

        bldr.add_element(table)

    def _format_by_focal_length_and_focus_distance(self, bldr: HtmlBuilder) -> None:
        table = Table()
        self._add_common_header(table)
        table.add_thead_element(Tr([Th(str(self._focus_distance))]))

        for i, fn in enumerate(DofConstants.FNUMBER_LIST):
            row = Tr()
            row.add_element(Th(str(fn)))

            v = self._dof_result[i]
            row.add_element(Td(f'[{v.dof_near},{v.dof_far},{v.dof_depth}]'))

            table.add_tbody_element(row)

        bldr.add_element(table)

    def _format_by_focal_length_and_fnumber(self, bldr: HtmlBuilder) -> None:
        table = Table()
        self._add_common_header(table, len(DofConstants.FOCUS_DISTANCE_LIST))

        focus_distance_vals = Tr()
        for fd in DofConstants.FOCUS_DISTANCE_LIST:
            focus_distance_vals.add_element(Th(str(fd)))
        table.add_thead_element(focus_distance_vals)

        row = Tr()
        row.add_element(Th(str(self._fnumber)))

        for v in self._dof_result:
            row.add_element(Td(f'[{v.dof_near},{v.dof_far},{v.dof_depth}]'))

        table.add_tbody_element(row)

        bldr.add_element(table)

    def _format_by_all(self, bldr: HtmlBuilder) -> None:
        table = Table()
        self._add_common_header(table)
        table.add_thead_element(Tr([Th(str(self._focus_distance))]))

        row = Tr()
        row.add_element(Th(str(self._fnumber)))

        v = self._dof_result[0]
        row.add_element(Td(f'[{v.dof_near},{v.dof_far},{v.dof_depth}]'))

        table.add_tbody_element(row)

        bldr.add_element(table)

    @staticmethod
    def _add_common_header(table: Table, focus_distance_colspan: int = 0) -> None:
        header = Tr()
        header.add_element(Th("F-number", rowspan=2))
        header.add_element(Th('Focus distance, m', colspan=focus_distance_colspan))
        table.add_thead_element(header)


import sqlite3 as sql

banco = 'banco.bd'

# Função
def abrir_conexao(banco):
    conexao = sql.connect(banco)
    cursor = conexao.cursor()
    return conexao, cursor

def fechar_conexao(conexao):
    conexao.commit()
    conexao.close()

# Comandos SQL
contagem = "SELECT COUNT(*) FROM produtos;"
select_todos = "SELECT * FROM produtos;"
select_nome = "SELECT * FROM produtos WHERE nome = ?;"
insert = "INSERT INTO produtos VALUES (:nome,:preco,:qtd);"
delete = "DELETE FROM produtos WHERE nome = ?;"
update = '''
UPDATE produtos SET
    qtd = :qtd
WHERE nome like :nome
'''

def insert_produto(produtos):
    conexao, cursor = abrir_conexao(banco)
    cursor.execute(insert, produtos)
    fechar_conexao(conexao)

def func_leitura():
    conexao, cursor = abrir_conexao(banco)
    cursor.execute(select_todos)
    resultado = cursor.fetchall()
    fechar_conexao(conexao)
    return resultado

def func_delete(nome):
    conexao, cursor = abrir_conexao(banco)
    resultado = cursor.execute(delete, [nome]).rowcount
    fechar_conexao(conexao)

def func_read(nome):
    conexao, cursor = abrir_conexao(banco)
    resultado = cursor.execute(select_nome, [nome]).fetchall()
    fechar_conexao(conexao)
    return resultado

def func_update(nome, produtos):
    conexao, cursor = abrir_conexao(banco)
    resp = {"nome": nome, "qtd": produtos["qtd"]}
    cursor.execute(update, resp)
    fechar_conexao(conexao)
    return resp


from sigma.backends.splunk import SplunkBackend
from sigma.rule import SigmaRule
from sigma.collection import SigmaCollection
from sigmaiq.backends.sigmaiq_abstract_backend import AbstractGenericSigmAIQBackendClass
from copy import copy, deepcopy
import re
from importlib_resources import files

SAVEDSEARCHES_TEMPLATE = files("sigmaiq.backends.splunk").joinpath("savedsearches_template.txt").read_text()

class SigmAIQSplunkBackend(AbstractGenericSigmAIQBackendClass, SplunkBackend):
    """SigmAIQ backend interface for the pySigma Splunk Backend library to translate a SigmaRule object
    to a Splunk search query"""

    custom_formats = {"stanza": "Enterprise Security savedsearches.conf stanza"}
    associated_pipelines = ["splunk_windows", "splunk_wineventlog", "splunk_windows_sysmon_acc", "splunk_cim_dm"]
    default_pipeline = "splunk_windows"

    def handle_output_format(self, sigma_rule, output):
        """Converts Splunk search to savedsearches.conf stanza if output_format given"""
        if self.custom_output_format == "stanza":
            output = self._convert_to_stanza(sigma_rule, output)
        return output

    def _convert_to_stanza(self, sigma_rule, output: list):
        """Converts a list of SigmaRule Splunk query outputs to savedsearches.conf stanzas to use in
        Splunk Enterprise Security Correlation Searches
        """
        # Convert SigmaRule to SigmaCollection just for ease of use
        sigma_rule_temp = copy(sigma_rule)
        if isinstance(sigma_rule_temp, SigmaRule):
            collection = SigmaCollection([sigma_rule_temp])
        else:
            collection = sigma_rule_temp

        stanzas = []
        for i, rule in enumerate(collection):
            title = rule.title
            search = output[i]
            tags = self._extract_mitre_tags(rule.tags)
            replacements = {
                "%TITLE_PLACEHOLDER%": title,
                "%MITRE_ATTACK_PLACEHOLDER%": f"{tags}",
                "%NOTABLE_TITLE_PLACEHOLDER%": title,
                "%DRILLDOWN_TITLE_PLACEHOLDER%": title,
                "%DRILLDOWN_SEARCH_PLACEHOLDER%": search,
                "%SEARCH_PLACEHOLDER%": search,
            }

            stanza = deepcopy(SAVEDSEARCHES_TEMPLATE)
            for k, v in replacements.items():
                stanza = stanza.replace(k, v)
            stanzas.append(stanza)
        return stanzas

    @staticmethod
    def _extract_mitre_tags(tags):
        """Takes tags from a SigmaRule and outputs them into a format that a Splunk Correlation Search stanza will
        recognize for the action.correlationsearch.annotations field:
        i.e.    action.correlationsearch.annotations = {"mitre_attack":["T1055.011","T1560.001","T1205.002","T1583"]}
        """
        mitre_tags = {"mitre_attack": []}
        if not tags:
            return mitre_tags
        for tag in tags:
            matches = re.match(r"^(attack\.)(t\d{4}(\.\d{3})?)", str(tag))
            if matches:
                mitre_tags["mitre_attack"].append(matches[2].upper())
        return mitre_tags


from Pessoa import Endereco, Pessoa

local=Endereco(34,"Manoel","Pureza", "RN","Brasil")
local2=Endereco(55,"Nova Descoberta", "Pureza","RN","Brasil")
pessoa=Pessoa(123,"Ana",5738372)
pessoa.adicionar_endereco(local)
pessoa.adicionar_endereco(local2)
pessoa.apresentar()
pessoa.remover_local(34)
pessoa.apresentar()


from __future__ import annotations

from dataclasses import asdict, dataclass
from typing import TYPE_CHECKING

from sec_parser.semantic_elements.abstract_semantic_element import (
    AbstractSemanticElement,
)

if TYPE_CHECKING:
    from sec_parser.parsing_engine.html_parsers.html_tag import HtmlTag

class HighlightedTextElement(AbstractSemanticElement):
    """
    The HighlightedElement class used for detecting title elements.
    The process begins with the detection of highlighted elements,
    which are then further classified into title elements.
    """

    def __init__(
        self,
        html_tag: HtmlTag,
        inner_elements: list[AbstractSemanticElement],
        *,
        style: TextStyle | None = None,
    ) -> None:
        super().__init__(html_tag, inner_elements)
        if style is None:
            msg = "styles must be specified for HighlightedElement"
            raise ValueError(msg)
        self.style = style

    @classmethod
    def convert_from(
        cls,
        source: AbstractSemanticElement,
        *,
        style: TextStyle | None = None,
    ) -> HighlightedTextElement:
        return cls(
            source.html_tag,
            source.inner_elements,
            style=style,
        )

@dataclass(frozen=True)
class TextStyle:
    PERCENTAGE_THRESHOLD = 80
    BOLD_THRESHOLD = 600

    bold_with_font_weight: bool
    italic: bool
    # underline?
    # all-caps?

    def __bool__(self) -> bool:
        return any(asdict(self).values())

    @classmethod
    def from_style_string(
        cls,
        style_string: dict[tuple[str, str], float],
    ) -> TextStyle:
        filtered_styles = {
            (k, v): p for (k, v), p in style_string.items()
            if p >= cls.PERCENTAGE_THRESHOLD
        }

        bold_with_font_weight = any(
            cls._is_bold_with_font_weight(k, v)
            for (k, v) in filtered_styles
        )

        italic = any(
            k == "font-style" and v == "italic"
            for (k, v) in filtered_styles
        )

        return cls(
            bold_with_font_weight=bold_with_font_weight,
            italic=italic,
        )

    @classmethod
    def _is_bold_with_font_weight(cls, key: str, value: str) -> bool:
        if key != "font-weight":
            return False
        if value == "bold":
            return True
        try:
            return int(value) >= cls.BOLD_THRESHOLD
        except ValueError:
            return False


import csv

with open("test.csv", "w") as testCSV:
    csvHeaders = ["nome", "idade", "salario"]
    csvWriter = csv.DictWriter(testCSV, fieldnames=csvHeaders)
    listaPessoas = [{"nome": "Manoel", "idade": 25, "salario": 3000},
                    {"nome": "Juliana", "idade": 30, "salario": 4000}]
    csvWriter.writeheader()

    for pessoa in listaPessoas:

        csvWriter.writerow(pessoa)

Programador de Sistemas - UC 2/Repositório de Exemplos - Turma 2/Aula 3/teste.py


from __future__ import absolute_import
from __future__ import print_function
from .._abstract.abstract import BaseAGSServer
import os
########################################################################
class Uploads(BaseAGSServer):
    """
    This resource is a collection of all the items that have been uploaded
    to the server.
    See: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Uploads/02r3000001qr000000/
    """
    _uploads = None
    _securityHandler = None
    _proxy_port = None
    _proxy_url = None
    _url = None

    #----------------------------------------------------------------------
    def __init__(self, url, securityHandler,
                 proxy_url=None, proxy_port=None,
                 initialize=False):
        """Constructor"""
        if url.lower().find("uploads") < -1:
            self._url = url + "/uploads"
        else:
            self._url = url
        self._securityHandler = securityHandler
        self._proxy_port = proxy_port
        self._proxy_url = proxy_url

    #----------------------------------------------------------------------
    @property
    def uploads(self):
        """
        returns a collection of all the items that have been uploaded to
        the server.
        """
        params = {
            "f" :"json"
        }
        return self._get(url=self._url,
                            param_dict=params,
                            securityHandler=self._securityHandler,
                            proxy_url=self._proxy_url,
                            proxy_port=self._proxy_port)

    #----------------------------------------------------------------------
    def deleteItem(self, itemId):
        """
           Deletes the uploaded item and its configuration.
           Inputs:
              itemId - unique ID of the item
        """
        url = self._url + "/%s/delete" % itemId
        params = {
            "f" : "json"
        }
        return self._post(url=url, param_dict=params,
                             securityHandler=self._securityHandler,
                             proxy_url=self._proxy_url,
                             proxy_port=self._proxy_port)
    #----------------------------------------------------------------------
    def item(self, itemId):
        """
        This resource represents an item that has been uploaded to the
        server. Various workflows upload items and then process them on the
        server. For example, when publishing a GIS service from ArcGIS for
        Desktop or ArcGIS Server Manager, the application first uploads the
        service definition (.SD) to the server and then invokes the
        publishing geoprocessing tool to publish the service.
        Each uploaded item is identified by a unique name (itemID). The
        pathOnServer property locates the specific item in the ArcGIS
        Server system directory.
        The committed parameter is set to true once the upload of
        individual parts is complete.
        """
        url = self._url + "/%s" % itemId
        params = {
            "f" : "json"
        }
        return self._get(url=url, param_dict=params,
                            securityHandler=self._securityHandler,
                            proxy_url=self._proxy_url,
                            proxy_port=self._proxy_port)
    #----------------------------------------------------------------------
    def uploadItem(self, filePath, description):
        """
        This operation uploads an item to the server. Each uploaded item is
        identified by a unique itemID. Since this request uploads a file, it
        must be a multi-part request as per IETF RFC1867.

        Inputs:
            filePath - the file to be uploaded.
            description - optional description for the uploaded item.
        """
        import urlparse
        url = self._url + "/upload"
        params = {
            "f" : "json"
        }
        files = {}
        files['itemFile'] = filePath
        return self._post(url=url,
                          param_dict=params,
                          files=files,
                          securityHandler=self._securityHandler,
                          proxy_url=self._proxy_url,
                          proxy_port=self._proxy_port)


#On suppose que nous avons un GridWorld de taille 3*3
#que l'objectif se trouve en L1, C3 et que le "contre-objectif" (case interdite)
#se trouve en L2,C2

import numpy as np

#On note 0, 1, 2 et 3 les directions Up, Right, Down, Left
def Move(pos, dir):
  new_x = pos[0]
  new_y = pos[1]
  if dir==0:
    new_x -=1
  elif dir==1:
    new_y +=1
  elif dir==2:
    new_x +=1
  elif dir==3:
    new_y -=1
  else:
    print('Direction invalide')

  if (new_x<0):
    new_x = 0
  elif (new_x>2):
    new_x = 2
  elif (new_y<0):
    new_y = 0
  elif (new_y>2):
    new_y = 2

  return (new_x, new_y)

#La meilleure direction est (l'une de) celle(s) qui
#contien(nen)t la plus grande valeur de Q
#dans le voisinage de la position pos

def bestDirection(tabQ, pos):
  x = pos[0]
  y = pos[1]
  best = []
  mx   = max(tabQ[x][y][0], tabQ[x][y][1], tabQ[x][y][2], tabQ[x][y][3])
  for i in range(3):
    if (tabQ[x][y][i]==mx):
      best.append(i)

  choice = np.random.randint(len(best))

  return best[choice], tabQ[x][y][best[choice]]

#Valeur du reward correspondant à une case

#Coeur de l'algorithme : mise-à-jour de la table Q
#Q(s,a) = Q(s,a) + alpha(r+maxQ(s',a')-Q(s,a))

def updateQ(tabQ, alpha, gamma, start, nbIter, tauxExplor, obj, cobj):
   for numiter in range(nbIter):
     pos = start
     while((pos!=obj)and(pos!=cobj)):
       rnd = np.random.rand()
       if (rnd<tauxExplor):
         dir = np.random.randint(3)
       else:
         dir = bestDirection(tabQ,pos)[0]

       new_x, new_y = Move(pos, dir)

       r = tabReward[new_x][new_y]
       maxQ = max(tabQ[new_x][new_y][0], tabQ[new_x][new_y][1], tabQ[new_x][new_y][2], tabQ[new_x][new_y][3])
       tabQ[pos[0]][pos[1]][dir] =tabQ[pos[0]][pos[1]][dir]+alpha*(r+maxQ-tabQ[pos[0]][pos[1]][dir])
       pos = (new_x, new_y)

def afficherTabQ(tabQ):
   for x in range(3):
     for y in range(3):
       print(x,y,np.argmax((tabQ[x][y][0], tabQ[x][y][1], tabQ[x][y][2], tabQ[x][y][3])))

#Programme principal
#gridWorld = np.zeros(3,3,4)

tabQ = np.zeros([3,3,4])
tabReward = np.zeros([3,3])
tabReward[0][2]=1
tabReward[1][1]=-1

alpha = 0.2
gamma = 0.9
start = (2,0)
nbIter = 100
tauxExplor = 0.7
obj = (0,2)
cobj = (1,1)

updateQ(tabQ, alpha, gamma, start, nbIter, tauxExplor, obj, cobj)
afficherTabQ(tabQ)


import argparse
import logging
import dataset
from model import ListNet

logging.basicConfig(level=logging.INFO)
"""
    entrance
"""

def run(args):
    logging.info("Loading data...")
    id, x_train, x_test, y_train, y_test = dataset.load_random_data()
    logging.info("loading {} id".format(len(id)))
    logging.info("loading {} items data for training, dims {}".format(x_train.shape[0], x_train.shape[1]))
    logging.info("loading {} items data as training label, dims {}".format(y_train.shape[0], y_train.shape[1]))
    logging.info("loading {} items data for testing, dims {}".format(x_test.shape[0], x_test.shape[1]))
    logging.info("loading {} items data as testing result, dims {}".format(y_test.shape[0], y_test.shape[1]))
    listnet = ListNet(h1_input=x_train.shape[1],
                      h1_output=10,
                      h2_input=10,
                      h2_output=1)
    listnet.train(x_train, y_train, 100, 0.001, optmz='adam')
    listnet.predict(x_test)
    perms=listnet.permutation(id)
    print(perms)

if __name__ == '__main__':
    p = argparse.ArgumentParser()
    p.add_argument('--train',
                   type=str,
                   help='input train json file',
                   default='random')
    p.add_argument('--env',
                   required=False,
                   help='input dev/prod to alter environment',
                   default='dev')
    p.print_help()
    args = p.parse_args()
    print(args)
    run(args)


from sumpy.system._base import _SystemBase
from sumpy.annotators import (WordTokenizerMixin, LedeMixin, MMRMixin,
        CentroidMixin)
from sumpy.document import Summary

class LedeSummarizer(WordTokenizerMixin, LedeMixin, _SystemBase):

    def __init__(self, sentence_tokenizer=None, word_tokenizer=None,
            verbose=False):
        self._sentence_tokenizer = sentence_tokenizer
        self._word_tokenizer = word_tokenizer
        super(LedeSummarizer, self).__init__(verbose=verbose)

    def build_summary(self, input_df, ndarray_data):
        output_df = input_df[input_df[u"f:lede"] == 1].sort(
            ["doc id"], ascending=True)
        return Summary(output_df)

class CentroidSummarizer(CentroidMixin, _SystemBase):

    def __init__(self, sentence_tokenizer=None, word_tokenizer=None,
            verbose=False):
        self._sentence_tokenizer = sentence_tokenizer
        self._word_tokenizer = word_tokenizer
        super(CentroidSummarizer, self).__init__(verbose=verbose)

    def build_summary(self, input_df, ndarray_data):
        output_df = input_df.sort(["f:centroid"], ascending=False)
        return Summary(output_df)

class MMRSummarizer(MMRMixin, _SystemBase):
    def __init__(self, sentence_tokenizer=None, word_tokenizer=None,
            lam=.4, verbose=False):
        self._sentence_tokenizer = sentence_tokenizer
        self._word_tokenizer = word_tokenizer
        self.lam = lam
        super(MMRSummarizer, self).__init__(verbose=verbose)

    def build_summary(self, input_df, ndarray_data):
        output_df = input_df.sort(["f:mmr"], ascending=False)
        return Summary(output_df)


# -*- encoding: utf8 -*-
from open_api.model.base import BaseModel

class OrderModel(BaseModel):

    def __init__(self):
        """
        业务参数
        :return:
        """
        self.shop_no = None
        self.origin_id = None
        self.city_code = None
        self.cargo_price = None
        self.is_prepay = 0
        self.receiver_name = None
        self.receiver_address = None
        self.receiver_lat = None
        self.receiver_lng = None
        self.callback = None
        self.receiver_phone = None

    def field_check(self):
        """
        :return:
        """
        for key, value in self.__dict__.iteritems():
            if value is None:
                raise TypeError("%s value can not be null" % key)

        return True


"""
5
affect effect
except accept
alternately alternatively
bare bear
censor sensor
4
The colors had a great affect on him, accept blue.
We alternatively took turns fighting the bare, bear handed.
China wants to sensor the affect of a bare in the cities.
The college will except me into their college, or alternately will reject me.
"""
"""
import os
path="D:\\JudgeFiles\\"
fin=open(os.path.join(path, "word.txt"), "r")
lines=fin.readlines()
"""
fin=open("word.txt", "r")
lines=fin.readlines()
switches=[]
start=int(lines[0])+1
mid=int(lines[start])
for i in range(1, start):
    lines[i]=lines[i].split(" ")
    lines[i][1]=lines[i][1][0: len(lines[i][1])-1]
    switches.append(lines[i])

tw=""

for i in range(start+1, start+1+mid):
    a=lines[i].split(" ")
    for s in switches:
        for word in a:
            if word==s[0]:
                a[a.index(word)]=s[1]
            elif word==s[0]+",":
                a[a.index(word)]=s[1]+","
            elif word==s[0]+".":
                a[a.index(word)]=s[1]+"."
            elif word==s[0]+"\n":
                a[a.index(word)]=s[1]+"\n"
            elif word==s[0]+".\n":
                a[a.index(word)]=s[1]+".\n"
            elif word==s[1]:
                a[a.index(word)]=s[0]
            elif word==s[1]+",":
                a[a.index(word)]=s[0]+","
            elif word==s[1]+".":
                a[a.index(word)]=s[0]+"."
            elif word==s[1]+"\n":
                a[a.index(word)]=s[0]+"\n"
            elif word==s[1]+".\n":
                a[a.index(word)]=s[0]+".\n"
    b=""
    for word in range(len(a)-1):
        b+=a[word]+" "
    b+=a[len(a)-1]
    tw+=b
print(tw)


from typing import AnyStr

from lxml.etree import strip_elements
from lxml.html import HTMLParser
from lxml.html import fromstring

USELESS_TAGS = frozenset(
    {
        "head",
        "script",
        "style",
        "iframe",
        "noscript",
    },
)

def get_root(
    html: AnyStr,
    *,
    useless_tags: list[str] | None = None,
    remove_comments: bool = True,
):
    """Get root of DOM Tree without useless data"""

    parser = HTMLParser(remove_comments=remove_comments)
    h = fromstring(html, parser=parser)
    if useless_tags is None:
        useless_tags = list(USELESS_TAGS)
    strip_elements(h, *useless_tags, with_tail=False)
    return h

def strip_tags(text: str) -> str:
    """Remove HTML Tags from input text"""

    return str(fromstring(text).text_content())