# 2503. Maximum Number of Points From Grid Queries
# https://leetcode.com/problems/maximum-number-of-points-from-grid-queries/

from bisect import bisect_left
from collections import defaultdict
import heapq

class Solution:
    def maxPoints(self, grid, queries):
        '''
        # TLE
        def dfs(i,j,max_val,visited):
            temp=0
            for x,y in d:
                if 0<=i+x<m and 0<=j+y<n and grid[i+x][j+y]<max_val and (i+x,j+y) not in visited:
                    visited.add((i+x,j+y))
                    temp+=(1+dfs(i+x,j+y,max_val,visited))
            return temp

        m,n=len(grid),len(grid[0])
        ans=[]
        d={(0,1),(1,0),(0,-1),(-1,0)}
        for limit in queries:
            if grid[0][0]<limit:
                ans.append(1+dfs(0,0,limit,set([(0,0)])))
            else:
                ans.append(0)
        return ans
        '''

        m,n=len(grid),len(grid[0])
        queue=[(grid[0][0],0,0)]
        grid[0][0]=0
        d=defaultdict(int)
        curr=0
        direction=[(0,1),(1,0),(-1,0),(0,-1)]
        while queue:
            value,i,j=heapq.heappop(queue)
            curr=max(curr,value)
            d[curr]+=1
            for x,y in direction:
                if 0<=i+x<m and 0<=j+y<n and grid[i+x][j+y]:
                    heapq.heappush(queue,(grid[i+x][j+y],i+x,j+y))
                    grid[i+x][j+y]=0

        l=[[i,j] for i,j in d.items()]
        l.sort()
        for idx in range(1,len(l)):
            l[idx][1]+=l[idx-1][1]
        ans=[]
        for q in queries:
            idx=bisect_left(l,[q,0])
            if not idx:
                ans.append(0)
            else:
                ans.append(l[idx-1][1])
        return ans

        '''
        m,n=len(grid),len(grid[0])
        queue=[(grid[0][0],0,0)]
        grid[0][0]=0
        l=[]
        direction=[(0,1),(1,0),(-1,0),(0,-1)]
        while queue:
            value,i,j=heapq.heappop(queue)
            l.append(value)
            for x,y in direction:
                if 0<=i+x<m and 0<=j+y<n and grid[i+x][j+y]:
                    heapq.heappush(queue,(grid[i+x][j+y],i+x,j+y))
                    grid[i+x][j+y]=0

        max_val=l[0]
        for i in range(1,len(l)):
            max_val=max(max_val,l[i])
            l[i]=max_val
        ans=[]
        for q in queries:
            idx=bisect_left(l,q)
            ans.append(idx)
        return ans
        '''

Weekly Contest/Weekly Contest 323/4_Maximum Number of Points From Grid Queries.py


"""
A simple script to log changes in a folder using watchdog library
Default path = script location, stop run = keyboard interrupt
"""

import time

from watchdog.events import PatternMatchingEventHandler
from watchdog.observers import Observer

def main():
    try:
        my_observer = Observer()
        my_observer.schedule(my_event_handler, path, recursive=go_recursively)
        my_observer.start()
        try:
            while True:
                time.sleep(1)
        except KeyboardInterrupt:
            my_observer.stop()
            my_observer.join()
    except ValueError:
        pass

def on_created(event):
    print(f"- {event.src_path} has been created!")

def on_deleted(event):
    print(f" - someone deleted {event.src_path}!")

def on_modified(event):
    print(f"- {event.src_path} has been modified")

def on_moved(event):
    print(f"- someone moved {event.src_path} to {event.dest_path}")

if __name__ == "__main__":
    patterns = "*"
    ignore_patterns = ""
    ignore_directories = False
    case_sensitive = True
    my_event_handler = PatternMatchingEventHandler(patterns, ignore_patterns, ignore_directories, case_sensitive)
    my_event_handler.on_created = on_created
    my_event_handler.on_deleted = on_deleted
    my_event_handler.on_modified = on_modified
    my_event_handler.on_moved = on_moved
    path = "."
    go_recursively = True
    main()


from dataclasses import dataclass, field
import enum
import math
import random
from typing import List, Optional, Union, Iterable, TypeVar, Dict

from aidoodle.core import Engine, Game, Move, Player

C = math.sqrt(2)  # from literature
EPS = 1e-12  # for numerical stability
VERBOSE = 0
MAX_DEPTH = 10000

Numeric = Union[float, int]
T = TypeVar('T')

@dataclass
class Edge:
    move: Move
    w: float = 0.0
    s: int = 0

    def __repr__(self) -> str:
        return f"Edge({self.move}, w={self.w}, s={self.s})"

@dataclass
class Node:
    game: Game
    edges: List[Edge] = field(default_factory=list)

    def __repr__(self) -> str:
        g = str(hash(self.game) % 1000) + '..'
        return f"Node(n_children={len(self.edges)}, game={g})"

    def __hash__(self) -> int:
        return hash(self.game)

_Players = List[Player]
_Edges = List[Edge]
_Nodes = List[Node]
Cache = Dict[Game, Node]
MaybeNode = Optional[Node]

class Strategy(enum.Enum):
    random = 0
    ucb1 = 1

def _selectmax(keys: Iterable[T], vals: Iterable[Numeric]) -> T:
    return max(zip(keys, vals), key=lambda tup: tup[1])[0]

def _ucb1_values(edges: _Edges, c: float = C) -> List[float]:
    s_tot = sum(edge.s for edge in edges)
    const = c * math.log(s_tot + 1)
    vals = [e.w / (e.s + EPS) + const / math.sqrt(e.s + EPS) for e in edges]
    return vals

def select_ucb1(edges: _Edges, c: float = C) -> Edge:
    vals = _ucb1_values(edges=edges, c=c)
    edge = _selectmax(edges, vals)
    return edge

def select(edges: _Edges, strategy: Strategy = Strategy.ucb1) -> Edge:
    if strategy == Strategy.random:
        return random.choice(edges)
    if strategy == Strategy.ucb1:
        return select_ucb1(edges)
    raise ValueError("Unknown strategy")

def choose_edge(edges: _Edges) -> Edge:
    edge = _selectmax(edges, (e.s for e in edges))
    if VERBOSE:
        print(f"Number of visits: {edge.s}, wins: {100*edge.w/edge.s:.1f}%")
    return edge

def expand(node: Node, engine: Engine) -> None:
    # Careful: if a move is the identity move, there will be an
    # infinite recursion
    moves: List[Move] = engine.get_legal_moves(node.game)
    edges = [Edge(move) for move in moves]
    assert not node.edges
    node.edges = edges

def simulate(game: Game, engine: Engine) -> float:
    # init a game with random players
    game = engine.init_game(
        board=game.board,
        player_idx=game.player_idx,
    )

    if VERBOSE:
        print("-" * 40)
        print(game.board)

    while not game.winner:
        # by default uses random play
        move = random.choice(engine.get_legal_moves(game))
        game = engine.make_move(game=game, move=move)

    if VERBOSE:
        print(game.board, end=' ')
        print(game.winner)

    score: float = engine.game_score(game)
    return score

def _update_edge(edge: Edge, value: float) -> None:
    edge.s += 1
    edge.w += value

COUNTER = 0
def update(edges: _Edges, players: _Players, value: float) -> None:
    value_other = 1 - value
    for edge, player in zip(edges, players):
        if player == 1:
            _update_edge(edge=edge, value=value)
        elif player == 2:
            _update_edge(edge=edge, value=value_other)

def _retrieve_node(game: Game, cache: Cache) -> Node:
    maybe_node: MaybeNode = cache.get(game)
    if maybe_node is not None:
        return maybe_node

    node = Node(game=game)
    cache[game] = node
    return node

def search_iteration(
        node: Node,
        engine: Engine,
        cache: Cache,
        strategy: Strategy = Strategy.ucb1,
) -> None:
    cache[node.game] = node
    edges: _Edges = []
    players: _Players = []

    # selection
    while node.edges:
        edge = select(node.edges, strategy=strategy)
        edges.append(edge)
        players.append(node.game.player)
        game = engine.make_move(game=node.game, move=edge.move)
        node = _retrieve_node(game=game, cache=cache)  # updates cache if necessary

        if len(edges) > MAX_DEPTH:
            raise RuntimeError(f"Max depth of {MAX_DEPTH} in tree search encountered, "
                               "are there cycles in the game tree?")

    # expansion
    expand(node, engine=engine)

    if node.edges:  # game end not reached
        # -> choose random move
        edge = random.choice(node.edges)
        game = engine.make_move(game=node.game, move=edge.move)
        edges.append(edge)
        players.append(game.player)
    else:  # end state reached
        game = node.game

    # simulate
    value = simulate(game, engine=engine)

    # update
    update(edges, players=players, value=value)


"""
A module with some scripts for automatic documentation generation

By Ian Bell, NIST, 2016-
"""

from __future__ import print_function
from io import StringIO
import glob, os, json, six, sys, textwrap, time

name_remapping = {'CCRIT':'CSTAR',
                  'SATPEST':None,
                  'SATTEST':None}

fallback_arguments = {'GERG04dll': 'GERG08', 'THERM2dll': ['THERMdll','THERM3dll','AG','DERVPVTdll']}

FLSH_funcs = [k+'FLSHdll' for k in ['DE','DH','DS','ES','HS','PD','PE','PH','PQ','PS','TD','TE','TH','TP','TQ','TS','DQ']]
FLSH_funcs += [k+'FL1dll' for k in ['DE','DH','DS','ES','HS','PD','PE','PH','PQ','PS','TD','TE','TH','TP','TQ','TS','DQ']]
FLSH_funcs += [k+'FL2dll' for k in ['DE','DH','DS','ES','HS','PD','PE','PH','PQ','PS','TD','TE','TH','TP','TQ','TS','DQ']]
FLSH_funcs += ['ENTHALdll','ENTROdll','CVCPdll']

FLSH_other_input_args = ['Z','DMIN','DMAX']
FLSH_args = {
    'P': 'Pressure [kPa]',
    'Q': 'Vapor quality [mol/mol]',
    'T': 'Temperature [K]',
    'E': 'Internal energy [J/mol]',
    'H': 'Enthalpy [J/mol]',
    'S': 'Entropy [J/mol-K]',
    'D': 'Density [mol/L]',
    'DL': 'Molar density of the liquid phase [mol/L]',
    'DV': 'Molar density of the vapor phase [mol/L]',
    'CV': 'Isochoric heat capacity [J/mol-K]',
    'CP': 'Isobaric heat capacity [J/mol-K]',
    'W': 'Speed of sound [m/s]',
    'HJT': 'Isenthalpic Joule-Thomson coefficient [K/kPa]',
    'HERR': 'Error string (character*255)',
    'IERR': 'Error code (no error if ierr==0)',
    'Z': 'Bulk Composition (array of mole fractions)',
    'X': 'Composition of the liquid phase (array of mole fractions)',
    'Y': 'Composition of the vapor phase (array of mole fractions)',
    'DMIN': 'Lower bound on density [mol/L]',
    'DMAX': 'Upper bound on density [mol/L]'
}

High_Level_Header = """

.. This file was auto-generated on {datetime:s}. DO NOT(!!!!) modify this file directly.  Modify the generator script in the scripts folder.

.. _high_level_api:

**************
High-Level API
**************

"""

Legacy_Header = """

.. This file was auto-generated on {datetime:s}. DO NOT(!!!!) modify this file directly.  Modify the generator script in the scripts folder.

**********
Legacy API
**********

.. warning::

    The functions in this legacy application program interface (API) have all been deprecated and will be removed in some future release.  Please use the :ref:`high_level_api`:

"""

High_level_functions = ['REFPROPdll','REFPROP1dll','REFPROP2dll','ALLPROPSdll','ALLPROPS0dll','ALLPROPS1dll','ABFLSHdll','GETENUMdll','ERRMSGdll','SETFLUIDSdll','SETMIXTUREdll','SETPATHdll','FLAGSdll']

def generate_manual_content(FOR_path, JSON_ofname = None):
    """
    Generate a dictionary mapping from function name to documentation

    FOR_path: string
        Path to the folder containing the .FOR files
    JSON_ofname: string, optional
        If provided, the file to which the content will be written in JSON format
    """

    # Get all the fortran files
    for_files = []
    for ending in ['*.FOR','*.for']:
        for_files += glob.glob(os.path.join(FOR_path, ending))
    assert(len(for_files) > 0)

    # Join all the files into one big string
    joined = ''
    for for_file in for_files:
        with open(for_file,'r') as fp:
            joined += fp.read() + '\n'

    # Munge function arguments as needed to replace arguments that span lines
    isubstart = 0
    while isubstart > -1:
        isubstart = joined.find('subroutine',isubstart)

        isubopen = joined.find('(', isubstart)
        isubclose = joined.find(')', isubopen)
        iEOL = joined.find('\n', isubstart)

        # Skip ones with newline between end of subroutine and (
        if iEOL < isubopen:
            isubstart += 1 # go to next instance of subroutine
            continue

        # Skip ones that are in the comments block
        ipreEOL = joined.rfind('\n', 0, isubstart) # Find preceding EOL

        if joined[ipreEOL+1:ipreEOL+3].startswith('c '):
            isubstart = isubclose
            continue

        if '\n' in joined[isubstart:isubclose+1]:
            old = joined[isubstart:isubclose+1]
            new = old.replace('\n','').replace('&','')
            joined = joined.replace(old, new)
            isubstart += 1
            continue

        isubstart = joined.find('subroutine',isubclose)
        if isubstart < 0:
            break

    ####### Uncomment next lines to see what it did
    with open('joined.txt','w') as fp:
        fp.write(joined)

    objects = {}

    lines = joined.split('\n')
    for i in range(len(lines)):

        if lines[i].strip().startswith('subroutine') or lines[i].strip().startswith('function'):

            objname = lines[i].split('(')[0].replace('subroutine ','').replace('function ','').strip()
            objlines = []
            for j in range(10000):
                if i+j == len(lines): break
                if "ritten by" in lines[i+j] or 'original version' in lines[i+j]:
                    break
                elif ' include \'' in lines[i+j] and not lines[i+j].strip().startswith('c '):
                    break
                elif lines[i+j] == ' ':
                    break
                else:
                    objlines.append(lines[i+j])

            objects[objname] = '\n'.join(objlines)

            i += j

    if JSON_ofname:
        with open(JSON_ofname,'w') as fp:
            json.dump(objects, fp, indent =2)
    return objects

def deconstruct_function_info(contents):

    def line_decomment(line):
        if line == 'c': return ''
        if line.startswith('c '):
            return line[1::]
        else:
            return line.strip()

    def line_startswith(s, search, EOL = None):
        o = None
        for iline, line in enumerate(s):
            decomm = line_decomment(line).lstrip()
            if EOL is not None:
                if decomm.startswith(search) and decomm.strip().endswith(EOL):
                    return iline
            else:
                if decomm.startswith(search):
                    return iline
        return o

    def line_containing(s, search):
        o = None
        for iline, line in enumerate(s):
            if search in line:
                return iline
        return o

    def deconstruct_parameters(lines):
        # Find the lines that have '--' in them, and add another at the end
        seps = [iline for iline, line in enumerate(lines) if '--' in line] + [len(lines)]
        args, flags = {}, {}
        # Get all the arguments
        for j in range(len(seps)-1):
            istart,iend = seps[j],seps[j+1]
            # Get the argument based on the first line
            try:
                arg, desc = line_decomment(lines[istart]).strip().split('--')
                if ':' in desc:
                    desc = desc.split(':')[0]
            except ValueError as VE:
                print(line_decomment(lines[istart]).strip())

            # If the line has a ': in it, then the stuff that follows is a list of flags, otherwise, the following lines are glommed together
            if ':' in line_decomment(lines[istart]).strip():
                otherlines = [lines[istart].split(':')[1]] + lines[istart+1:iend]
                if otherlines and iend > istart+1:
                    if len(otherlines) == 1 and not line_decomment(otherlines[0]).strip():
                        # Empty line, don't do anything
                        continue
                    else:
                        lastkey = None
                        info = {}
                        for line in otherlines:
                            cleaned = line_decomment(line).strip()
                            if ' - ' not in cleaned:
                                # if lastkey is None:
                                #     print(lines, info, line)
                                print(lastkey, info, cleaned)
                                if cleaned:
                                    info[lastkey] += ' ' + cleaned
                                # else:
                                #     print('BAD!!!: ', cleaned, '<--', line)
                            else:
                                k,v = cleaned.split(' - ',1)
                                info[k.strip()] = v.strip()
                                lastkey = k.strip()
                        flags[arg.strip().lower()] = info
            else:
                # Keep on glomming the rest in, with spaces between lines
                otherlines = lines[istart+1:iend]
                desc += ' '+ ' '.join([line_decomment(l).strip() for l in otherlines])

            args[arg.strip().lower()] = desc
            # print('OOOOOOOOOOOOOOOOO', lines[istart-1], '||', otherlines, info)
        return args, flags

    # Find the line that contains "Input" and "Output"
    iInputs = line_startswith(contents, 'Input', EOL=':') or line_startswith(contents, 'Inputs', EOL=':')
    iOutput = line_startswith(contents, 'Output', EOL=':') or line_startswith(contents, 'Outputs', EOL=':')

    print(iInputs, iOutput)

    class struct(object): pass
    info = struct()
    info.doc_block = '\n\n'+ ' '*4+'XXXXXXXXXXXXXXXXXXXX  CANNOT GET DOCS\n\n'
    info.in_args, info.in_flags = {},{}
    info.out_args, info.out_flags = {},{}
    def indent(lines, n):
        return '\n'.join([' '*n + l for l in lines])

    if iInputs is None and iOutput is None:
        info.doc_block = indent(textwrap.dedent('\n'.join([line_decomment(line) for line in contents[1::]])).split('\n'), 4)

    if iInputs is not None or iOutput is not None:
        iMax = iInputs if iInputs is not None else iOutput
        info.doc_block = indent(textwrap.dedent('\n'.join([line_decomment(line) for line in contents[1:iMax]])).split('\n'), 4)

        if iInputs is not None:
            if iOutput is not None:
                info.in_args, info.in_flags = deconstruct_parameters(contents[iInputs+1:iOutput])
            else:
                info.in_args, info.in_flags = deconstruct_parameters(contents[iInputs+1::])
        if iOutput is not None:
            info.out_args, info.out_flags = deconstruct_parameters(contents[iOutput+1::])
    # print(info.in_args)
    return info

def parse_manual_contents(contents, function_dict, dll_functions):
    """
    Write the RST data needed by the sphinx-fortran package
    """
    def chop_dll(s):
        if s.endswith('dll'):
            return s[0:-3]
        else:
            return s
    # Functions that end with dll in the PASS_FTN.FOR file
    has_dll = [funcname for funcname, lines in six.iteritems(contents) if funcname.endswith('dll')]
    #
    missing = [chop_dll(func) for func in has_dll if chop_dll(func) not in contents]

    sout_high, sout_legacy = '', ''
    funcs_legacy = 'Function Listing\n----------------\n\n'
    funcs_high = 'Function Listing\n----------------\n\n'
    print(sorted(set(has_dll)))
    for func in sorted(set(has_dll)):
        print('XXXXXXXXXX', func, chop_dll(func))

        # Get remapped name, or the same dll-stripped name back again otherwise
        func = name_remapping.get(chop_dll(func), chop_dll(func))
        if func is None:
            print('skipping deprecated function:', func)
            continue

        # Format the output
        something_outputted = False

        # Skip missing functions
        if func in missing:
            print('skipping missing function:', func)
            continue

        info = deconstruct_function_info(contents[func].split('\n'))
        print(func, info.__dict__)

        args_string = ''
        if func+'dll' in function_dict:
            args = function_dict[func+'dll']['argument_list']
            for arg in args:
                # arg is (name, type, length) or (name, type)
                docs = None
                inout = ''
                argname = arg[0].lower()
                # Nasty workaround...
                if argname == 'hunitsarray' and func+'dll' == 'ALLPROPSdll':
                    argname = 'hUnits'
                    docs = "String with units. Will also contain error messages when necessary. The string will be empty if iFlag=0."
                    inout = '[out]'
                else:
                    if argname in info.in_args:
                        inout = ' [in]'
                        docs = info.in_args[argname]
                    if argname in info.out_args:
                        inout = ' [out]'
                        docs = info.out_args[argname]
                    if docs is None:
                        badx = 'XXXXXXXXXX'
                        docs = badx
                        if func+'dll' in fallback_arguments:
                            # Get docs from fallback(s)
                            fb_names = fallback_arguments[func+'dll']
                            if not isinstance(fb_names, list):
                                fb_names = [fb_names]

                            for fb_name in fb_names:
                                fallinfo = deconstruct_function_info(contents[fb_name].split('\n'))

                                if argname in fallinfo.in_args:
                                    inout = ' [in]'
                                    docs = fallinfo.in_args[argname]
                                if argname in fallinfo.out_args:
                                    inout = ' [out]'
                                    docs = fallinfo.out_args[argname]

                                if docs != badx:
                                    break

                                # print(func, argname, docs, fallinfo.in_args)

                        elif func+'dll' in FLSH_funcs:
                            if argname.upper() in FLSH_args:
                                docs = FLSH_args[argname.upper()]
                                if argname.upper() in func[0:2] or argname.upper() in FLSH_other_input_args:
                                    inout = ' [in]'
                                else:
                                    inout = ' [out]'

                        # print(func, argname, docs, fallinfo.in_args)

                size = ''
                if len(arg) == 3 and int(arg[2]) > 0:
                    size = '(' + str(arg[2]) + ')'
                # print(argname)

                name = arg[0].strip()
                if arg[0] == 'hUnitsArray' and func+'dll' == 'ALLPROPSdll':
                    name = 'hUnits'
                args_string += ' '*4 + ':p {type:s} {name:s}{size:s}{inout:s}: {docs:s}\n'.format(name = name, type = arg[1].strip('*').strip(), size =size, inout = inout, docs= docs)

            if dll_functions:
                for arg in function_dict[func+'dll']['string_arguments']:
                    args_string += ' '*4 + ':p int ' + arg[0] + ': length of variable ``' + arg[0].replace('_length','') + '`` (default: '+str(arg[1])+')\n'
        else:
            print('Cannot find function arguments for:', func+'dll')
            continue

        flags_string = ''
        if info.in_flags or info.out_flags:
            flags_string = ' '*4 + ':Flags: \n\n'
            #if info.out_flags: raise ValueError('IMPOSSIBLE:'+str(info.out_flags))
            def spit_out_flags(flags):
                s = ''
                for flag,data in six.iteritems(flags):
                    s += ' '*8 + '``' + flag + '`` flags\n\n'
                    for k,v in six.iteritems(data):
                        s += ' '*8 + ':' + k + ': ' + v + '\n'
                    s += '\n'
                return s

            flags_string += spit_out_flags(info.in_flags)
            flags_string += spit_out_flags(info.out_flags)

        sout = ''
        # This is the definition of the function prototype
        theargs = ', '.join([a[0] if not (func+'dll'=='ALLPROPSdll' and a[0] == 'hUnitsArray') else 'hUnits' for a in function_dict[func+'dll']['argument_list']])
        # Add on the arguments at the end with the string lengths if you are documenting the DLL
        if dll_functions:
            theargs += ', ' + ', '.join([a[0] for a in function_dict[func+'dll']['string_arguments']])
        sout += '.. f:subroutine:: {func:s} ({args:s})\n\n'.format(func=func+'dll', args = theargs)

        # The block of documentation
        sout += info.doc_block#.replace('*','\*')

        # The list of arguments to the function
        sout += '\n' + args_string + '\n'

        # The list of flags to the function
        sout += '\n' + flags_string + '\n'

        if func+'dll' in High_level_functions:
            sout_high += sout
            funcs_high += '- :f:func:`' + func+'dll' + '`\n'
        else:
            sout_legacy += sout
            funcs_legacy += '- :f:func:`' + func+'dll' + '`\n'

    funcs_high += '\n\nFunction Documentation\n----------------------\n'
    funcs_legacy += '\n\nFunction Documentation\n----------------------\n'

    return (High_Level_Header.format(datetime=time.strftime("%d %b %Y %H:%M:%S", time.localtime())) + funcs_high + sout_high,
           Legacy_Header.format(datetime=time.strftime("%d %b %Y %H:%M:%S", time.localtime())) + funcs_legacy + sout_legacy)

if __name__=='__main__':
    # This path is hardcoded, change as needed
    FOR_path = 'FORTRAN'

    # Use the script in REFPROP-headers repo to generate a dictionary of function parameter data
    # from the functions defined in the PASS_FTN.FOR file
    # ------------------------------------------------------------------------------------------
    sys.path.append('../externals/REFPROP-headers')
    import generate_header
    generate_header.generate_interface_file(os.path.join(FOR_path,'PASS_FTN.FOR'), 'REFPROP.pyf')
    function_dict = generate_header.generate_function_dict('REFPROP.pyf')
    # Write to file for debugging if desired/needed:
    with open('functions.json','w') as fp: fp.write(json.dumps(function_dict, indent =2))

    # Parse the .FOR files and extract docs; write to joined.json file
    # ----------------------------------------------------------------
    objects = generate_manual_content(FOR_path, JSON_ofname = 'joined.json')

    # print(objects['ALLPROPS0'])
    # print(deconstruct_function_info(objects['ALLPROPS0'].split('\n')).__dict__)
    # sys.exit()

    # Generate the RST string
    # -----------------------
    rst_high, rst_legacy = parse_manual_contents(objects, function_dict, True)

    # Write RST bits to file
    # ----------------------
    docs_path = os.path.join('sphinx')
    for fname, rst in [('high_level.rst',rst_high),('legacy.rst',rst_legacy)]:
        rst_file = os.path.join(docs_path, fname)
        with open(rst_file, 'w') as fp:
            fp.write(rst)
        this_dir = os.path.dirname(__file__)
        with open(os.path.join(this_dir, '..', 'doc', 'DLL', fname), 'w') as fp:
            fp.write(rst)

    import subprocess
    for i in range(3):
        try:
            subprocess.check_call('activate py36 && make html', cwd='sphinx', shell = True, stdout = sys.stdout, stderr = sys.stderr)
            break
        except:
            continue
    for i in range(3):
        try:
            subprocess.call('activate py36 && make latex', cwd='sphinx', shell = True, stdout = sys.stdout, stderr = sys.stderr)
            break
        except:
            continue
    for i in range(3):
        subprocess.call('pdflatex REFPROP.tex', cwd='sphinx/_build/latex', shell = True, stdout = sys.stdout, stderr = sys.stderr)


from flask import Blueprint, render_template, request, flash, jsonify, redirect
from flask_login import login_required, current_user
from .models import Upload
import os
from . import db
import json
import paramiko
import time
#from .tasks import send_and_process_fastq

host = 'calc.cod.phystech.edu'
secret = 'Gq~#aCztH%6A}u'
username = 'kumondorova.a'
port = 22

views = Blueprint('views', __name__)

@views.route('/', methods=['GET', 'POST'])
@login_required
def home():
    if request.method == 'POST':
        uploaded_file = request.files['file_upload']
        if uploaded_file.filename != '':
            uploaded_file.save(f'./uploads/{uploaded_file.filename}')

            if 1==1:
                new_file = Upload(filename=uploaded_file.filename, user_id=current_user.id,status=0 )  #providing the schema for the note
                db.session.add(new_file) #adding the note to the database
                db.session.commit()
                flash('Файл загружен', category='success')

    return render_template("home.html", user=current_user)

@views.route('/send/<int:id>')
def send(id):
    file_to_cluster = Upload.query.get_or_404(id)
    dir = f"uploads/{file_to_cluster.filename}"
    abs_dir = os.path.abspath(dir)
    #send_and_process_fastq.apply_async(args = [host, username, secret, port, file_to_cluster], countdown=210)

    #flash(list(db.session.query(Upload).all()), category='success')
    #flash(list(db.session.query(Upload).filter(Upload.status == 0).all()),category='success')
    return redirect('/')

@views.route('/delete/<int:id>')
def delete(id):
    update_to_delete = Upload.query.get_or_404(id)

    try:
        db.session.delete(update_to_delete)
        db.session.commit()
        #update_to_delete.filename Дает имя файла с расширением
        return redirect('/')

    except:
        return "Возникла проблема в удалении загруженного файла"

@views.route('/ks.rsmu',methods=['GET', 'POST'] )
def find():

    return redirect('/')


import logging
import subprocess
import sys
from concurrent.futures import ThreadPoolExecutor
from os import listdir, path
from pathlib import Path
from typing import TYPE_CHECKING, List, Optional

from hummingbot.logger.struct_logger import StructLogger, StructLogRecord

if TYPE_CHECKING:
    from hummingbot.client.config.config_helpers import ClientConfigAdapter as _ClientConfigAdapter

STRUCT_LOGGER_SET = False
DEV_STRATEGY_PREFIX = "dev"
_prefix_path = None

# Do not raise exceptions during log handling
logging.setLogRecordFactory(StructLogRecord)
logging.setLoggerClass(StructLogger)

_shared_executor = None
_data_path = None
_cert_path = None

def root_path() -> Path:
    from os.path import join, realpath
    return Path(realpath(join(__file__, "../../")))

def get_executor() -> ThreadPoolExecutor:
    global _shared_executor
    if _shared_executor is None:
        _shared_executor = ThreadPoolExecutor()
    return _shared_executor

def prefix_path() -> str:
    global _prefix_path
    if _prefix_path is None:
        from os.path import join, realpath
        _prefix_path = realpath(join(__file__, "../../"))
    return _prefix_path

def set_prefix_path(p: str):
    global _prefix_path
    _prefix_path = p

def data_path() -> str:
    global _data_path
    if _data_path is None:
        from os.path import join, realpath
        _data_path = realpath(join(prefix_path(), "data"))

    import os
    if not os.path.exists(_data_path):
        os.makedirs(_data_path)
    return _data_path

def set_data_path(path: str):
    global _data_path
    _data_path = path

_independent_package: Optional[bool] = None

def is_independent_package() -> bool:
    global _independent_package
    import os
    if _independent_package is None:
        _independent_package = not os.path.basename(sys.executable).startswith("python")
    return _independent_package

def check_dev_mode():
    try:
        if is_independent_package():
            return False
        if not path.isdir(".git"):
            return False
        current_branch = subprocess.check_output(["git", "symbolic-ref", "--short", "HEAD"]).decode("utf8").rstrip()
        if current_branch != "master":
            return True
    except Exception:
        return False

def chdir_to_data_directory():
    if not is_independent_package():
        # Do nothing.
        return

    import os

    import appdirs
    app_data_dir: str = appdirs.user_data_dir("Hummingbot", "hummingbot.io")
    os.makedirs(os.path.join(app_data_dir, "logs"), 0o711, exist_ok=True)
    os.makedirs(os.path.join(app_data_dir, "conf"), 0o711, exist_ok=True)
    os.makedirs(os.path.join(app_data_dir, "pmm_scripts"), 0o711, exist_ok=True)
    os.makedirs(os.path.join(app_data_dir, "certs"), 0o711, exist_ok=True)
    os.makedirs(os.path.join(app_data_dir, "scripts"), 0o711, exist_ok=True)
    os.chdir(app_data_dir)
    set_prefix_path(app_data_dir)

def get_logging_conf(conf_filename: str = 'hummingbot_logs.yml'):
    import io
    from os.path import join
    from typing import Dict

    from ruamel.yaml import YAML

    file_path: str = join(prefix_path(), "conf", conf_filename)
    yaml_parser: YAML = YAML()
    if not path.exists(file_path):
        return {}
    with open(file_path) as fd:
        yml_source: str = fd.read()
        io_stream: io.StringIO = io.StringIO(yml_source)
        config_dict: Dict = yaml_parser.load(io_stream)
        return config_dict

def init_logging(conf_filename: str,
                 client_config_map: "_ClientConfigAdapter",
                 override_log_level: Optional[str] = None,
                 strategy_file_path: str = "hummingbot"):
    import io
    import logging.config
    from os.path import join
    from typing import Dict

    import pandas as pd
    from ruamel.yaml import YAML

    from hummingbot.logger.struct_logger import StructLogger, StructLogRecord
    global STRUCT_LOGGER_SET
    if not STRUCT_LOGGER_SET:
        logging.setLogRecordFactory(StructLogRecord)
        logging.setLoggerClass(StructLogger)
        STRUCT_LOGGER_SET = True

    # Do not raise exceptions during log handling
    logging.raiseExceptions = False

    file_path: str = join(prefix_path(), "conf", conf_filename)
    yaml_parser: YAML = YAML()
    with open(file_path) as fd:
        yml_source: str = fd.read()
        yml_source = yml_source.replace("$PROJECT_DIR", prefix_path())
        yml_source = yml_source.replace("$DATETIME", pd.Timestamp.now().strftime("%Y-%m-%d-%H-%M-%S"))
        yml_source = yml_source.replace("$STRATEGY_FILE_PATH", strategy_file_path.replace(".yml", ""))
        io_stream: io.StringIO = io.StringIO(yml_source)
        config_dict: Dict = yaml_parser.load(io_stream)
        if override_log_level is not None and "loggers" in config_dict:
            for logger in config_dict["loggers"]:
                if logger in client_config_map.logger_override_whitelist:
                    config_dict["loggers"][logger]["level"] = override_log_level
        logging.config.dictConfig(config_dict)

def get_strategy_list() -> List[str]:
    """
    Search `hummingbot.strategy` folder for all available strategies
    Automatically hide all strategies that starts with "dev" if on master branch
    """
    try:
        folder = path.realpath(path.join(__file__, "../strategy"))
        # Only include valid directories
        strategies = [d for d in listdir(folder) if path.isdir(path.join(folder, d)) and not d.startswith("__")]
        on_dev_mode = check_dev_mode()
        if not on_dev_mode:
            strategies = [s for s in strategies if not s.startswith(DEV_STRATEGY_PREFIX)]
        return sorted(strategies)
    except Exception as e:
        logging.getLogger().warning(f"Error getting strategy set: {str(e)}")
        return []


import tensorflow as tf
from nltk.translate.bleu_score import sentence_bleu, SmoothingFunction
# https://www.nltk.org/_modules/nltk/translate/bleu_score.html

def bleu_eval(test_data, encoder, decoder, batch_size, idx2word_output):
    bleu_scores = []

    for batch, data in enumerate(test_data):
        encoder_in, decoder_in, decoder_out = data

        encoder_state = encoder.init_state(batch_size)
        encoder_out, encoder_state = encoder(encoder_in, encoder_state)
        decoder_state = encoder_state
        decoder_pred, encoder_state = decoder(decoder_in, decoder_state)

        decoder_out = decoder_out.numpy()
        decoder_pred = tf.argmax(decoder_pred, axis=-1).numpy()

        # decoder_out.shape  = 10000, 10 (num_samples, seq_len)
        # for each sentence in decoder_out
        for i in range(decoder_out.shape[0]):
            decoder_output_list = decoder_out[i].tolist()
            correct_sentences = [idx2word_output[word] for word in decoder_output_list if word != 0][:-1]
            decoder_prediction_list = decoder_pred[i].tolist()
            predicted_sentences = [idx2word_output[word] for word in decoder_prediction_list if word != 0]
            predicted_sentences = [word for word in predicted_sentences if word != "<eos>"]

            smoothing = SmoothingFunction()
            bleu = sentence_bleu([correct_sentences], predicted_sentences, smoothing_function=smoothing.method1)
            bleu_scores.append(bleu)

    final_bleu = sum(bleu_scores) / len(bleu_scores)
    print("Bleu score: {:.4f}".format(final_bleu))
    return final_bleu

def compute_bleu_LSTM(test_data, encoder, decoder, batch_size, idx2word_output):
    bleu_scores = []
    smoothing = SmoothingFunction()

    for batch, data in enumerate(test_data):

        encoder_in, decoder_in, decoder_out = data
        encoder_state = encoder.init_state(batch_size)
        encoder_out, enc_h, enc_c = encoder(encoder_in, encoder_state)
        decoder_state = [enc_h, enc_c]
        decoder_pred, dec_h, dec_c = decoder(decoder_in, decoder_state)

        # get the tensor with predictions(decoder_pred) and correct sentences(deocder_out)
        # decoder pred.shape = batch_size, seq_len, words, get the best prediction for axis words : -1
        # convert to numpy
        decoder_pred = tf.argmax(decoder_pred, axis=-1).numpy()
        # decoder_out is (batch_size, seq_len) , just convert it to numpy
        decoder_out = decoder_out.numpy()
        num_sentences = decoder_out.shape[0]
        # convert each tensor to list
        decoder_pred = decoder_pred.tolist()
        decoder_out = decoder_out.tolist()
        # go through all sentences in the batch
        for i in range(num_sentences):

            predicted_sentences = [idx2word_output[word] for word in decoder_pred[i] if word != 0]
            expected_sentences = [idx2word_output[word] for word in decoder_out[i] if word != 0][:-1]
            predicted_sentences = [word for word in predicted_sentences if word != "<eos>"]

            bleu = sentence_bleu([expected_sentences], predicted_sentences, smoothing_function=smoothing.method1)
            bleu_scores.append(bleu)

    final_bleu = sum(bleu_scores) / len(bleu_scores)
    print("Bleu score: {:.4f}".format(final_bleu))
    return final_bleu


from utils.utils import calculate_rectangles, get_room_dims, get_security_dist, get_table_dims
from utils.draw_utils import create_diagram
from rectpack import newPacker

def run(room_size_split, security_distance, table_sizes, draw=True):
    for room_size in room_size_split:
        _opt_room_size = [dim + security_distance for dim in room_size]
        rectangles = calculate_rectangles(_opt_room_size, security_distance, table_sizes)
        packer = newPacker()
        for r in rectangles:
            packer.add_rect(*r)
        packer.add_bin(*_opt_room_size)
        packer.pack()
        if draw:
            create_diagram(packer[0], security_distance, room_size, 'diagram'+str(room_size))
        else:
            for box in packer[0]:
                print(box)

if __name__=='__main__':
    print('Welcome to the restaurant optimiser!')
    print('Hope this can help you! Remember all units are in m.')

    restaurant_list = []
    i = 1
    while True:
        restaurant_list.append(get_room_dims(i))
        _continue = input('Are there any more spaces?(n/y): ')
        _continue = _continue or 'n'
        i += 1
        if _continue=='n':
            break
    security = get_security_dist()

    table_list = []
    while True:
        table_list.append(get_table_dims())
        _continue = input('Are there any more table sizes?(n/y): ')
        _continue = _continue or 'n'
        if _continue=='n':
            break
    _draw = input('Do you want to save the outcome as png images?(y/n): ')
    _draw = _draw or 'y'

    if _draw=='y':
        draw = True
        print('We are gonna save it in your current location.')
    elif _draw=='n':
        draw = False
        print('Here is your result!')
    run(restaurant_list, float(security), table_list, draw)


# -*- coding: utf-8 -*-

import io
import xlsxwriter
import base64

from odoo import models, fields, api, _

class PartnerLedgerWizard(models.TransientModel):
    _name = "tax.return.report"
    _description = "Tax return report"

    start_date = fields.Date(string="Start Date",required=True)
    end_date = fields.Date(string="End Date",required=True)
    report_type = fields.Selection([
        ('excel', 'Excel'),
        ('pdf', 'PDF'),
    ], string="Report Type", required=True,default='excel')

    def get_taxed_lines(self):
        query = """
            select sml.price_subtotal,sml.l10n_gcc_invoice_tax_amount,sml.price_total,sml.partner_id,sml.move_name ,
                 sml.name,sml.date,sml.id from
                account_move sm inner join account_move_line sml on sm.id = sml.move_id INNER JOIN
                account_move_line_account_tax_rel AS move_tax ON sml.id = move_tax.account_move_line_id inner join
                account_tax tax on move_tax.account_tax_id = tax.id
                AND sm.date > %s
                AND sm.date <= %s
        """
        self.env.cr.execute(query, (self.start_date, self.end_date))
        return self._cr.fetchall()

    def get_report(self):
        result = self.get_taxed_lines()
        if self.report_type == 'excel':
            output = io.BytesIO()
            workbook = xlsxwriter.Workbook(output, {'in_memory': True})
            sheet = workbook.add_worksheet()
            head = workbook.add_format({'align': 'center', 'bold': True, 'font_size': 10})
            title_style = workbook.add_format(
            {'font_name': 'Arial', 'bold': True,'bg_color': 'white','font_size': 10, 'font_color': 'black',
             'align': 'left', 'border': False})
            title_style2 = workbook.add_format(
            {'font_name': 'Arial', 'bold': True,'bg_color': 'white','font_size': 10, 'font_color': 'black',
             'align': 'center','bottom': 30, 'border': False})
            title_style3 = workbook.add_format(
            {'font_name': 'Arial', 'bold': True,'bg_color': 'white','font_size': 10, 'font_color': 'black',
             'align': 'right','bottom': 30, 'border': False})
            title_style4 = workbook.add_format(
            {'font_name': 'Arial','font_size': 14, 'font_color': 'black',
             'align': 'center','bottom': 30, 'color': 'red','border':2, 'valign': 'vcenter', 'text_wrap': True})
            title_style4.set_border_color('black')
            table_header = workbook.add_format(
            {'font_name': 'Arial','font_size': 12, 'bold':10,
             'align': 'center','font_color': '#3b5a90','border':0, 'valign': 'vcenter','bg_color': 'white'})
            table_content = workbook.add_format(
            {'font_name': 'Arial','font_size': 10, 'font_color': 'black','bold':10,
             'align': 'center','color': 'black','border':0, 'valign': 'vcenter','bg_color': 'white'})
            table_content.set_num_format('#,##0.00')
            sequence_format = workbook.add_format(
            {'font_name': 'Arial','font_size': 10, 'font_color': 'black','bold':10,
             'align': 'center','color': 'black','border':0, 'valign': 'vcenter','bg_color': 'white'})
            table_header2 = workbook.add_format(
            {'font_name': 'Arial','font_size': 12, 'bold':10,
             'align': 'right','font_color': '#3b5a90','border':0, 'valign': 'vcenter','bg_color': 'white'})
            report_title = 'Snabel al-meshaan'
            y = 0
            x = 0
            sheet.set_row(y,20)
            sheet.merge_range('A1:E1', report_title, title_style)
            y+=1
            sheet.set_row(y,20)
            sheet.merge_range('A2:E2', 'ksa-Hail -saptco', title_style)
            y+=1
            sheet.set_row(y,20)
            sheet.merge_range('A3:E3', 'L:3353001291 TEL:065310101', title_style)
            sheet.merge_range('A4:E8', '', title_style)
            sheet.merge_range('Q1:Z99', '', title_style)
            company_image = io.BytesIO(base64.b64decode(self.env.company.logo))
            sheet.merge_range('F1:K7', '', title_style)

            sheet.insert_image('H1', self.env.company.logo, {'image_data': company_image, 'x_scale': 0.6, 'y_scale': 0.4})
            sheet.merge_range('L1:P1', 'مجموعة سنابل المشعان', title_style3)
            sheet.merge_range('L2:P2', 'السعودية-حائل - النقل الجماعي', title_style3)
            sheet.merge_range('L3:P3', 'س.ت:3353001291 ت:065310101', title_style3)
            sheet.merge_range('L4:P8', '', title_style)
            # sheet.merge_range('F8:K8', '', title_style)
            y=7
            sheet.set_row(y,40)
            sheet.merge_range('F8:K8', 'الاقرار الضريبي لضريبة القيمة المضافة تحليلي', title_style4)
            sheet.merge_range('A9:P10', '', title_style)
            y=10
            sheet.set_row(y,30)
            x=0
            sheet.merge_range(y, x,y,x+2,str(self.end_date), table_header)
            x+=3
            sheet.write(y, x, 'إلى', table_content)
            x+=3
            sheet.merge_range(y, x,y,x+2,str(self.start_date), table_header)
            x+=3
            sheet.write(y, x, 'من', table_content)
            x+=3
            sheet.merge_range('E11:F11', '', title_style)
            sheet.merge_range('K11:L11', '', title_style)
            sheet.merge_range('K11:O11', 'المشتريات الخاضعة للنسبة الاساسية', table_header2)
            sheet.write('P11', 'النوع', table_header2)
            y=11
            x=0
            sheet.set_row(y,30)
            sheet.set_column(x,x,5)
            sheet.set_column(1,1,5)
            sheet.set_column(2,2,5)
            sheet.merge_range(y, x,y,x+2, 'المبلغ بعد الضريبة', table_header)
            x+=3
            sheet.set_column(x,x,5)
            sheet.set_column(x+1,x+1,5)
            sheet.set_column(x+2,x+2,5)
            sheet.merge_range(y, x,y,x+2, 'الضريبة', table_header)
            x+=3
            sheet.set_column(x,x,5)
            sheet.set_column(x+1,x+1,5)
            sheet.merge_range(y, x,y,x+1, 'المبلغ قبل الضريبة', table_header)
            x+=2
            sheet.set_column(x,x,5)
            sheet.set_column(x+1,x+1,5)
            sheet.merge_range(y, x,y,x+1, 'ملف ضريبي', table_header)
            x+=2
            sheet.set_column(x,x,10)
            sheet.write(y, x, 'المورد / العميل', table_header)
            x+=1
            sheet.set_column(x,x,10)
            sheet.write(y, x, 'رقم الفاتورة', table_header)
            x+=1
            sheet.set_column(x,x,10)
            sheet.write(y, x, 'الشرح الخاص', table_header)
            x+=1
            sheet.set_column(x,x,10)
            sheet.write(y, x, 'القيد', table_header)
            x+=1
            sheet.set_column(x,x,10)
            sheet.write(y, x, 'تاريخ القيد', table_header)
            x+=1
            sheet.set_column(x,x,5)
            sheet.write(y, x, 'م', table_header)

            sequence=1
            for record in result:
                partner_id = self.env['res.partner'].search([('id','=',record[3])],limit=1)
                y+=1
                x=0
                sheet.set_row(y,25)
                sheet.merge_range(y, x,y,x+2, record[0], table_content)
                x+=3
                sheet.merge_range(y, x,y,x+2, record[1], table_content)
                x+=3
                sheet.merge_range(y, x,y,x+1, record[2], table_content)
                x+=2
                sheet.merge_range(y, x,y,x+1, partner_id.vat, table_content)
                x+=2
                sheet.write(y, x, partner_id.name, table_content)
                x+=1
                sheet.write(y, x,record[4], table_content)
                x+=1
                sheet.set_column(x,x,20)
                sheet.write(y, x,record[5], table_content)
                x+=1
                sheet.write(y, x,record[4], table_content)
                x+=1
                sheet.write(y, x,str(record[6]), table_content)
                x+=1
                sheet.write(y, x,sequence, sequence_format)
                x+=1

            workbook.close()
            file_download = base64.b64encode(output.getvalue())
            output.close()
            wizardmodel = self.env['wiz.excel.reports']
            res_id = wizardmodel.create({'name': 'Tax Return Report', 'file_download': file_download})
            return {
                    'name': 'Files to Download',
                    'view_type': 'form',
                    'view_mode': 'form',
                    'res_model': 'wiz.excel.reports',
                    'type': 'ir.actions.act_window',
                    'target': 'new',
                    'res_id': res_id.id,
                }
        else:
            data={
            'docs' : result,
            'start_date': self.start_date,
            'end_date': self.end_date
            }
            return self.env.ref('tax_return_report.tax_return_report_action').report_action(self, data)

class Wizexel(models.TransientModel):
    _name = 'wiz.excel.reports'

    name = fields.Char('File Name', size=256, readonly=True)
    file_download = fields.Binary('File to Download', readonly=True)


# -*- coding: utf-8 -*-
import os
os.chdir('D:\Kaggle\Shelter Animal Outcomes')
import pandas as pd
import numpy as np
from importlib import reload
import data_preprocessing as dp
import prepare_for_model as pfm
import other_functions as of
import explanatory_analysis as ea
import sklearn.linear_model as lr
from sklearn.metrics import log_loss, confusion_matrix
from sklearn import cross_validation as cv

reload(of)
reload(pfm)
reload(ea)
reload(dp)
data = pd.read_csv('train.csv')
dp.preprocess(data, is_prediction = False, path = 'values_to_keep')
data2 = pfm.prepare(data)
y = data.OutcomeType
timeInc = True
model_col = [c for c in data2.columns if not 'AnimalType_' in c \
            and (timeInc or (not 'Year_' in c and
                             not 'Month_' in c and
                             not 'Day_' in c and
                             not 'DayOfWeek_' in c and
                             not 'Hour_' in c)) ]
## prepare model for dogs ###########################################
X_train, X_test, y_train, y_test = cv.train_test_split(
    data2.loc[data2.AnimalType_Dog == 1,model_col],
    y[data2.AnimalType_Dog == 1],
    test_size=0.0, random_state=13)
# test of C parameters
Cs = np.power(10,np.linspace(-10, 3, 10))
scores = of.cv_and_plot(X_train,y_train,Cs,'plots' )
# test parameters closer to minimum
Cs_2 = np.linspace(0.03, 2, 10)
scores_2 = of.cv_and_plot(X_train,y_train,Cs_2,'plots' )
# fitting model to whole training dataset
model_dog = lr.LogisticRegression(penalty = 'l1', C = 0.25, n_jobs = 4)
model_dog.fit(X_train,y_train)
# validation model
test_pre = model_dog.predict(X_test)
test_pro = model_dog.predict_proba(X_test)
confusion_matrix(y_test, test_pre)
ld = log_loss(y_test,test_pro)
# plotting coefficients
coefs = pd.DataFrame(model_dog.coef_, columns = X_train.columns)
for c in data.columns:
    ea.plot(c,coefs, model_dog.classes_, 'results')

## prepare model for cats #############################################
# test of C parameters
X_train_cat, X_test_cat, y_train_cat, y_test_cat = cv.train_test_split(
    data2.loc[data2.AnimalType_Dog == 0,model_col],
    y[data2.AnimalType_Dog == 0],
    test_size=0, random_state=13)
# first test of parameters
Cs = np.power(10,np.linspace(-10, 3, 10))
scores = of.cv_and_plot(X_train_cat,y_train_cat,Cs,'plots' )
# second test of parameters
Cs_2 = np.linspace(0.05, 1, 10)
scores_2 = of.cv_and_plot(X_train_cat,y_train_cat,Cs_2,'plots' )

Cs_3 = np.linspace(0.10, 0.5, 10)
scores_3 = of.cv_and_plot(X_train_cat,y_train_cat,Cs_3,'plots')
# model
model_cat = lr.LogisticRegression(penalty = 'l1', C = 0.25, n_jobs = 4)
model_cat.fit(X_train_cat,y_train_cat)
# coefficients
coefs_cat = pd.DataFrame(model_cat.coef_, columns = X_train_cat.columns)
for c in data.columns:
    ea.plot(c,coefs_cat, model_cat.classes_, 'results_cat')

test_pre_cat = model_cat.predict(X_test_cat)
test_pro_cat = model_cat.predict_proba(X_test_cat)
confusion_matrix(y_test_cat, test_pre_cat)
lc = log_loss(y_test_cat,test_pro_cat)
(lc * y_test_cat.shape[0] + ld * y_test.shape[0])/(y_test_cat.shape[0] +  y_test.shape[0])

# kaggle test data
eval_data = pd.read_csv('test.csv')
dp.preprocess(eval_data, is_prediction = True, path = 'values_to_keep')
eval_data2 = pfm.prepare(eval_data, model_dummies_names = data2.columns)
eval_pro_dog = model_dog.predict_proba(eval_data2.loc[eval_data2.AnimalType_Dog == 1, model_col])
eval_pro_cat = model_cat.predict_proba(eval_data2.loc[eval_data2.AnimalType_Dog == 0, model_col])
eval_pro_dog = pd.DataFrame(eval_pro_dog, columns = model_dog.classes_)
eval_pro_cat = pd.DataFrame(eval_pro_cat, columns = model_cat.classes_)

eval_pro_dog.insert(0,'ID',eval_data.loc[eval_data2.AnimalType_Dog == 1, 'ID'].values)
eval_pro_cat.insert(0,'ID',eval_data.loc[eval_data2.AnimalType_Dog == 0, 'ID'].values)

result = pd.concat([eval_pro_dog, eval_pro_cat]).sort_values(by = 'ID')
result.to_csv('submission1.csv', index = False)


import pandas as pd
import requests
import time
import numpy as np

# see all columns in a wide DataFrame
pd.set_option('display.max_column', None)

# collecting data from url
nba_stats = 'https://stats.nba.com/stats/leagueLeaders?LeagueID=00&PerMode=PerGame&Scope=S&Season=2022-23&SeasonType=Regular%20Season&StatCategory=PTS'

r = requests.get(url=nba_stats).json()

# defining rows and headers and creating table
table_header = r['resultSet']['headers']
table_rows = r['resultSet']['rowSet']
pd.DataFrame(table_rows,columns=table_header)

df_cols = ['Year','Season_Type'] + table_header
df = pd.DataFrame(columns=df_cols)
season_type = ['Regular%20Season','Playoffs']
years = ['2022-23']#,'2011-12','2012-13','2013-14','2014-15','2015-16','2016-17','2017-18','2018-19','2019-20','2020-21','2021-22','2022-23']

headers = {
    'Accept': '*/*',
    'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'en-US,en;q=0.9',
    'Connection': 'keep-alive',
    'Host': 'stats.nba.com',
    'Origin': 'https://www.nba.com',
    'Referer': 'https://www.nba.com/',
    'Sec-Ch-Ua': '"Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"',
    'Sec-Ch-Ua-Mobile': '?0',
    'Sec-Ch-Ua-Platform': '"Windows"',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-site',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
}

begin_loop = time.time()

for y in years:
    for s in season_type:
        api_url = 'https://stats.nba.com/stats/leagueLeaders?LeagueID=00&PerMode=PerGame&Scope=S&Season='+y+'&SeasonType='+s+'&StatCategory=PTS'
        r = requests.get(url=api_url, headers=headers).json()
        temp_df1 = pd.DataFrame(table_rows,columns=table_header)
        temp_df2 = pd.DataFrame({'Year':[y for i in range(len(temp_df1))],
                                'Season_Type':[s for i in range(len(temp_df1))]})
        temp_df3 = pd.concat([temp_df2,temp_df1],axis=1)
        df = pd.concat([df, temp_df3], axis=0)
        print(f'Finished scraping data for {y} {s}.')

print(f'Process Completed. Total run time: {round((time.time()-begin_loop)/60,2)}')
df.to_excel('2022-23_data.xlsx', index=False)


import base64

from hash import Hasher
import threading
from crypto2.utils.matrices import mult_matrix, def_pitrix, subs_matrix
from ecc import Curve

def psuedo_combine(a, b):
    for i in range(64):
        a[i] ^= b[a[i] & 63]
    return a

class KeyScheduler:
    def __init__(self, generator_hash, rounds, blocks):
        self.__rounds__ = rounds
        self.__blocks__ = blocks

        self.__key_hash__ = base64.b64decode(generator_hash)

        self.__matrix__, self.__inv_matrix__ = self.def_matrices()
        self.__block_starts__ = None

    def block_keys(self, block_start):
        __block_keys__ = [block_start]
        for i in range(self.__rounds__ * 2):
            __block_keys__.append(psuedo_combine(__block_keys__[-1], block_start)[:])
        return __block_keys__[0:-1]

    def gen_block_starts(self):
        if self.__block_starts__:
            return self.__block_starts__

        self.__block_starts__ = []

        for i in range(self.__blocks__):
            if i == 0:
                self.__block_starts__.append(self.__key_hash__)
            else:
                """
                This provides high resistance to quantum and traditional attacks, but is very expensive
                I decided pitrix should be non-linear enough, with a few other combinations and sboxes to form a light-
                weight hash function of sufficient strength for a key scheduler
                """
                self.__block_starts__.append(
                    mult_matrix(subs_matrix(psuedo_combine(self.__block_starts__[-1], self.__key_hash__)), def_pitrix())
                )

        return self.__block_starts__

    def def_matrices(self):
        return 1, 2

def encrypt(key_hash, data, rounds=4):
    # This ensures that the KeyScheduler is unique per file/key combo
    # It also reduces memory attack potential for pass the hash
    hasher = Hasher(key_hash)
    hasher.hash(data)
    generator_hash = int(hasher.digest(as_b64=True)[2:])  # sooooo we need to only play with 62 bytes

    ks_hash = KeyScheduler(key_hash, rounds=rounds, blocks=1)
    ks_data = KeyScheduler(generator_hash, rounds=rounds, blocks=len(data)//62 + 1)
    blocks = data
    output = None
    curve = Curve()

    # Encrypt generator hash
    for i in range(rounds):
        h = curve.point_addition(curve.encode_point(5))

    """
    encrypt(key_scheduler_hash as ks, file_hash as h):
        for rounds min 4:
            h = ECC.add( h as ecc.point, ks.next as ecc.point)
        for rounds min 4:
            h = ks.matrix_mult(h as matrix)
            h += ks.next

        h, -1 -> encrypted

    encrypt(key_scheduler as ks, data as data):
        ks.generate_starts(data#), block, block# -> queue
        encrypted;

        queue -> get(ks, block)
            for rounds min 4:
                block = ECC.add( block as ecc.point, ks.next as ecc.point)
            for rounds min 4:
                block = ks.matrix_mult(block as matrix)
                block += ks.next
            block, block# -> encrypted

        return order(encrypted)
    """

    pass

def decrypt(key_hash, encrypted, rounds=4):
    """
    key_scheduler_hash(key_hash, rounds, reverse)
    file_hash:
        decrypt(encrypted[0] as e, key_scheduler_hash as ks):
            for rounds min 4:
                e += ks.next
                e = ks.matrix_mult_inv(e as matrix)
            for rounds min 4:
                e = ECC.add( e as ecc.point, ks.next as ecc.point)

    key_scheduler(key_hash, file_hash, rounds, reverse)

    decrypt(key_scheduler as ks, encrypted as e):
        ks.generate_starts(e#), e, e# -> queue
        decrypted;

        queue -> get(ks, block)
            for rounds min 4:
                block += ks.next
                block = ks.matrix_mult(block as matrix)
            for rounds min 4:
                block = ECC.add( block as ecc.point, ks.next as ecc.point)
            block, block# -> decrypted

    if file_hash(decrypted) == file_hash:
        return decrypted
    else:
        raise("Error in ")
    """

    pass

"""
def encryption(p, ks, r):

    for R in range(r-1):
        p = shift_rows(xor_2d_matrices(matrix_mult(p, enc), ks.get_key()))

    return xor_2d_matrices(matrix_mult(p, enc), ks.get_key())

def decryption(p, ks, r):

    p = matrix_mult(xor_2d_matrices(p, ks.get_key()), dec)

    for R in range(r-1):
        p = matrix_mult(xor_2d_matrices(inv_shift_rows(p), ks.get_key()), dec)

    return p
"""

c = Curve()
v= 65189726
p = c.encode_point(v)
d = c.decode_point(p)
print(v==d, v, p, d)


import cv2 as cv
import numpy as np

noise = cv.imread('diamondsquare.png')
maps = cv.imread('bounding.jpg')
noise_gry = cv.cvtColor(noise, cv.COLOR_BGR2GRAY)
map_gry = cv.cvtColor(maps, cv.COLOR_BGR2GRAY)

cv.namedWindow("images", cv.WINDOW_NORMAL)
cv.imshow('images', map_gry)
cv.waitKey()

newImg = map_gry * (150/255) + noise_gry * (105/255)
newImg = np.rint(newImg).astype(np.uint8)
cv.imshow('images', newImg)
cv.imwrite('combinedImage.jpg', newImg)
cv.waitKey()


from setuptools import setup, find_packages

def calculate_version(inputfile):
    version_list =  [x.split('\'')[1] for x in open(inputfile, 'r')
                     if x.startswith('__version__')]
    if version_list:
        return version_list[0]
    else:
        return '1.0'

package_version = calculate_version('./pdxSPA/_version.py')

setup(
    name='pdxSPA',
    version=package_version,
    author='Xi Cheng',
    author_email='chengxi0237@sjtu.edu.cn,',
    packages=find_packages(),
    install_requires=[
        'Click',
        'numpy',
        'pandas',
    ],

    entry_points="""
    [console_scripts]
    pdxSPA=pdxSPA.cli:main
    """,

    description='SPA (Shared Peptides Allocation) for quantifying the MS data from the PDX models.',
    license='GPL-3.0',
    classifiers=[
        'Intended Audience :: Proteomics',
        'Operating System :: POSIX :: Linux',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
    ],
    url='https://github.com/cathy0237/pdxSPA.git',

)


from pysam import VariantFile
import argparse
import os.path as path
import pandas as pd
import configparser

# Get chrom pos ref alt from location file
def locations_from_file(filename):
    result = pd.read_csv(filename)[["chrom","pos","ref","alt"]].values
    return result

# Get variant at position from bcf filename
# For bcf files fetch takes 0 based positions
def get_variant(chrom, pos, ref, alt, bcf_filename_template):
    contig = f"chr{chrom}"
    bcf_filename = bcf_filename_template.format(chrom=chrom)
    bcf_in = VariantFile(bcf_filename)
    results = list()
    header = bcf_in.header
    for rec in bcf_in.fetch(contig, int(pos)-1, int(pos)):
        if (rec.pos == int(pos) and
                rec.ref == ref and
                rec.alts[0] == alt):
            results.append(rec)
    bcf_in.close()
    return (header, results)

# Combine dosages and write to outputfile
def get_dosages(location_filename, output_filename, bcf_filename_template):
    dat = locations_from_file(location_filename)
    results = [get_variant(*info,bcf_filename_template) for info in dat]

    # Check that the samples in the files are in the same order
    samples_in_first_vcf = list(results[0][0].samples)
    sample_orders_are_identical = all([list(x[0].samples)
                                       == samples_in_first_vcf for x in results])
    # We are not using pandas just in case the file is large.
    if sample_orders_are_identical:
        with open(output_filename, "wt") as fout:
            samples_str  =",".join(samples_in_first_vcf)
            header=f"variant,{samples_str}\n"
            fout.write(header)
            for ((_, res), info) in zip(results, dat):
                if len(res) == 1:
                    rec = res[0]
                    if len(rec.alts) > 1:
                        raise NameError("Multi-allelic")
                    name =":".join([rec.chrom, str(rec.pos), rec.ref, rec.alts[0]])
                    gts = [rec.samples[s]["GT"] for s in samples_in_first_vcf]
                    dosages = [str(sum(x)) if (-1 not in x) else "" for x in gts]
                    dosages_str = ",".join(dosages)
                    out = f"{name},{dosages_str}\n"
                    fout.write(out)
                elif len(res) > 1:
                    raise NameError(f"Something is off multiple results for variant: {info}")
                else:
                    print(f"No results were found for {info}")
    else:
        raise NameError("Sample order/ samples are not the same between all the files used can't do merge")

def get_counts(dosages_filename, locations_filename, dictionary_csv, counts_output_filename):
    dosages = pd.read_csv(dosages_filename).set_index("variant")
    nwd_ids = dosages.apply(lambda x: list(dosages.columns[x != 0]), axis=1)
    df = pd.DataFrame( { "nwd_ids": nwd_ids, "counts": nwd_ids.apply(len)})

    dict_df = pd.read_csv(dictionary_csv)[["framid", "NWD_ID"]]
    dict_df = dict_df.loc[~dict_df.NWD_ID.isna()]

    my_dict = dict(zip(dict_df["NWD_ID"],dict_df["framid"]))

    df["framids"] = df.nwd_ids.apply(lambda x: [str(my_dict[y]) for y in x])
    df["nwd_ids"] = df.nwd_ids.apply(";".join)
    df["framids"] = df.framids.apply(";".join)

    popseq = pd.read_csv(locations_filename)
    popseq["variant"] = popseq.apply(lambda x: "chr" + ":".join(map(str,x[["chrom","pos","ref","alt"]])),axis=1)
    result_df = popseq.set_index("variant").join(df, how="left")
    result_df.to_csv(counts_output_filename)

def main():
    parser = argparse.ArgumentParser(description="Get bcf file with variants defined in input file")
    parser.add_argument('input', metavar='FILE',
                        help="File with variants csv with cols variant,Amino acid,spid,chrom,pos,ref,alt,bcftoolsQuery")
    parser.add_argument('--output_prefix', '-o', metavar='OUTPUT_PREFIX',
                        help="Output directory")

    parser.add_argument('--config', '-c', metavar='CONFIG_FILE',
                        help="configuration file", default="generate_ror.config")

    # Get args
    args = parser.parse_args()
    locations_filename = args.input
    # Read config file
    config = configparser.ConfigParser()
    config.read(args.config)
    dictionary_csv = config["config"]["dictionary"]
    bcf_filename_template = config["config"]["bcf_template"]

    if not path.exists(dictionary_csv):
        raise NameError("Dictionary file does not exist")
    test_bcf = bcf_filename_template.format(chrom=1)
    if not path.exists(test_bcf):
        raise NameError(f"BCF file for chromosome 1 does not exist: {test_bcf}")

    # Construct output filenames
    locations_filename = args.input
    output_dosages_filename = f"{args.output_prefix}_dosages.csv"
    counts_filename = f"{args.output_prefix}_counts.csv"

    # Get dosage file
    get_dosages(locations_filename, output_dosages_filename,bcf_filename_template)

    # Get counts file
    get_counts(output_dosages_filename, locations_filename, dictionary_csv, counts_filename)


import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, \
    QSizePolicy, QMessageBox
import chess
import chess.svg
import chess.engine
from io import BytesIO
from PyQt5.QtGui import QPixmap
from ChessAI_3 import ChessAiv3
from ChessAi002 import ChessAiv3N
import time
import re

class ChessGameGUI(QWidget):
    def __init__(self):
        super().__init__()
        self.board = chess.Board()
        self.mode = '1'
        self.color = True
        self.ai = self.createAI(ChessAiv3)
        self.initUI()

    def initUI(self):
        # Componentes da interface
        self.ai_color = QLabel(self)
        self.image_label = QLabel(self)
        self.player_move_field = QLineEdit(self)
        self.play_button = QPushButton('Jogar', self)
        self.play_button.clicked.connect(self.play_move)
        self.error_label = QLabel(self)
        self.error_label.setStyleSheet("color: red")

        # Layout principal
        main_layout = QHBoxLayout()

        self.ai_color.setText(f"IA: {'Branco' if self.color else 'Preto'}")
        # Layout para a imagem
        chess_layout = QVBoxLayout()
        chess_layout.addWidget(self.ai_color)
        chess_layout.addWidget(self.image_label)

        # Layout para o input_field
        input_layout = QHBoxLayout()
        input_layout.addWidget(self.player_move_field)
        input_layout.addWidget(self.play_button)
        chess_layout.addLayout(input_layout)

        main_layout.addLayout(chess_layout)

        main_layout.addWidget(self.error_label)

        # Layout para os modos de jogo
        mode_layout = QVBoxLayout()

        # Botão para trocar de cor
        change_color_button = QPushButton('Trocar cor', self)
        change_color_button.clicked.connect(lambda: self.change_color())
        mode_layout.addWidget(change_color_button)

        # Botão "Jogar contra IA"
        play_vs_ai_button = QPushButton('Jogar contra IA', self)
        play_vs_ai_button.clicked.connect(lambda: self.change_mode('1'))
        mode_layout.addWidget(play_vs_ai_button)

        # Botão "IA vs IA"
        ai_vs_ai_button = QPushButton('IA vs IA', self)
        ai_vs_ai_button.clicked.connect(lambda: self.change_mode('2'))
        mode_layout.addWidget(ai_vs_ai_button)

        # Botão "IA vs StockFish"
        play_vs_stockfish_button = QPushButton('IA vs StockFish', self)
        play_vs_stockfish_button.clicked.connect(lambda: self.change_mode('3'))
        mode_layout.addWidget(play_vs_stockfish_button)

        main_layout.addLayout(mode_layout)

        # Definindo tamanhos relativos
        self.image_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.player_move_field.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.play_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)

        play_vs_ai_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        ai_vs_ai_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        play_vs_stockfish_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        self.setLayout(main_layout)
        self.update_board_image()

        # Config
        self.player_move_field.setDisabled(True)
        self.play_button.setDisabled(True)
        ai_vs_ai_button.setDisabled(True)
        play_vs_stockfish_button.setDisabled(True)

        # Ajustes da janela
        self.setGeometry(100, 100, 800, 600)
        self.setWindowTitle('Chess Game')
        self.show()

    def show_popup(self, title, message):
        msg_box = QMessageBox()
        msg_box.setWindowTitle(title)
        msg_box.setText(message)
        msg_box.exec_()

    def change_color(self):
        self.color = not self.color
        self.board = chess.Board()

        self.player_move_field.setDisabled(True)
        self.play_button.setDisabled(True)
        self.error_label.clear()
        # Update Board
        self.ai_color.setText(f"IA: {'Branco' if self.color else 'Preto'}")
        self.update_board_image()

    def play_move(self):
        # Padrões 4 – 5 letras indicando [a-h][1-8][a-h][1-8](n|b|r|q)?
        padrao = re.compile(r'^([a-h][0-8])[a-h][0-8]([n|b|r|q])?$')
        move = self.player_move_field.text()
        if not move:
            self.error_label.setText("Erro: O campo de entrada está vazio.")
            return
        elif not bool(padrao.match(move)):
            self.error_label.setText("Erro: Jogada Invalida.")
            return
        else:
            self.player_move_field.clear()
            move = chess.Move.from_uci(move)

            if move in self.board.legal_moves:
                self.board.push(move)
                self.update_board_image()
                self.ai_play()
            else:
                self.error_label.setText("Erro: Jogada não existe Invalida.")
        if self.board.is_game_over():
            outcome = self.board.outcome()
            winner = outcome.winner
            title = outcome.termination.name
            if winner:
                message = "Brancas Venceram!"
            elif winner is None:
                message = "Empate!"
            else:
                message = "Pretas Venceram!"
            self.show_popup(title=title, message=message)

    def change_mode(self, mode):
        # Reiniciando Jogo
        self.board = chess.Board()
        self.update_board_image()
        self.mode = mode
        if mode == '1':
            self.player_move_field.setDisabled(False)
            self.play_button.setDisabled(False)
            self.error_label.clear()
            if self.color:
                self.ai_play()
        elif mode == '2':
            self.player_move_field.setDisabled(True)
            self.play_button.setDisabled(True)
            self.ai_game()
        elif mode == '3':
            self.player_move_field.setDisabled(True)
            self.play_button.setDisabled(True)
            self.stockfish_game()

    def createAI(self, source_code, ai_name='ChessAiv3'):
        compiled_code = compile(source_code, '<string>', 'exec')
        namespace = {}
        exec(compiled_code, namespace)
        AI = namespace[ai_name]
        return AI()

    def update_board_image(self):
        try:
            lastmove = self.board.peek()
        except:
            lastmove = None

        board_svg = chess.svg.board(board=self.board, lastmove=lastmove)

        image_bytes = BytesIO(board_svg.encode('utf-8'))
        pixmap = QPixmap()
        pixmap.loadFromData(image_bytes.read())

        self.image_label.setPixmap(pixmap)

    def ai_play(self):
        move = self.ai.make_move(self.board, 4)
        self.board.push(move)

        # Update Board
        self.error_label.setText(f"Jogada: {move}")
        self.update_board_image()

    def ai_game(self, n_games=5):
        ai_white = self.createAI(ChessAiv3, 'ChessAiv3')
        ai_black = ChessAiv3N()

        match_history = {
            "ChessAiv3": 0,
            "ChessAi002": 0,
            "Draw": 0,
            "ChessAiv3_time": 0,
            "ChessAi002_time": 0,
            "Total Time": 0
        }

        for i in range(n_games):
            game_start = time.time_ns()
            movehistory = []
            self.board = chess.Board()
            self.update_board_image()
            time_w = 0
            time_b = 0

            while not self.board.is_game_over():
                if self.board.turn:
                    st = time.time_ns()
                    move = ai_black.make_move(self.board, 3)
                    time_w += time.time_ns() - st
                    movehistory.append(move)
                    self.board.push(move)

                    # Update board
                    self.update_board_image()
                    QApplication.processEvents()
                else:
                    st = time.time_ns()

                    move = ai_white.make_move(self.board, 3)
                    time_b += time.time_ns() - st
                    movehistory.append(move)
                    self.board.push(move)

                    # Update Board
                    self.update_board_image()
                    QApplication.processEvents()

            game_finish = time.time_ns()
            match_history["Total Time"] += (game_finish - game_start)
            match_history["ChessAiv3_time"] += time_w
            match_history["ChessAi002_time"] += time_b
            print(self.board.outcome().winner)
            if self.board.outcome().winner:
                match_history["ChessAiv3"] += 1
            elif self.board.outcome().winner == False:
                match_history["ChessAi002"] += 1
            else:
                match_history["Draw"] += 1
            print(f"{i + 1}º game time: " + str((game_finish - game_start) / 1000000) + "ms")
            print(f"ChessAiv3 AI: {time_w / 1000000000}s")
            print(f"ChessAi002 AI: {time_b / 1000000000}s")
            print(f"rounds {self.board.fullmove_number}\n")

        print(f"ChessAi002 wins: {match_history['ChessAi002']}\n"
              f"ChessAiv3 wins: {match_history['ChessAiv3']}\n"
              f"Draws: {match_history['Draw']}\n"
              f"ChessAi002 time per match: {(match_history['ChessAi002_time'] / 1000000000) / n_games}s/match\n"
              f"ChessAiv3 time per match: {(match_history['ChessAiv3_time'] / 1000000000) / n_games}s/match\n"
              f"Time per Match: {(match_history['Total Time'] / 1000000000) / n_games}s/match\n")
        outcome = self.board.outcome()
        winner = outcome.winner
        title = outcome.termination.name
        if winner:
            message = "Brancas Venceram!"
        elif winner is None:
            message = "Empate!"
        else:
            message = "Pretas Venceram!"
        self.show_popup(title=title, message=message)

    def stockfish_game(self, n_games=2):
        my_ai = self.createAI(ChessAiv3, 'ChessAiv3')
        engineStockFish = chess.engine.SimpleEngine.popen_uci("./OtherEngines/stockfish/stockfish.exe")

        match_history = {
            "My Ai": 0,
            "Stockfish": 0,
            "Draw": 0,
            "Ai_time": 0,
            "Stockfish_time": 0,
            "Total Time": 0
        }

        for i in range(n_games):
            game_start = time.time_ns()
            movehistory = []
            self.board = chess.Board()
            self.update_board_image()
            time_w = 0
            time_b = 0

            while not self.board.is_game_over():
                if self.board.turn:
                    st = time.time_ns()
                    move = my_ai.make_move(self.board, 3)
                    time_w += time.time_ns() - st
                    movehistory.append(move)
                    self.board.push(move)

                    # Update board
                    self.update_board_image()
                    QApplication.processEvents()
                else:
                    st = time.time_ns()
                    move = engineStockFish.play(self.board, chess.engine.Limit(time=0.1))
                    time_b += time.time_ns() - st
                    movehistory.append(move.move)
                    self.board.push(move.move)
                    # Update Board
                    self.update_board_image()
                    QApplication.processEvents()

            game_finish = time.time_ns()
            print(self.board.outcome().winner)
            if self.board.outcome().winner:
                match_history["My AI"] += 1
            elif self.board.outcome().winner == False:
                match_history["Stockfish"] += 1
            else:
                match_history["Draw"] += 1
            match_history["Total Time"] += (game_finish - game_start)
            print(f"{i + 1}º game time: {(game_finish - game_start) / 1000000}ms")
            print(f"My AI: {time_w / 1000000000}s")
            match_history["Ai_time"] += time_w
            print(f"Stockfish: {time_b / 1000000000}s")
            match_history["Stockfish_time"] += time_b
            print(f"rounds {self.board.fullmove_number}")

        for i in range(n_games):
            game_start = time.time_ns()
            movehistory = []
            self.board = chess.Board()
            self.update_board_image()
            time_w = 0
            time_b = 0

            while not self.board.is_game_over():
                if self.board.turn:
                    st = time.time_ns()
                    move = engineStockFish.play(self.board, chess.engine.Limit(time=0.1))
                    time_w += time.time_ns() - st
                    movehistory.append(move.move)
                    self.board.push(move.move)

                    # Update board
                    self.update_board_image()
                    QApplication.processEvents()
                else:
                    st = time.time_ns()
                    move = my_ai.make_move(self.board, 3)
                    time_b += time.time_ns() - st
                    movehistory.append(move)
                    self.board.push(move)
                    # Update Board
                    self.update_board_image()
                    QApplication.processEvents()

            game_finish = time.time_ns()
            print(self.board.outcome().winner)
            if self.board.outcome().winner:
                match_history["Stockfish"] += 1
            elif self.board.outcome().winner == False:
                match_history["My Ai"] += 1
            else:
                match_history["Draw"] += 1
            match_history["Total Time"] += (game_finish - game_start)
            print(f"{i + 1}º game time: {(game_finish - game_start) / 1000000}ms")
            print(f"Stockfish: {time_w / 1000000000}s")
            match_history["Stockfish_time"] += time_w
            print(f"My AI: {time_b / 1000000000}s")
            match_history["Ai_time"] += time_b
            print(f"rounds {self.board.fullmove_number}")

        print(f"ChessAI wins: {match_history['My Ai']}\n"
              f"StockFish wins: {match_history['Stockfish']}\n"
              f"Draws: {match_history['Draw']}\n"
              f"Stockfish time per match: {(match_history['Stockfish_time'] / 1000000000) / n_games}s\n"
              f"My Ai time per match: {(match_history['Ai_time'] / 1000000000) / n_games}s\n"
              f"Time per Match: {(match_history['Total Time'] / 1000000000) / n_games}s/match\n")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = ChessGameGUI()
    sys.exit(app.exec_())


""" Behaviours to enable calendarish event extension to dexterity content
types.

"""

from zope import schema
from zope.component import adapts
from zope.interface import implements, alsoProvides
from plone.directives import form
from plone.app.event import messageFactory as _
from plone.dexterity.interfaces import IDexterityContent

# TODO: create different, minimalist behaviors for every aspect of an event.
# ILocationAware, IAttendee, IContact, IRecurrence

class IEvent(form.Schema):
    """Add tags to content
    """

    form.fieldset(
            'event',
            label=_(u'label_fieldset_event', default=u'Event'),
            fields=(
                'start',
                'end',
                'timezone',
                'recurrence',
                'whole_day',
                'location',
                'attendees',
                'event_url',
                'contact_name',
                'contact_email',
                'contact_phone',
                ),
        )

    start = schema.Datetime(
        title = _(u'label_start', default=u'Event start date'),
        description = _(u'help_start', default=u'Date and Time, when the event begins.'),
        required = True
        )

    end = schema.Datetime(
        title = _(u'label_end', default=u'Event end date'),
        description = _(u'help_end', default=u'Date and Time, when the event ends.'),
        required = True
        )

    timezone = schema.TextLine(
        title = _(u'label_timezone', default=u'Timezone'),
        description = _(u'help_timezone', default=u'Timezone of the event'),
        required = True,
        )

    recurrence = schema.TextLine(
        title = _(u'label_recurrence', default=u'Recurrence'),
        description = _(u'help_recurrence', default=u'RFC5545 compatible recurrence definition'),
    )

    whole_day = schema.Bool(
        title = _(u'label_whole_day', default=u'Whole Day'),
        description = _(u'help_whole_day', default=u'Event lasts whole day'),
        )

    location = schema.TextLine(
        title = _(u'label_location', default=u'Location'),
        description = _(u'help_location', default=u'Location of the event'),
        )

    attendees = schema.Text(
        title = _(u'label_attendees', default=u'Attendees'),
        description = _(u'help_attendees', default=u'List of attendees'),
        )

    event_url = schema.TextLine(
        title = _(u'label_event_url', default=u'Event Url'),
        description = _(u'help_event_url', default=u'Website of the event'),
        )

    contact_name = schema.TextLine(
        title = _(u'label_contact_name', default=u'Contact Name'),
        description = _(u'help_contact_name', default=u'Name of a person to contact about this event.'),
        )

    contact_email = schema.TextLine(
        title = _(u'label_contact_email', default=u'Contact Email'),
        description = _(u'help_contact_email', default=u'Email address to contact about this event.'),
        )

    contact_phone = schema.TextLine(
        title = _(u'label_contact_phone', default=u'Contact Phone'),
        description = _(u'help_contact_phone', default=u'Phone number to contact about this event.'),
        )

alsoProvides(IEvent, form.IFormFieldProvider)

class EventBase(object):
    """ This adapter acts as a Base Adapter for more specific Event Behaviors.
    """
    implements(IEvent)
    adapts(IDexterityContent)

    def __init__(self, context):
        self.context = context


from django.db import models

from wagtail.admin.edit_handlers import (
    FieldPanel,
    PageChooserPanel,
    StreamFieldPanel,
)
from wagtail.core import blocks
from wagtail.core.fields import RichTextField, StreamField
from wagtail.core.models import Page
from wagtail.images.blocks import ImageChooserBlock
from wagtail.search import index

from streams import blocks as wf_blocks

class CommunityPage(Page):
    body = StreamField(
        [
            ("heading", wf_blocks.HeadingBlock()),
            ("rich_text", blocks.RichTextBlock()),
            ("image", ImageChooserBlock()),
            ("card", wf_blocks.CardBlock()),
            (
                "card_row",
                blocks.ListBlock(
                    wf_blocks.PageCardBlock(label="Page"),
                    template="streams/blocks/card_row.html",
                ),
            ),
            ("spacer", wf_blocks.SpacerBlock()),
        ],
        null=True,
    )

    content_panels = Page.content_panels + [
        StreamFieldPanel("body"),
    ]

    max_count = 1

    parent_page_types = ["home.HomePage"]
    subpage_types = [
        "contact.MeetingIndexPage",
        "contact.OrganizationIndexPage",
        "contact.PersonIndexPage",
        "community.CommunityDirectoryIndexPage",
        "community.OnlineWorshipIndexPage",
        "memorials.MemorialIndexPage",
    ]

class OnlineWorship(Page):
    description = RichTextField(blank=True)

    hosted_by = models.ForeignKey(
        "wagtailcore.Page",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="online_worship",
    )

    times_of_worship = RichTextField(blank=True)

    website = models.URLField(null=True, blank=True)

    content_panels = Page.content_panels + [
        FieldPanel("description"),
        PageChooserPanel("hosted_by", ["contact.Meeting", "contact.Organization"]),
        FieldPanel("times_of_worship"),
        FieldPanel("website"),
    ]

    parent_page_types = [
        "community.OnlineWorshipIndexPage",
    ]
    subpage_types = []

    search_template = "search/online_worship.html"

    search_fields = Page.search_fields + [
        index.SearchField("description", partial_match=True),
    ]

class OnlineWorshipIndexPage(Page):
    intro = RichTextField(blank=True)

    content_panels = Page.content_panels + [FieldPanel("intro")]

    parent_page_types = ["community.CommunityPage"]
    subpage_types = ["community.OnlineWorship"]

    max_count = 1

    template = "community/online_worship_index_page.html"

class CommunityDirectory(Page):
    description = RichTextField(blank=True)

    website = models.URLField(null=True, blank=True)

    content_panels = Page.content_panels + [
        FieldPanel("description"),
        FieldPanel("website"),
    ]

    parent_page_types = [
        "community.CommunityDirectoryIndexPage",
    ]
    subpage_types = []

    search_template = "search/community_directory.html"

    search_fields = Page.search_fields + [
        index.SearchField("description", partial_match=True),
    ]

    class Meta:
        verbose_name_plural = "community directories"

class CommunityDirectoryIndexPage(Page):
    intro = RichTextField(blank=True)

    content_panels = Page.content_panels + [FieldPanel("intro")]

    parent_page_types = ["community.CommunityPage"]
    subpage_types = ["community.CommunityDirectory"]

    max_count = 1

    template = "community/community_directory_index_page.html"


"""
This file contains extra hpy tests in addition to the ones which are in
test/_vendored.

The idea is that during development, sometimes it is useful to write tests
about certain specific features/code paths/corner cases which are not covered
(yet!) by the official hpy tests, so this is a place to collect them.

Once the development phase is finished, please move these tests to the main
hpy repo, and then copy them back here via ./update_vendored.sh.
"""

from pypy.module._hpy_universal.test._vendored.support import HPyTest

class TestExtra(HPyTest):
    pass

    """
    Additional tests to write:

      - check the .readonly field of HPyDef_MEMBER (and also the corresponding
        flag for the PyMemberDef cpy_compat case)

    ListBuilder:

      - in the C code there is logic to delay the MemoryError until we call
        ListBuilder_Build, but it is not tested

      - ListBuilder_Cancel is not tested

    """
    def test_import_failure(self):
        import pytest
        with pytest.raises(RuntimeError):
            self.make_module("""
                HPy_MODINIT(test)
                static HPy init_test_impl(HPyContext *ctx)
                {
                    HPyErr_SetString(ctx, ctx->h_RuntimeError, "foo");
                    return HPyLong_FromLong(ctx, 42);
                }
            """, name='test')

    def test_import_bad_module(self):
        import pytest
        with pytest.raises(SystemError):
            self.make_module("""
                HPy_MODINIT(test)
                static HPy init_test_impl(HPyContext *ctx)
                {
                    return HPy_NULL;
                }
            """, name='test')

    def test_HPyModule_Create(self):
        mod = self.make_module("""
            HPyDef_METH(f, "f", f_impl, HPyFunc_NOARGS)
            static HPy f_impl(HPyContext *ctx, HPy self)
            {
                HPyModuleDef def = {
                    .m_name = "foo",
                    .m_doc = "Some doc",
                    .m_size = -1,
                };
                return HPyModule_Create(ctx, &def);
            }
            @EXPORT(f)
            @INIT
        """)
        m = mod.f()
        assert m.__name__ == "foo"
        assert m.__doc__ == "Some doc"
        assert m.__package__ is None
        assert m.__loader__ is None
        assert m.__spec__ is None
        assert set(vars(m).keys()) == {
            '__name__', '__doc__', '__package__', '__loader__', '__spec__'}

class TestExtraCPythonCompatibility(HPyTest):
    # these tests are run with cpyext support, see conftest.py
    USE_CPYEXT = True


import pygame as pg

class Viewport(object):
    """A simple viewport/camera to handle scrolling and zooming a surface."""

    def __init__(self, base_map, view_size=(800, 800)):
        """The base_map argument should be a pygame.Surface object.
            Works best with view_size[0] == view_size[1]"""
        self.base_map = base_map
        self.base_rect = self.base_map.get_rect()
        self.zoom_levels = {}
        for i in range(10):
            self.zoom_levels[i] = (self.base_rect.width // 2**i,
                                             self.base_rect.height // 2**i)
        self.zoom_level = 0
        self.max_zoom = len(self.zoom_levels) - 1
        self.view_size = view_size
        self.zoom_rect = pg.Rect((0, 0), self.zoom_levels[self.zoom_level])
        self.scroll_margin = 20
        self.scroll_speed = 5
        self.scroll([0, 0])

    def scroll(self, offset):
        """Move self.room_rect by offset and update image."""
        self.zoom_rect.move_ip(offset)
        self.zoom_rect.clamp_ip(self.base_rect)
        self.zoom_image()

    def zoom_image(self):
        """Set self.zoomed_image to the properly scaled subsurface."""
        subsurface = self.base_map.subsurface(self.zoom_rect)
        self.zoomed_image = pg.transform.scale(subsurface, self.view_size)

    def get_map_pos(self, screen_pos):
        """Takes in a tuple of screen coordinates and returns a tuple of
            the screen_position translated to the proper map coordinates
            for the current zoom level."""
        view_width, view_height = self.view_size
        x, y = screen_pos
        x_scale = self.zoom_levels[self.zoom_level][0] / float(view_width)
        y_scale = self.zoom_levels[self.zoom_level][1] / float(view_height)
        mapx = self.zoom_rect.left + (x * x_scale)
        mapy = self.zoom_rect.top + (y * y_scale)
        return mapx, mapy

    def get_zoom_rect(self, mapx, mapy):
        """Return a Rect of the current zoom resolution centered at mapx, mapy."""
        zoom_rect = pg.Rect((0, 0), self.zoom_levels[self.zoom_level])
        zoom_rect.center = (mapx, mapy)
        zoom_rect.clamp_ip(self.base_rect)
        return zoom_rect

    def get_event(self, event):
        """Respond to MOUSEBUTTONDOWN events, zooming in on
            left click and out on right click."""
        if event.button == 1:
            if self.zoom_level < self.max_zoom:
                mapx, mapy = self.get_map_pos(event.pos)
                self.zoom_level += 1
                self.zoom_rect = self.get_zoom_rect(mapx, mapy)
                self.zoom_image()

        elif event.button == 3:
            if self.zoom_level > 0:
                mapx, mapy = self.get_map_pos(event.pos)
                self.zoom_level -= 1
                self.zoom_rect = self.get_zoom_rect(mapx, mapy)
                self.zoom_image()

    def update(self, surface=None):
        """Check for scrolling each frame."""
        if surface:
            self.base_map = surface
        mouse_pos = pg.mouse.get_pos()
        offset = [0, 0]
        if mouse_pos[0] < self.scroll_margin:
            offset[0] -= self.scroll_speed
        elif mouse_pos[0] > self.view_size[0] - self.scroll_margin:
            offset[0] += self.scroll_speed
        if mouse_pos[1] < self.scroll_margin:
            offset[1] -= self.scroll_speed
        elif mouse_pos[1] > self.view_size[1] - self.scroll_margin:
            offset[1] += self.scroll_speed
        if offset != [(0, 0)]:
            self.scroll(offset)

    def draw(self, surface):
        surface.blit(self.zoomed_image, (0, 0))


import pandas as pd
import time
import os
import json
import sys
import datetime

os.chdir(r"/Users/bholmes/Desktop/DeleteMeSoon/orus/JSON/hl7json/")
listOfFiles = os.listdir('.')

alltests = set()

sourceList = list()
source = ""
healthOrgList = list()
healthOrg = ""
reportIdList = list()
reportId = ""
MRNList = list()
MRN = ""
firstNameList = list()
firstName = ""
lastNameList = list()
lastName = ""
middleNameList = list()
middleName = ""
DOBList = list()
DOB = ""
genderList = list()
gender = ""
testTypeList = list()
testType = ""
resultList = list()
result = ""
orderedDateList = list()
orderedDate = ""

isLargeSample = False

for sampleJSON in listOfFiles:
    with open(sampleJSON) as json_file:
        print(sampleJSON)
        data = json.load(json_file)
        if len(data['patient_identification']) != 1:
            print("THE ASSUMPTION WAS WRONG, THERE CAN BE MORE THAN ONE PATIENT")
        firstName = data['patient_identification'][0]['patient_name']['name_first']
        lastName = data['patient_identification'][0]['patient_name']['name_last']

        # Names are probably difficult to get just right, and might have a low return on investment.
        # If we're getting MRN, don't worry about name TOO much.
        try:
            middleName = data['patient_identification'][0]['patient_name']['name_middle']
        except:
            middleName = ""
        if len(' '.split(firstName)) == 2:
            middleName = ' '.split(firstName)[1]
            firstName = ' '.split(firstName)[0]

        gender = data['patient_identification'][0]['administrative_sex']['identifier']
        mrn = data['patient_identification'][0]['patient_identifier_list']['id_number']
        DOB = data['patient_identification'][0]['date_time_of_birth']
        # Kind of making the decision that hour/minute/second doesn't matter for DOB. Could be wrong? Probably not.
        DOBobj = datetime.datetime.strptime(DOB, '%Y-%m-%dT%H:%M:%S.%fZ')
        new_format = "%Y-%m-%d"
        DOB = DOBobj.strftime(new_format)
        source = data['message_header'][0]['receiving_facility']
        healthOrg = data['message_header'][0]['sending_facility']
        reportId = data['message_header'][0]['message_control_id']
        testType = data['observation_request'][0]['universal_service_identifier']['text']

        for i in range(0, len(data['observation_result'])):
            result = ""
            # There are two kinds of results - one in which there are a number of observations together
            # with units, and another in which there is one large observation. We'll try to get the
            # individual units of the list, and, failing
            try:
                result = result + data['observation_result'][i]['observation_identifier']['original_text'] + " - "
                result = result + data['observation_result'][i]['observation_value'] + " "
                result = result + data['observation_result'][i]['units']['alternate_identifier']
            except:
                result = data['observation_result'][i]['observation_value']
                isLargeSample = True

            if isLargeSample:
                isLargeSample = False
                sourceList.append(source)
                healthOrgList.append(healthOrg)
                reportIdList.append(reportId)
                MRNList.append(MRN)
                firstNameList.append(firstName)
                middleNameList.append(middleName)
                lastNameList.append(lastName)
                DOBList.append(DOB)
                genderList.append(gender)
                testTypeList.append(testType)
                resultList.append(result)
                orderedDateList.append(orderedDate)

        source = ""
        healthOrg = ""
        reportId = ""
        MRN = ""
        firstName = ""
        middleName = ""
        lastName = ""
        DOB = ""
        gender = ""
        testType = ""
        result = ""
        orderedDate = ""

unformedDataFrame = pd.DataFrame(list(zip(reportIdList, sourceList, healthOrgList, MRNList, firstNameList,
                                          middleNameList, lastNameList, DOBList, genderList, testTypeList,
                                          orderedDateList, resultList)),
                                                            columns=['ReportId', 'Source', 'healthOrg', 'MRN',
                                                                 'firstName', 'middleName', 'lastName', 'DOB',
                                                                 'gender', 'testType', 'testOrderDate', 'result'])

#export_csv = unformedDataFrame.to_csv ('~/Desktop/DeleteMeSoon/LungAdenocarcinomaJson.csv', index=False)