__copyright__ = '2019 Frootlab'
__license__ = 'GPLv3'
__docformat__ = 'google'
__author__ = 'Frootlab Developers'
__email__ = 'contact@frootlab.org'
__authors__ = ['Patrick Michl <patrick.michl@frootlab.org>']

import dataclasses
import operator
import math
import unittest
from unittest import mock
from hup.base import parser, test
from hup.typing import AnyOp
from hup.base.test import Case

try:
    import numpy as np
except ModuleNotFoundError:
    np = None

#
# Test Vocabulary for Parser
#

class PyExprEval(parser.Vocabulary):
    """Symbols used by py-expression-eval 0.3.6."""

    def __init__(self) -> None:
        super().__init__()

        rnd: AnyOp = lambda x: random.uniform(0., x)
        iif: AnyOp = lambda a, b, c: b if a else c
        concat: AnyOp = lambda *args: ''.join(map(str, args))
        iand: AnyOp = lambda a, b: a and b
        ior: AnyOp = lambda a, b: a or b

        self.update([
            # Sequence Operators
            parser.Symbol(parser.BINARY, ',', parser.pack, 0, True),
            parser.Symbol(parser.BINARY, '||', concat, 1),

            # Arithmetic Operators
            parser.Symbol(parser.UNARY, '-', operator.neg, 0, True),
            parser.Symbol(parser.BINARY, '+', operator.add, 2, True),
            parser.Symbol(parser.BINARY, '-', operator.sub, 2, True),
            parser.Symbol(parser.BINARY, '*', operator.mul, 3, True),
            parser.Symbol(parser.BINARY, '/', operator.truediv, 4, True),
            parser.Symbol(parser.BINARY, '%', operator.mod, 4, True),
            parser.Symbol(parser.BINARY, '^', math.pow, 6),

            # Ordering Operators
            parser.Symbol(parser.BINARY, '==', operator.eq, 1, True),
            parser.Symbol(parser.BINARY, '!=', operator.ne, 1, True),
            parser.Symbol(parser.BINARY, '>', operator.gt, 1, True),
            parser.Symbol(parser.BINARY, '<', operator.lt, 1, True),
            parser.Symbol(parser.BINARY, '>=', operator.ge, 1, True),
            parser.Symbol(parser.BINARY, '<=', operator.le, 1, True),

            # Boolean Operators
            parser.Symbol(parser.BINARY, 'and', iand, 0, True),
            parser.Symbol(parser.BINARY, 'or', ior, 0, True),

            # Functions
            parser.Symbol(parser.FUNCTION, 'abs', abs, 0, True),
            parser.Symbol(parser.FUNCTION, 'round', round, 0, True),
            parser.Symbol(parser.FUNCTION, 'min', min, 0, True),
            parser.Symbol(parser.FUNCTION, 'max', max, 0, True),
            parser.Symbol(parser.FUNCTION, 'sin', math.sin, 0),
            parser.Symbol(parser.FUNCTION, 'cos', math.cos, 0),
            parser.Symbol(parser.FUNCTION, 'tan', math.tan, 0),
            parser.Symbol(parser.FUNCTION, 'asin', math.asin, 0),
            parser.Symbol(parser.FUNCTION, 'acos', math.acos, 0),
            parser.Symbol(parser.FUNCTION, 'atan', math.atan, 0),
            parser.Symbol(parser.FUNCTION, 'sqrt', math.sqrt, 0),
            parser.Symbol(parser.FUNCTION, 'log', math.log, 0),
            parser.Symbol(parser.FUNCTION, 'ceil', math.ceil, 0),
            parser.Symbol(parser.FUNCTION, 'floor', math.floor, 0),
            parser.Symbol(parser.FUNCTION, 'exp', math.exp, 0),
            parser.Symbol(parser.FUNCTION, 'random', rnd, 0),
            parser.Symbol(parser.FUNCTION, 'fac', math.factorial, 0),
            parser.Symbol(parser.FUNCTION, 'pow', math.pow, 0),
            parser.Symbol(parser.FUNCTION, 'atan2', math.atan2, 0),
            parser.Symbol(parser.FUNCTION, 'if', iif, 0),
            parser.Symbol(parser.FUNCTION, 'concat', concat, 0),

            # Constants
            parser.Symbol(parser.CONSTANT, 'E', math.e, 0),
            parser.Symbol(parser.CONSTANT, 'PI', math.pi, 0)])

#
# Test Cases
#

class TestParser(test.ModuleTest):
    module = parser

    def test_pack(self) -> None:
        self.assertCaseEqual(parser.pack, [
            Case(('x', 'y'), {}, ['x', 'y']),
            Case((['x', 'y'], 'z'), {}, [['x', 'y'], 'z']),
            Case((parser.pack('x', 'y'), 'z'), {}, ['x', 'y', 'z'])])

    def test_parse(self) -> None:
        pass # Implicitely tested

    def test_Symbol(self) -> None:
        conj: AnyOp = lambda z: complex(z).real - complex(z).imag * 1j
        self.assertCaseRaises(TypeError, parser.Symbol, [
            Case(tuple()), # Too few args
            Case((None, )), # Too few args
            Case((None, None)), # Too few args
            Case((None, None, None)), # Wrong type for 'type'
            Case((parser.UNARY, None, None)), # Wrong type for 'key'
            Case((parser.UNARY, '*', None)), # Unary must be callable
            Case((parser.UNARY, '*', conj, None))]) # Wrong type for 'priority'

        sym = parser.Symbol(parser.UNARY, '*', conj)
        self.assertEqual(
            dataclasses.astuple(sym),
            (parser.UNARY, '*', conj, 0, False, False))

    def test_Vocabulary(self) -> None:
        voc = parser.PyOperators()
        self.assertEqual(voc.search(type=parser.FUNCTION), {})

        mean: AnyOp = lambda s: sum(s) / len(s)
        voc.add(parser.Symbol(parser.FUNCTION, 'mean', mean))
        self.assertIn('mean', voc.search(type=parser.FUNCTION, builtin=False))
        self.assertNotIn('mean', voc.search(type=parser.FUNCTION, builtin=True))

        p = parser.Parser(vocabulary=voc)
        self.assertEqual(p.parse('mean(s)').variables, ('s', ))
        self.assertEqual(p.parse('mean(s)').symbols, ('mean', 's'))
        self.assertEqual(p.parse('mean(s)').eval([1, 2, 3]), 2)

    def test_PyOperators(self) -> None:
        # The individual operators are tested within seperate tests. Here the
        # operator associativity and precedence is tested.
        # Note: The Precedence is not required to be tested between different
        # operators of same precedence, like comparison operators. In this case
        # the operators are always evaluated from left to right.
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Logical Operators
        with self.subTest():
            self.assertCaseEqual(peval, [
                Case(('x and not(y)', 1, 0), {}, True),
                Case(('not(x and y)', 1, 0), {}, True),
                Case(('x or y and z', 1, 0, 0), {}, True),
                Case(('(x or y) and z', 1, 0, 0), {}, False)])

        # Bitwise Operators
        with self.subTest():
            self.assertCaseEqual(peval, [
                Case(('x | (~y)', 1, 0), {}, -1),
                Case(('~(x | y)', 1, 0), {}, -2),
                Case(('x | y ^ z', 1, 0, 3), {}, 3),
                Case(('(x | y) ^ z', 1, 0, 3), {}, 2),
                Case(('x ^ y ^ z', 1, 0, 3), {}, 2),
                Case(('x ^ y & z', 3, 1, 0), {}, 3),
                Case(('(x ^ y) & z', 3, 1, 0), {}, 0),
                Case(('x & y >> z', 2, 4, 1), {}, 2),
                Case(('(x & y) >> z', 2, 4, 1), {}, 0)])

        # Arithmetic Operators
        with self.subTest():
            self.assertCaseEqual(peval, [
                Case(('x + (-y)', 1, 1), {}, 0),
                Case(('-(x + y)', 1, 1), {}, -2),
                Case(('x + y * z', 1, 0, 0), {}, 1),
                Case(('(x + y) * z', 1, 0, 0), {}, 0),
                Case(('x * y ** z', 2, 2, 2), {}, 8),
                Case(('(x * y) ** z', 2, 2, 2), {}, 16)])

        # Comparison Operators
        # The Precedence is not required to be tested between different
        # comparison operators, since it is always evaluated from left to right

        # Mixed Operators
        with self.subTest():
            self.assertCaseEqual(peval, [
                Case(('x and y | z', 0, 2, 3), {}, 0),
                Case(('(x and y) | z', 0, 2, 3), {}, 3),
                Case(('x << y + z', 1, 2, 3), {}, 32),
                Case(('(x << y) + z', 1, 2, 3), {}, 7)])

    def test_PyOperators_logical(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Boolean OR
        with self.subTest(symbol='or'):
            self.assertCaseEqual(peval, [
                Case(('x or y', True, False), {}, True),
                Case(('x or y', False, True), {}, True),
                Case(('x or y', False, False), {}, False),
                Case(('x or y', True, True), {}, True)])

        # Boolean AND
        with self.subTest(symbol='and'):
            self.assertCaseEqual(peval, [
                Case(('x and y', True, False), {}, False),
                Case(('x and y', False, True), {}, False),
                Case(('x and y', False, False), {}, False),
                Case(('x and y', True, True), {}, True)])

        # Boolean NOT
        with self.subTest(symbol='not'):
            self.assertCaseEqual(peval, [
                Case(('not(x)', True), {}, False),
                Case(('not(x)', False), {}, True)])

    def test_PyOperators_comparison(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Equality
        with self.subTest(symbol='=='):
            self.assertCaseEqual(peval, [
                Case(('x == y', 1, 1), {}, True),
                Case(('x == y', 1, 2), {}, False),
                Case(('x == y', 'a', 'a'), {}, True),
                Case(('x == y', 'a', 'b'), {}, False)])

        # Inequality
        with self.subTest(symbol='!='):
            self.assertCaseEqual(peval, [
                Case(('x != y', 1, 1), {}, False),
                Case(('x != y', 1, 2), {}, True),
                Case(('x != y', 'a', 'a'), {}, False),
                Case(('x != y', 'a', 'b'), {}, True)])

        # Greater
        with self.subTest(symbol='>'):
            self.assertCaseEqual(peval, [
                Case(('x > y', 1, 1), {}, False),
                Case(('x > y', 2, 1), {}, True),
                Case(('x > y', 'a', 'a'), {}, False),
                Case(('x > y', 'b', 'a'), {}, True)])

        # Greater or Equal
        with self.subTest(symbol='>='):
            self.assertCaseEqual(peval, [
                Case(('x >= y', 1, 2), {}, False),
                Case(('x >= y', 1, 1), {}, True),
                Case(('x >= y', 'a', 'b'), {}, False),
                Case(('x >= y', 'a', 'a'), {}, True)])

        # Lower
        with self.subTest(symbol='<'):
            self.assertCaseEqual(peval, [
                Case(('x < y', 1, 1), {}, False),
                Case(('x < y', 1, 2), {}, True),
                Case(('x < y', 'a', 'a'), {}, False),
                Case(('x < y', 'a', 'b'), {}, True)])

        # Lower or Equal
        with self.subTest(symbol='<='):
            self.assertCaseEqual(peval, [
                Case(('x <= y', 2, 1), {}, False),
                Case(('x <= y', 1, 1), {}, True),
                Case(('x <= y', 'b', 'a'), {}, False),
                Case(('x <= y', 'a', 'a'), {}, True)])

        # Identity
        with self.subTest(symbol='is'):
            self.assertCaseEqual(peval, [
                Case(('x is y', True, True), {}, True),
                Case(('x is y', True, False), {}, False)])

        # Containment
        with self.subTest(symbol='in'):
            self.assertCaseEqual(peval, [
                Case(('x in y', 'a', 'a'), {}, True),
                Case(('x in y', 'a', 'b'), {}, False),
                Case(('x in y', 'a', 'ba'), {}, True),
                Case(('x in y', 'ab', 'ba'), {}, False)])

    def test_PyOperators_bitwise(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Bitwise Inversion
        with self.subTest(symbol='~'):
            self.assertCaseEqual(peval, [
                Case(('~x', 0), {}, -1),
                Case(('~x', -1), {}, 0),
                Case(('~x', 1), {}, -2),
                Case(('~x', -2), {}, 1),
                Case(('~(~x)', 3), {}, 3)])

        # Bitwise Right Shift
        with self.subTest(symbol='>>'):
            self.assertCaseEqual(peval, [
                Case(('x >> y', 1, 1), {}, 0),
                Case(('x >> y', 2, 2), {}, 0),
                Case(('x >> y', 1, 2), {}, 0),
                Case(('x >> y', 2, 1), {}, 1)])

        # Bitwise Left Shift
        with self.subTest(symbol='>>'):
            self.assertCaseEqual(peval, [
                Case(('x << y', 1, 1), {}, 2),
                Case(('x << y', 2, 2), {}, 8),
                Case(('x << y', 1, 2), {}, 4),
                Case(('x << y', 2, 1), {}, 4)])

        # Bitwise AND
        with self.subTest(symbol='&'):
            self.assertCaseEqual(peval, [
                Case(('x & y', 2, 2), {}, 2),
                Case(('x & y', 2, 3), {}, 2),
                Case(('x & y', 1, 3), {}, 1),
                Case(('x & y', 1, 2), {}, 0)])

        # Bitwise XOR
        with self.subTest(symbol='^'):
            self.assertCaseEqual(peval, [
                Case(('x ^ y', 2, 2), {}, 0),
                Case(('x ^ y', 2, 3), {}, 1),
                Case(('x ^ y', 1, 3), {}, 2),
                Case(('x ^ y', 1, 2), {}, 3)])

        # Bitwise OR
        with self.subTest(symbol='|'):
            self.assertCaseEqual(peval, [
                Case(('x | y', 2, 2), {}, 2),
                Case(('x | y', 2, 3), {}, 3),
                Case(('x | y', 1, 3), {}, 3),
                Case(('x | y', 1, 2), {}, 3)])

    def test_PyOperators_arithmetic(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Unary Plus
        with self.subTest(symbol='+'):
            self.assertCaseEqual(peval, [
                Case(('+x', 1), {}, 1),
                Case(('+x', -1), {}, -1),
                Case(('+(+x)', 1), {}, 1),
                Case(('+(+x)', -1), {}, -1)])

        # Negation
        with self.subTest(symbol='-'):
            self.assertCaseEqual(peval, [
                Case(('-x', 1), {}, -1),
                Case(('-x', -1), {}, 1),
                Case(('-(-x)', 1), {}, 1),
                Case(('-(-x)', -1), {}, -1)])

        # Exponentiation
        with self.subTest(symbol='**'):
            self.assertCaseEqual(peval, [
                Case(('x ** y', 1, 1), {}, 1),
                Case(('x ** y', 1., 1), {}, 1.),
                Case(('x ** y', 4, .5), {}, 2.),
                Case(('x ** y', 2, 2.), {}, 4.)])

        # Division
        with self.subTest(symbol='/'):
            self.assertCaseEqual(peval, [
                Case(('x / y', 1, 1), {}, 1.),
                Case(('x / y', 2, 1), {}, 2.),
                Case(('x / y', 1, .2), {}, 5.),
                Case(('x / y', 1, 2), {}, .5)])

        # Floor Division
        with self.subTest(symbol='//'):
            self.assertCaseEqual(peval, [
                Case(('x // y', 1, 1), {}, 1),
                Case(('x // y', 2, 1), {}, 2),
                Case(('x // y', 1, .2), {}, 4),
                Case(('x // y', 1, 2), {}, 0)])

        # Remainder
        with self.subTest(symbol='%'):
            self.assertCaseEqual(peval, [
                Case(('x % y', 2, 3), {}, 2),
                Case(('x % y', 3, 2), {}, 1),
                Case(('x % y', 2, 1), {}, 0),
                Case(('x % y', .1, .5), {}, .1)])

        # Multiplication
        with self.subTest(symbol='*'):
            self.assertCaseEqual(peval, [
                Case(('x * y', -1, -1), {}, 1),
                Case(('x * y', 2, .5), {}, 1),
                Case(('x * y', 2, 2), {}, 4),
                Case(('x * y', -.5, .5), {}, -.25)])

        # Addition
        with self.subTest(symbol='+'):
            self.assertCaseEqual(peval, [
                Case(('x + y', 0, 1), {}, 1),
                Case(('x + y', -1, 1), {}, 0),
                Case(('x + y', 2, 2), {}, 4),
                Case(('x + y', .5, .5), {}, 1)])

        # Subtraction
        with self.subTest(symbol='-'):
            self.assertCaseEqual(peval, [
                Case(('x - y', 0, 1), {}, -1),
                Case(('x - y', -1, 1), {}, -2),
                Case(('x - y', 2, 2), {}, 0),
                Case(('x - y', .5, .5), {}, 0)])

    @unittest.skipUnless(np, 'requires numpy')
    def test_PyOperators_matrix_product(self) -> None:
        p = parser.Parser(vocabulary=parser.PyOperators())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Matrix Product
        with self.subTest(symbol='@'):
            N = np.matrix([(0, 0), (0, 0)]) # Zero Matrix
            I = np.matrix([(1, 0), (0, 1)]) # Identity Matrix
            C = np.matrix([(0, 1), (1, 0)]) # Row Exchange Matrix
            X = np.matrix([(1, 0), (0, 0)]) # Projection to 'x' Component
            Y = np.matrix([(0, 0), (0, 1)]) # Projection to 'y' Component

            self.assertCaseEqual(peval, [
                Case(('X @ Y', I, I), {}, I),
                Case(('X @ Y', I, X), {}, X),
                Case(('X @ Y', Y, I), {}, Y),
                Case(('X @ Y', N, I), {}, N),
                Case(('X @ Y', X, N), {}, N),
                Case(('X @ Y', C, C), {}, I),
                Case(('X @ Y', X, Y), {}, N)])

    def test_PyBuiltin(self) -> None:
        # The parser evaluation of the Python Builtin Vocabulary is seperately
        # tested within individual categories
        pass

    def test_PyBuiltin_constants(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Builtin Constants
        self.assertCaseEqual(peval, [
            Case(('True', ), {}, True),
            Case(('False', ), {}, False),
            Case(('None', ), {}, None),
            Case(('Ellipsis', ), {}, Ellipsis)])

    def test_PyBuiltin_types(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Builtin Number Types
        self.assertCaseEqual(peval, [
            Case(('bool(x)', 1), {}, True),
            Case(('complex(x)', 1), {}, 1+0j),
            Case(('float(x)', 1), {}, 1.),
            Case(('int(x)', 1.), {}, 1.)])

        # Builtin Container Types
        self.assertCaseEqual(peval, [
            Case(('bytearray(x)', 1), {}, bytearray(b'\x00')),
            Case(('bytearray(x, e)', 'x', 'utf8'), {}, bytearray(b'x')),
            Case(('bytes(x)', 1), {}, b'\x00'),
            Case(('bytes(x, e)', 'x', 'utf8'), {}, b'x'),
            Case(('dict(s)', [(1, 1)]), {}, {1: 1}),
            Case(('frozenset(l)', [1, 2]), {}, frozenset([1, 2])),
            Case(('list(a)', (1, 2, 3)), {}, [1, 2, 3]),
            Case(('list(memoryview(x))', b'x'), {}, [120]),
            Case(('str(o)', list()), {}, '[]'),
            Case(('set(l)', [1, 2, 3]), {}, {1, 2, 3}),
            Case(('tuple(l)', [1, 2, 3]), {}, (1, 2, 3))])

        # Further Builtin Types
        # Note: object and type are tested within test_PyBuiltin_oop()
        self.assertCaseEqual(peval, [
            Case(('slice(n)', 3), {}, slice(3))])

    def test_PyBuiltin_conversion(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Conversion
        self.assertCaseEqual(peval, [
            Case(('ascii(x)', 1), {}, '1'),
            Case(('bin(x)', 1), {}, '0b1'),
            Case(('chr(x)', 65), {}, 'A'),
            Case(('format(x)', 'A'), {}, 'A'),
            Case(('hex(x)', 1), {}, '0x1'),
            Case(('oct(x)', 1), {}, '0o1'),
            Case(('ord(x)', 'A'), {}, 65)])

    def test_PyBuiltin_math(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Simple mathematical functions
        self.assertCaseEqual(peval, [
            Case(('abs(x)', -1), {}, 1),
            Case(('divmod(a, b)', 2, 1), {}, (2, 0)),
            Case(('max(l)', [1, 2, 3]), {}, 3),
            Case(('min(l)', [1, 2, 3]), {}, 1),
            Case(('pow(x, y)', 2, 2), {}, 4),
            Case(('round(x)', .6), {}, 1),
            Case(('sum(l)', [1, 2, 3]), {}, 6)])

    def test_PyBuiltin_oop(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Builtin Types for Object Oriented Programming
        self.assertCaseEqual(peval, [
            Case(('isinstance(object(), c)', object), {}, True),
            Case(('type(o)', object), {}, type)])

        # Builtin functions for Object and Class Tree Organisation
        self.assertCaseEqual(peval, [
            Case(('isinstance(a, b)', 1, int), {}, True),
            Case(('issubclass(a, b)', int, int), {}, True)])

        # Builtin functions for Attribute Organisation
        self.assertCaseEqual(peval, [
            Case(('delattr(o, a)', mock.Mock(), 'a'), {}, None),
            Case(('dir(o)', object), {}, dir(object)),
            Case(('getattr(o, a)', 1j, 'imag'), {}, 1.),
            Case(('hasattr(o, a)', 1j, 'imag'), {}, True),
            Case(('setattr(o, a, v)', mock.Mock(), 'a', 0), {}, None)])

        # Builtin functions for special Methods
        self.assertCaseEqual(peval, [
            Case(('bool(classmethod(o))', object), {}, True),
            Case(("hasattr(property(), 'getter')", ), {}, True),
            Case(("hasattr(staticmethod(f), '__func__')", list), {}, True)])

        # Builtin functions for special Attributes
        self.assertCaseEqual(peval, [
            Case(('callable(o)', object), {}, True),
            Case(('hash(o)', 1), {}, 1),
            Case(('len(o)', [1, 2, 3]), {}, 3),
            Case(('repr(o)', 'x'), {}, "'x'"),
            Case(('sorted(vars(o))', type), {}, sorted(vars(type)))])

    def test_PyBuiltin_functional(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Functional Programming and Iterator functions
        self.assertCaseEqual(peval, [
            Case(('all(l)', [1, 1, 0]), {}, False),
            Case(('any(l)', [1, 1, 0]), {}, True),
            Case(('list(enumerate(l))', [1, 2]), {}, [(0, 1), (1, 2)]),
            Case(('list(filter(None, l))', []), {}, []),
            Case(('list(iter(l))', [1, 2, 3]), {}, [1, 2, 3]),
            Case(('list(map(f, l))', bool, [0]), {}, [False]),
            Case(('next(iter(l))', [1, 2, 3]), {}, 1),
            Case(('list(range(n))', 3), {}, [0, 1, 2]),
            Case(('sorted(l)', [3, 2, 1]), {}, [1, 2, 3]),
            Case(('list(zip(l, l))', range(2)), {}, [(0, 0), (1, 1)])])

    def test_PyBuiltin_runtime(self) -> None:
        p = parser.Parser(vocabulary=parser.PyBuiltin())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        # Runtime Evaluation and Meta Programming
        # TODO: Untested functions: breakpoint(), help(), input(), print()
        self.assertCaseEqual(peval, [
            Case(('bool(compile(a, b, c))', '1', '1', 'eval'), {}, True),
            Case(('eval(e)', 'True'), {}, True),
            Case(('exec(e)', 'True'), {}, None),
            Case(('bool(globals())', ), {}, True),
            Case(('id(x)', None), {}, id(None)),
            Case(('bool(locals())', ), {}, True)])

    def test_Parser(self) -> None:
        # Implicitely tested within test_PyOperators() and test_PyBuiltin()
        pass

    def test_Expression(self) -> None:
        pass # Explicitely tested by partial test of the methods

    def test_Expression_eval(self) -> None:

        p = parser.Parser(vocabulary=PyExprEval())
        peval: AnyOp = lambda expr, *args: p.parse(expr).eval(*args)

        self.assertCaseEqual(peval, [
            Case(("Ee1", 2), {}, 2),
            Case(("Ee1 + 1", 1), {}, 2),
            Case(('2^x', 3), {}, 8.),
            Case(('2 - 3^x', 4), {}, -79.),
            Case(('-2 - 3^x', 4), {}, -83.),
            Case(('-3^x', 4), {}, -81.),
            Case(('(-3)^x', 4), {}, 81.),
            Case(('2*x + y', 4, 1), {}, 9),
            Case(("'x' == 'x'", ), {}, True),
            Case(("(a + b) == c", 1, 2, 3), {}, True),
            Case(("(a + b) != c", 1, 2, 3), {}, False),
            Case(("x || y", 'hi ', 'u'), {}, 'hi u'),
            Case(("'x' || 'y'", ), {}, 'xy'),
            Case(("concat('hi', ' ', 'u')", ), {}, 'hi u'),
            Case(('if(a>b, 5, 6)', 8, 3), {}, 5),
            Case(('if(a, b, c)', None, 1, 3), {}, 3),
            Case(('a, 3', [1, 2]), {}, [[1, 2], 3]),
            Case((".1", ), {}, .1),
            Case((".5^3", ), {}, .125),
            Case(("16^.5", ), {}, 4.),
            Case(("8300*.8", ), {}, 6640.),
            Case(('"abc"*2', 2), {}, 'abcabc'),
            Case(("a^2-b^2==(a+b)*(a-b)", 12, 4), {}, True),
            Case(("a^2-b^2+1==(a+b)*(a-b)", 5, 2), {}, False),
            Case(("concat('a\n','\n','\rb')=='a\n\n\rb'", ), {}, True),
            Case(("a==''", ''), {}, True)])

        self.assertRaises(ValueError, peval, '..5')

    def test_Expression_subst(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        peval: AnyOp = lambda e, v, w, *args: p.parse(e).subst(v, w).eval(*args)

        self.assertCaseEqual(peval, [
            Case(('2*x + 1', 'x', '4*x', 3), {}, 25),
            Case(('a + 1', 'a', 'b', 3), {}, 4)])

    def test_Expression_simplify(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        psubs: AnyOp = lambda e, d, *args: p.parse(e).simplify(d).eval(*args)
        pvars: AnyOp = lambda e, d: p.parse(e).simplify(d).variables

        # expr = p.parse('x * (y * atan(1))').simplify({'y': 4})
        # self.assertIn('x*3.141592', expr.to_string())

        self.assertCaseEqual(psubs, [
            Case(("x / ((x + y))", {}, 1, 1), {}, .5),
            Case(('x * (y * 1)', {'y': 4}, 2), {}, 8)])

        self.assertCaseEqual(pvars, [
            Case(('x * (y * atan(1))', {'y': 4}), {}, ('x', ))])

    def test_Expression_to_string(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        pstr: AnyOp = lambda e: str(p.parse(e))

        self.assertCaseEqual(pstr, [
            Case(("'a'=='b'", ), {}, "'a' == 'b'"),
            Case(("func(a,1.51,'ok')", ), {}, "func(a, 1.51, 'ok')")])

    def test_Expression_variables(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        pvars: AnyOp = lambda e: p.parse(e).variables

        self.assertCaseEqual(pvars, [
            Case(('x * (y * atan(1))', ), {}, ('x', 'y')),
            Case(('pow(x, y)', ), {}, ('x', 'y')),
            Case(("PI", ), {}, tuple()),
            Case(("PI ", ), {}, tuple()),
            Case(("E ", ), {}, tuple()),
            Case((" E", ), {}, tuple()),
            Case(("E", ), {}, tuple()),
            Case(("E+1", ), {}, tuple()),
            Case(("E/1", ), {}, tuple()),
            Case(("sin(PI)+E", ), {}, tuple()),
            Case(('Pie', ), {}, ('Pie', )),
            Case(('PIe', ), {}, ('PIe', )),
            Case(('Eval', ), {}, ('Eval', )),
            Case(('Eval1', ), {}, ('Eval1', )),
            Case(('EPI', ), {}, ('EPI', )),
            Case(('PIE', ), {}, ('PIE', )),
            Case(('Engage', ), {}, ('Engage', )),
            Case(('Engage * PIE', ), {}, ('Engage', 'PIE')),
            Case(('Engage_', ), {}, ('Engage_', )),
            Case(('Engage1', ), {}, ('Engage1', )),
            Case(('E1', ), {}, ('E1', )),
            Case(('PI2', ), {}, ('PI2', )),
            Case(('(E1 + PI)', ), {}, ('E1', )),
            Case(('E1_', ), {}, ('E1_', )),
            Case(('E_', ), {}, ('E_', ))])

    def test_Parser_symbols(self) -> None:
        p = parser.Parser(vocabulary=PyExprEval())
        psyms: AnyOp = lambda e: p.parse(e).symbols

        self.assertCaseEqual(psyms, [
            Case(('pow(x,y)', ), {}, ('pow', 'x', 'y'))])

    def test_Token(self) -> None:
        pass # Implicitely tested by test_Parser


import pickle
import pandas as pd
from sklearn.linear_model import LogisticRegression

df = pd.read_csv("churn_agg1.csv")
X = df.iloc[:, :-1]
y = df.iloc[:, -1] # churn (1) or non-churn (0)

model = LogisticRegression(class_weight = 'balanced',
                                    penalty = 'l2',
                                    C = 0.9,
                                    solver = 'saga',
                                    #l1_ratio = 0.5,
                                    n_jobs = -1,
                                    random_state = 2)
model.fit(X, y)

with open('model.pkl', 'wb') as f:
    pickle.dump(model, f)


import subprocess

rule126 = {
    '000' : '0',
    '001' : '1',
    '010' : '1',
    '011' : '1',
    '100' : '1',
    '101' : '1',
    '110' : '1',
    '111' : '0',
}

def _rule126(_in):
    # binstr = bin(_in)[2:].rjust(32,'0')
    binstr = _in
    binstr = binstr[-1:] + binstr + binstr[:2]
    _out = ''
    for i in range(len(binstr)-3) :
        _out += rule126[binstr[i:i+3]]
    return hex(int(_out,2))

def reverse(_in,_out):
    binstr = bin(_in)[2:].rjust(32,'0')

    binstr = binstr[-1:] + binstr + binstr[:2]
    _out = ''
    for i in range(len(binstr)-3) :
        _out += rule126[binstr[i:i+3]]
    return hex(int(_out,2))

# 0110011011011110001111000001101111111000011111111101111111001111

# def reversebit(idx, cur, target):

cur = ['00','11']

target = '0110011011011110001111000001101111111000011111111101111111001111'
# target = '01110011111111111110001110111000'
idx = 0
res = set()

def reversebit(idx,cur,target):
    if idx == len(target) :
        if cur[-1] == cur[0]:
            if _rule126(cur[1:-1]) == '0x66de3c1bf87fdfcf':
                res.add(cur[1:-1])
        return
    for b in ['0','1'] :
        cand = cur[-2:] + b
        if rule126[cand] == target[idx]:
            reversebit(idx+1,cur + b,target)

for c in cur :
    reversebit(idx,c,target)

for r in res:
    key = hex(int(r,2))[2:]
    flag = "U2FsdGVkX1/andRK+WVfKqJILMVdx/69xjAzW4KUqsjr98GqzFR793lfNHrw1Blc8UZHWOBrRhtLx3SM38R1MpRegLTHgHzf0EAa3oUeWcQ="
    p = subprocess.Popen(f'echo "{key}" > /tmp/plain.key;', stdout=subprocess.PIPE)
    p = subprocess.Popen(f'xxd -r -p /tmp/plain.key > /tmp/enc.key;', stdout=subprocess.PIPE)
    p = subprocess.Popen(f'echo "{flag}" | openssl enc -d -aes-256-cbc -pbkdf2 -md sha1 -base64 --pass file:/tmp/enc.key;', stdout=subprocess.PIPE)
    result = p.communicate()[0]
    print(result)

googleCTF/Reverse a cellular automata/rule.py


from __future__ import annotations

from dataclasses import dataclass
from typing import Optional
from leeger.model.abstract.EqualityCheck import EqualityCheck
from leeger.util.CustomLogger import CustomLogger

from leeger.util.JSONDeserializable import JSONDeserializable
from leeger.util.JSONSerializable import JSONSerializable
from leeger.util.equality import modelEquals

@dataclass(kw_only=True, eq=False)
class YearSettings(EqualityCheck, JSONSerializable, JSONDeserializable):
    __LOGGER = CustomLogger.getLogger()
    leagueMedianGames: Optional[bool] = False

    def __post_init__(self):
        if self.leagueMedianGames is None:
            self.leagueMedianGames = False

    def equals(
        self,
        otherYearSettings: YearSettings,
        *,
        ignoreIds: bool = False,
        ignoreBaseIds: bool = False,
        logDifferences: bool = False,
    ) -> bool:
        """
        Checks if *this* YearSettings is the same as the given YearSettings.
        """

        return modelEquals(
            objA=self,
            objB=otherYearSettings,
            baseFields={"leagueMedianGames"},
            parentKey="YearSettings",
            ignoreIdFields=ignoreIds,
            ignoreBaseIdField=ignoreBaseIds,
            logDifferences=logDifferences,
        )

    def __eq__(self, otherYearSettings: YearSettings) -> bool:
        self.__LOGGER.info("Use .equals() for more options when comparing YearSettings instances.")
        return self.equals(otherYearSettings=otherYearSettings)

    def toJson(self) -> dict:
        return {"leagueMedianGames": self.leagueMedianGames}

    @staticmethod
    def fromJson(d: dict) -> YearSettings:
        return YearSettings(leagueMedianGames=d.get("leagueMedianGames"))


'''
Copy the original classified pictures to one directory
'''

import os
import os.path as op
from shutil import copy

img_dir = './MASAD_imgs'
os.mkdir(img_dir)

imgs_path = []
imgs_set = set()
root = './MASAD_data'
for root in [op.join(root, 'train', 'image'), op.join(root, 'test', 'image')]:
    for polarity in ['negative', 'positive']:
        path1 = op.join(root, polarity)
        for cata in os.listdir(path1):
            path2 = op.join(path1, cata)
            if op.isdir(path2):
                for img in os.listdir(path2):
                    if img in imgs_set:  # there may be same images in different directories
                        continue
                    else:
                        imgs_set.add(img)
                        path3 = op.join(path2, img)  # full image path
                        imgs_path.append(path3)
print(len(imgs_path))
for img in imgs_path:
    copy(img, img_dir)


print("\033[1:34m==========TENTE ADIVINHAR O NÚMERO!==========\033[m")
print("\033[1:34m================ ( 0 a 10 ) =================\033[m")
print("=-="*15)
import random
n = random.randint(0,10)
c=1
tentativas = 0
while c != n:
    c = int(input("Qual número eu pensei? "))
    if n != c:
        tentativas += 1
        print("Você errou! Tente novamente!")
    else:
        print("\033[1:34mVocê acertou!\033[m")
        print("VOCÊ TENTOU {} VEZES!".format(tentativas))


import requests
import time

'''
****************
CONFIG
****************
'''

dataURL = "http://pulsedata57.hkustvis.org/data"
allowedPeopleLessThan = 400
attemptsMax = 100
watchKeyword = "ct1"
from barkKey import barkKey
barkURL = "https://api.day.app/" + barkKey + "/"

MSGtitle = "Eating Time"
MSGbody = "Less people than your setting"

barkURL += MSGtitle + "/" + MSGbody

'''
****************
END OF CONFIG
****************
'''

def getRawDate():
    try:
        response= requests.get(dataURL)
        if response.status_code!=200:
            return None
    except RequestException:
        return None
    raw = response.json()
    return raw['count']['zones'][watchKeyword]

def main():
    attempts = 0
    rev = getRawDate()
    while rev == None:
        attempts += 1
        time.sleep(3)
        rev = getRawDate()
        if attempts > attemptsMax:
            return -1
    if rev <= allowedPeopleLessThan:
        while rev != 200:
            URL = barkURL + ": " + str(rev) + " people."
            response = requests.get(URL)
            rev = response.json()["code"]

if __name__ == "__main__":
    main()


#!/usr/bin/env python3

"""A simple JAX process launcher for multiple devices on a single host.

You must import jax_local_cluster somewhere inside the script you are launching.
"""

import argparse
from functools import partial
import os
import signal
import socketserver
from subprocess import Popen, TimeoutExpired
import sys

import jax
import jax._src as _src

error = partial(print, file=sys.stderr)

class LocalCluster(_src.clusters.ClusterEnv):
    @classmethod
    def is_env_present(cls):
        return "JAX_COORDINATOR_ADDRESS" in os.environ

    @classmethod
    def get_coordinator_address(cls):
        return os.environ["JAX_COORDINATOR_ADDRESS"]

    @classmethod
    def get_process_count(cls):
        return int(os.environ["JAX_PROCESS_COUNT"])

    @classmethod
    def get_process_id(cls):
        return int(os.environ["JAX_PROCESS_ID"])

    @classmethod
    def get_local_process_id(cls):
        return int(os.environ["JAX_LOCAL_PROCESS_ID"])

def get_free_port():
    with socketserver.TCPServer(("127.0.0.1", 0), None) as s:
        return s.server_address[1]

def signal_and_wait(signum, procs, ctx, timeout=None):
    for proc in procs:
        proc.send_signal(signum)
    for i, proc in enumerate(procs):
        ctx["i"] = i
        proc.wait(timeout)
    ctx["i"] = None

def interactive_shutdown(procs):
    ctx = {"i": None}
    try:
        signal_and_wait(signal.SIGINT, procs, ctx)
    except KeyboardInterrupt:
        try:
            error(
                f"Process {ctx['i']} (pid {procs[ctx['i']].pid}) did not exit on SIGINT, trying SIGTERM"
            )
            signal_and_wait(signal.SIGTERM, procs, ctx, timeout=1)
        except (KeyboardInterrupt, TimeoutExpired):
            error(
                f"Process {ctx['i']} (pid {procs[ctx['i']].pid}) did not exit on SIGTERM, trying SIGKILL"
            )
            for proc in procs:
                proc.kill()

class TerminationHandler:
    def __init__(self, procs, verbose):
        self.procs = procs
        self.verbose = verbose
        self.was_called = False

    def __call__(self, signum, frame):
        self.was_called = True
        if self.verbose:
            error("SIGTERM received, shutting down")
        try:
            signal_and_wait(signal.SIGTERM, self.procs, {}, timeout=1)
        except TimeoutExpired:
            if self.verbose:
                error("SIGTERM timed out, sending SIGKILL")
            for proc in self.procs:
                proc.kill()
        raise KeyboardInterrupt

def main():
    p = argparse.ArgumentParser(description=__doc__)
    p.add_argument(
        "-n",
        type=int,
        default=0,
        help="Number of processes to launch (default: one per local device)",
    )
    p.add_argument(
        "--port",
        type=int,
        default=0,
        help="Port to use for the coordinator (default: a free port)",
    )
    p.add_argument("-v", "--verbose", action="store_true", help="Verbose output")
    p.add_argument("command", type=str, nargs=argparse.REMAINDER, help="Command to run")
    args = p.parse_args()

    if not args.command:
        p.print_help()
        sys.exit(1)

    n = args.n if args.n else jax.local_device_count()
    if args.verbose:
        error(f"Launching {n} processes")
    port = args.port if args.port else get_free_port()
    if args.verbose:
        error(f"Using port {port} for coordinator")

    procs = []
    sigterm_handler = TerminationHandler(procs, args.verbose)
    signal.signal(signal.SIGTERM, sigterm_handler)

    try:
        for i in range(n):
            env = os.environ.copy()
            env.pop("OMPI_MCA_orte_hnp_uri", None)
            env.pop("SLURM_JOB_ID", None)
            env["JAX_COORDINATOR_ADDRESS"] = f"127.0.0.1:{port}"
            env["JAX_PROCESS_COUNT"] = str(n)
            env["JAX_PROCESS_ID"] = str(i)
            env["JAX_LOCAL_PROCESS_ID"] = str(i)
            proc = Popen(args.command, env=env)
            if args.verbose:
                error(f"Launched process {i} (pid {proc.pid})")
            procs.append(proc)
        for proc in procs:
            proc.wait()
    except KeyboardInterrupt:
        pass
    finally:
        if not sigterm_handler.was_called:
            interactive_shutdown(procs)
        if args.verbose:
            error("All processes terminated")

if __name__ == "__main__":
    main()


import csv
import matplotlib.pyplot as plt
import sqlite3
import requests
import json
import os

#create table that will contain data for number of positive COVID-19 cases in DC given a date
def create_covid_cases_table(cur, conn):
    cur.execute("CREATE TABLE IF NOT EXISTS Cases (Date INTEGER, Cases INTEGER)")
    conn.commit()

#get the request url to access the COVID tracking API based on the date
def get_request_url(date):
    base_url = "https://api.covidtracking.com"
    request_url = base_url + "/v1/states/dc/{}.json" .format(date)
    return request_url

#gets data from the API only if data does not already exist in Cases table
def get_covid_cases_data(cur, conn, date):
    #gets request url
    url = get_request_url(date)

    #checking to see if date is already in table
    cur.execute("SELECT * FROM Cases WHERE Date = ?", (date, ))
    exists = cur.fetchone()

    #if data not already in table, try grabbing data and returning # of positive cases
    if exists == None:
        try:
            response = requests.get(url)
            json_data = json.loads(response.text)
            cases = json_data.get('positive')
            return cases
    #if exception occurs, prints exception
        except:
            print("Exception")
            return None
    #lets me know if data does already exist in table
    else:
        print("Data already exists")
        return None

#adds data to database table Cases 25 items at a time for the first 100 items
def add_data_to_database(cur, conn, dates, cases):
    cur.execute("SELECT * FROM Cases")
    entries = cur.fetchall()
    if len(entries) == 0:
        for i in range(25):
            cur.execute("INSERT INTO Cases (Date, Cases) Values (?,?)", (dates[i], cases[i],))
            conn.commit()
    elif len(entries) == 25:
        for i in range(25,50):
            cur.execute("INSERT INTO Cases (Date, Cases) Values (?,?)", (dates[i], cases[i],))
            conn.commit()
    elif len(entries) == 50:
        for i in range(50,75):
            cur.execute("INSERT INTO Cases (Date, Cases) Values (?,?)", (dates[i], cases[i],))
            conn.commit()
    elif len(entries) == 75:
        for i in range(75,100):
            cur.execute("INSERT INTO Cases (Date, Cases) Values (?,?)", (dates[i], cases[i],))
            conn.commit()
    elif len(entries) == 100:
        for i in range(100, len(dates)):
            cur.execute("INSERT INTO Cases (Date, Cases) Values (?,?)", (dates[i], cases[i],))
            conn.commit()

def main():

#the following lists are just creating lists of dates in the appropriate format for the API
    march_dates_list = []
    for i in range (7,32):
        if i < 10:
            date_string = "2020030" + str(i)
        else:
            date_string = "202003" + str(i)
        march_dates_list.append(date_string)

    april_dates_list1 = []
    for i in range(1,26):
        if i < 10:
            date_string = "2020040" + str(i)
        else:
            date_string = "202004" + str(i)
        april_dates_list1.append(date_string)

    april_dates_list2 = []
    for i in range(26,31):
        date_string = "202004" + str(i)
        april_dates_list2.append(date_string)

    may_dates_list1 = []
    for i in range (1,26):
        if i < 10:
            date_string = "2020050" + str(i)
        else:
            date_string = "202005" + str(i)
        may_dates_list1.append(date_string)

    may_dates_list2 = []
    for i in range(26,32):
        date_string = "202005" + str(i)
        may_dates_list2.append(date_string)

    june_dates_list1 = []
    for i in range (1,26):
        if i < 10:
            date_string = "2020060" + str(i)
        else:
            date_string = "202006" + str(i)
        june_dates_list1.append(date_string)

    june_dates_list2 = []
    for i in range(26,31):
        date_string = "202006" + str(i)
        june_dates_list2.append(date_string)

    july_dates_list1 = []
    for i in range (1,26):
        if i < 10:
            date_string = "2020070" + str(i)
        else:
            date_string = "202007" + str(i)
        july_dates_list1.append(date_string)

    july_dates_list2 = []
    for i in range(26,32):
        date_string = "202007" + str(i)
        july_dates_list2.append(date_string)

    august_dates_list1 = []
    for i in range (1,26):
        if i < 10:
            date_string = "2020080" + str(i)
        else:
            date_string = "202008" + str(i)
        august_dates_list1.append(date_string)

    august_dates_list2 = []
    for i in range(26,32):
        date_string = "202008" + str(i)
        august_dates_list2.append(date_string)

    september_dates_list1 = []
    for i in range (1,26):
        if i < 10:
            date_string = "2020090" + str(i)
        else:
            date_string = "202009" + str(i)
        september_dates_list1.append(date_string)

    september_dates_list2 = []
    for i in range(26,31):
        date_string = "202009" + str(i)
        september_dates_list2.append(date_string)

    october_dates_list1 = []
    for i in range (1,26):
        if i < 10:
            date_string = "2020100" + str(i)
        else:
            date_string = "202010" + str(i)
        october_dates_list1.append(date_string)

    october_dates_list2 = []
    for i in range(26,32):
        date_string = "202010" + str(i)
        october_dates_list2.append(date_string)

    november_dates_list1 = []
    for i in range (1,26):
        if i < 10:
            date_string = "2020110" + str(i)
        else:
            date_string = "202011" + str(i)
        november_dates_list1.append(date_string)

    november_dates_list2 = []
    for i in range(26,31):
        date_string = "202011" + str(i)
        november_dates_list2.append(date_string)

    december_dates_list = []
    for i in range(1,8):
        date_string = "2020120" + str(i)
        december_dates_list.append(date_string)

#this adds all of the lists together into one final list with every date from March 7th-December 7th in the appropriate format for the COVID API
    total_dates = []
    total_dates = [march_dates_list,april_dates_list1,april_dates_list2,may_dates_list1,may_dates_list2,june_dates_list1,june_dates_list2,july_dates_list1,july_dates_list2,august_dates_list1,august_dates_list2,september_dates_list1,september_dates_list2,october_dates_list1,october_dates_list2,november_dates_list1,november_dates_list2,december_dates_list]
    flat_dates_list = []
    for sublist in total_dates:
        for item in sublist:
            flat_dates_list.append(item)

#getting the current working directory, connecting to the database, and creating the Cases table
    path = os.path.dirname(os.path.abspath(__file__))
    conn = sqlite3.connect(path+ '/' + "covid_data.db")
    cur = conn.cursor()
    create_covid_cases_table(cur,conn)

#getting a list of the positive cases in chronological order to be added to the table
    cases_list = []
    for date in flat_dates_list:
        data = get_covid_cases_data(cur,conn,date)
        cases_list.append(data)

#adding data to Cases table based on dates list and postiive cases list
    add_data_to_database(cur,conn,flat_dates_list,cases_list)

if __name__ == "__main__":
    main()


import collections
import numpy as np
from typing import List

#cant binary search it. it requires two-pointer.
#There is no correlation between the middle value and the left and right pointers.
class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        l, r = 0, len(numbers)-1
        while l < r:
            mid = l + (r-l)//2
            if numbers[mid] + numbers[mid+1] == target:
                return [mid+1, mid+2]
            if numbers[mid-1] + numbers[mid] == target:
                return [mid, mid+1]
            if numbers[l] + numbers[r]==target and l!=r:
                return [l+1,r+1]
            if numbers[r] > target:
                r-=1
            elif numbers[mid]+numbers[r] < target:
                l = mid + 1
            else:
                r = mid
            print(l,r,mid)
        print('s')
        return sorted([l+1,r+1])

s = Solution()
#2,3
print(s.twoSum([5, 25, 75], 100))
#1,2
print(s.twoSum([2,7,11,15], 9))
#2,3
print(s.twoSum([2,3,4], 6))
#1,2
print(s.twoSum([0,0,3,4], 0))
#3,6
print(s.twoSum([3,24,50,79,88,150,345],200))


import fnmatch
import os
import warnings
from concurrent.futures import ProcessPoolExecutor, as_completed
from functools import partial
from pprint import pprint

import exiftool
from tqdm import tqdm

import micasense.capture as capture
import micasense.image as image

warnings.simplefilter(action="once")

# FIXME: mirrors Capture.append_file(). Not used. Does this still belong here?
def image_from_file(filename):
    return image.Image(filename)

def parallel_process(function, iterable, parameters, progress_callback=None, use_tqdm=False):
    """
    Multiprocessing Pool handler.
    :param function: function used in multiprocessing call
    :param iterable: iterable holding objects passed to function for each process
    :param parameters: dict of any function parameters other than the iterable object
    :param use_tqdm: boolean True to use tqdm progress bar
    :param progress_callback: function to report progress to
    :return: None
    """

    with ProcessPoolExecutor() as pool:
        # run multiprocessing
        futures = [pool.submit(partial(function, parameters), i) for i in iterable]

        if use_tqdm:
            # kwargs for tqdm
            kwargs = {
                'total': len(futures),
                'unit': 'Capture',
                'unit_scale': False,
                'leave': True
            }

            # Receive Future objects as they complete. Print out the progress as tasks complete
            for _ in tqdm(iterable=as_completed(futures), desc='Processing ImageSet', **kwargs):
                pass
        elif progress_callback is not None:
            futures_len = float(len(futures))
            for i, _ in enumerate(as_completed(futures)):
                progress_callback(float(i) / futures_len)

def save_capture(params, cap):
    """
    Process an ImageSet according to program parameters. Saves rgb
    :param params: dict of program parameters from ImageSet.process_imageset()
    :param cap: micasense.capture.Capture object
    """
    try:
        # align capture
        if len(cap.images) == params['capture_len']:
            cap.create_aligned_capture(
                irradiance_list=params['irradiance'],
                warp_matrices=params['warp_matrices'],
                img_type=params['img_type']
            )
        else:
            print(f"\tCapture {cap.uuid} only has {len(cap.images)} Images. Should have {params['capture_len']}. "
                  f"Skipping...")
            return

        if params['output_stack_dir']:
            output_stack_file_path = os.path.join(params['output_stack_dir'], cap.uuid + '.tif')
            if params['overwrite'] or not os.path.exists(output_stack_file_path):
                cap.save_capture_as_stack(output_stack_file_path)
        if params['output_rgb_dir']:
            output_rgb_file_path = os.path.join(params['output_rgb_dir'], cap.uuid + '.jpg')
            if params['overwrite'] or not os.path.exists(output_rgb_file_path):
                cap.save_capture_as_rgb(output_rgb_file_path)

        cap.clear_image_data()
    except Exception as e:
        print(e)
        pprint(params)
        quit()

class ImageSet(object):
    """An ImageSet is a container for a group of Captures that are processed together."""

    def __init__(self, captures):
        self.captures = captures
        captures.sort()

    @classmethod
    def from_directory(cls, directory, progress_callback=None, use_tqdm=False, exiftool_path=None):
        """
        Create an ImageSet recursively from the files in a directory.
        :param directory: str system file path
        :param progress_callback: function to report progress to
        :param use_tqdm: boolean True to use tqdm progress bar
        :param exiftool_path: str system file path to exiftool location
        :return: ImageSet instance
        """

        # progress_callback deprecation warning
        if progress_callback is not None:
            warnings.warn(message='The progress_callback parameter will be deprecated in favor of use_tqdm',
                          category=PendingDeprecationWarning)

        # ensure exiftoolpath is found per MicaSense setup instructions
        if exiftool_path is None and os.environ.get('exiftoolpath') is not None:
            exiftool_path = os.path.normpath(os.environ.get('exiftoolpath'))

        cls.basedir = directory
        matches = []
        for root, _, filenames in os.walk(directory):
            [matches.append(os.path.join(root, filename)) for filename in fnmatch.filter(filenames, '*.tif')]

        images = []

        with exiftool.ExifTool(exiftool_path) as exift:
            if use_tqdm:  # to use tqdm progress bar instead of progress_callback
                kwargs = {
                    'total': len(matches),
                    'unit': ' Files',
                    'unit_scale': False,
                    'leave': True
                }
                for path in tqdm(iterable=matches, desc='Loading ImageSet', **kwargs):
                    images.append(image.Image(path, exiftool_obj=exift))
            else:
                print('Loading ImageSet from: {}'.format(directory))
                for i, path in enumerate(matches):
                    images.append(image.Image(path, exiftool_obj=exift))
                    if progress_callback is not None:
                        progress_callback(float(i) / float(len(matches)))

        # create a dictionary to index the images so we can sort them into captures
        # {
        #     "capture_id": [img1, img2, ...]
        # }
        captures_index = {}
        for img in images:
            c = captures_index.get(img.capture_id)
            if c is not None:
                c.append(img)
            else:
                captures_index[img.capture_id] = [img]
        captures = []
        for cap_imgs in captures_index:
            imgs = captures_index[cap_imgs]
            newcap = capture.Capture(imgs)
            captures.append(newcap)
        if progress_callback is not None:
            progress_callback(1.0)
        return cls(captures)

    def as_nested_lists(self):
        """
        Get timestamp, latitude, longitude, altitude, capture_id, dls-yaw, dls-pitch, dls-roll, and irradiance from all
        Captures.
        :return: List data from all Captures, List column headers.
        """
        columns = [
            'timestamp',
            'latitude', 'longitude', 'altitude',
            'capture_id',
            'dls-yaw', 'dls-pitch', 'dls-roll'
        ]
        irr = ["irr-{}".format(wve) for wve in self.captures[0].center_wavelengths()]
        columns += irr
        data = []
        for cap in self.captures:
            dat = cap.utc_time()
            loc = list(cap.location())
            uuid = cap.uuid
            dls_pose = list(cap.dls_pose())
            irr = cap.dls_irradiance()
            row = [dat] + loc + [uuid] + dls_pose + irr
            data.append(row)
        return data, columns

    def dls_irradiance(self):
        """
        Get utc_time and irradiance for each Capture in ImageSet.
        :return: dict {utc_time : [irradiance, ...]}
        """
        series = {}
        for cap in self.captures:
            dat = cap.utc_time().isoformat()
            irr = cap.dls_irradiance()
            series[dat] = irr
        return series

    def process_imageset(self,
                         output_stack_directory=None,
                         output_rgb_directory=None,
                         warp_matrices=None,
                         irradiance=None,
                         img_type=None,
                         multiprocess=True,
                         overwrite=False,
                         progress_callback=None,
                         use_tqdm=False):
        """
        Write band stacks and rgb thumbnails to disk.
        :param warp_matrices: 2d List of warp matrices derived from Capture.get_warp_matrices()
        :param output_stack_directory: str system file path to output stack directory
        :param output_rgb_directory: str system file path to output thumbnail directory
        :param irradiance: List returned from Capture.dls_irradiance() or Capture.panel_irradiance()    <-- TODO: Write a better docstring for this
        :param img_type: str 'radiance' or 'reflectance'. Desired image output type.
        :param multiprocess: boolean True to use multiprocessing module
        :param overwrite: boolean True to overwrite existing files
        :param progress_callback: function to report progress to
        :param use_tqdm: boolean True to use tqdm progress bar
        """

        if progress_callback is not None:
            warnings.warn(message='The progress_callback parameter will be deprecated in favor of use_tqdm',
                          category=PendingDeprecationWarning)

        # ensure some output is requested
        if output_stack_directory is None and output_rgb_directory is None:
            raise RuntimeError('No output requested for the ImageSet.')

        # make output dirs if not exist
        if output_stack_directory is not None and not os.path.exists(output_stack_directory):
            os.mkdir(output_stack_directory)
        if output_rgb_directory is not None and not os.path.exists(output_rgb_directory):
            os.mkdir(output_rgb_directory)

        # processing parameters
        params = {
            'warp_matrices': warp_matrices,
            'irradiance': irradiance,
            'img_type': img_type,
            'capture_len': len(self.captures[0].images),
            'output_stack_dir': output_stack_directory,
            'output_rgb_dir': output_rgb_directory,
            'overwrite': overwrite,
        }

        print('Processing {} Captures ...'.format(len(self.captures)))

        # multiprocessing with concurrent futures
        if multiprocess:
            parallel_process(function=save_capture, iterable=self.captures, parameters=params,
                             progress_callback=progress_callback, use_tqdm=use_tqdm)

        # else serial processing
        else:
            if use_tqdm:
                kwargs = {
                    'total': len(self.captures),
                    'unit': 'Capture',
                    'unit_scale': False,
                    'leave': True
                }
                for cap in tqdm(iterable=self.captures, desc='Processing ImageSet', **kwargs):
                    save_capture(params, cap)
            else:
                for i, cap in enumerate(self.captures):
                    save_capture(params, cap)
                    if progress_callback is not None:
                        progress_callback(float(i) / float(len(self.captures)))

        print('Processing complete.')


from flask import Flask, request, jsonify
from flask_cors import CORS
from recommendations import get_recommendations

app = Flask(__name__)
# CORS(app)
CORS(app, resources={r"/api/*": {"origins": "*"}})

@app.route('/', methods=['GET'])
def home():
    return "Welcome to the recommendation service!"

@app.route('/recommendations', methods=['GET'])
def recommendations():
    user_id = request.args.get('user_id', type=int)
    recommended_professionals = get_recommendations(user_id)
    return jsonify(recommended_professionals.tolist())

@app.after_request
def after_request(response):
    response.headers.add('Access-Control-Allow-Origin', '*')
    response.headers.add('Access-Control-Allow-Headers',
                         'Content-Type,Authorization')
    response.headers.add('Access-Control-Allow-Methods',
                         'GET,PUT,POST,DELETE,OPTIONS')
    return response

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


import json

from fastapi import FastAPI

from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Allows all origins
    allow_credentials=True,
    allow_methods=["*"],  # Allows all methods
    allow_headers=["*"],  # Allows all headers
)

@app.get("/")
async def root():
    # # get food data
    with open("foods.json") as f:
        data = json.load(f)
    return data


#!/usr/bin/env python

"""
@Author: gorywong
@Date: 2019-01-23 15:15:01
@Software: Visual Studio Code
@Last Modified by: gorywong
@Last Modified time: 2019-01-23 15:15:01
@Description:
"""
import logging
from abc import abstractmethod

from django.db import models
from django.urls import reverse
from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils.functional import cached_property
from django.utils.timezone import now
from ckeditor_uploader.fields import RichTextUploadingField

from lbyledu.utils import cache_decorator, cache
from users.models import UserGroup, UserProfile
from organization.models import Organization

logger = logging.getLogger(__name__)

# Create your models here.
class BaseModel(models.Model):
    id = models.AutoField(primary_key=True)
    created_time = models.DateTimeField(default=now, verbose_name="创建时间")
    last_mod_time = models.DateTimeField(default=now, verbose_name="修改时间")

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

    class Meta:
        abstract = True

    @abstractmethod
    def get_absolute_url(self):
        pass

class Document(BaseModel):
    title = models.CharField(max_length=200, verbose_name="标题")
    author = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name="发布人")
    content = RichTextUploadingField(verbose_name="正文")
    receiver = models.ManyToManyField(UserProfile, blank=True, related_name="documents", verbose_name="收件人")
    receiver_group = models.ForeignKey(UserGroup, on_delete=models.CASCADE, verbose_name="收件用户组")
    checked_receiver = models.ManyToManyField(UserProfile, blank=True, related_name="checked_documents", verbose_name="已签收的用户")
    number = models.IntegerField(unique=True, verbose_name="编号")

    class Meta:
        verbose_name = "公文"
        verbose_name_plural = verbose_name
        ordering = ['-created_time']
        get_latest_by = 'id'

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("office:document_detail", kwargs={"number": self.number})

class OrganizationAdmins(BaseModel):
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, verbose_name="单位")
    admin  = models.ForeignKey(UserProfile, on_delete=models.CASCADE, verbose_name="管理员")

    class Meta:
        verbose_name = "网站管理员"
        verbose_name_plural = verbose_name


from __future__ import print_function
import sys
import copy
import logging
import itertools
import time
import torch
from torch.autograd import Variable
import torch.nn.functional as F
from sklearn.metrics import precision_recall_curve, average_precision_score, roc_auc_score
from sklearn import metrics
from scipy.stats import pearsonr, spearmanr
import numpy as np
from fingerprint.graph import load_from_mol_tuple
from utils import get_lstm_embedding

class Evaluator():
    def __init__(self, ikey2smiles=None,
                       ikey2mol=None,
                       berttokenizer=None,
                       uniprot2triplets=None,
                       prediction_mode=None,
                       protein_embedding_type=None,
                       datatype='train',
                       max_steps=1000,
                       batch=64,
                       shuffle=False):

        self.ikey2smiles=ikey2smiles
        self.ikey2mol=ikey2mol
        self.berttokenizer=berttokenizer
        self.uniprot2triplets=uniprot2triplets
        self.prediction_mode=prediction_mode
        self.prottype=protein_embedding_type
        self.datatype=datatype
        self.max_steps=max_steps
        self.batch=batch
        self.shuffle=shuffle
        logging.info("{} Evaluator for {} data initialized. Max {} steps for batch-size {}. \
        Shuffle {}".format(self.prediction_mode,datatype,max_steps,batch,shuffle))

    def eval(self,model,pairs,labels,epoch):
        def run_model(chem_repr, prot_repr, label, evaluate=True):
            chem_repr = load_from_mol_tuple(chem_repr)
            if isinstance(chem_repr, Variable) and torch.cuda.is_available():
                chem_repr = chem_repr.cuda()
            if isinstance(prot_repr, Variable) and torch.cuda.is_available():
                prot_repr = prot_repr.cuda()
            batch_input = {'protein': prot_repr, 'ligand': chem_repr}
            with torch.no_grad():
                logits = model(batch_input)
            batch_labels = torch.tensor(label)
            batch_labels = batch_labels.cpu().detach().numpy()
            logits = logits.cpu().detach().numpy()
            logging.debug("Evaluator-run_model: batch_labels {}, logits {}".format(batch_labels.shape, logits.shape))
            if evaluate:
                f1, auc, aupr = evaluate_binary_predictions(batch_labels, logits)
            else:
                return batch_labels, logits

        def get_repr_from_pairs_3(pairs):
            chem_repr = [(self.ikey2smiles[pair[0]], self.ikey2mol[pair[0]]) for pair in pairs]
            prot_repr = torch.stack(
                [torch.tensor(self.berttokenizer.encode(self.uniprot2triplets[pair[1]])) for pair in pairs])
            return (chem_repr, prot_repr)

        model.eval()

        datatype=self.datatype

        since=time.time()
        collected_logits = []
        collected_labels = []

        if len(pairs)<= self.batch:
            #sample size smaller than a batch
            chem_repr, prot_repr = get_repr_from_pairs(pairs)
            metrics = run_model(chem_repr,prot_repr,labels,evaluate=True)
            eval_time=time.time() - since
            logging.info("{:.2f} seconds for {} evaluation. Epoch {}".format(eval_time,datatype,epoch))
            print("{}\t{}\t{:.5f}\t{:.5f}\t{:.5f}\t{:.5f}\t{:.5f}\t{:.5f}\t{:.5f}\t{:.5f}\t{:.5f}".format(epoch,
                datatype,metrics[0],metrics[1],metrics[2]))
            return metrics

        elif len(pairs)<= self.max_steps*self.batch:
            #evaluate all pairs if small enough
            maxsteps=int(np.ceil(float(len(pairs))/float(self.batch)))
            for step in range(maxsteps):
                pairs_part=pairs[self.batch*step:self.batch*(step+1)]
                if len(pairs_part)==self.batch:
                    labels_part=labels[self.batch*step:self.batch*(step+1)]
                    chem_repr, prot_repr = get_repr_from_pairs_3(pairs_part)
                    # chem_repr,prot_repr = get_repr_from_pairs(pairs_part)
                    batch_labels,logits=run_model(chem_repr,prot_repr,labels_part,evaluate=False)
                    logging.debug("in-loop: batch_labels {}, logits {}".format(batch_labels.shape,logits.shape))
                    collected_logits.append(logits)
                    collected_labels.append(batch_labels)

        else:
            idxs = np.arange(len(pairs))
            np.random.shuffle(idxs)
            for step in range(self.max_steps):
                pairs_part=pairs[self.batch*step:self.batch*(step+1)]
                labels_part=labels[self.batch*step:self.batch*(step+1)]
                chem_repr, prot_repr = get_repr_from_pairs(pairs_part)
                batch_labels,logits=run_model(chem_repr,prot_repr,labels_part,evaluate=False)
                logging.debug("in-loop: batch_labels {}, logits {}".format(batch_labels.shape,logits.shape))
                collected_logits.append(logits)
                collected_labels.append(batch_labels)

        collected_labels = np.concatenate(collected_labels,axis=0)
        collected_logits = np.concatenate(collected_logits,axis=0)
        if self.prediction_mode.lower() in ['binary']:
            metrics = evaluate_binary_predictions(collected_labels,collected_logits)
        else:
            metrics = evaluate_continuous_predictions(collected_labels,collected_logits)

        eval_time=time.time() - since
        logging.info("{:.2f} seconds for {} evaluation. Epoch {}".format(eval_time,datatype,epoch))
        print("{}\t{}\t{:.5f}\t{:.5f}\t{:.5f}".format(epoch,datatype,metrics[0],metrics[1],metrics[2]))
        return metrics

def evaluate_binary_predictions(label,predprobs):
    logging.debug("label {}, predprobs {}".format(label.shape,predprobs.shape))
    probs=np.array(predprobs)
    predclass=np.argmax(probs,axis=1)

    f1 = metrics.f1_score(label, predclass, average='weighted')
    fpr,  tpr, thresholds = metrics.roc_curve(label, probs[:,1], pos_label=1)
    auc=metrics.auc(fpr, tpr)
    prec, reca, thresholds = metrics.precision_recall_curve(label, probs[:,1], pos_label=1)
    aupr=metrics.auc(reca,prec)
    return f1,auc,aupr


# -*- coding: utf-8 -*-
"""
Created on Wed Jul  8 22:06:23 2020

@author: Lou
"""

import sys, yaml, os
#os.chdir('C:/Users/Keith/Documents/GitHub/LNT')
## with open('.' + os.sep + 'loc_settings.yaml', 'r') as f:
##     loc_info = yaml.load(f)
#sys.path.append('C:/Users/Keith/Documents/GitHub/LNT'+ os.sep + "Analysis")
#sys.path.append('C:/Users/Keith/Documents/GitHub/LNT'+ os.sep + "Imaging")
#sys.path.append('C:/Users/Keith/Documents/GitHub/OASIS-master')

os.chdir(r'C:\Users\Lou\Documents\repos\LNT')
sys.path.append(r'C:\Users\Lou\Documents\repos\LNT'+ os.sep + "Analysis")
sys.path.append(r'C:\Users\Lou\Documents\repos\LNT'+ os.sep + "Imaging")
sys.path.append(r'C:\Users\Lou\Documents\repos\OASIS-master')

import warnings; warnings.simplefilter('ignore')

import matplotlib.pyplot as plt
import h5py
import numpy as np
from scipy import stats
from align_dF_interp_mpi import align_dF
from load_behavior_data import load_data
from oasis.functions import deconvolve
from sklearn import linear_model

def process_and_align_caiman(data_path, sess, dff_file, behavior_file):
    eye_data = None
    session_crop=[0,1]

    print('Loading df/f data...')
    df_signal_path = data_path + os.sep + dff_file
    dF_signal_bef =  h5py.File(df_signal_path, 'r+')

    try:
        del dF_signal_bef['dF_aligned']
    except KeyError:
        pass
    try:
        del dF_signal_bef['behaviour_aligned']
    except KeyError:
        pass

    dF_signal = np.copy(dF_signal_bef['F_dff'])
    frame_brightness = np.zeros(len(dF_signal))

    print('Loading behavior data for alignment...')
    fname = data_path + os.sep + behavior_file
    raw_data = np.genfromtxt(fname, delimiter=';')

    dF_aligned, behaviour_aligned, bri_aligned = align_dF(raw_data, dF_signal, frame_brightness,[-1, -3], [2, -4], True, True, session_crop, eye_data)

    # del dF_signal_bef['dF_aligned']
    dF_signal_bef.create_dataset('dF_aligned', data=dF_aligned)
    # del dF_signal_bef['behaviour_aligned']
    dF_signal_bef.create_dataset('behaviour_aligned', data=behaviour_aligned)
    dF_signal_bef.close()

    print('done...')

    return dF_aligned, behaviour_aligned

def factor_out_baseline(data_path, sess, dff_file):

    print('Loading df/f data...')
    df_signal_path = data_path + os.sep + dff_file
    dF_signal_bef =  h5py.File(df_signal_path, 'r+')
    try:
        del dF_signal_bef['new_dF']
    except KeyError:
        pass
    try:
        del dF_signal_bef['calcium_dF']
    except KeyError:
        pass
    dF_signal = np.copy(dF_signal_bef['dF_aligned'])
    new_dF = np.zeros((len(dF_signal[:,0]),len(dF_signal[0,:])))
    calcium_dF = np.zeros((len(dF_signal[:,0]),len(dF_signal[0,:])))
    print('Calculate baselines.')
    for num in range(len(dF_signal[0,:])):
        test_sig = dF_signal[:,num]
        rep_sig = np.zeros(len(test_sig))
        ker_leg = 1000
        x_up_lim = len(test_sig) - ker_leg
        for x in range(len(test_sig)):
            if x < ker_leg:
                cur_vals = test_sig[:x + ker_leg]
            elif x > x_up_lim:
                cur_vals = test_sig[x-ker_leg:]
            else:
                cur_vals = test_sig[x-ker_leg:x+ker_leg]
            sort_val = np.sort(cur_vals)
            bottom_20 = int(len(cur_vals)*0.2)
            cur_val = np.sum(sort_val[:bottom_20])
            rep_sig[x] = cur_val/bottom_20
        current_dF = test_sig-rep_sig

        xx = np.fft.fft(current_dF)
        xx[0] = 0
        yy = np.fft.ifft(xx)
        final_dF = yy.astype('float64')
        new_dF[:,num] = final_dF

        ransac = linear_model.RANSACRegressor()
        ransac.fit(np.arange(len(current_dF)).reshape(-1, 1), current_dF.reshape(-1, 1))
        prediction_ransac = ransac.predict(np.arange(len(current_dF)).reshape(-1, 1))
        calcium_dF[:,num] = current_dF-prediction_ransac[int(len(current_dF)/2),0]

    dF_signal_bef.create_dataset('new_dF', data=new_dF)
    dF_signal_bef.create_dataset('calcium_dF', data=calcium_dF)
    dF_signal_bef.close()

    print('done...')

    return None

def calculate_detrend_and_deconvolve(data_path, sess, dff_file):

    print('Loading df/f data...')
    df_signal_path = data_path + os.sep + dff_file
    dF_signal_bef =  h5py.File(df_signal_path, 'r+')
    dF_signal = np.copy(dF_signal_bef['new_dF'])
    try:
        del dF_signal_bef['deconv']
    except KeyError:
        pass
    try:
        del dF_signal_bef['spikes']
    except KeyError:
        pass
    deconv = np.zeros((len(dF_signal[:,0]),len(dF_signal[0,:])))
    spikes = np.zeros((len(dF_signal[:,0]),len(dF_signal[0,:])))

    print('Calculate detrends and convolutions.')
    for num in range(len(dF_signal[0,:])):
        current_dF = dF_signal[:,num]
        c, s, b, g, lam = deconvolve(current_dF, penalty=0)
        deconv[:,num] = c
        spikes[:,num] = s

    dF_signal_bef.create_dataset('deconv', data=deconv)
    dF_signal_bef.create_dataset('spikes', data=spikes)
    dF_signal_bef.close()
    print('done...')

    return None

def run_test():
    MOUSE= 'LF191022_1'
    sess = '20191209'
    dff_file = 'M01_000_000_results.mat'
    data_path = 'Q:\Documents\Harnett UROP' + os.sep + MOUSE + os.sep + sess
    factor_out_baseline(data_path, sess, dff_file)

if __name__ == '__main__':
    run_test()

        # ransac = linear_model.RANSACRegressor()
        # ransac.fit(np.arange(len(current_dF)).reshape(-1, 1), current_dF.reshape(-1, 1))
        # offset_predict = ransac.predict(np.arange(len(current_dF)).reshape(-1, 1))


from processors.awards import AwardProcessor,Column,PLAYER_COL
from models import model_mgr
from models.vehicles import STATION

class Processor(AwardProcessor):
    '''
    Overview
    This processor keeps track of kills against players on turrets (ground mounted).

    Implementation
	Whenever a kill event is received involving the killing of a player on a
	ground mounted turret, the kill event is cached.

    Notes
	None.
    '''

    def __init__(self):
        AwardProcessor.__init__(self, 'Storm the Castle',
                'Most Kills Against Turrets',
                [PLAYER_COL, Column('Kills', Column.NUMBER, Column.DESC)])

    def on_kill(self, e):

        # Ignore suicides and team kills
        if not e.valid_kill:
            return

        victim_vehicle = model_mgr.get_vehicle(e.victim.vehicle_id)
        if victim_vehicle.group == STATION:
            self.results[e.attacker] += 1


import requests
import numpy as np
import os
import re
import time
import boto3
from fastapi import FastAPI
from mangum import Mangum
from typing import Optional
import traceback

# from amazon.paapi import AmazonAPI
from starlette.middleware.cors import CORSMiddleware  # 追加

app = FastAPI()
# CORSを回避するために追加
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,  # 追記により追加
    allow_methods=["*"],  # 追記により追加
    allow_headers=["*"],  # 追記により追加
)

# AMAZON_ACCESS_KEY = os.environ["AMAZON_ACCESS_KEY"]
# AMAZON_SECRET_KEY = os.environ["AMAZON_SECRET_KEY"]
# AMAZON_ASSOCIATE_ID = os.environ["AMAZON_ASSOCIATE_ID"]
# AMAZON_COUNTRY = os.environ["AMAZON_COUNTRY"]
# RAKUTEN_APP_ID = os.environ["RAKUTEN_APP_ID"]
# RAKUTEN_AFFILIATE_ID = os.environ["RAKUTEN_AFFILIATE_ID"]
# RAKUTEN_SEARCH_API_URL = os.environ["RAKUTEN_SEARCH_API_URL"]
# RAKUTEN_RANKING_API = os.environ["RAKUTEN_RANKING_API"]

# amazon_api = AmazonAPI(
#     AMAZON_ACCESS_KEY, AMAZON_SECRET_KEY, AMAZON_ASSOCIATE_ID, AMAZON_COUNTRY
# )

athena = boto3.client("athena")

def get_rakuten_result(item_json, rank=1):
    point = np.round(int(item_json["itemPrice"]) / 1.1) // 100 * item_json["pointRate"]
    res_json = {
        "item_code": item_json["itemCode"],
        "item_name": item_json["itemName"],
        "item_description": re.sub("^.*＞", "", item_json["itemCaption"]),
        "item_price": int(item_json["itemPrice"]),
        "item_url": item_json["itemUrl"],
        "item_img": item_json["mediumImageUrls"][0],
        "item_point_rate": item_json["pointRate"],
        "item_point": point,
        "ranking": rank,
        "shop": "楽天",
    }
    return res_json

def get_amazon_result(item_json, rank=1):
    item_feature = item_json.item_info.features
    description = "" if item_feature is None else item_feature.display_values
    res_json = {
        "item_code": item_json.asin,
        "item_name": item_json.item_info.title.display_value,
        "item_description": description,
        "item_price": item_json.offers.listings[0].price.amount,
        "item_url": item_json.detail_page_url,
        "item_img": item_json.images.primary.large.url,
        "item_point_rate": 0,
        "item_point": 0,
        "ranking": rank,
        "shop": "amazon",
    }
    return res_json

# def search_item(
#     keyword, category="全て", max_price=100000, min_price=0, sort="standard", page=1
# ):
#     search_category = {
#         "全て": {"rakuten": 100533, "amazon": "344845011"},
#         "チャイルドシート": {"rakuten": 566088, "amazon": "2490442051"},
#         "ファッション": {"rakuten": 111102, "amazon": "345991011"},
#         "シューズ": {"rakuten": 200811, "amazon": "2032360051"},
#         "ベビーカー": {"rakuten": 200833, "amazon": "345931011"},
#         "抱っこ紐": {"rakuten": 566089, "amazon": "345971011"},
#         "寝具": {"rakuten": 200822, "amazon": "1910016051"},
#         "ベッド": {"rakuten": 200822, "amazon": "1910002051"},
#         "インテリア": {"rakuten": 566090, "amazon": "1910002051"},
#         "おふろ・バス用品": {"rakuten": 200815, "amazon": "345914011"},
#         "おむつ・トイレ": {"rakuten": 213972, "amazon": "345889011"},
#         "ミルク・離乳食": {"rakuten": 200827, "amazon": "345977011"},
#         "その他": {"rakuten": 100533, "amazon": "344845011"},
#     }
#     sort_dict = {
#         "standard": {"rakuten": "standard", "amazon": "Featured"},
#         "min_price": {"rakuten": "+itemPrice", "amazon": "Price:LowToHigh"},
#         "max_price": {"rakuten": "-itemPrice", "amazon": "Price:HighToLow"},
#         "review": {"rakuten": "-reviewAverage", "amazon": "AvgCustomerReviews"},
#     }
#     params = {
#         "applicationId": RAKUTEN_APP_ID,
#         "formatVersion": 2,
#         "keyword": keyword,
#         "format": "json",
#         "genreId": search_category[category]["rakuten"],
#         "maxPrice": max_price,
#         "minPrice": min_price,
#         "sort": sort_dict[sort]["rakuten"],
#         "affiliateId": RAKUTEN_AFFILIATE_ID,
#         "page": page,
#         "carrier": 2,
#     }
#     res_rakuten = requests.get(RAKUTEN_SEARCH_API_URL, params=params).json()
#     res_amazon = amazon_api.search_items(
#         keywords=keyword,
#         browse_node_id=search_category[category]["amazon"],
#         sort_by=sort_dict[sort]["amazon"],
#         item_page=page,
#     )

#     rakuten_items = [get_rakuten_result(j) for j in res_rakuten["Items"]]
#     amazon_items = [get_amazon_result(j) for j in res_amazon["data"]]
#     items_list = rakuten_items + amazon_items
#     sorted_items_list = sorted(items_list, key=lambda x: x["item_price"])
#     item_json = {"result": sorted_items_list}

#     return item_json

def get_query(query):
    database = "easy_joy"
    query_id = athena.start_query_execution(
        QueryString=query,
        QueryExecutionContext={"Database": database},
        ResultConfiguration={"OutputLocation": f"s3://ec-ranking-data/athena-results/"},
    )["QueryExecutionId"]

    # Athenaのクエリが完了するまで待つ
    while True:
        response = athena.get_query_execution(QueryExecutionId=query_id)
        if response["QueryExecution"]["Status"]["State"] in [
            "SUCCEEDED",
            "FAILED",
            "CANCELLED",
        ]:
            break
        time.sleep(1)

    query_result_paginator = athena.get_paginator("get_query_results")
    query_result_iter = query_result_paginator.paginate(
        QueryExecutionId=query_id, PaginationConfig={"PageSize": 1000}
    )

    user_data = sum(list(map(lambda x: x["ResultSet"]["Rows"], query_result_iter)), [])

    query_list = []
    colmuns = [d["VarCharValue"] for d in user_data[0]["Data"]]
    for ud in user_data[1:]:
        values = [d["VarCharValue"] for d in ud["Data"]]
        query_dict = {k: v for k, v in zip(colmuns, values)}
        query_list.append(query_dict)
    return {
        "statusCode": 200,
        "result": query_list,
    }

def get_category_ranking(get_month, category, max_price=100000, min_price=0):
    database = "easy_joy"
    table = "ec_ranking"
    # Athenaテーブルの情報をPythonから呼び出す
    query = f"""
    SELECT
        item_code,
        item_name,
        item_description,
        CAST(item_price AS int) AS item_price,
        item_url,
        item_img,
        item_point_rate,
        CAST(item_point AS int) AS item_point,
        shop,
        get_month,
        category,
        CAST(ROW_NUMBER()OVER(PARTITION BY shop ORDER BY ranking) AS int) AS ranking
    FROM {database}.{table}
    WHERE category = '{category}' AND item_price BETWEEN {min_price} AND {max_price} AND get_month = '{get_month}'
    ORDER BY ranking
    LIMIT 20
    """

    responce = get_query(query)

    return responce

@app.get("/health")
async def get_health():
    return {"message": "OK !"}

@app.get("/ranking")
async def get_ranking(
    get_month: str,
    category: str,
    min_price: int = None,
    max_price: int = None,
):
    try:
        # Noneでないパラメーターだけを抽出
        params = {
            "get_month": get_month,
            "category": category,
            "min_price": min_price,
            "max_price": max_price,
        }
        valid_params = {k: v for k, v in params.items() if v is not None}
        response = get_category_ranking(**valid_params)
    except Exception as e:
        print(f"エラーが発生しました: {e}")
        print(traceback.format_exc())

    return response

@app.get("/ranking_test")
async def get_ranking_test():
    try:
        response = get_query("select 200")
    except Exception as e:
        print(f"エラーが発生しました: {e}")
        print(traceback.format_exc())

    return response

# @app.get("/search_item")
# async def post_search(
#     keyword: str,
#     category: str = None,
#     max_price: int = None,
#     min_price: int = None,
#     sort: str = None,
#     page: int = None,
# ):
#     params = {
#         "keyword": keyword,
#         "category": category,
#         "max_price": max_price,
#         "min_price": min_price,
#         "sort": sort,
#         "page": page,
#     }

#     # Noneでないパラメーターだけを抽出
#     valid_params = {k: v for k, v in params.items() if v is not None}

#     response = search_item(**valid_params)
#     return response

handler = Mangum(app)


import torch
import torch.nn as nn
from torch.utils import data

from datasets import Dataset
from networks import TransformerNet

def train(training_input, training_labels, num_unique_tokens, sequence_length):
    # Loader Parameters
    params = {'batch_size': 32,
              'shuffle': True,
              'num_workers': 12}
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

    # Create Batch Generator
    training_dataset = Dataset(training_input, training_labels)
    training_dataloader = torch.utils.data.DataLoader(training_dataset, **params)

    # Define network, loss function and optimizer
    net = TransformerNet(embedding_dim=500, num_mappings=num_unique_tokens,
                         num_heads=4, num_blocks=3, seq_length=sequence_length)
    criterion = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(net.parameters(), lr=1e-4, weight_decay=1e-3)

    # Define number of epochs
    num_epochs = 10
    print_batch_step = 100
    best_epoch_loss = 1000

    # Start training
    net = net.to(device)
    net.train(mode=True)
    for epoch in range(num_epochs):

        running_loss = 0
        epoch_loss = 0

        for i, data_ in enumerate(training_dataloader, 1):

            inputs, labels = data_[0].to(device), data_[1].to(device)

            optimizer.zero_grad()
            outputs = net(inputs)

            # flatten sequence dim to batch dim before Softmax + CE
            batch, seq, num_classes = outputs.size()
            outputs = outputs.view(batch * seq, num_classes)
            labels = labels.view(batch * seq)
            loss = criterion(outputs, labels)

            loss.backward()
            optimizer.step()

            # print statistics
            running_loss += loss.item()
            epoch_loss += loss.item() * params['batch_size']
            if i % print_batch_step == 0:
                print('[%d, %5d] loss: %.3f' % (epoch + 1, i, running_loss / print_batch_step))
                running_loss = 0

        epoch_num = epoch + 1
        average_epoch_loss = epoch_loss / len(training_dataset)
        print(f"Epoch {epoch_num}: average loss is {average_epoch_loss}")

        if average_epoch_loss < best_epoch_loss:
            net.save_checkpoint(epoch_num, average_epoch_loss, optimizer.state_dict())
            best_epoch_loss = average_epoch_loss

    print('Finished Training')


# coding:utf-8
from net import VOCDataset, TrainPipeline
from utils.augmentation_utils import SSDAugmentation

if __name__ == '__main__':
    # load dataset
    root = 'data/VOCtrainval_06-Nov-2007/VOCdevkit/VOC2007'
    dataset = VOCDataset(root, 'trainval', SSDAugmentation(), True)

    # train config
    config = {
        'dataset': dataset,
        'n_classes': len(dataset.classes)+1,
        'vgg_path': 'model/vgg16_reducedfc.pth',
        'lr': 5e-4,
        'batch_size': 8,
        'num_workers': 4,
        'start_iter': 0,
        'max_iters': 120000,
        'warm_up_iters': 500,
        'lr_steps': (80000, 100000, 120000),
        'save_frequency': 5000,
    }

    # train
    train_pipeline = TrainPipeline(**config)
    train_pipeline.train()


import serial
import time

ser = serial.Serial('/dev/ttyAMA0', 115200)

class serial_communication:
    def __init__(self):
        ready = self.handshake()
        while ready == False:
            print('no handshake')
            ready = self.handshake()
        while ready:
            global rcv
            global los
            data = self.readlineCR()
            if (data == '0'):
                print(rcv)
                los = len(rcv)
            if (data == '1'):
                print(rcv)
                if(los == int(rcv)):
                    print('size is correct')
                else :
                    print ('size is wrong')
                los = ""
            if (data == '2'):
                print('checksum is {}'.format(rcv))

    def handshake(self):
        ser.write('0'.encode())
        ack1 = ser.read().decode('ascii')
        if ack1 == '1':
            ser.write('1'.encode())
            print('handshake pass')
            return True
        else:
            print("\r\n\Handshake not completed!")
            return False

    def readlineCR(self):
        global rcv
        rcv = ""
        checksum = 0
        while True:
            ch = ser.read().decode('ascii')
            if(ch == 'd'):
                return '0'
            if(ch == 's'):
                return '1'
            if (ch == 'c'):
                return '2'
            rcv += ch

my_serial_communication = serial_communication()


"""
4. Написать функцию season, принимающую 1 аргумент — номер месяца (от 1 до 12), и возвращающую время года,
которому этот месяц принадлежит (зима, весна, лето или осень).
"""

def season(month):
    if 1 <= month <= 2 or month == 12:
        return "Зима"
    elif 3 <= month <= 5:
        return "Весна"
    elif 6 <= month <= 8:
        return "Лето"
    elif 9 <= month <= 11:
        return "Осень"
    else:
        return "Ошибка! Число должно быть от 1 до 12"

month_number = int(input("Введите число от 1 до 12: "))

result = season(month_number)

print("-" * 50)
print("Месяц {} принадлежит ко времени года - {}.".format(month_number, result))