import os
import socket
import logging
from argparse import Namespace
from ossearch.node import Node
from ossearch.dbio import GraphTree
from ossearch.fileio import check_directory, walk_directory

log = logging.getLogger('ossearch')

def build_main(args: Namespace) -> bool:
    gt = GraphTree()

    # connect to tinkerpop server
    server = f'{args.address}:{args.port}'
    if not gt.connect(server):
        log.critical(f'Cannot connect to {server}')

    # check directory exists
    path = os.path.realpath(args.directory)
    if not check_directory(path):
        log.critical('Cannot build database')
        return False

    # check root node exists
    if gt.set_root(Node(name=path, path=path)):
        log.error(f'Root node {path} already exists in database')
        return False

    # add nodes to database
    print('Creating vertices')
    vertices = {}
    for node in walk_directory(path, args.include_bad):
        n = Node(name=node['name'], path=node['path'], parent=node['parent'], type=node['type'],
                 digest=node['digest'])

        if args.verbose:
            print(f'Adding {n.get_path()}')

        # collect vertices
        vertices[n.get_path()] = (gt.add_node(n), n.get_parent(), n.get_path() == path)

    # add edges
    print('Adding edges')
    gt.add_edges(vertices)

    print(f'Successfully created tree {path}')
    return True


from Interface import *
from Minimax import minimax
from MCTS2 import *
import time

class OthelloGame:
    def __init__(self):
        self.board = OthelloBoard(show_moves=True)
        self.board.playOutMoves([])

    def readCoord(self, coordinate):
        coordinate = coordinate.strip()
        if coordinate == "" or coordinate == "-":
            return "-"
        if len(coordinate) < 2:
            return False
        letter = coordinate.lower()[0]
        number = coordinate[1:]
        if letter.isalpha() and number.isnumeric():
            return Point(ord(letter)-97, int(number)-1)

    def simulateGames(self, number):
        win = draw = lose = 0
        for num in range(number):
            print(f"Game {num+1}")
            self.board.playOutMoves([])
            MCTS_agent = MC_Tree(exploration=1.4, player=State.White)
            MCTS_node = Node(self.board.compact_info)
            while not self.board.checkGameEnd():
                if (self.board.currentTurn is State.Black):
                    node, s = minimax(self.board, 3, State.Black, 0.4)
                    user_move = node.history[len(self.board.history)]
                else:
                    for _ in range(50):
                        MCTS_agent.playOut(MCTS_node)
                    user_move = MCTS_agent.choose(MCTS_node)
                self.board.placeMove(user_move)
                MCTS_node = MCTS_agent.child_from_parent(MCTS_node, user_move)
            if (self.board.whiteScore > self.board.blackScore):
                win += 1
            elif (self.board.whiteScore < self.board.blackScore):
                lose += 1
            else:
                draw += 1
            print(self.board)
            print(
                f"Wins:{win} Lose:{lose} Draw:{draw} Total:{win+lose+draw}\nAve win rate:{win/(win+draw+lose)}")

    def gameLoop(self):
        self.board.playOutMoves([])
        MCTS_agent = MC_Tree(exploration=1.4, player=State.White)
        MCTS_node = Node(self.board.compact_info)
        while not self.board.checkGameEnd():
            print(self.board)
            print("Black:{}, White:{}".format(
                self.board.blackScore, self.board.whiteScore))
            print("{}'s turn".format(str(self.board.currentTurn)))
            if len(self.board.history):
                print("Last move:", self.board.history[-1])
            if (self.board.currentTurn is State.Black):
                #node, s = minimax(self.board, 3, State.Black, 0.4)
                #user_move = node.history[len(self.board.history)]

                user_move = self.readCoord(input("Enter your move: "))
                user_move = Move(State.Black, user_move)
            else:
                startTime = time.time()
                counter=0
                while time.time() - startTime <= 5:
                    MCTS_agent.playOut(MCTS_node)
                    counter+=1
                print(f"iterations done:{counter}")
                user_move = MCTS_agent.choose(MCTS_node)
                # player
                #user_move = self.readCoord(input("Enter your move: "))
            if user_move.point not in self.board.getAvailablePoints():
                print(f"{str(user_move)} is invalid")
                continue
            self.board.placeMove(user_move)
            MCTS_node = MCTS_agent.child_from_parent(MCTS_node, user_move)
        print(self.board)
        print("Black:{}\nWhite:{}".format(
            self.board.blackScore, self.board.whiteScore))
        print("Game End!")
        if (self.board.whiteScore > self.board.blackScore):
            print("White Wins!")
        elif (self.board.whiteScore < self.board.blackScore):
            print("Black Wins!")
        else:
            print("Draw!")

class OthelloBoard:
    def __init__(self, length=8, show_moves=False):
        # all 8 directions
        self.allDir = [(0, 1), (0, -1), (1, 0), (-1, 0),
                       (1, 1), (-1, -1), (1, -1), (-1, 1)]
        self.history = []
        self.length = length
        self.showMoves = show_moves

    def playOutMoves(self, moveHistory):
        cO = self.length//2
        cI = cO - 1
        self.currentTurn = State.Black
        self.othelloBoard = [[State.Empty] *
                             self.length for _ in range(self.length)]
        self.othelloBoard[cI][cI] = self.othelloBoard[cO][cO] = State.White
        self.othelloBoard[cO][cI] = self.othelloBoard[cI][cO] = State.Black
        self.blackScore = 2
        self.whiteScore = 2

        for move in moveHistory:
            self.placeMove(move)

    def isValidMove(self, move):
        if self.othelloBoard[move.point.x][move.point.y] is not State.Empty:
            return False
        for direction in self.allDir:
            if len(self.getFlankPoints(move, direction)):
                return True
        return False

    def getAvailablePoints(self, player=None):
        if not player:
            player = self.currentTurn
        moves = [Point(x, y) for x in range(0, self.length) for y in range(0, self.length)
                 if self.isValidMove(Move(player, Point(x, y)))]
        if len(moves) == 0:
            moves = ["-"]
        return moves

    def getFlankPoints(self, move, direction):
        # direction is a tuple of (change X, change Y)
        changeX, changeY = direction
        checkPosX = move.point.x + changeX
        checkPosY = move.point.y + changeY
        flippedPointsList = []
        while 0 <= checkPosX < self.length and 0 <= checkPosY < self.length:
            if self.othelloBoard[checkPosX][checkPosY] is State.Empty:
                return []
            if self.othelloBoard[checkPosX][checkPosY] is move.player:
                return flippedPointsList
            flippedPointsList.append(Point(checkPosX, checkPosY))
            checkPosX += changeX
            checkPosY += changeY
        return []

    def placeMove(self, move, check=True):
        if str(move.point) == "-":
            self.currentTurn = move.player.opposite
            self.history.append(move)
            return
        if check and not self.isValidMove(move):
            return False
        flankedList = [move.point]
        for direction in self.allDir:
            flankedList += self.getFlankPoints(move, direction)
        for point in flankedList:
            self.othelloBoard[point.x][point.y] = move.player

        if move.player is State.White:
            self.whiteScore += len(flankedList)
            self.blackScore -= len(flankedList) - 1
        else:
            self.blackScore += len(flankedList)
            self.whiteScore -= len(flankedList) - 1
        self.currentTurn = move.player.opposite
        self.history.append(move)

    def checkGameEnd(self):
        if (self.getAvailablePoints()[0] == "-"):
            nextPhase = self.getCopy()
            nextPhase.placeMove(Move(self.currentTurn, "-"))
            return nextPhase.getAvailablePoints()[0] == "-"

    def getCopy(self):
        ObjSelf = OthelloBoard()
        ObjSelf.othelloBoard = [[*x] for x in self.othelloBoard]
        ObjSelf.history = [*self.history]
        ObjSelf.blackScore = self.blackScore
        ObjSelf.whiteScore = self.whiteScore
        ObjSelf.currentTurn = self.currentTurn
        return ObjSelf

    @property
    def compact_info(self):
        # [0] indicate current player, 0/1 => black/white
        # [1] indicate board length, even integer
        # [2:] indicate flattened current board placement -1: empty, 0 black, 1 white
        flatBoard = [
            item.value for sublist in self.othelloBoard for item in sublist]
        return [self.currentTurn.value-1, len(self.othelloBoard)] + flatBoard

    def load_compact_info(self, cryptedInfo):
        self.currentTurn = State.White if cryptedInfo[0] else State.Black
        self.length, flat_board = cryptedInfo[1], cryptedInfo[2:]
        self.othelloBoard = []
        self.whiteScore = 0
        self.blackScore = 0

        def convertToState(x):
            if x == 1:
                self.blackScore += 1
                return State.Black
            if x == 2:
                self.whiteScore += 1
                return State.White
            return State.Empty

        i = 0
        for j in range(self.length, self.length**2+1, self.length):
            self.othelloBoard.append([convertToState(x)
                                      for x in flat_board[i:j]])
            i = j

    def __hash__(self):
        return hash(str(self.compact_info))

    def __str__(self):
        print_string = ' '.join(['']+[chr(num+97)
                                      for num in range(0, self.length)]) + '\n'

        if self.showMoves and "-" not in self.getAvailablePoints():
            transposeBoard = [[*x] for x in self.othelloBoard]
            for point in self.getAvailablePoints():
                transposeBoard[point.x][point.y] = "."
            transposeBoard = zip(*transposeBoard)
        else:
            transposeBoard = zip(*self.othelloBoard)
        for rowNum, row in enumerate(transposeBoard):
            print_string += "|".join([str(x)
                                      for x in ['', *row, rowNum+1]]) + '\n'
        return print_string

if __name__ == "__main__":
    game = OthelloGame()
    a = time.time()
    # game.simulateGames(100)
    game.gameLoop()
    print(f"Average time per game: {(time.time()-a)/100}s")


import logging
import json
from resilient_circuits import AppFunctionComponent, app_function, FunctionResult
from resilient_lib import validate_fields
from fn_googlesafebrowsing.lib import constants

PACKAGE_NAME = "fn_googlesafebrowsing"
FN_NAME = "fn_googlesafebrowsing"

LOG = logging.getLogger(__name__)

class FunctionComponent(AppFunctionComponent):
    """Component that implements function 'fn_googlesafebrowsing'"""

    def __init__(self, opts):
        super(FunctionComponent, self).__init__(opts, PACKAGE_NAME)

    @app_function(FN_NAME)
    def lookup_urls(self, fn_inputs):
        """Lookup a URL"""

        yield self.status_message("Starting App Function: '{0}'".format(FN_NAME))

        artifact_type = fn_inputs.googlesafebrowsing_artifact_type
        artifact_value = fn_inputs.googlesafebrowsing_artifact_value

        validate_fields([
            {"name": "googlesafebrowsing_api_key"},
            {"name": "googlesafebrowsing_url"}],
            self.app_configs)

        # SOAR will always send one artifact value at a time
        threat_entries = [{'url' : artifact_value}]

        LOG.info("Google Safe Browsing lookup started for Artifact Type %s - Artifact Value %s",
                 artifact_type, artifact_value)

        reqbody = {
            'client': {
                 'clientId': constants.SB_CLIENT_ID,
                 'clientVersion': constants.SB_CLIENT_VER
            },
            'threatInfo': {
                'threatTypes': ['THREAT_TYPE_UNSPECIFIED',
                             'MALWARE',
                             'SOCIAL_ENGINEERING',
                             'UNWANTED_SOFTWARE',
                             'POTENTIALLY_HARMFUL_APPLICATION'],
                'platformTypes': ['ANY_PLATFORM'],
                'threatEntryTypes': ['URL'],
                'threatEntries': threat_entries
            }
        }

        LOG.debug(reqbody)

        response = self.rc.execute('post', '{}{}'.format(self.app_configs.googlesafebrowsing_url,
                                    self.app_configs.googlesafebrowsing_api_key),
                                    headers={'Content-Type': 'application/json'},
                                    data=json.dumps(reqbody))

        results = response.json()

        yield self.status_message("Endpoint reached successfully and returning results for App Function: '{0}'".format(FN_NAME))

        yield FunctionResult(results)


cards = input().split()
number_of_decks = int(input())
middle_lenght = len(cards) // 2

for i in range(number_of_decks):
    res = []

    for index in range(middle_lenght):
        first_card = cards[index]

        current_index_second_deck = index + middle_lenght
        second_card = cards[current_index_second_deck]

        res.append(first_card)
        res.append(second_card)
    cards = res
print(cards)

# index_one = 0
# index_two = len(string_list) // 2
#
#
# for deck in range(0,number_of_decks):
#     for half_one in range(0, (len(string_list) // 2)):
#         for half_two in range((len(string_list) // 2), len(string_list)+1):
#             print(string_list[half_one], string_list[half_two], end="")
#             index_one += 1


# -*- coding: utf-8 -*-
# @Author: lnorb.com
# @Date:   2022-01-18 17:03:03
# @Last Modified by:   lnorb.com
# @Last Modified time: 2022-02-08 05:33:50

from invoke import task
import os

# ./build.py -H ubuntu@18.118.53.220 -i orbdb.cer app-store.provision

@task
def start(c, env=os.environ):
    env["PYTHONPATH"] = "../"
    uvcpath = "/Library/Frameworks/Python.framework/Versions/3.7/bin/uvicorn"
    with c.cd("server"):
        c.run(f"{uvcpath} orb_server:app --reload", env=env)

@task
def create_db(c, env=os.environ):
    with c.cd("server"):
        c.run(
            "/Library/Frameworks/Python.framework/Versions/3.9/bin/python3 create_db.py"
        )


import get_column_stats
import os
import random
import statistics
import unittest

class TestGetColumnStats(unittest.TestCase):

    def test_mean(self):
        for i in range(0, 500):
            V = []
            for j in range(0, 500):
                V.append(random.randint(-1000, 1000))

            self.assertAlmostEqual(
                get_column_stats.get_mean(V),
                statistics.mean(V))

    def test_stdev(self):
        for i in range(0, 500):
            V = []
            for j in range(0, 500):
                V.append(random.randint(-1000, 1000))

            self.assertAlmostEqual(
                get_column_stats.get_stdev(V),
                statistics.pstdev(V))

    def test_mean_error(self):
        V = []
        self.assertRaises(ZeroDivisionError, get_column_stats.get_mean, V)

    def test_stdev_error(self):
        V = []
        self.assertRaises(ZeroDivisionError, get_column_stats.get_stdev, V)

if __name__ == '__main__':
    unittest.main()


"""
You're now a baseball game point recorder.

Given a list of strings, each string can be one of the 4 following types:

1. Integer (one round's score): Directly represents the number of points
you get in this round.
2. "+" (one round's score): Represents that the points you get in this
round are the sum of the last two valid round's points.
3. "D" (one round's score): Represents that the points you get in this
round are the doubled data of the last valid round's points.
4. "C" (an operation, which isn't a round's score): Represents the last
valid round's points you get were invalid and should be removed.
Each round's operation is permanent and could have an impact on
the round before and the round after.

You need to return the sum of the points you could get in all the rounds.

Example 1:
    Input: ["5","2","C","D","+"]
    Output: 30
Explanation:
    Round 1: You could get 5 points. The sum is: 5.
    Round 2: You could get 2 points. The sum is: 7.
    Operation 1: The round 2's data was invalid. The sum is: 5.
    Round 3: You could get 10 points (the round 2's data has been removed). The sum is: 15.
    Round 4: You could get 5 + 10 = 15 points. The sum is: 30.

Note:
    The size of the input list will be between 1 and 1000.
    Every integer represented in the list will be between -30000 and 30000.
"""

class Solution:
    """
    Runtime: 36 ms, faster than 92.73% of Python3.
    Memory Usage: 13.1 MB, less than 86.75% of Python3.

    Stack holds values of previos computations and perfectly fits to this kind of problems.
    """
    def calPoints(self, ops: list) -> int:
        stack = []
        for round in ops:
            if round.lstrip('-').isdigit():
                stack.append(int(round))
            elif round == "C":
                if stack:
                    stack.pop()
            elif round == "D":
                stack.append(int(stack[-1])*2 if stack else 0)
            elif round == "+":
                if len(stack) >= 2:
                    stack.append(int(stack[-2]) + int(stack[-1]))
                elif len(stack) == 1:
                    stack.append(int(stack[-1]))
        return sum(stack)

if __name__ == "__main__":
    s = Solution()
    assert s.calPoints(["5","2","C","D","+"]) == 30
    assert s.calPoints(["5","-2","4","C","D","9","+","+"]) == 27


import os
import shutil
from flask import render_template,request, redirect, send_file, session, url_for, make_response
from app import app, CVATapi, comparedb, dbquery, truthdb, predictdb
from dotenv import load_dotenv
from queue import Queue
from threading import Thread

load_dotenv()

url_cvat = os.getenv('URL_CVAT')

## PRIMA DI OGNI RICHIESTA FACCIO QUESTO CONTROLLO ##
#####################################################################################################

@app.before_request
def before_request():

    # controllo che il server cvat sia in run
    #status = CVATapi.check_serverCVAT_connection()
    #if status == 'Server not connect':
        #return make_response(render_template("serverError.html", info="Server non connesso"), 404)

    # controllo che i progetti cvat esistenti nel db siano esistenti anche su cvat (in questo modo
    # eventuali progetti eliminati lato cvat saranno eliminati anche lato db)
    # p_cvat contiene i progetti esistenti su cvat, a prescindere da MVE
    # ps_db contiene i progetti cvat esistenti sul db
    projectsCVAT = CVATapi.get_projects_id()
    projectsCVATdb = dbquery.get_projectsCVAT_id()

    for p in projectsCVATdb:
        if p not in projectsCVAT:
            dbquery.delete_projectCVAT(p)

## HOME ##
#####################################################################################################

# home page con la vista dei progetti (MVE e CVAT)
@app.route("/")
@app.route("/index")
def index():

    # prendo tutti i progetti MVE e CVAT
    projectsMVE = dbquery.get_projectsMVE()
    projectsCVAT =  dbquery.get_projectMVExProjectCVAT()
    predictions = dbquery.get_predList(id)

    return render_template('index.html', projectsMVE=projectsMVE, projectsCVAT=projectsCVAT, predictions=predictions, url_cvat=url_cvat)

## GESTIONE PROGETTI MVE ##
#####################################################################################################

# CREAZIONE di un nuovo progetto MVE
@app.route("/new_projectMVE")
def new_projectMVE():
    return render_template('new_projectMVE.html')

# Ricezione dei dati per la creazione di un nuovo progetto MVE
@app.route("/new_projectMVE_data", methods=['POST', 'GET'])
def new_projectMVE_data():

    if request.method == "POST":
        name_prj = request.form['name-project']
        desc_prj = request.form['desc-project']
        img_prj = request.files['img-project']
        dbquery.new_projectMVE(name_prj,desc_prj, img_prj)

        return redirect(url_for('index'))
    return ('',204)

# MODIFICA di un nuovo progetto MVE
@app.route("/edit_projectMVE/<id>")
def edit_projectMVE(id):
    data = dbquery.get_projectMVE(id)
    if (data == []):
        return make_response(render_template("404.html", info="Il progetto {} non esiste".format(id)), 404)

    predictions = dbquery.get_predList_by_id(id)

    return render_template('edit_projectMVE.html', id=id, data=data, predictions=predictions)

# Ricezione dei dati per la modifica di un nuovo progetto MVE
@app.route("/edit_projectMVE_data", methods=['POST', 'GET'])
def edit_projectMVE_data():

    if request.method == "POST":
        id_prj = request.form['id-project']
        name_prj = request.form['name-project']
        desc_prj = request.form['desc-project']
        img_prj = request.files['img-project']

        dbquery.edit_projectMVE(id_prj, name_prj,desc_prj, img_prj)

        return redirect(url_for('index'))
    return ('',204)

# ELIMINAZIONE di un progetto MVE
@app.route("/delete_projectMVE/<id>")
def delete_projectMVE(id):

    # controllo che il progetto mve esista
    project = dbquery.get_projectMVE(id)
    if (project == []):
        return make_response(render_template("404.html", info="Il progetto {} non esiste".format(id)), 404)

    # prendo i progetti cvat associati al progetto mve da eliminare
    prjsCVAT = dbquery.get_projectsCVAT(id)
    dbquery.delete_projectMVE(id)
    dbquery.delete_MVSxCVAT_MVE(id)

    # se esistono elimino ogni progetto cvat
    if (len(prjsCVAT) != 0):
        for pCVAT in prjsCVAT:
            CVATapi.delete_project(pCVAT[1])

    return redirect(url_for('index'))

## GESTIONE PROGETTI CVAT ##
#####################################################################################################

# VISUALIZZAZIONE di un progetto CVAT
@app.route("/project/<id>")
def project(id):

    # controlliamo che il progetto esista
    project = dbquery.get_projectCVAT(id)

    # otteniamo tutti i progetti per poter cambiare la scelta del progetto corrente dalla pagina project.html
    projectsMVE = dbquery.get_projectsMVE()
    projectsCVAT =  dbquery.get_projectMVExProjectCVAT()

    if (project == []):
        return render_template('project.html', id=id, projectsMVE=projectsMVE, projectsCVAT=projectsCVAT, info="progetto non esistente")

    # l'api di cvat ritorna solo 10 task (in questo caso gli ultimi)
    tasks = CVATapi.get_tasks(id)

    return render_template('project.html', id=id, projectsMVE=projectsMVE, projectsCVAT=projectsCVAT, tasks=tasks, info="", url_cvat=url_cvat)

# CREAZIONE di un nuovo progetto CVAT, dato un progetto MVE
@app.route("/new_projectCVAT/<id_prj_MVE>")
def new_projectCVAT(id_prj_MVE):

    # controllo che il progetto mve esista
    project = dbquery.get_projectMVE(id_prj_MVE)
    if (project == []):
        return make_response(render_template("404.html", info="Il progetto {} non esiste".format(id_prj_MVE)), 404)

    name_prj_MVE = request.args.get('name_prj_MVE')

    return render_template('new_projectCVAT.html', id_prj_MVE=id_prj_MVE, name_prj_MVE=name_prj_MVE)

# Ricezione dei dati per la creazione di un nuovo progetto CVAT
@app.route("/new_projectCVAT_data", methods=['POST', 'GET'])
def new_projectCVAT_data():
    if request.method == "POST":
        name_prj = request.form['name-project']
        id_prj_MVE = request.form['id-prj-MVE']

        id_prj_CVAT = CVATapi.create_project(name_prj)

        dbquery.new_projectCVAT(id_prj_MVE, id_prj_CVAT)

        return redirect(url_for('index'))
    return ('',204)

# ELIMINAZIONE di un progetto CVAT
@app.route("/delete_projectCVAT/<id>")
def delete_projectCVAT(id):

    # controllo che il progetto mve esista
    project = dbquery.get_projectCVAT(id)
    if (project == []):
        return make_response(render_template("404.html", info="Il progetto {} non esiste".format(id)), 404)

    tasks = CVATapi.get_tasks_ids(id)
    for task in tasks:
        dbquery.delete_MVSxCVAT_task(task)

    dbquery.delete_projectCVAT(id)
    CVATapi.delete_project(id)

    return redirect(url_for('index'))

## TASK MANAGEMENT - THREAD ##
#####################################################################################################

# La funzione prende dalla coda il primo task inserito poi in un ciclo for scorre tutte le richieste
# finche non trova qeulla con il task corrispondente. a quel punto prende i dati (uuid, nametask, id)
# e genera n task cvat con le immagini caricate
def worker(queue):
    while True:
        # get the next task, blocking until one is available.
        task = queue.get()
        # The app is available to the worker, but be wary of
        # using app services without locking.
        ##### WORK TO DO IN BACKGROUND #####

        for request in requests:
            if (request['task']==task):
                uuid = request['uuid']
                name_task = request['name_task']
                id = request['id_prjCVAT']
                keyLogin = CVATapi.generate_key_login()

                idMVE = dbquery.get_projectCVAT(id)[0]

                directory = 'temp{}'.format(uuid)
                dir = os.listdir(directory)
                current_task = 1

                # Checking if the list is empty or not
                while len(dir) != 0:
                    taskId = CVATapi.create_empty_task(id, name_task, current_task, keyLogin)

                    fs = CVATapi.select_images(uuid, idMVE, taskId)

                    CVATapi.upload_images(uuid, fs, keyLogin, taskId)
                    current_task = current_task + 1
                    dir = os.listdir(directory)

                shutil.rmtree(directory)
        for request in requests.copy():
            if (request['task']==task):
                requests.remove(request)

                #duration = app.config.get('WORK_TIME', 3)

                #sleep(duration)  # simulate doing work
                print("did task {!r}".format(task))

# Give the worker thread a Queue that's shared with the app, and start
# the worker. The worker will block immediately until a task is added
# to the queue.
work_queue = Queue()
worker_thread = Thread(target=worker, args=(work_queue,), daemon=True)
worker_thread.start()
requests = []
task = 0

## CARICAMENTO IMMAGINI - CREAZIONE DI TASK - ELIMINAZIONE TASK ##
#####################################################################################################

# CARICAMENTO immagini
@app.route('/upload/<id>')
def upload(id):
    # controllo che il progetto sia esistente
    project = dbquery.get_projectCVAT(id)
    if (project == []):
        return make_response(render_template("404.html", info="Il progetto {} non esiste".format(id)), 404)

    return render_template('upload_img.html', id=id)

@app.route('/get_regex_file', methods=['GET', 'POST'])
def get_regex_file():
    if request.method == "POST":
        data = request.get_json()
        print(data['uuid'])
        print(data['data'])

    session['regex'+data['uuid']] = data['data']

    return "ok"
# Caricamento effettivo delle immagini e creazione di n task a seconda del peso totale delle immagini
# NB. questa rotta viene raggiunta quando viene eseguito il submit del form presente alla pagina upload_img.html;
# ogni volta che viene fatto un submit viene incrementato il numero di task (niente a che fare con cvat, in qeusto caso è
# una variabile globale) e viene creata una istanza this_request con i dati della richiesta corrente con anche il numero del task
# corrispondente. questa istanza viene aggiunta ad una lista di richieste (requests). viene creato un nuovo thread che chiama
# la funzione "warker" con parametro una coda (work_queue) di task. Vedi funzione per vedere cosa succede
@app.route('/uploader/<id>', methods=['POST', 'GET'])
def uploader(id):
    this_name_task = request.form['name-task']
    files = request.files.getlist('fileList')
    this_uuid = request.form.get('uuid')
    regex = session['regex'+this_uuid]
    regex_files = []
    for file in files:
        if file.filename in regex:
            regex_files.append(file)
    session.pop('regex'+this_uuid)

    totalSize = CVATapi.get_files(regex_files, this_uuid)
    global task
    task += 1
    this_request = {
        'task': task,
        'uuid': this_uuid,
        'name_task': this_name_task,
        'id_prjCVAT': id
    }
    global requests
    requests.append(this_request)
    print("add task {!r}".format(task))
    work_queue.put(task)
    return redirect(url_for('project', id=id))

# ELIMINAZIONE di un task
@app.route("/delete_task/<id>")
def delete_task(id):

    prj_id = request.args.get('prj_id')
    CVATapi.delete_task(id)
    dbquery.delete_MVSxCVAT_task(id)

    return redirect(url_for('project', id=prj_id))

## VERITA ##
#####################################################################################################

# NB l'id che passo come parametro è l'id del progetto MVE scelto

# CARICAMENTO truth
@app.route("/upload_truth/<id>")
def upload_truth(id):
    # controllo che il progetto mve esista
    project = dbquery.get_projectMVE(id)
    if (project == []):
        return make_response(render_template("404.html", info="Il progetto {} non esiste".format(id)), 404)

    return render_template('upload_truth.html', id=id)

# Caricamento effettivo del file e aggiunta di istanze nelle tabelle Truth e TruthValues
@app.route('/uploader_truth/<id>', methods=['POST', 'GET'])
def uploader_truth(id):
    file_truth = request.files['file-truth']
    resp = truthdb.read_file(file_truth,id)
    session['duplicates'] = resp

    return redirect(url_for('upload_truth', id=id))

# SCARICAMENTO verita
@app.route('/download_truth/<id>', methods=['POST', 'GET'])
def download_truth(id):
    truthdb.download_truth(id)
    namefile = truthdb.download_truth(id)
    return send_file("../"+namefile, as_attachment=True)

## PREDIZIONI ##
#####################################################################################################

# NB l'id che passo come parametro è l'id del progetto MVE scelto

# CARICAMENTO predizione
@app.route("/upload_prediction/<id>")
def upload_prediction(id):
    # controllo che il progetto mve esista
    project = dbquery.get_projectMVE(id)
    if (project == []):
        return make_response(render_template("404.html", info="Il progetto {} non esiste".format(id)), 404)

    return render_template('upload_prediction.html', id=id)

# Caricamento effettivo del file e aggiunta di istanze nelle tabelle Truth e TruthValues
@app.route('/uploader_prediction/<id>', methods=['POST', 'GET'])
def uploader_prediction(id):
    file_truth = request.files['file-pred']

    return predictdb.read_file(file_truth,id)

# ELIMINAZIONE di una predizione
@app.route("/delete_prediction/<id>")
def delete_prediction(id):

    dbquery.delete_prediction(id)
    prj_id = request.args.get('prj_id')

    return redirect(url_for('edit_projectMVE', id=prj_id))

# SCARICAMENTO predizione
@app.route('/download_pred/<id>', methods=['POST', 'GET'])
def download_pred(id):
    if request.method == "POST":
        pred = request.form['select-prediction']
        namefile = predictdb.download_pred(id, pred)
        return send_file("../"+namefile, as_attachment=True)
    return redirect(url_for('index'))

## CONFRONTO PREDIZIONI/VERITA  ##
#####################################################################################################

state_compare = False

# pagina principale
@app.route("/compare/<id>")
def compare(id):
    comparisons = comparedb.get_comparisons(id)
    predictions = dbquery.get_predList_by_id(id)
    truth = dbquery.get_truth_mve(id)
    dname = session.get('dname', None)
    session.pop('dname', None)
    info = session.get('info', None)
    session.pop('info', None)
    status = session.get('status', None)
    session.pop('status', None)

    return render_template('compare.html', id=id, predictions=predictions, comparisons=comparisons, truth=truth, dname=dname, info=info, status=status)

# Visualizza predizione
@app.route("/view_prediction/<id>",  methods=['POST', 'GET'])
def view_prediction(id):
    if request.method == "POST":
        pred = request.form['select-prediction']

        global state_compare
        if state_compare == False:
            state_compare = True
            database = comparedb.view_prediction(id, pred)
            session['dname'] = database.name
            state_compare = False
        else:
            session['info'] = "Server occupato. riprova tra qualche secondo."
        session['status']="pred"

    return redirect(url_for('compare', id=id))

# Confronto predizioni
@app.route("/compare_predictions/<id>",  methods=['POST', 'GET'])
def compare_predictions(id):
    if request.method == "POST":
        pred1 = request.form['select-first-prediction']
        pred2 = request.form['select-second-prediction']
        global state_compare
        if state_compare == False:
            state_compare = True
            database = comparedb.compare_predictions(id, pred1, pred2)
            session['dname'] = database.name
            state_compare = False
        else:
            session['info'] = "Server occupato. riprova tra qualche secondo."
        session['status']="pred-vs-pred"

    return redirect(url_for('compare', id=id))

# Confronto predizione vs verita
@app.route("/compare_pred_truth/<id>",  methods=['POST', 'GET'])
def compare_pred_truth(id):
    if request.method == "POST":
        pred = request.form['select-prediction']
        global state_compare
        if state_compare == False:
            state_compare = True
            database = comparedb.compare_pred_truth(id, pred)
            session['dname'] = database.name
            state_compare = False
        else:
            session['info'] = "Server occupato. riprova tra qualche secondo."
        session['status']="pred-vs-truth"

    return redirect(url_for('compare', id=id))

# ELIMINAZIONE di un confronto
@app.route("/delete_compare/<id>")
def delete_compare(id):
    dir_name = request.args.get('dir_name')
    shutil.rmtree('datasets/'+dir_name)
    return redirect(url_for('compare', id=id))

# Visualizza qualcosa di gia esistente
@app.route("/compare_existing/<id>",  methods=['POST', 'GET'])
def compare_existing(id):
    pred1 = request.args.get('pred1')
    tab = request.args.get('pred2')
    global state_compare
    if state_compare == False:
        state_compare = True
        if (tab == "/"):
            database = comparedb.view_prediction(id, pred1)
        elif (tab == "Truth"):
            database = comparedb.compare_pred_truth(id, pred1)
        else:
            database = comparedb.compare_predictions(id, pred1, tab)
        state_compare = False
        session['dname'] = database.name
    else:
        session['info'] = "Server occupato. riprova tra qualche secondo."

    return redirect(url_for('compare', id=id))

## GESTIONE ERRORI  ##
#####################################################################################################

@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html', info="Pagina non trovata"), 404


import os
import json

# Keras Imports
from keras import layers
from keras import metrics
import keras.backend as K
from keras.optimizers import Adam
from keras.models import Model, load_model
from keras.layers.convolutional import Conv1D, Conv2D,  MaxPooling1D, MaxPooling2D
from keras.callbacks import ModelCheckpoint, EarlyStopping, TensorBoard, ReduceLROnPlateau
from keras.layers import Input, Dense, Dropout, BatchNormalization, SpatialDropout1D, SpatialDropout2D, Activation, Flatten, AlphaDropout

from . import plots
from . import defines
from . import arguments
from . import tensor_maps

def start_session_get_args_and_model(intra_ops, inter_ops, semantics_json, weights_hd5=None, tensor_type=None):
    K.clear_session()
    K.get_session().close()
    cfg = K.tf.ConfigProto(intra_op_parallelism_threads=intra_ops, inter_op_parallelism_threads=inter_ops)
    cfg.gpu_options.allow_growth = True
    K.set_session(K.tf.Session(config=cfg))
    return args_and_model_from_semantics(semantics_json, weights_hd5, tensor_type)

def args_and_model_from_semantics(semantics_json, weights_hd5=None, tensor_type=None):
    args = arguments.parse_args()

    if semantics_json is not None and os.path.exists(semantics_json):
        model = set_args_and_get_model_from_semantics(args, semantics_json, weights_hd5)
    else:
        model = load_model(weights_hd5, custom_objects=get_metric_dict(args.labels))
        args.tensor_name = tensor_type

    return args, model

def set_args_and_get_model_from_semantics(args, semantics_json, weights_hd5=None):
    """Recreate a model from a json file specifying model semantics.

    Update the args namespace from the semantics file values.
    Assert that the serialized tensor map and the recreated one are the same.

    Arguments:
        args.tensor_name: String which indicates tensor map to use or None
        args.window_size: sites included in the tensor map
        args.read_limit: Maximum reads included in the tensor map
        args.annotations: List of annotations or None
        semantics_json: Semantics json file (created with serialize_model_semantics())

    Returns:
        The Keras model
    """
    with open(semantics_json, 'r') as infile:
        semantics = json.load(infile)

    if 'model_version' in semantics:
        assert(args.model_version == semantics['model_version'])

    if 'input_tensor_map' in semantics:
        args.tensor_name = semantics['input_tensor_map_name']
        args.window_size = semantics['window_size']
        args.read_limit = semantics['read_limit']
        tm = tensor_maps.get_tensor_channel_map_from_args(args)
        assert(len(tm) == len(semantics['input_tensor_map']))
        for key in tm:
            assert(tm[key] == semantics['input_tensor_map'][key])

    if 'input_annotations' in semantics:
        args.annotations = semantics['input_annotations']
        args.annotation_set = semantics['input_annotation_set']

    args.input_symbols = semantics['input_symbols']
    args.labels = semantics['output_labels']

    if 'channels_last' in semantics:
        args.channels_last = semantics['channels_last']
        if args.channels_last:
            K.set_image_data_format('channels_last')
        else:
            K.set_image_data_format('channels_first')

    if weights_hd5 is None:
        weights_hd5 = os.path.join(os.path.dirname(semantics_json), semantics['architecture'])

    print('Updated arguments:', args, '\nWeight file from:', weights_hd5)
    model = load_model(weights_hd5, custom_objects=get_metric_dict(args.labels))
    model.summary()
    return model

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~ Models ~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def build_default_1d_annotation_model(args):
    return build_reference_annotation_1d_model_from_args(args,
                                                         conv_width=7,
                                                         conv_layers=[256, 216, 128, 64, 32],
                                                         conv_dropout=0.1,
                                                         conv_batch_normalize=True,
                                                         spatial_dropout=True,
                                                         max_pools=[],
                                                         padding='same',
                                                         annotation_units=64,
                                                         annotation_shortcut=True,
                                                         fc_layers=[64, 64],
                                                         fc_dropout=0.2,
                                                         annotation_batch_normalize=True,
                                                         fc_batch_normalize=False)

def build_1d_annotation_model_from_args(args):
    return build_reference_annotation_1d_model_from_args(args,
                                                         conv_width=args.conv_width,
                                                         conv_layers=args.conv_layers,
                                                         conv_dropout=args.conv_dropout,
                                                         conv_batch_normalize=args.conv_batch_normalize,
                                                         spatial_dropout=args.spatial_dropout,
                                                         max_pools=args.max_pools,
                                                         padding=args.padding,
                                                         annotation_units=args.annotation_units,
                                                         annotation_shortcut=args.annotation_shortcut,
                                                         fc_layers=args.fc_layers,
                                                         fc_dropout=args.fc_dropout,
                                                         fc_batch_normalize=args.fc_batch_normalize)

def build_2d_annotation_model_from_args(args):
    return read_tensor_2d_annotation_model_from_args(args,
                                                     conv_width = args.conv_width,
                                                     conv_height = args.conv_height,
                                                     conv_layers = args.conv_layers,
                                                     conv_dropout = args.conv_dropout,
                                                     conv_batch_normalize = args.conv_batch_normalize,
                                                     spatial_dropout = args.spatial_dropout,
                                                     max_pools = args.max_pools,
                                                     padding = args.padding,
                                                     annotation_units = args.annotation_units,
                                                     annotation_shortcut = args.annotation_shortcut,
                                                     fc_layers = args.fc_layers,
                                                     fc_dropout = args.fc_dropout,
                                                     fc_batch_normalize = args.fc_batch_normalize)

def build_default_2d_annotation_model(args):
    return read_tensor_2d_annotation_model_from_args(args,
                                                     conv_width = 25,
                                                     conv_height = 25,
                                                     conv_layers = [64, 48, 32, 24],
                                                     conv_dropout = 0.1,
                                                     conv_batch_normalize = False,
                                                     spatial_dropout = True,
                                                     max_pools = [(3,1),(3,1)],
                                                     padding='valid',
                                                     annotation_units = 64,
                                                     annotation_shortcut = False,
                                                     fc_layers = [24],
                                                     fc_dropout = 0.3,
                                                     fc_batch_normalize = False)

def read_tensor_2d_annotation_model_from_args(args,
                                              conv_width = 6,
                                              conv_height = 6,
                                              conv_layers = [128, 128, 128, 128],
                                              conv_dropout = 0.0,
                                              conv_batch_normalize = False,
                                              spatial_dropout = True,
                                              residual_layers = [],
                                              max_pools = [(3,1), (3,3)],
                                              padding='valid',
                                              annotation_units = 16,
                                              annotation_shortcut = False,
                                              annotation_batch_normalize = True,
                                              fc_layers = [64],
                                              fc_dropout = 0.0,
                                              fc_batch_normalize = False,
                                              kernel_initializer='glorot_normal',
                                              kernel_single_channel=True,
                                              fc_initializer='glorot_normal'):
    '''Builds Read Tensor 2d CNN model with variant annotations mixed in for classifying variants.

    Arguments specify widths and depths of each layer.
    2d Convolutions followed by dense connection mixed with annotation values.
    Dynamically sets input channels based on args via defines.total_input_channels_from_args(args)
    Uses the functional API. Supports theano or tensorflow channel ordering.
    Prints out model summary.

    Arguments
        args.window_size: Length in base-pairs of sequence centered at the variant to use as input.
        args.labels: The output labels (e.g. SNP, NOT_SNP, INDEL, NOT_INDEL)
        args.weights_hd5: An existing model file to load weights from
        args.channels_last: Theano->False or Tensorflow->True channel ordering flag
        conv_layers: list of number of convolutional filters in each layer
        batch_normalization: Boolean whether to apply batch normalization or not
    Returns
        The keras model
    '''
    in_channels = tensor_maps.total_input_channels_from_args(args)

    if K.image_data_format() == 'channels_last':
        in_shape = (args.read_limit, args.window_size, in_channels)
        concat_axis = -1
    else:
        in_shape = (in_channels, args.read_limit, args.window_size)
        concat_axis = 1

    x = read_tensor_in = Input(shape=in_shape, name=args.tensor_name)

    max_pool_diff = max(0, len(conv_layers)-len(max_pools))

    # Add convolutional layers
    for i,f in enumerate(conv_layers):
        if kernel_single_channel and i%2 == 0:
            cur_kernel = (conv_width, 1)
        elif kernel_single_channel:
            cur_kernel = (1, conv_height)
        else:
            cur_kernel = (conv_width, conv_height)

        if conv_batch_normalize:
            x = Conv2D(int(f), cur_kernel, activation='linear', padding=padding, kernel_initializer=kernel_initializer)(x)
            x = BatchNormalization(axis=concat_axis)(x)
            x = Activation('relu')(x)
        else:
            x = Conv2D(int(f), cur_kernel, activation='relu', padding=padding, kernel_initializer=kernel_initializer)(x)

        if conv_dropout > 0 and spatial_dropout:
            x = SpatialDropout2D(conv_dropout)(x)
        elif conv_dropout > 0:
            x = Dropout(conv_dropout)(x)

        if i >= max_pool_diff:
            x = MaxPooling2D(max_pools[i-max_pool_diff])(x)

    for i,r in enumerate(residual_layers):
        if kernel_single_channel and i%2 == 0:
            cur_kernel = (conv_width, 1)
        elif kernel_single_channel:
            cur_kernel = (1, conv_height)
        else:
            cur_kernel = (conv_width, conv_height)

        y = Conv2D(r.filters[0], (1, 1), strides=r.strides)(x)
        y = BatchNormalization(axis=concat_axis)(y)
        y = Activation('relu')(y)

        y = Conv2D(r.filters[1], cur_kernel, padding='same')(y)
        y = BatchNormalization(axis=concat_axis)(y)
        y = Activation('relu')(y)

        y = Conv2D(r.filters[2], (1, 1))(y)
        y = BatchNormalization(axis=concat_axis)(y)

        if r.identity:
            x = layers.add([y, x])
        else:
            shortcut = Conv2D(r.filters[2], (1, 1), strides=r.strides)(x)
            shortcut = BatchNormalization(axis=concat_axis)(shortcut)
            x = layers.add([y, shortcut])

        x = Activation('relu')(x)

    x = Flatten()(x)

    # Mix the variant annotations in
    annotations = annotations_in = Input(shape=(len(args.annotations),), name=args.annotation_set)
    if annotation_batch_normalize:
        annotations_in = BatchNormalization(axis=-1)(annotations)

    annotations_mlp = Dense(units=annotation_units, kernel_initializer=fc_initializer, activation='relu')(annotations_in)
    x = layers.concatenate([x, annotations_mlp], axis=concat_axis)

    # Fully connected layers
    for fc_units in fc_layers:

        if fc_batch_normalize:
            x = Dense(units=fc_units, kernel_initializer=fc_initializer, activation='linear')(x)
            x = BatchNormalization(axis=1)(x)
            x = Activation('relu')(x)
        else:
            x = Dense(units=fc_units, kernel_initializer=fc_initializer, activation='relu')(x)

        if fc_dropout > 0:
            x = Dropout(fc_dropout)(x)

    if annotation_shortcut:
        x = layers.concatenate([x, annotations_in], axis=concat_axis)

    # Softmax output
    prob_output = Dense(units=len(args.labels), kernel_initializer=fc_initializer, activation='softmax')(x)

    # Map inputs to outputs
    model = Model(inputs=[read_tensor_in, annotations], outputs=[prob_output])

    # adamo = Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, clipnorm=1.)
    adamo = Adam(lr=args.optimizer_learning_rate, beta_1=args.optimizer_beta_1,
                beta_2=args.optimizer_beta_1, epsilon=args.optimizer_epsilon, clipnorm=args.optimizer_clipnorm)
    model.compile(loss='categorical_crossentropy', optimizer=adamo, metrics=get_metrics(args.labels))
    model.summary()

    if os.path.exists(args.weights_hd5):
        model.load_weights(args.weights_hd5, by_name=True)
        print('Loaded model weights from:', args.weights_hd5)

    return model

def build_reference_annotation_1d_model_from_args(args,
                                                  conv_width = 6,
                                                  conv_layers = [128, 128, 128, 128],
                                                  conv_dropout = 0.0,
                                                  conv_batch_normalize = False,
                                                  spatial_dropout = True,
                                                  max_pools = [],
                                                  padding='valid',
                                                  activation = 'relu',
                                                  annotation_units = 16,
                                                  annotation_shortcut = False,
                                                  annotation_batch_normalize = True,
                                                  fc_layers = [64],
                                                  fc_dropout = 0.0,
                                                  fc_batch_normalize = False,
                                                  fc_initializer = 'glorot_normal',
                                                  kernel_initializer = 'glorot_normal',
                                                  alpha_dropout = False
                                                  ):
    '''Build Reference 1d CNN model for classifying variants.

    Architecture specified by parameters.
    Dynamically sets input channels based on args via defines.total_input_channels_from_args(args)
    Uses the functional API.
    Prints out model summary.

    Arguments
        args.annotations: The variant annotations, perhaps from a HaplotypeCaller VCF.
        args.labels: The output labels (e.g. SNP, NOT_SNP, INDEL, NOT_INDEL)

    Returns
        The keras model
    '''
    in_channels = tensor_maps.total_input_channels_from_args(args)
    concat_axis = -1
    x = reference = Input(shape=(args.window_size, in_channels), name=args.tensor_name)

    max_pool_diff = len(conv_layers)-len(max_pools)
    for i,c in enumerate(conv_layers):

        if conv_batch_normalize:
            x = Conv1D(filters=c, kernel_size=conv_width, activation='linear', padding=padding, kernel_initializer=kernel_initializer)(x)
            x = BatchNormalization(axis=concat_axis)(x)
            x = Activation(activation)(x)
        else:
            x = Conv1D(filters=c, kernel_size=conv_width, activation=activation, padding=padding, kernel_initializer=kernel_initializer)(x)

        if conv_dropout > 0 and alpha_dropout:
            x = AlphaDropout(conv_dropout)(x)
        elif conv_dropout > 0 and spatial_dropout:
            x = SpatialDropout1D(conv_dropout)(x)
        elif conv_dropout > 0:
            x = Dropout(conv_dropout)(x)

        if i >= max_pool_diff:
            x = MaxPooling1D(max_pools[i-max_pool_diff])(x)

    f = Flatten()(x)

    annotations = annotations_in = Input(shape=(len(args.annotations),), name=args.annotation_set)
    if annotation_batch_normalize:
        annotations_in = BatchNormalization(axis=concat_axis)(annotations_in)
    annotation_mlp = Dense(units=annotation_units, kernel_initializer=fc_initializer, activation=activation)(annotations_in)

    x = layers.concatenate([f, annotation_mlp], axis=1)
    for fc in fc_layers:
        if fc_batch_normalize:
            x = Dense(units=fc, activation='linear', kernel_initializer=fc_initializer)(x)
            x = BatchNormalization(axis=1)(x)
            x = Activation(activation)(x)
        else:
            x = Dense(units=fc, activation=activation, kernel_initializer=fc_initializer)(x)

        if fc_dropout > 0 and alpha_dropout:
            x = AlphaDropout(fc_dropout)(x)
        elif fc_dropout > 0:
            x = Dropout(fc_dropout)(x)

    if annotation_shortcut:
        x = layers.concatenate([x, annotations_in], axis=1)

    prob_output = Dense(units=len(args.labels), activation='softmax', name='softmax_predictions')(x)

    model = Model(inputs=[reference, annotations], outputs=[prob_output])

    # adam = Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, clipnorm=1.)
    adam = Adam(lr=args.optimizer_learning_rate, beta_1=args.optimizer_beta_1,
                beta_2=args.optimizer_beta_1, epsilon=args.optimizer_epsilon, clipnorm=args.optimizer_clipnorm)
    model.compile(optimizer=adam, loss='categorical_crossentropy', metrics=get_metrics(args.labels))
    model.summary()

    if os.path.exists(args.weights_hd5):
        model.load_weights(args.weights_hd5, by_name=True)
        print('Loaded model weights from:', args.weights_hd5)

    return model

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~ Optimizing ~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def train_model_from_generators(args, model, generate_train, generate_valid, save_weight_hd5):
    '''Train an image model for classifying variants.

    Training data lives on disk, it will be loaded by generator functions.
    Plots the metric history after training. Creates a directory to save weights at if necessary.

    Arguments
        args.batch_size: size of the mini-batches
        args.patience: Maximum number of epochs to run without validation loss improvement
        args.epochs: Maximum number of epochs to run regardless of Early Stopping
        args.training_steps: Number of mini-batches in each so-called epoch
        args.validation_steps: Number of validation mini-batches to examine after each epoch.
        model: the model to optimize
        generate_train: training data generator function
        valid_tuple: Validation data data generator function
        save_weight_hd5: path to save the model weights at

    Returns
        The now optimized keras model
    '''
    if not os.path.exists(os.path.dirname(save_weight_hd5)):
        os.makedirs(os.path.dirname(save_weight_hd5))
    serialize_model_semantics(args, save_weight_hd5)

    history = model.fit_generator(generate_train,
                                  steps_per_epoch=args.training_steps, epochs=args.epochs, verbose=1,
                                  validation_steps=args.validation_steps, validation_data=generate_valid,
                                  callbacks=get_callbacks(args, save_weight_hd5))
    print('Training complete, model weights saved at: %s' % save_weight_hd5)
    if args.image_dir:
        plots.plot_metric_history(history, plots.weight_path_to_title(save_weight_hd5), prefix=args.image_dir)

    return model

def get_callbacks(args, save_weight_hd5):
    callbacks = []

    callbacks.append(ModelCheckpoint(filepath=save_weight_hd5, verbose=1, save_best_only=True))
    callbacks.append(EarlyStopping(monitor='val_loss', patience=args.patience*4, verbose=1))
    callbacks.append(ReduceLROnPlateau(monitor='val_loss', patience=args.patience, verbose=1))

    if args.tensor_board:
        callbacks.append(TensorBoard())

    return callbacks

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~ Metrics ~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def precision(y_true, y_pred):
    '''Calculates the precision, a metric for multi-label classification of
    how many selected items are relevant.
    '''
    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + K.epsilon())
    return precision

def recall(y_true, y_pred):
    '''Calculates the recall, a metric for multi-label classification of
    how many relevant items are selected.
    '''
    true_positives = K.sum(K.round(K.clip(y_true*y_pred, 0, 1)))
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + K.epsilon())
    return recall

def per_class_recall(labels):
    recall_fxns = []

    for label_key in labels:
        label_idx = labels[label_key]
        fxn = 'def '+ label_key + '_recall(y_true, y_pred):\n'
        fxn += '\ttrue_positives = K.sum(K.round(K.clip(y_true*y_pred, 0, 1)), axis=0)\n'
        fxn += '\tpossible_positives = K.sum(K.round(K.clip(y_true, 0, 1)), axis=0)\n'
        fxn += '\treturn true_positives['+str(label_idx)+'] / (possible_positives['+str(label_idx)+'] + K.epsilon())\n'

        exec(fxn)
        recall_fxn = eval(label_key + '_recall')
        recall_fxns.append(recall_fxn)

    return recall_fxns

def per_class_precision(labels):
    precision_fxns = []

    for label_key in labels:
        label_idx = labels[label_key]
        fxn = 'def '+ label_key + '_precision(y_true, y_pred):\n'
        fxn += '\ttrue_positives = K.sum(K.round(K.clip(y_true*y_pred, 0, 1)), axis=0)\n'
        fxn += '\tpredicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)), axis=0)\n'
        fxn += '\treturn true_positives['+str(label_idx)+'] / (predicted_positives['+str(label_idx)+'] + K.epsilon())\n'

        exec(fxn)
        precision_fxn = eval(label_key + '_precision')
        precision_fxns.append(precision_fxn)
    return precision_fxns

def get_metric_dict(labels=defines.SNP_INDEL_LABELS):
    metrics = {'precision':precision, 'recall':recall}
    precision_fxns = per_class_precision(labels)
    recall_fxns = per_class_recall(labels)
    for i,label_key in enumerate(labels.keys()):
        metrics[label_key+'_precision'] = precision_fxns[i]
        metrics[label_key+'_recall'] = recall_fxns[i]
    return metrics

def per_class_recall_3d(labels):
    recall_fxns = []

    for label_key in labels:
        label_idx = labels[label_key]
        fxn = 'def '+ label_key + '_recall(y_true, y_pred):\n'
        fxn += '\ttrue_positives = K.sum(K.sum(K.round(K.clip(y_true*y_pred, 0, 1)), axis=0), axis=0)\n'
        fxn += '\tpossible_positives = K.sum(K.sum(K.round(K.clip(y_true, 0, 1)), axis=0), axis=0)\n'
        fxn += '\treturn true_positives['+str(label_idx)+'] / (possible_positives['+str(label_idx)+'] + K.epsilon())\n'

        exec(fxn)
        recall_fxn = eval(label_key + '_recall')
        recall_fxns.append(recall_fxn)

    return recall_fxns

def per_class_precision_3d(labels):
    precision_fxns = []

    for label_key in labels:
        label_idx = labels[label_key]
        fxn = 'def '+ label_key + '_precision(y_true, y_pred):\n'
        fxn += '\ttrue_positives = K.sum(K.sum(K.round(K.clip(y_true*y_pred, 0, 1)), axis=0), axis=0)\n'
        fxn += '\tpredicted_positives = K.sum(K.sum(K.round(K.clip(y_pred, 0, 1)), axis=0), axis=0)\n'
        fxn += '\treturn true_positives['+str(label_idx)+'] / (predicted_positives['+str(label_idx)+'] + K.epsilon())\n'

        exec(fxn)
        precision_fxn = eval(label_key + '_precision')
        precision_fxns.append(precision_fxn)

    return precision_fxns

def get_metrics(classes=None, dim=2):
    if classes and dim == 2:
        return [metrics.categorical_accuracy] + per_class_precision(classes) + per_class_recall(classes)
    elif classes and dim == 3:
        return [metrics.categorical_accuracy] + per_class_precision_3d(classes) + per_class_recall_3d(classes)
    else:
        return [metrics.categorical_accuracy, precision, recall]

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~ Serialization ~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def serialize_model_semantics(args, architecture_hd5):
    """Save a json file specifying model semantics, I/O contract.

    Arguments
        args.tensor_name: String which indicates tensor map to use (from defines.py) or None
        args.window_size: sites included in the tensor map
        args.read_limit: Maximum reads included in the tensor map
        args.annotations: List of annotations or None
        args.id: the id of the run will be the name of the semantics file
        architecture_hd5: Keras model and weights hd5 file (created with save_model())
    """
    semantics = {
        'id': args.id,
        'output_labels': args.labels,
        'architecture': os.path.basename(architecture_hd5),
        'input_symbols': args.input_symbols,
        'model_version': args.model_version,
        'gatk_version': args.gatk_version,
    }

    if args.tensor_name:
        semantics['input_tensor_map_name'] = args.tensor_name
        semantics['input_tensor_map'] = tensor_maps.get_tensor_channel_map_from_args(args)
        semantics['window_size'] = args.window_size
        semantics['read_limit'] = args.read_limit

    if args.annotation_set and args.annotation_set != '_':
        semantics['input_annotations'] = args.annotations
        semantics['input_annotation_set'] = args.annotation_set

    if args.data_dir:
        semantics['data_dir'] = args.data_dir

    semantics['channels_last'] = args.channels_last

    json_file_name = args.output_dir + args.id + '.json'
    with open(json_file_name, 'w') as outfile:
        json.dump(semantics, outfile)

    print('Saved model semantics at:', json_file_name)


from bs4 import BeautifulSoup
from html.parser import HTMLParser
from html.entities import name2codepoint
import xlsxwriter

def parcing_html_table(table):
    table_dict = []
    row_index = 0
    for row in table.children:
        if row.name != 'tr':
            continue
        cell_index = 0
        if type(row).__name__ != 'NavigableString':
            table_dict.append([])
            table_dict[row_index] = {}
            table_dict[row_index]['context'] = 'table, tr'
            table_dict[row_index]['cells'] = []
            table_dict[row_index]['attrs'] = row.attrs

            for cell in row.children:
                if type(cell).__name__ != 'NavigableString':
                    table_dict[row_index]['cells'].append([])
                    table_dict[row_index]['cells'][cell_index] = {}
                    table_dict[row_index]['cells'][cell_index]['attrs'] = cell.attrs
                    values_index = 0
                    table_dict[row_index]['cells'][cell_index]['values'] = []
                    for cell_values in cell.contents:
                        cell_text = cell_values.string.replace('\n', '').strip()
                        if len(cell_text) > 0:
                            table_dict[row_index]['cells'][cell_index]['values'].append([])
                            table_dict[row_index]['cells'][cell_index]['values'][values_index] = {}
                            table_dict[row_index]['cells'][cell_index]['values'][values_index]['text'] = cell_text
                            if type(cell_values).__name__ != 'NavigableString':
                                cell_class = cell_values.attrs.get('class', None)
                                if cell_class:
                                    cell_class = cell_class[0]
                                table_dict[row_index]['cells'][cell_index]['values'][values_index]['context'] = cell_class
                            values_index += 1
                    cell_index += 1
            row_index += 1
    return table_dict

def parcing_html_styles(html):
    styles_dict = {}
    for tag in html:
        if tag.name == 'style':
            styles_name = ''
            styles_atrib_name = ''
            styles_atrib_values = ''
            what_we_read = 'styles_name'
            for tag_style_string in tag.children:
                for symbol in tag_style_string:
                    if symbol == '\n':
                        continue
                    elif what_we_read in ('styles_name', 'styles_atrib_name') and symbol == ' ':
                        continue
                    elif symbol == '{':
                        styles_name = styles_name.strip()
                        styles_dict[styles_name] = {}
                        what_we_read = 'styles_atrib_name'
                    elif symbol == ':':
                        styles_atrib_name = styles_atrib_name.strip()
                        styles_dict[styles_name][styles_atrib_name] = []
                        what_we_read = 'styles_atrib_values'
                    elif symbol == ';':
                        styles_atrib_values = styles_atrib_values.strip()
                        if ',' in styles_atrib_values:
                            styles_atrib_values = styles_atrib_values.split(',')
                        else:
                            styles_atrib_values = styles_atrib_values.split(' ')
                        styles_dict[styles_name][styles_atrib_name].append(styles_atrib_values)
                        styles_atrib_name = ''
                        styles_atrib_values = ''
                        what_we_read = 'styles_atrib_name'
                    elif symbol == '}':
                        styles_name = ''
                        what_we_read = 'styles_name'
                    else:
                        if what_we_read == 'styles_name':
                            styles_name += symbol
                        if what_we_read == 'styles_atrib_name':
                            styles_atrib_name += symbol
                        if what_we_read == 'styles_atrib_values':
                            styles_atrib_values += symbol
    return styles_dict

def table_to_excel(table_dict, cursor_start):
    def add_to_set(adding_cells_set, start_x, start_y, cell_end_x, cell_end_y):
        for i in range(start_x, cell_end_x + 1):
            for j in range(start_y, cell_end_y + 1):
                adding_cells_set.add((i, j))
        return adding_cells_set
    def get_cell_size(cell):
        rowspan = 1
        colspan = 1
        if cell['attrs'].get('rowspan', None):
            rowspan = int(cell['attrs'].get('rowspan', None))
        if cell['attrs'].get('colspan', None):
            colspan = int(cell['attrs'].get('colspan', None))
        return rowspan, colspan
    def calc_end_of_cell(cell_start_x, cell_start_y, rowspan, colspan):
        cell_end_x = cell_start_x + rowspan - 1
        cell_end_y = cell_start_y + colspan - 1
        return cell_end_x, cell_end_y
    def get_cell_text(cell, rowspan, colspan):
        cell_text = ''
        for i in cell['values']:
            if rowspan > 1:
                cell_text += i['text'] + str('\n')
            else:
                cell_text += i['text']
        return cell_text
    def write_cell(cell_start_x, cell_start_y, cell_end_x, cell_end_y, cell_text):
        if rowspan + colspan > 2:
            if rowspan > 1:
                cell_format = workbook.add_format()
                cell_format.set_text_wrap()
                cell_format.set_align('left')
                cell_format.set_align('top')
                cell_format.set_border()
                worksheet.merge_range(cell_start_x, cell_start_y, cell_end_x, cell_end_y, cell_text, cell_format)
            else:
                cell_format_two = workbook.add_format()
                cell_format_two.set_border()
                worksheet.merge_range(cell_start_x, cell_start_y, cell_end_x, cell_end_y, cell_text, cell_format_two)
        else:
            cell_format_two = workbook.add_format()
            cell_format_two.set_border()
            worksheet.write(cell_start_x, cell_start_y, cell_text, cell_format_two)
    def get_start_next_cell(cell_start_x, cell_start_y, cell_end_y, adding_cells_set):
        cell_start_y = cell_end_y
        while (cell_start_x, cell_start_y) in adding_cells_set:
            cell_start_y += 1
        return cell_start_y
    def get_start_next_cell_on_new_row(cell_start_x, cell_start_y):
        cell_start_y = 0
        cell_start_x += 1
        while (cell_start_x, cell_start_y) in adding_cells_set:
            cell_start_y += 1
        return cell_start_x, cell_start_y

    workbook = xlsxwriter.Workbook('hello.xlsx')
    worksheet = workbook.add_worksheet()
    cell_start_x = int(cursor_start[0])
    cell_start_y = int(cursor_start[1])
    adding_cells_set = set()

    for row in table_dict:
        for cell in row['cells']:
            rowspan, colspan = get_cell_size(cell)
            cell_end_x, cell_end_y = calc_end_of_cell(cell_start_x, cell_start_y, rowspan, colspan)
            adding_cells_set = set(add_to_set(adding_cells_set, cell_start_x, cell_start_y, cell_end_x, cell_end_y))
            cell_text = get_cell_text(cell, rowspan, colspan)
            write_cell(cell_start_x, cell_start_y, cell_end_x, cell_end_y, cell_text)
            cell_start_y = get_start_next_cell(cell_start_x, cell_start_y, cell_end_y, adding_cells_set)
        cell_start_x, cell_start_y = get_start_next_cell_on_new_row(cell_start_x, cell_start_y)
    workbook.close()

def main():
    with open('examples\only table.html', 'r', encoding='utf-8') as html_file_code:
        html_code = html_file_code.read()

    soup = BeautifulSoup(html_code, 'html.parser')

    table_dict = list(parcing_html_table(soup.table))
    cursor_start = (0, 0)
    table_to_excel(table_dict, cursor_start)

if __name__ == "__main__":
    main()


from LeetCodeLib.LinkedList import *

class Solution(object):
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        node.val = node.next.val
        node.next = node.next.next

LL = BuildLinkedList([1, 2, 3, 4])
PrintLinkedList(LL)
pointer = LL.next.next
s = Solution()
s.deleteNode(pointer)
PrintLinkedList(LL)


import socket
import threading

from proxyconf import conf

class ProxyServer:

    def __init__(self):
        # Create a TCP socket
        self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # the SO_REUSEADDR flag tells the kernel to reuse a local socket in TIME_WAIT state,
        # without waiting for its natural timeout to expire.
        self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        # bind the socket to given host and port
        self.serverSocket.bind((conf['HOST'], conf['PORT']))

        self.serverSocket.listen()

    def handle_connections(self):
        while True:
            # Accept connections
            connection, client_address = self.serverSocket.accept()

            # Create a thread for every client
            proxy_thread = ProxyThread(connection, client_address)
            proxy_thread.run()

class ProxyThread(threading.Thread):

    def __init__(self, client_connection, client_address):
        threading.Thread.__init__(self)

        self.client_connection = client_connection
        self.client_address = client_address

        # The entire python program exists once all non daemon threads exited
        # so making the proxy threads daemons leads to them exiting once the main thread
        # finishes execution
        self.daemon = True

    def run(self):
        print('[*] Starting Proxy Thread')
        self.request = self.get_request()
        if self.request:
            self.url, self.port = self.get_url_and_port_from_http_request()
            self.target_connection = self.connect_to_target_server()
            self.send_request_to_target_server()
            self.return_response_to_client()
            self.close_connections()
        print('[*] Exiting Proxy Thread')

    def get_request(self):
        request = self.client_connection.recv(4096)
        print('[*] Request is: {}'.format(request))
        return request

    def get_url_and_port_from_http_request(self):
        """ Gets URL and PORT from the request. In case no port is specified the default HTTP port 80 is used. It also
        cleans the URL to make it usable for socket connections.
        """
        first_line = self.request.split(b'\n')[0]
        url = first_line.split(b' ')[1]

        # find and remove http://
        http_pos = url.find(b'://')
        if http_pos >= 0:
            url = url[(http_pos + 3):]

        # find and remove / as otherwise no socket connection can be established
        url = url.split(b'/')[0]

        # find and handle port
        url_parts = url.split(b':')
        if len(url_parts) > 1:
            url = url_parts[0]
            port = int(url_parts[1])
        else:
            # use default http port if not specified
            port = 80

        print('[*] The URL is: {}'.format(url))
        print('[*] The port is: {}'.format(port))
        return url, port

    def connect_to_target_server(self):
        target_connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        target_connection.connect((self.url, self.port))
        return target_connection

    def send_request_to_target_server(self):
        self.target_connection.send(self.request)

    def return_response_to_client(self):
        while True:
            data = self.target_connection.recv(4096)
            print('[*] Response from target server is: {} \n Sending to Client'.format(str(data)))
            if len(data):
                self.client_connection.send(data)  # send to browser/client
            else:
                break

    def close_connections(self):
        self.client_connection.close()
        self.target_connection.close()

if __name__ == '__main__':
    proxyServer = ProxyServer()
    proxyServer.handle_connections()


class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        list1=[]
        left=0
        right=len(matrix[0])-1
        top=0
        bottom=len(matrix)-1
        while left<=right and top<=bottom:
            for i in range(left,right+1):
                list1.append(matrix[top][i])
            top+=1
            for i in range(top,bottom+1):
                list1.append(matrix[i][right])
            right-=1
            if len(list1)==(len(matrix)*len(matrix[0])):
                break
            for i in range(right,left-1,-1):
                list1.append(matrix[bottom][i])
            bottom-=1
            for i in range(bottom,top-1,-1):
                list1.append(matrix[i][left])
            left+=1
        return list1


from sqlalchemy import *
import json
from flask import Flask
from flask import request, jsonify
import os

keyT=os.path.join(os.getcwd(),'cc-ca.crt')
print(f"cockroachdb://moustafa:MoustafaHTN2021@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/red-coyote-284.defaultdb?sslmode=verify-full&sslrootcert={keyT}")
engine = create_engine(f"cockroachdb://moustafa:MoustafaHTN2021@free-tier.gcp-us-central1.cockroachlabs.cloud:26257/red-coyote-284.defaultdb?sslmode=verify-full&sslrootcert={keyT}")
connection = engine.connect()
print(engine.table_names())
metadata = MetaData()

labels = Table('labels', metadata, autoload=True, autoload_with=engine)

def outputResults():
    result = []
    select_st = select([labels])
    tags_res_list = connection.execute(select_st)
    for res in tags_res_list:
        output = {
        "label":res.label,
        "start_time":float(res.start_time),
        "end_time":float(res.end_time),
        "confidence":float(res.confidence)
        }
        result.append(output)
    output_string = json.dumps(result)
    return output_string

def insertLabel(labelList):
    for l in labelList:
        info = json.loads(l);
        # insert data via insert() construct
        ins = labels.insert().values(
            label=info['label'],
            start_time = info['start_time'],
            end_time = info['end_time'],
            confidence = info['confidence'])
        res = connection.execute(ins)

def searchText(search1):
    result = []
    query_sql = text("SELECT * FROM labels WHERE label LIKE '%" + search1 + "%'")
    tags_res_list = (connection.execute(query_sql)).fetchall()
    for res in tags_res_list:
        output = {
        "label":res.label,
        "start_time":float(res.start_time),
        "end_time":float(res.end_time),
        "confidence":float(res.confidence)
        }
        result.append(output)
    output_string = json.dumps(result)
    return output_string

def searchTime(startTime, endTime):
    result = []
    query_sql = text("SELECT * FROM labels WHERE start_time >= " + str(startTime) + " AND end_time <= "+ str(endTime))
    tags_res_list = (connection.execute(query_sql)).fetchall()
    for res in tags_res_list:
        output = {
        "label":res.label,
        "start_time":float(res.start_time),
        "end_time":float(res.end_time),
        "confidence":float(res.confidence)
        }
        result.append(output)
    output_string = json.dumps(result)
    return output_string

app = Flask(__name__)
@app.route("/output")
def out():
    return outputResults()
@app.route("/search-text")
def searchTex():
    return searchText(str(request.args.get('text')))
@app.route("/search-time")
def searchTim():
    return searchTime(float(request.args.get('start')), float(request.args.get('end')))
@app.route("/")
def hello():
  return "Hello World!"

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


from keras.datasets import mnist
from keras.utils import np_utils
from tensorflow.python.keras.models import load_model

(X_train, y_train), (X_test, y_test) = mnist.load_data()
reconstructed_model = load_model("mnistSmall.h5")
X_test = X_test.astype('float32')
# Normalizing data
X_test /= 255
# one-hot encoding using keras numpy-related utilities
n_classes = 10
Y_test = np_utils.to_categorical(y_test, n_classes)
results = reconstructed_model.evaluate(X_test, Y_test, batch_size=128)
print("test loss, test acc:", results)


import logging
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QTextEdit, QVBoxLayout
from PyQt5.QtWidgets import QAction, QActionGroup, QMenu
from macro_manager import MacroMgr
from utils.logging_qt import QLogHandler
from utils.translator import string_to_level, level_to_string

class LogWidget(QWidget):
    def __init__(self, parent):
        super(LogWidget, self).__init__(parent)
        self._init_ui()
        # 绑定root logger
        self._log_handler = QLogHandler()
        self._log_handler.new_message.connect(self._text_edit.append)
        logging.getLogger().addHandler(self._log_handler)

    def _init_ui(self):
        self._text_edit = QTextEdit(self)
        self._text_edit.setReadOnly(True)
        lay = QVBoxLayout()
        lay.addWidget(self._text_edit)
        self.setLayout(lay)
        self._init_context_menu()

    def _init_context_menu(self):
        clear_act = QAction("清空日志", self)
        clear_act.triggered.connect(self._text_edit.clear)
        level_group = QActionGroup(self)
        level_menu = QMenu(self)
        level_menu.addAction(level_group.addAction(level_to_string(logging.DEBUG)))
        level_menu.addAction(level_group.addAction(level_to_string(logging.INFO)))
        level_menu.addAction(level_group.addAction(level_to_string(logging.WARNING)))
        level_menu.addAction(level_group.addAction(level_to_string(logging.ERROR)))
        for a in level_group.actions():
            a.setCheckable(True)
        level_group.triggered.connect(self._set_level)
        for action in level_group.actions():
            if string_to_level(action.text()) == MacroMgr.config().log_level:
                self._set_level(action)
                break
        log_level_act = QAction("日志等级", self)
        log_level_act.setMenu(level_menu)
        # 自定义右键菜单
        self._text_edit.setContextMenuPolicy(Qt.ContextMenuPolicy.ActionsContextMenu)
        self._text_edit.addAction(clear_act)
        self._text_edit.addAction(log_level_act)

    @staticmethod
    def _set_level(action: QAction):
        action.setChecked(True)
        MacroMgr.config().log_level = string_to_level(action.text())


# Chapter 9-2
# CSV 파일 읽기 및 쓰기
# CSV : MEMETYPE = text/csv

import csv

# EX 1
with open('./resource/test1.csv', 'r') as f:
    reader = csv.reader(f) #CSV 패키지를 읽을 떄 reader로 연
    #a = next(reader)    #Header Skip <-커서 이용
    #객체 확인
    print(reader)
    #타입 확인
    print(type(reader))
    #속성 확인
    print(dir(reader)) #__iter__ ->for문 사용 가능
    print()
    for c in reader:
        #print(c)    #csv파일의 헤더부분까지 출력 -> 리스트로 출력
        #print(type(c))
        #list to str
        print(' : '.join(c)) #-c의 리스트의 요소를 구분자로 구분

# EX 2
with open('./resource/test2.csv', 'r') as f:
    reader = csv.reader(f, delimiter = '|') #잘못된 구분자를 사용 -> 하나의 원소로 가져옴

    for c in reader:
        print(c)

# EX 3
with open('./resource/test1.csv', 'r') as f:
    reader = csv.DictReader(f) #csv파일을 딕셔너리로 가져옴
    #확인
    print(reader)
    print(type(reader))
    print(dir(reader))
    print()

    for c in reader:
        for k,v in c.items():
            print(k,v)
        print('---------------------')

# EX 4
w = [[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18],[19,20,21]]

with open('./resource/write1.csv', 'w', encoding = 'UTF-8') as f:
    print(dir(csv))
    wt = csv.writer(f) #파일과 연동되서 쓰기 직전에 준비상태

    #dir 확인
    #print(dir(wt))
    #타입 확인
    #print(type(wt))

    for v in w:
        wt.writerow(v)

    #print write1.csv
with open('./resource/write1.csv','r') as f:
    read2 = csv.reader(f)

    for v in read2:
        print(' : '.join(v))

# EX 5
with open('./resource/write2.csv', 'w', encoding = 'UTF-8') as f:
    #필드명
    fields = ['One','Two','Three']
    #DictWriter
    wt = csv.DictWriter(f, fieldnames = fields) #fieldnames라는 인수 지정 -> 필드명 작성 가능
    #Header Writer
    wt.writeheader()#헤더 이름이 내부적으로 작성된 상태

    for v in w:
        wt.writerow({'One' : v[0], 'Two' : v[1], 'Three' : v[2]})


from dynamic.elasticsearch_connection.es_connect import es

def update_files_with_query(filename):
    return {
          "script": {
            "lang": "painless",
            "inline": "def updated = false; for (int i=0;i<ctx._source.files.size();i++) { if (ctx._source.files[i]['filename'] == params.file.filename){ctx._source.files[i].error_count += 1; updated=true;break}}if(!updated){ctx._source.files.add(params.file)}",
            "params": {
              "file" : {
                "filename" : filename,
                "error_count": 1
              }
            }
          }
        }

user = {
    "email" : "",
    "additions" : 0,
    "deletions" : 0,
    "jira_issues": [],
    "error_count": 0
}

def update_users_error_with_query(email):
    query_user = user
    query_user['email'] = email
    query_user['error_count'] = 1
    return {
          "script": {
            "lang": "painless",
            "inline": "def updated = false;"
                      "for (int i=0;i<ctx._source.users.size();i++) { if (ctx._source.users[i]['email'] == params.user.email){ctx._source.users[i].error_count += 1; updated=true;break}}if(!updated){ctx._source.users.add(params.user)}",
            "params": {
              "user" : query_user
            }
          }
        }

def update_users_git_info(email, additions, deletions):
    query_user = user
    query_user['email'] = email
    query_user['additions'] = additions
    query_user['deletions'] = deletions
    return {
          "script": {
            "lang": "painless",
            "inline": "def updated = false;"
                      "for (int i=0;i<ctx._source.users.size();i++) { if (ctx._source.users[i]['email'] == params.user.email){ctx._source.users[i].additions += params.user.additions; ctx._source.users[i].deletions += params.user.deletions; updated=true;break}}if(!updated){ctx._source.users.add(params.user)}",
            "params": {
              "user" : query_user
            }
          }
        }

def update_issues(issue, assignee_email):
    query_user = user
    query_user['email'] = assignee_email
    return {
      "script": {
        "lang": "painless",
        "inline": "def updated = false; int user_index = -1; for (int i=0;i<ctx._source.users.size();i++) { if (ctx._source.users[i]['email'] == params.user.email){ user_index = i; for(int j=0;j<ctx._source.users[i].jira_issues.size();j++) {def issue = ctx._source.users[i].jira_issues[j]; if (issue.summary == params.issue.summary) {issue.status = params.issue.status; issue.curr_start_time = params.issue.curr_start_time; issue.total_time += params.issue.total_time; ctx._source.users[i].jira_issues[j] = issue; updated=true; break } } break } } if(!updated){if (user_index == -1) {def user_copy = params.user; user_copy.jira_issues.add(params.issue); ctx._source.users.add(user_copy) } else {ctx._source.users[user_index].jira_issues.add(params.issue) } }",
        "params": {
          "issue" : issue,
          "user": query_user
        }
      }
    }

def get_issue_start_time(summary):
    query_body = {
        "query":{
            "nested":{
                "path" : "users.jira_issues",
                "query":{
                    "match":{
                        "users.jira_issues.summary": summary,
                    }
                },
                "inner_hits":{}
            }
        }
    }
    search_result = es.search(index='dev_meter', doc_type='project_registration', body=query_body)
    if search_result['hits']['total'] > 0:
        return search_result['hits']['hits'][0]['inner_hits']['users.jira_issues']['hits']['hits'][0]['_source']['curr_start_time']
    else:
        return None


import os

import webapp2
from google.appengine.ext import db
import jinja2

import authentication

class Handler(webapp2.RequestHandler):
	template_dir = os.path.join(
			os.path.dirname(__file__), 'templates')
	jinja_env = jinja2.Environment(
		loader = jinja2.FileSystemLoader(template_dir),
		autoescape = True)

	def write(self, *a, **kw):
		'''Writes directly to the http request'''
		self.response.out.write(*a, **kw)

	def render_str(self, template, **params):
		'''Returns a string of the rendered template'''
		t = self.jinja_env.get_template(template)
		return t.render(params)

	def render(self, template, **kw):
		'''Render using the template and parameters'''
		username = authentication.getUserName(self)
		self.write(self.render_str(template,
			_user=username, _url=self.request.url, **kw))

	def throw_error(self, code):
		'''Throws an error, e.g. 404'''
		self.response.set_status(code)
		message = 'An error was encountered. Terribly sorry.'
		if code == 403:
			message = 'Access denied. You do not have permission to access this resource.'\
			' Please do not try again'
		if code == 404:
			message = 'The page or resource you requested could not be found. '\
			'If you caught a broken link, please report it to the naughty admin.'
		self.render('error.html', errorcode=code, errormessage=message)

class ErrorHandler(Handler):
	''''''
	def get(self, params):
		self.throw_error(404)

class SlashRedirect(Handler):
	'''Removes multiple trailing slashes and redirects'''
	def get(self, path):
		self.redirect(path)


from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _

class Info(models.Model):
    user = models.OneToOneField(User, verbose_name='auth_user')

    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    phone = models.CharField(_('phone'), max_length=20, blank=True)

    avatar_path = models.CharField(
        _('avatar path'), max_length=255, blank=True)
    background_path = models.CharField(
        _('background path'), max_length=255, blank=True)

    def serialized_user(self):
        u = UserSerializer(instance=self.user)
        return u.data

    def followers(self):
        objs = self.user.followerships.filter(
            is_active=True, is_confirm=True)
        # temporary test
        followers_id = []
        for obj in objs:
            followers_id.append(obj.follower_id)
        return followers_id

    def followeds(self):
        objs = self.user.followedships.filter(
            is_active=True, is_confirm=True)
        # temporary test
        followeds_id = []
        for obj in objs:
            followeds_id.append(obj.followed_id)
        return followeds_id

    def follow(self, followed_id):
        follower = self.user
        if follower.id == int(followed_id):
            return 'Cannot Follow Yourself'
        try:
            followed = User.objects.get(pk=followed_id)
        except User.DoesNotExist:
            return 'User DoesNotExist'
        obj = Friendship.objects.get_or_create(
            followed=followed, follower=follower)
        if obj[1]:
            if followed.setting.need_permission_to_listen:
                obj[0].is_confirm = False
                obj[0].save()
            else:
                obj[0].active_dateline = obj[0].dateline
                obj[0].save()
            return 'Success'
        else:
            if not obj[0].is_active:
                obj[0].is_active = True
                obj[0].save()
                return 'Success'
            else:
                return 'Already Exist'

    def confirm(self, follower_id):
        try:
            obj = self.user.followerships.get(follower_id=follower_id)
            obj.confirm()
            return 'Success'
        except Friendship.DoesNotExist:
            return 'Friendship DoesNotExist'

    def unfollow(self, followed_id):
        try:
            obj = self.user.followedships.get(
                followed_id=followed_id)
            obj.delete()
            return 'Success'
        except Friendship.DoesNotExist:
            return 'Friendship DoesNotExist'

    def remove_follower(self, follower_id):
        try:
            obj = self.user.followerships.get(
                follower_id=follower_id)
            obj.delete()
            return 'Success'
        except Friendship.DoesNotExist:
            return 'Friendship DoesNotExist'

@receiver(post_save, sender=User)
def user_create_info(sender, **kwargs):
    if kwargs.get('created'):
        i = kwargs.get('instance')
        info = Info(
            user=i,
            first_name=i.first_name,
            last_name=i.last_name,
            email=i.email,
            phone='',
            avatar_path='',
            background_path=''
        )
        info.save()
    else:
        i = kwargs.get('instance')
        info = Info.objects.get(user=i)
        info.first_name = i.first_name
        info.last_name = i.last_name
        info.email = i.email
        info.save()

class Setting(models.Model):
    user = models.OneToOneField(User, verbose_name=_('auth_user'))
    need_permission_to_listen = models.BooleanField(
        default=False, verbose_name=_('need permission to listen'))
    need_permission_to_message = models.BooleanField(
        default=False,  verbose_name=_('need permission to msg'))

@receiver(post_save, sender=User)
def user_create_setting(sender, **kwargs):
    if kwargs.get('created'):
        i = kwargs.get('instance')
        setting = Setting(
            user=i,
            need_permission_to_message=False,
            need_permission_to_listen=False
        )
        setting.save()

class Friendship(models.Model):
    followed = models.ForeignKey(User, related_name='followerships')
    follower = models.ForeignKey(User, related_name='followedships')
    dateline = models.DateTimeField(auto_now_add=True)
    is_confirm = models.BooleanField(default=True)
    is_active = models.BooleanField(default=True)
    active_dateline = models.DateTimeField(blank=True, null=True)

    class Meta:
        unique_together = ('followed', 'follower')

    def __unicode__(self):
        return "%s listen to %s" % (self.follower, self.followed)

    def confirm(self):
        '''only followed user has permission'''
        self.is_confirm = True
        self.save()

    def delete(self):
        '''followed and follower user both have permission'''
        self.is_active = False
        self.save()

from users.serializers import UserSerializer


# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
# 03. 円周率
# "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."という文を単語に分解し，
# 各単語の（アルファベットの）文字数を先頭から出現順に並べたリストを作成せよ．
string = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
string = string.replace(",", "").replace(".", "")
string = string.split(" ")
word_cnt = []
for s in string:
    word_cnt.append(len(s))

print(word_cnt)


#Author: Andrew Eisenhour
#Date: 9/24/19
#Shipping Program

#Obtain the user input
country = input("Enter the country: ")
state = input("Enter the state or province: ")

#Compute the shipping cost
shippingCost = 0.0

if country == "USA":
    if state == "AK" or state == "HI" :
        shippingCost = 10.0
    else:
        shippingCost = 5.0
else:
    shippingCost = 10.0

#Print the results
print("Shipping cost to %s, %s: $%.2f" % (state, country, shippingCost))


from django.db import models

# Create your models here.

class Persona(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def full_name(self):
        return self.first_name + " " + self.last_name

    class Meta:
        abstract = True

class Profesor(Persona):

    salario = models.FloatField(default=0)
    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields = ['id', 'first_name', 'last_name'], name = 'primary_key_profesor'
            )
        ]

class Salon(models.Model):
    aula = models.CharField(max_length=2)
    hora_entrada = models.TimeField()
    profesor_id = models.ForeignKey(Profesor, on_delete = models.CASCADE, default = 0)

class Alumno(Persona):
    idSalon = models.ForeignKey(Salon, on_delete = models.CASCADE)
    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields = ['id', 'first_name', 'last_name'], name = 'primary_key_alumno'
            )
        ]

class OrderedAlum(Alumno):
    class Meta:
        ordering = ["last_name"]
        proxy = True

class Evaluacion(models.Model):
    hora_fecha = models.DateTimeField()
    curso = models.CharField(max_length=30)
    evaluador = models.CharField(max_length=50)

    class Meta:
        abstract = True

class Examen_Final(Evaluacion):
    duracion = models.IntegerField()
    n_preguntas = models.IntegerField()
    puntaje_total = models.IntegerField()

    def puntaje_pregunta(self):
        return self.puntaje_total / n_preguntas

class Proyecto(Evaluacion):
    tema_proyecto = models.CharField(max_length=100)
    n_grupos = models.IntegerField()

class OrderedNameProject(Proyecto):
    class Meta:
        proxy = True
        ordering = ["tema_proyecto"]