from __future__ import annotations

import abc
import re
import sys
import types
from collections.abc import Callable
from typing import (
    get_args, get_origin, Iterable, NewType, Optional, overload, Pattern,
    Protocol, runtime_checkable, Type, TypedDict, TypeVar, Union)

import torch
from more_itertools import collapse
from pyro import distributions as dist
from pyro.poutine.indep_messenger import CondIndepStackFrame
from typing_extensions import TypeAlias

__all__ = (
    '_T', '_KT', '_VT', '_Tout', '_Tin',
    'AnyRegex',
    '_Distribution', '_Site', '_Model', '_Guide'
)

_T = TypeVar('_T')
_T1 = TypeVar('_T1')
_T2 = TypeVar('_T2')
_KT = TypeVar('_KT')
_VT = TypeVar('_VT')
_Tin = TypeVar('_Tin')
_Tout = TypeVar('_Tout')

if sys.version_info < (3, 9):
    class GenericAlias(abc.ABC):
        def __instancecheck__(self, instance):
            return get_origin(instance) and get_args(instance)

    types.GenericAlias = GenericAlias

@runtime_checkable
class SupportsItems(Protocol[_KT, _VT]):
    def items(self) -> Iterable[tuple[_KT, _VT]]: ...

@runtime_checkable
class Descriptor(Protocol[_T, _VT]):
    def __get__(self, instance: Optional[_T], owner: Type[_T]) -> _VT: ...

@runtime_checkable
class GetSetDescriptor(Protocol[_T, _VT]):
    def __get__(self, instance: Optional[_T], owner: Type[_T]) -> _VT: ...
    def __set__(self, instance: Optional[_T], value: _VT): ...

_Pattern: TypeAlias = Union[str, Pattern]
_Iterable_etc_of_Pattern: TypeAlias = Iterable[Union[_Pattern, '_Iterable_etc_of_Pattern']]
_AnyRegexable: TypeAlias = Union['AnyRegex', _Iterable_etc_of_Pattern]

class AnyRegex:
    def __init__(self, *patterns: _Pattern):
        self.patterns = tuple(map(re.compile, patterns))

    @classmethod
    @overload
    def get(cls, arg: AnyRegex) -> AnyRegex: ...

    @classmethod
    @overload
    def get(cls, *args: Union[_Pattern, _Iterable_etc_of_Pattern]) -> AnyRegex: ...

    @classmethod
    def get(cls, *args) -> AnyRegex:
        return args[0] if isinstance(args[0], AnyRegex) else AnyRegex(*collapse(args))

    def match(self, value: str, *args, **kwargs):
        return any(p.match(value, *args, **kwargs) for p in self.patterns)

_Distribution: TypeAlias = dist.TorchDistribution
_Site = TypedDict('_Site', {
    'done': bool,
    'name': str, 'fn': _Distribution, 'mask': torch.Tensor,
    'value': torch.Tensor, 'type': str, 'infer': dict, 'is_observed': bool,
    'cond_indep_stack': Iterable[CondIndepStackFrame]
}, total=False)
_Model = NewType('_Model', Callable)
_Guide = NewType('_Guide', Callable)


from math import prod
from tokenize import group
from tg.bot import  Bot
from configs.config import TOKEN
from database.fetcher import get_poll_from_database

import sys

poll_dicts = get_poll_from_database()
bot = Bot(TOKEN, poll_dicts)

states = bot.define_states(list(range(0,999)), bot.respond)
conv_handler = bot.generate_conv_handler(states=states, entry='start', fallback='cancel')
bot.add_handler(conv_handler, group=1)

states = bot.define_states(list(range(0,999)), bot.respond)
conv_handler = bot.generate_conv_handler(states=states, entry='admin', fallback='cancel_admin')
bot.add_handler(conv_handler, group=1)

states = bot.define_states(list(range(0,999)), bot.respond)
conv_handler = bot.generate_conv_handler(states=states, entry='register', fallback='cancel_register')
bot.add_handler(conv_handler, group=1)

states = bot.define_states(list(range(0,999)), bot.respond)
conv_handler = bot.generate_conv_handler(states=states, entry='report', fallback='cancel_report')
bot.add_handler(conv_handler, group=1)

# location_handler = bot.location_handler()
# bot.add_handler(location_handler,group=0)

bot.run()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#    @Author : 李将
#
#              _____               ______
#     ____====  ]OO|_n_n__][.      |    |]
#    [________]_|__|________)<
#     oo    oo  'oo OOOO-| oo\_   ~o~~~o~'
# +--+--+--+--+--+--+--+--+--+--+--+--+--+
#    @Time : 2022/9/2 14:40
#    @FIle： client.py
#    @Software: PyCharm

from google.protobuf import json_format

from grpc.pb2 import hello_billbil_pb2 as pb2

request = pb2.HelloDeWeiReq()
request.name = 'boby'
request.age = 11

res_str = request.SerializeToString()  # 序列化 变成二进制

print('res_str', res_str)

request2 = pb2.HelloDeweiRsp()

request2.ParseFromString(res_str)  # 反序列化，将二进制转化成对象

res_json = json_format.MessageToJson(request2)  # 设置为json
print(res_json)


def midpoint(f,a,b,n):
    total = 0
    h = (b-a)/n
    for i in range(0,n):
        total += f(((a+(i*h)+(i+1)*h)/2)*h)
    return total

functionlambda = lambda a : a**a

#def midpointplot(f,a=0,b=1,n=100):


import re
import numpy as np

single_token_feature = ['tag', 'pos', 'dep', 'is_punct', 'is_space',
                        'is_stop', 'is_alpha', 'ent_type','lemma',
                        'is_quote', 'lex_id']

prefix = ['king', 'duke', 'lord', 'dowager', 'master', 'prince', 'emperor', 'lady', 'Long', 'Marquis']

def get_span_features(token):
    features = {}
    for attr in single_token_feature:
        features['span_'+attr] = getattr(token, attr)
    return features

def get_features(tokens, this_tokens, gram_idx, grams, sentence, span):
    #'upcase_ratio': find_ngram_upcase(grams),
    features = {
        'has_quote_s': u"'s" in " ".join(grams),
        'next_has_quote_s': u"'s" in get_next(tokens, gram_idx, 'text'),
        'pre_has_prefix': get_prev(tokens, gram_idx, 'text').lower() in prefix,
        'has_prefix': has_prefix(grams),
        'prev_is_of': get_prev(tokens, gram_idx, 'text').lower().strip() == "of"
    }
    for attr in single_token_feature:
        features['prev_'+attr] = get_prev(tokens, gram_idx, attr)
        features['next_'+attr] = get_next(tokens, gram_idx, attr)
    return features

def filtering(items, doc_id):
    assert(len(items) > 0)
    for item in items:
        if not ('A' <= item[0] <= 'Z'):
            return True
        if has_non_ascii(item):
            print("NON-ASCII in document {}".format(doc_id))
            return True
    return False

def has_prefix(grams):
    for t in grams:
        if t.lower() in prefix:
            return True
    return False

def has_non_ascii(string):
    return string is not None and any([ord(s) >= 128 for s in string])

def find_ngram_upcase(items):
    total = 0
    for item in items:
        if 'A' <= item[0] <= 'Z':
            total += 1
    return float(total) / len(items)

def get_prev(tokens, gram_idx, attr):
    first_idx = gram_idx[0]
    if first_idx-1 < 0:
        if attr == "text":
            return ""
        if isinstance(getattr(tokens[first_idx],attr), np.bool_):
            return np.bool_(False)
        return 0
    return getattr(tokens[first_idx-1], attr)

def get_next(tokens, gram_idx, attr):
    last_idx = gram_idx[-1]
    if last_idx+1 >= len(tokens):
        if attr == "text":
            return ""
        if isinstance(getattr(tokens[last_idx],attr), np.bool_):
            return np.bool_(False)
        return 0
    return getattr(tokens[last_idx+1], attr)


import math
import functools
import re
import random
import collections

if __name__ == "__main__":
    with open("./input/14.txt") as f:
        data = f.read()

        template, rules = data.split("\n\n")
        rules = rules.split("\n")

        result_of_pair = dict()
        for rule in rules:
            input, output = rule.split(" -> ")
            input = (input[0], input[1])
            result_of_pair[input] = output

        # part 1
        amount_of_each_pair = collections.defaultdict(int)
        for i in range(len(template) - 1):
            amount_of_each_pair[(template[i], template[i + 1])] += 1

        # 10 for part 1, 40 for part 2
        for i in range(40):
            next_template = collections.defaultdict(int)
            for pair, count in amount_of_each_pair.items():
                result = result_of_pair[pair]
                next_template[(pair[0], result)] += count
                next_template[(result, pair[1])] += count
            amount_of_each_pair = next_template

        letter_count = collections.defaultdict(int)
        for pair, count in amount_of_each_pair.items():
            letter_count[pair[0]] += count
        letter_count[template[-1]] += 1
        print(max(letter_count.values()) - min(letter_count.values()))


# data.py

from pathlib import Path

import pandas as pd
import numpy as np

from abc import ABCMeta, abstractmethod
from event import MarketEvent

class DataHandler(object):
    """
    DataHandler — абстрактный базовый класс, предоставляющий интерфейс для всех наследованных обработчиков (для живой торговли и работы с историческими данными)

Цель (выделенного) объекта DataHandler заключается в выводе сгенерированного набора баров (OLHCVI) для каждого запрощенного финансового инструмента.

Это нужно для получения понимания о том, как будет функционировать стратегия, при использовании реальных торговых данных. Таким образом реальная и историческая система во всем наборе инструментов бэктестинга рассматриваются одинаково.
    """

    __metaclass__ = ABCMeta

    @abstractmethod
    def get_latest_bars(self, symbol, N=1):
        """
        Возвращает последние N баров из списка    latest_symbol или меньше, если столько баров еще недоступно.
        """
        raise NotImplementedError("Should implement get_latest_bars()")

    @abstractmethod
    def update_bars(self):
        """
        Накладывает последний бар на последнюю структуру инструмента для всех инструментов в списке.
        """
        raise NotImplementedError("Should implement update_bars()")

class HistoricCSVDataHandler(DataHandler):
    """
    HistoricCSVDataHandler создан для чтения CSV-файло с диска и создания интерфейса для получения «последнего» бара, как при реальной торговле.

    """

    def __init__(self, events, csv_dir, symbol_list, start_date):
        """
        Инициализирует обработчик исторических данных запросом местоположения CSV-файлов и списка инструментов.

        Предполагается, что все файлы имеют форму  'symbol.csv', где symbol — это строка списка.

        Параметры:
        events - очередь событий.
        csv_dir - Абсолютный путь к директории с CSV-файлами.
        symbol_list - Список строк инструментов.
        """
        self.events = events
        self.csv_dir = Path(Path.cwd() / csv_dir)
        self.symbol_list = symbol_list
        self.start_date = start_date

        self.symbol_data = {}
        self.latest_symbol_data = {}
        self.continue_backtest = True

        self._open_convert_csv_files()

    def _open_convert_csv_files(self):
        """
       Открывает CSV-файлы из директории, конвертирует их в pandas DataFrames внутри словаря инструментов.

Для данного обработчика предположим, что данные берутся из фида DTN IQFeed, и работа идет с этим форматом.
        """
        comb_index = None
        for s in self.symbol_list:
            # Загрузка CSV-файла без заголовочной информации, индексированный по дате

            self.symbol_data[s] = pd.read_csv(
                self.csv_dir / f'{s}.csv',
                header=0, index_col=0,
                names=['timestamp', 'open', 'low', 'high', 'close', 'volume'], parse_dates=['timestamp']
            )

            # если даты нет в датасете, ищем первую дату после стартовой
            if self.start_date >= self.symbol_data[s].index[0]:
                raise Exception('Date not in dataset')
            else:
                while self.start_date not in self.symbol_data[s].index:
                    # Если даты нет в датасете, , берем следующий день
                    new_date = self.start_date + np.timedelta64(1, 'D')
                    self.start_date = new_date

            self.symbol_data[s] = self.symbol_data[s][:self.start_date].iloc[::-1]

            # Комбинируется индекс для «подкладывания» значений
            if comb_index is None:
                comb_index = self.symbol_data[s].index
            else:
                comb_index.union(self.symbol_data[s].index)

            # Set the latest symbol_data to None
            self.latest_symbol_data[s] = []

        # Reindex the dataframes
        for s in self.symbol_list:
            self.symbol_data[s] = self.symbol_data[s].reindex(index=comb_index, method='pad').iterrows()

    def _get_new_bar(self, symbol):
        """
        Возвращает последний бар из дата-фида в формате:
        (sybmbol, datetime, open, low, high, close, volume).
        """
        for b in self.symbol_data[symbol]:
            yield tuple([symbol, b[0],
                         b[1][0], b[1][1], b[1][2], b[1][3], b[1][4]])
            # b[1][0], b[1][1], b[1][2], b[1][3], b[1][4]])

    def get_latest_bars(self, symbol, N=1):
        """
        Возвращает N последних баров из списка latest_symbol, или N-k, если доступно меньше.

        """
        try:
            bars_list = self.latest_symbol_data[symbol]
        except KeyError:
            print('That symbol is not available in the historical data set.')
        else:
            return bars_list[-N:]

    def update_bars(self):
        """
        Отправляет последний бар в структуру данных инструментов для всех инструментов в списке.
"""
        for s in self.symbol_list:
            try:
                bar = next(self._get_new_bar(s))

            except StopIteration:
                self.continue_backtest = False
            else:
                if bar is not None:
                    self.latest_symbol_data[s].append(bar)
                    self.events.put(MarketEvent(bar[1]))


import sys
import pyvisa as visa

# GPIB0::9::INSTR

def find(searchString):

    resourceManager = visa.ResourceManager()

    print('Find with search string \'%s\':' % searchString)
    devices = resourceManager.list_resources(searchString)
    if len(devices) > 0:
        for device in devices:
            print('\t%s' % device)
    else:
        print('... didn\'t find anything!')

    resourceManager.close()

if __name__ == '__main__':

    rm = visa.ResourceManager()
    print(rm.list_resources())

    # Finding all devices and interfaces is straightforward
    print('Find all devices and interfaces:\n')
    find('?*')

    # You can specify other device types using different search strings. Here are some common examples:

    # All instruments (no INTFC, BACKPLANE or MEMACC)
    find('?*INSTR')
    # PXI modules
    find('PXI?*INSTR')
    # USB devices
    find('USB?*INSTR')
    # GPIB instruments
    find('GPIB?*')
    # GPIB interfaces
    find('GPIB?*INTFC')
    # GPIB instruments on the GPIB0 interface
    find('GPIB0?*INSTR')
    # LAN instruments
    find('TCPIP?*')
    # SOCKET (::SOCKET) instruments
    find('TCPIP?*SOCKET')
    # VXI-11 (inst) instruments
    find('TCPIP?*inst?*INSTR')
    # HiSLIP (hislip) instruments
    find('TCPIP?*hislip?*INSTR')
    # RS-232 instruments
    find('ASRL?*INSTR')

    print('Done.')


import cv2
vid = cv2.VideoCapture(0)

blurVal = 20

font                   = cv2.FONT_HERSHEY_SIMPLEX
bottomLeftCornerOfText = (10,30)
fontScale              = 1
fontColor              = (0,0,0)
thickness              = 4
lineType               = 2

while True:
    ret, frame = vid.read()
    frame = cv2.flip(frame, 1)
    grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    blurredFrame = cv2.blur(grayFrame, (blurVal, blurVal), cv2.BORDER_DEFAULT)
    lineFrame = grayFrame / blurredFrame
    cv2.imshow('linedFrame', lineFrame)
    cv2.putText(blurredFrame, str(blurVal), bottomLeftCornerOfText, font, fontScale, fontColor, thickness, lineType)
    cv2.imshow('Frame', blurredFrame)
    k = cv2.waitKey(1)
    if k == 27:
        break
    if cv2.getWindowProperty('linedFrame',cv2.WND_PROP_VISIBLE) < 1:
        break
    if k == 45: #   -
        blurVal-=2
    if k == 61: #   = +
        blurVal+=2
    if(blurVal<=0):
        blurVal=2
vid.release()
cv2.destroyAllWindows()


#%% [markdown]
# # Structured Types, Mutability, and Higer-Order Functions
#
#    So far the programs we have seen dealt with three types of object **int, float, and str**. Int and float are type scalar, which means they have no internal accessible structure. On the other hand, str object can be thought as structured object (non scalar) since one can index to extract and individual. Now, we are going to introduce three structured types **tuple, list, dict**
#%% [markdown]
# ## Tuples
#
#    These are ordered sequences of elements, the difference is that the elements of a tuple need not to be characters, they can be of any type. They are written by enclosing a comma-separated list of elements within parentheses

#%%
t1 = ()
t2 = (1,'two', 3)

#%% [markdown]
# Which of these is a *tuple* and why??

#%%
tuple1 = (1)
tuple2 = (1,)
print(type(tuple1))
print(type(tuple2))

#%% [markdown]
# Like strings, tuples can be concatenated, indexed, and sliced

#%%
t1 = (1, "two", 3)
t2 = (t1, 2.25)
print(t2)
print((t1+t2))
print((t2+t1))
print((t1+t2)[3])
print((t1+t2)[2:5])

#%% [markdown]
# A for statement can be used to iterate over the elements of a tuple
#%% [markdown]
# ### Sequence and multiple assignment
#
# If you know the length of a sequence, it can be convenient to use Python's multiple assignment statement to extract the individual elements

#%%
x, y = (3, 4)
a, b, c = 'xyz'
print(a)

def do_something(x,y):
    '''
    x and y must be either float or integers
    return x+1 and y**2
    '''
    return (x+1, y**2)
no_separado = do_something(3,4)
m, n = do_something(3,4)
print(m)
print(n)
print(no_separado)

#%% [markdown]
# ## Lists and Mutability
#
# Like a tuple, a list is an ordered sequence of values where each value is identified by an index. The syntax to express literals of type list is similar to that used for tuples. The diference is that we use squared brackets insted of parenthesis

#%%
L = ['I did it all', 4, 'love', [1,2,3]]
for i in range(len(L)):
    print(L[i])

#%% [markdown]
# what do you obtain from the following piece of code

#%%
[1,2,3,4][1:3][1]

#%% [markdown]
# List differ from tuples in a HUGELY important way: lists are **mutable**. The types, tuple, int, float, and str are all **immutable**. The big difference is that variables of **inmutable** type cannot be modified after creation.
#
# Remember that in Python a variable is just a name, a label that can be attached to an object. Por ejemplo:
#

#%%
Tech = ["MIT", "Caltech"]
Ivys = ["Harvard", "Yale", "Brown"]

#%% [markdown]
# The the assignment statements

#%%
Univs = [Tech, Ivys]
Univs1 = [["MIT", "Caltech"],["Harvard", "Yale", "Brown"]]
print(Univs)
print(Univs1)
print(Univs == Univs1)

#%% [markdown]
# For the naive, it appears that Univ and Univ1 are binded to the same value. Appearances can be deceiving.

#%%
print("id of Univs = ", id(Univs))
print("id of Univs1 =", id(Univs1))

#%%
print('Ids of Univs[0] and Univs1[1]', id(Univs[0]), id(Univs1[0]))

#%% [markdown]
# Why does it matters?
#
# It matters because lists are mutable. Consider the **code**

#%%
Tech.append("RPI")
Tech

#%% [markdown]
# The **append** method has a **side effect**. Rather than create a new list, it mutates the existing list Tech by adding a new element. Univs still contains the same two list, but the contents of one of those list has been changed

#%%
print("Univs = ", Univs)
print("Univs1 = ", Univs1)

#%% [markdown]
# It is possible to observe that Univs[0], and Tech are the same object, and since we changed Tech we also changed Univs[0]. This effect is called **aliasing**, which means that we can mutate the object using either path and the change will be reflected in both objects.

#%%
print(id(Tech))
print(id(Univs[0]))

#%% [markdown]
# The examples above showed us that concatenation of list generate a list of lists. However, sometimes you want to create a flat list for what you can use the '+' simbol

#%%
flat = Tech + Ivys
flat

#%% [markdown]
# ### Cloning
#
# It is usually prudent to avoid mutating a list over which one is iterating. For example

#%%
def removeDups(L1, L2):
    """
    Assumes that L1 and L2 are list. Remove any element in L1 that is also in L2
    """
    for e1 in L1:
        print("e1=",e1)
        if e1 in L2:
            L1.remove(e1)

L1 = [1,2,3,4]
L2 = [1,2,5,6]

removeDups(L1, L2)
print("L1 = ",L1)

#%% [markdown]
# To avoid this problem use slicing to **clone**

#%%
def removeDups(L1, L2):
    """
    Assumes that L1 and L2 are list. Remove any element in L1 that is also in L2
    """
    for e1 in L1[:]:
        if e1 in L2:
            L1.remove(e1)

L1 = [1,2,3,4]
L2 = [1,2,5,6]

removeDups(L1, L2)
print("L1 = ",L1)

#%% [markdown]
# ### List comprehension
#
# The technique provides a concise way to apply an operation to the values in a sequence. It creates a new list in which element is result of an operation in another list

#%%
L = [x**2 for x in range(1,7)]
print(L)
result=[]
for i in range(1,7):
    result.append(i**2)
print(result)

#%%
mixed = [1,2,"a",3,4.2]
print([x**2 for x in mixed if type(x) == int])

#%% [markdown]
# ## Functions as Objects
#
# In Python, functions are **firts-class objects**. That means they can be treated like objects of any other type, e.g., int or list. They have types, can appear in expressions (right-hand side of an assignment statement) or as an argument to a function, etc.

#%%
type(removeDups)

#%%
def applyToEach(L,f):
    """
    Assumes L is a list, f is a function
    mutates L by replacing each element, e, of L by f(e)
    """
    for i in range(len(L)):
        L[i] = f(L[i])

#%% [markdown]
# The function *applyToEach* is called a **second-order** because it has an argument that is itself a function. Python has a built-in higher-order function, *map*.

#%%
L1 = [1, 28, 36]
L2 = [2, 57, 9]
a = [map(min, a) for a in zip(L1, L2)]
a

#%% [markdown]
# ## Dictionaries
#
# Objects of type **dict** are like the lists except that 'indices' need not to be integers. Since they are not ordered we call them **keys** rather than indices. The entries in a diccionary are unordered and cannot be accessed with an index.

#%%
monthNumbers = {'Jan': 1, 'Feb': 2, 'Mar' : 3, 'Apr': 4, 'May': 5,
               1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May'}

print('the third month is ' + monthNumbers[3])
dist = monthNumbers['Apr'] - monthNumbers['Jan']
print('Apr and Jan are ', dist, 'months apart')

#%%
monthNumbers.keys()

#%% [markdown]
# some of the most useful operations on dictionaries are: **len(d), d.keys(), d.values(), k in d** (True is key k in d)**, d[k], d.get(k,v], d[k] = v, del d[k], for k in d**.
#
# Objects of any **immutable type** can be used as dictionay keys. For example

#%%
monthNumbers[('Jun', 'Summer')] = 'Hot'
monthNumbers

#%% [markdown]
# It is relatively easy to implement a dictionary using a list in which each element is a key/value pair, but a dictionary is >>>> faster than this

#%%
def keySearch(L, k):
    for elem in L:
        if elem[0] == k:
            return elem[1]
    return None

#%% [markdown]
# # Testing and Debugging
#
# testing is the process of running a program to try and ascertain whether or not it works as intended. [Debugging](http://history-computer.com/ModernComputer/Relays/Aiken.html) is the process of trying to fix a program that you already know does not work as intended.
#
# ## Conducting Tests
#
# Testing is often thought of as occurring in two phases. One should always start with **unit testing** to ensure whether individual modules (e.g. functions) work properly. This is followed by **integration testing**, which is designed to ascertain whether the program as a whole behaves as intended.
#
# ## Debugging
#
# Runtime bugs can be categorized along two dimensions:
#
# * **overt -> covert:** An overt bug has an obvious manifestation, e.g., the program crashes or takes far longer to run. A **covert** bug has no obvious manifestation. The program my run to conclusion with no problem, but gives a wrong answer.
#
# * **Persistent -> Intermittent:** A persitent bug occurs every time the program is run. An ontermittent bug ocurrs only some of the time.
#
# Good programers try to write their programs in such a way that programming mistakes lead to bugs that are both overt and persistent. This is often called **defensive programming**
#
# ### When the going gets tough
#
# What to do when debugging gets tough:
#
# * Look for usual mistakes
#      * Arguments passed in the wrong order
#      * Misspelled of a name
#      * Failed to reinitialize a variable
#      * Tested that two floating point variables are (==) instead of nearly equal
#      * Tested value equality L1==L2 when you wanted object equality id(L1) == id(L2)
#      * Created an unintentional alias
#      * etc
#
# * Stop asking why the program is not doing what you want and ask why the program is doing what it is doing
# * Keep in mind that the bug is probably not where you think it is
# * Try to explain the problem to sombody else
# * Do not believe everything you read, since the code cannot be doing what the documentation says
# * Stop debugging and start writting documentation
# * Walk away and try tomorrow
#%% [markdown]
# # Exceptions and Assertions

#%%
test = [1,2,3]
test[2]

#%% [markdown]
# IndexError is the type of exception that Python raises when a program tries to access an element that is not within the bounds of and indexable type
#
# ## Handling Exception
#
# When an Exception is raised that caused the program to terminate, we say that an **unhandled exception** has been raised. Exceptions when raised can and should be **handled**

#%%
numSuccesses = 20
numFailures = 0
successFailureRatio = numSuccesses/float(numFailures)
print('The success/failure ratio is ', successFailureRatio)

#%%
numSuccesses = 2
numFailures = 0
try:
    successFailureRatio = numSuccesses/float(numFailures)
    print('The success/failure ratio is ', successFailureRatio)
except ZeroDivisionError:
    print('No failures so the success/failure ratio is undefined')

#%% [markdown]
# Let's look at another example

#%%
val = int(input('Enter int: '))
print('The square of the number you entered is: ', val**2)

#%%
while True:
    val = input('Enter int: ')
    try:
        val = int(val)
        print('The square of the number you entered is: ', val**2)
        break
    except ValueError:
        print(val + ' is not an integer')

#%% [markdown]
# If the program has many places where it is needed to enter an integer you can create a function to save both time and space

#%%
def readInt():
    while True:
        val = input('Enter int: ')
        try:
            val = int(val)
            return val**2
        except ValueError:
            print(val + ' is not an integer')

readInt()

#%% [markdown]
# But you can do even better creating a **polymorphic** function *readVal*

#%%
def readVal(valType, requestMsg, errorMsg):
    while True:
        val = input(requestMsg + ' ')
        try:
            val = valType(val)
            return val
        except ValueError:
            print(val + ' ' + errorMsg)

#val = readVal(int, 'Enter an integer:', 'is not an integer')
#val

val = readVal(str, 'Enter an string:', 'is not an string')

#%% [markdown]
# ## Exceptions as a Control Flow Mechanism

#%%
def getRatios(vect1, vect2):
    """
    Assumes: vect1 and vect2 are lists of equal length of numbers
    Returns: a list containing the meaninfull values of vect1[i]/vect2[i]
    """
    ratios = []
    for indx in range(len(vect1)):
        try:
            ratios.append(vect1[indx]/float(vect2[indx]))
        except ZeroDivisionError:
            ratios.append(float('nan')) #nan = Not a number
        except:
            raise ValueError('getRatios called with bad args')
    return ratios

try:
    print(getRatios([1.0,2.0,7.0,6.0],[1.0,2.0,0.0,3.0]))
    print(getRatios([],[]))
    print(getRatios([1.0,2.0],[3.0]))
except ValueError as msg:
    print(msg)

#%%
def getGrades(fname):
    try:
        gradesFile = open(fname, 'r') #open file for reading
    except IOError:
        raise ValueError('getGrades could not open '+ fname)
    grades = []
    for line in gradesFile:
        try:
            grades.append(float(line))
        except:
            raise ValueError('Unable to convert line to float')
    return grades

try:
    grades = getGrades('quizgrades.txt')
    grades.sort()
    median = grades[len(grades)//2]
    print('Median grade is', median)
except ValueError as errorMsg:
    print('Whoops, ', errorMsg)

#%% [markdown]
# ## Assertions
#
# The Python assert statement provides programmers with a simple way to confirm that the state of computation is as expected. The form of an assert statement is
#
#     assert Boolean expression, optional argument
#
# When the **assert** statement is encountered the boolean expression is evaluated. If it is evaluated to True, excecution proceeds on its merry way. If it evaluated to False and AssertionError exception is raised

#%%
def KelvinToFahrenheit(Temperature):
   assert (Temperature >= 0),"Colder than absolute zero!"
   return ((Temperature-273)*1.8)+32

try:
    KelvinToFahrenheit(-2)
except AssertionError as errMsg:
    print(errMsg)

#%% [markdown]
# # Classes and Object-Oriented Programming
#%% [markdown]
# The last major topic related to writing a program in Python is the use of clases. Classes can be used in the context of **object-oriented programming**, which requires that you think about an object as a collection of both data and the functions that operate on that data. We have been relaying in object oriented programming but you did not know it!!!
#
# ## Abstract data types and classes
#
# An **abstract data type** is a set of objects and the operations on those objects. These are bound together so one can pass an object from one part of the program to another, providing access not only to the data but also to the method that operate on that data.
#
# The specifications of these operations define an **interface** between the abstract data type and the rest of the program. The interface defines what the operation does, but not how it does it. The interface then, provides an **abstraction barrier**
#
# Programming is about managing complexity which can be acomplished through **decomposition and abstraction**. Decoposition creates structure and abstraction supresses complexity

#%%
class IntSet(object):
    """
    An IntSet is a set of integers
    The value is represented by a list of ints, self.vals
    Each int in the set occurs in self.vals exactly once
    """
    def __init__(self):
        '''
        Create an empty set of integers
        '''
        self.vals = []

    def insert(self, e):
        '''
        Assumes e is an integer and inserts e into self
        '''
        if not e in self.vals:
            self.vals.append(e)

    def member(self, e):
        '''
        Assumes e is an integer
        Return True if e is in self, and False otherwise
        '''
        return e in self.vals

    def remove(self, e):
        '''
        Assumes e is an integer and removes e from self
        Raises ValueError if e is not in self
        '''
        try:
            self.vals.remove(e)
        except:
            raise ValueError(str(e)+ ' not found')

    def __str__(self):
        '''
        Returns a string representation of self
        '''
        self.vals.sort()
        print(self.vals)
        result = ''
        for e in self.vals:
            result = result + str(e) + ','
        return '{' + result[:,-1] + '}'

#%%
print(type(IntSet)), print(type(IntSet.member))

#%% [markdown]
# When a function definition occurs within a class definition, the defined function is called a **method** and is associated with the class.
#
# Classes support two kinds of operations:
#
# * **Instantiation**: is used to create instances of the class. The statement s = IntSet() creates a new object of type IntSet. This object is called an **instance** of IntSet
# * **Attribute references**: Use dot notation to access attributes associated with the class, e.g. s.remove(e)
#
# When the line code
#
#     s = IntSet()
#
# is executed, the interpreter will create a new object, called an **instance**, of type IntSet, and then call IntSet.__init__ with the newly created object as the actual parameter that is bound to the formal parameter **self**. When invoked, IntSet.__init__ creates vals, an object of type list which is called a **data attribute**

#%%
s = IntSet()
s.insert(3)
s.insert(6)
s.remove(7)

#%% [markdown]
# A class should no be confussed with instances of that class, just as an object of type list should not be confused with the list type. Keep in mind that IntSet.member and s.member are different objects.
#
# When data attributes are associated with a class we call them **class variables**, and when they are associated with an instance we call them **instance variables**.
#
# Data abstraction achieves representation-independence. The **representation invariant** defines which values of the data attributes encode valid representation of abstract values.

#%%
import datetime

class Person(object):
    def __init__(self, name):
        '''
        Creates a person with name name
        '''
        self.name = name
        try:
            lastBlank = name.rindex(' ')
            self.lastName = name[lastBlank+1:]
        except:
            self.lastName = name
        self.birthDay = None

    def getLastName(self):
        '''
        returns self's last name
        '''
        return self.lastName

    def setBirthDay(self, birthDate):
        '''
        Assume birthDate is of type datetime.date
        set self's birthday to birthDate
        '''
        self.birthday = birthDate

    def getAge(self):
        '''
        returns self's current age in days
        '''
        if self.birthday == None:
            raise ValueError
        return(datetime.date.today()-self.birthday).days

    def __lt__(self, other):
        '''
        return True if self's name is lexicographically
        less than other's name, and False otherwise
        '''
        if self.lastName == other.lastName:
            return self.name < other.name
        return self.lastName < other.lastName

    def __str__(self):
        '''
        return self's name
        '''
        return self.name

#%%
me = Person('Rodrigo DeLaFuente')
him = Person('Barack Obama')
him2 = Person('Levi Campos')
print(me.getLastName())
me.setBirthDay(datetime.date(1981, 5, 4))
print(me.getAge()/365.25)
print(him2)

#%%
pList = [me, him, her]
for p in pList:
    print(p)

#%% [markdown]
# Now, use the __lt__ method to sort the list

#%%
pList.sort()
for p in pList:
    print(p)

#%% [markdown]
# ## Inheritance
#
# **Inheritance** provides a convenient mechanism for building groups of related abstractions. It allows programmers to create a type hierarchy in which each type inherits attributes from the type above it in the hierarchy. The class **object** is at the top of the hierarchy. Because **Person** inherits all of the properties of objects, programs can bind a variable to a **Person**, append a Person to a list, etc.

#%%
class MITPerson(Person):
    nextIdNum = 0 # this is a class variable
    def __init__(self, name):
        Person.__init__(self, name)
        self.idNum = MITPerson.nextIdNum
        MITPerson.nextIdNum += 1
    def getIdNum(self):
        return self.idNum
    def __lt__(self, other):
        return self.idNum < other.idNum

#%% [markdown]
# MITPerson is a **subclass** of Person, and therefore **inherits** the attributes of the **superclass**. In addition, the subclass can:
# * Add new attributes
# * **Override** attributes of the superclass (MITPerson overrode __init__ and __lt__)

#%%
p1 = MITPerson('Barbara Beaver')
print(str(p1) + '\'s id number is ' + str(p1.getIdNum()))
p2 = MITPerson('Rodrigo Alarcon')
print(str(p2) + '\'s id number is ' + str(p2.getIdNum()))
p3 = MITPerson('Rodrigo Tapia')
print(str(p3) + '\'s id number is ' + str(p3.getIdNum()))

#%%
print('p1 < p2 =', p1 < p2)

#%% [markdown]
# ### Multiple levels of inheritance

#%%
class Student(MITPerson):
    pass

class UG(Student):
    def __init__(self, name, classYear):
        MITPerson.__init__(self, name)
        self.year = classYear
    def getClass(self):
        return self.year

class Grad(Student):
    pass

#%% [markdown]
# By using the Python reserved word pass as the body, we indicate that the class has no attributes than those inherited from its superclass

#%%
p3 = Grad('Buzz Aldrin')
p4 = UG('Billy Beaver', 1984)
print(p3, ' is a graduate student is ', type(p3) == Grad)
print(p3, ' is an undergraduate student is ', type(p3) == UG)

#%%
class MITPerson(Person):
    nextIdNum = 0 # this is a class variable
    def __init__(self, name):
        Person.__init__(self, name)
        self.idNum = MITPerson.nextIdNum
        MITPerson.nextIdNum += 1
    def getIdNum(self):
        return self.idNum
    def isStudent(self):
        return isinstance(self, Student)
    def __lt__(self, other):
        return self.idNum < other.idNum

class Student(MITPerson):
    pass

class UG(Student):
    def __init__(self, name, classYear):
        MITPerson.__init__(self, name)
        self.year = classYear
    def getClass(self):
        return self.year

class Grad(Student):
    pass

p3 = Grad('Buzz Aldrin')
p4 = UG('Billy Beaver', 1984)
print(p3, 'is a student is', p3.isStudent())
print(p4, 'is a student is', p4.isStudent())

#%%
print(isinstance(p4, Student))
print(type(p4) == Student)

#%% [markdown]
# Adding a transfer student

#%%
class TransferStudent(Student):
    def __init__(self, name, fromSchool):
        MITPerson.__init__(self, name)
        self.fromSchool = fromSchool
    def getOldSchool(self):
        return self.fromSchool

#%% [markdown]
# ### The substitution principle
#
# The subclasses extend the behavior of their superclasses. For example TransferStudent extends Student by adding the notion of a former school. If a client code works correctly using an instance of the supertype, it should also work correctly when an instance of the subtype is substituted for the instance of the supertype. This is known as the **substitution principle**.
#%% [markdown]
# ## Encapsulation and information Hiding

#%%
class Grades(object):
    """
    A mapping from students to a list of grades
    """
    def __init__(self):
        '''
        Create empty grade book
        '''
        self.students = []
        self.grades = {}
        self.isSorted = True

    def addStudent(self, student):
        """
        Assumes: Student is of type Student
        Add student to the grade book
        """
        if student in self.students:
            raise ValueError("Duplicate Student")
        self.students.append(student)
        self.grades[student.getIdNum()] = []
        self.isSorted = False

    def addGrade(self, student, grade):
        '''
        Assumes: grade is a float
        Add grade to the list of grades for student
        '''
        try:
            self.grades[student.getIdNum()].append(grade)
        except:
            raise ValueError("Student not in mapping")

    def getGrades(self, student):
        '''
        Return a list of grades for students
        '''
        try:
            return self.grades[student.getIdNum()][:]
        except:
            raise ValueError('Student not in mapping')

    def allStudents(self):
        '''
        Return a list of the students in the grade book
        '''
        if not self.isSorted:
            self.students.sort()
        return self.students[:] # Return copy of list of students

def gradeReport(course):
    """
    Assumes: course is of type grades
    """
    report = ''
    for s in course.allStudents():
        tot = 0.0
        numGrades = 0
        for g in course.getGrades(s):
            tot += g
            numGrades += 1
        try:
            average = tot/numGrades
            report = report + '\n'                    + str(s) + '\'s mean grade is '                    + str(average)
        except ZeroDivisionError:
            report = report + '\n'                    + str(s) + ' has no grades'
    return report

ug1 = UG('Jane Doe', 2014)
ug2 = UG('John Doe', 2015)
ug3 = UG('David Henry', 2003)
g1 = Grad('Billy Buckner')
g2 = Grad('Bucky F. Dent')
SixHundred = Grades()
SixHundred.addStudent(ug1)
SixHundred.addStudent(ug2)
SixHundred.addStudent(g1)
SixHundred.addStudent(g2)
for s in SixHundred.allStudents():
    SixHundred.addGrade(s,75)
SixHundred.addGrade(g1, 25)
SixHundred.addGrade(g2, 100)
SixHundred.addStudent(ug3)
print(gradeReport(SixHundred))

#%%
SixHundred.getGrades(g2)

#%% [markdown]
# ### User-defined iterators
#
# A percived risk of information hiding is that preventing client programs from directly accessing critical data structures leads to an unacceptable loss of efficiency. The invocation of **course.allStudents** creates and return a list of size **n**, which can be a huge problem when n has more than a million elements. A better soluction is to add an **iterator** to the abstraction.
#
# Below, an improved version of the method is given. It uses a generator, which is like a function with the exception that it can stop in the middle, then return a value using a **yield** statement, and later resume from the point it has stopped.

#%%
class Grades(object):
    """
    A mapping from students to a list of grades
    """
    def __init__(self):
        '''
        Create empty grade book
        '''
        self.students = []
        self.grades = {}
        self.isSorted = True

    def addStudent(self, student):
        """
        Assumes: Student is of type Student
        Add student to the grade book
        """
        if student in self.students:
            raise ValueError("Duplicate Student")
        self.students.append(student)
        self.grades[student.getIdNum()] = []
        self.isSorted = False

    def addGrade(self, student, grade):
        '''
        Assumes: grade is a float
        Add grade to the list of grades for student
        '''
        try:
            self.grades[student.getIdNum()].append(grade)
        except:
            raise ValueError("Student not in mapping")

    def getGrades(self, student):
        '''
        Return a list of grades for students
        '''
        try:
            return self.grades[student.getIdNum()][:]
        except:
            raise ValueError('Student not in mapping')

    def allStudents(self):
        '''
        Return a list of the students in the grade book
        '''
        if not self.isSorted:
            self.students.sort()
        for s in self.students:
            yield s

def gradeReport(course):
    """
    Assumes: course is of type grades
    """
    report = ''
    for s in course.allStudents():
        tot = 0.0
        numGrades = 0
        for g in course.getGrades(s):
            tot += g
            numGrades += 1
        try:
            average = tot/numGrades
            report = report + '\n'                    + str(s) + '\'s mean grade is '                    + str(average)
        except ZeroDivisionError:
            report = report + '\n'                    + str(s) + ' has no grades'
    return report

ug1 = UG('Jane Doe', 2014)
ug2 = UG('John Doe', 2015)
ug3 = UG('David Henry', 2003)
g1 = Grad('Billy Buckner')
g2 = Grad('Bucky F. Dent')
SixHundred = Grades()
SixHundred.addStudent(ug1)
SixHundred.addStudent(ug2)
SixHundred.addStudent(g1)
SixHundred.addStudent(g2)
gen = SixHundred.allStudents()
print(gen)
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))


import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QIcon, QPixmap

class Emojis(QWidget):

    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 image - pythonspot.com'
        self.left = 50
        self.top = 50
        self.width = 640
        self.height = 480
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        poop_label = QLabel(self)
        self.show()

        input_str = input("Please Input the Name of the Emoji you want to see:)) \n To Finish Process type 'finish' ")
        while not input_str == "finish":
            input_str = input("Please Input the Name of the Emoji you want to see:))")

            if input_str == "poop":
                poop = QPixmap('poop.png')
                poop_label.setPixmap(poop)
                self.resize(poop.width(), poop.height())
                self.update()
            elif input_str == "smiley":
                smiley = QPixmap('smiley.png')
                poop_label.setPixmap(smiley)
                self.resize(smiley.width(), smiley.height())
                self.update()
            elif input_str == "smirk":
                smirk = QPixmap('smirk.png')
                poop_label.setPixmap(smirk)
                self.resize(smirk.width(), smirk.height())
                self.update()

            elif input_str == "surprised":
                surprised = QPixmap('surprised.png')
                poop_label.setPixmap(surprised)
                self.resize(surprised.width(), surprised.height())
                self.update()
            elif input_str == "heart_eyes":
                heart_eyes = QPixmap('heart_eyes.png')
                poop_label.setPixmap(heart_eyes)
                self.resize(heart_eyes.width(), heart_eyes.height())
                self.update()
            elif input_str == "crying":
                crying = QPixmap('crying.png')
                poop_label.setPixmap(crying)
                self.resize(crying.width(), crying.height())
                self.update()

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


# 1. 인덱스 활용을 위해 enumerate
# 2. 배열 안에서 max 탐색
# 3. max 좌 우로 다음 sec_max 탐색
# 4. 빗물 += sec_max - arr[i]
#    범위 sec_max_idx ~ max_idx
# 5. 왼쪽은 계속 왼쪽으로만, 오른쪽은 계속 오른쪽으로만 탐색

import sys
sys.stdin = open('input.txt')

def left(start, num):    # 좌측 탐색
    global sell
    arr = block[start:num]
    temp = max(arr, key=lambda x: x[1])
    for i in range(temp[0], num):
        sell += temp[1] - arr[i][1]
    if temp[0] > 0:
        left(start, temp[0])
    else:
        return

def right(num, end):    # 우측 탐색
    global sell
    arr = block[num:end]
    temp = max(arr, key=lambda x: x[1])
    for i in range(temp[0]-num):
        sell += temp[1] - arr[i][1]
    if temp[0] < w-1:
        right(temp[0]+1, end)
    else:
        return

h, w = map(int, sys.stdin.readline().split())
block = list(enumerate(map(int, sys.stdin.readline().split())))
sell = 0    # 빗물 고인 영역

maxi = max(block, key=lambda x:x[1])

if maxi[0] > 0:    # 탐색할 구간 존재 시 함수 실행
    left(0, maxi[0])
if maxi[0] < w-1:
    right(maxi[0]+1, w)

print(sell)

# print(block)
# print(max(block, key=lambda x:x[1]))
# print(max(block, key=lambda x:x[1])[1])


from modules.view.img import img
from PyQt5.QtWidgets import QPushButton, QLabel
from PyQt5 import QtCore, QtGui, QtWidgets
from modules.view.dictionaries import bg_images
from modules.controller.add_to_history import add_to_history

#This is part of popup class
def action_confirmed(self, ClickedWholeWidget, ClickedCardWidget, Ui, Game):
    from modules.controller.take_card import press_the_card
    from functools import partial
    Player = Game.CurrentPlayer

    if self.popup_type == 'BuyableStore':
        #If card is taken from one of two closest to right edge spots, it could contain extra coins.
        self.distance_to_right_edge = ClickedWholeWidget.parent().layout().count() - ClickedWholeWidget.parent().layout().indexOf(ClickedWholeWidget) - 1
        if self.distance_to_right_edge == 0:
            #This card could have gold coin on it!
            if Game.gold_coins_counter > 0:
                Game.gold_coins_counter -= 1
                ClickedCardWidget.Card.bonus = 3

        elif self.distance_to_right_edge == 1:
            #This card could have silver coin on it!
            if Game.silver_coins_counter > 0:
                Game.silver_coins_counter -= 1
                ClickedCardWidget.Card.bonus = 1

        #Display information about extra coins
        Ui.GoldCoinsLabel.setText(f'+ GOLD COIN
({Game.gold_coins_counter} left)')
        Ui.SilverCoinsLabel.setText(f'+ SILVER COIN
({Game.silver_coins_counter} left)')

        #Increase player Treasure points and Treasure counter
        Player.riches_points += ClickedCardWidget.Card.points
        Player.riches_count += 1

        #Check if card have any extra cions and add increase player coins if there was some
        if ClickedCardWidget.Card.bonus == 3:
            Player.coins_gold += 1
        if ClickedCardWidget.Card.bonus == 1:
            Player.coins_silver += 1
        ClickedCardWidget.Card.bonus = 0
        Player.coins_points = 3 * Player.coins_gold + 1 * Player.coins_silver

        #Remove Card cost from player resources after buying
        cost = ClickedCardWidget.Card.input_resources_list
        income = list()
        for x in ClickedCardWidget.Card.input_resources_list:
            if x != '':
                Player.resources.remove(x)

        try:
            #Pick new from the deck to PlayableStore
            NewCardWidget = Ui.display_card(Card=Game.DeckBuyable.pickOneCard(), Target=Ui.BuyableStore.HorizontalLayout)
            #Assign onclick event to this new card
            NewCardWidget.mouseReleaseEvent=partial(press_the_card, NewCardWidget.parent(), NewCardWidget, Ui,  Game, self)
        except:
            #When deck is empty and player cant pick new card we are adding empty widget with size of card
            NewCardWidget = QtWidgets.QWidget()
            NewCardWidget.resize(120, 200)
            Ui.BuyableStore.HorizontalLayout.insertWidget(0, NewCardWidget)

        #We are not keeping BuyableCards in player hand. We need to get information about this card and remove it.
        ClickedWholeWidget.deleteLater()

    TempCardPosition = len(Ui.PlayableStore.HorizontalLayout)-1
    if self.popup_type == 'PlayableStore':
        cost = self.resources_to_thorw_out
        for x in self.resources_to_thorw_out:
            #TempCardWidget represents each card which is gaining resources
            TempCardWidget=Ui.PlayableStore.HorizontalLayout.itemAt(TempCardPosition).widget().children()[1]
            TempCardPosition -= 1

            #We're removing one of dies choosen by player
            Player.resources.remove(x)

            #We're adding this die to specific Card
            TempCardWidget.BelowCardWidget_PlayableStore_Label.setText('')
            TempCardWidget.Card.resources.append(x)
            for x in ['k1', 'k2', 'k3', 'k4']:
                counter = TempCardWidget.Card.resources.count(x)
                if counter:
                    TempCardWidget.BelowCardWidget_PlayableStore_Label.setText(
                        f'{TempCardWidget.BelowCardWidget_PlayableStore_Label.text()}'
                        f'{counter} {img(file_name=x, width=14, height=16)}'
                        '|'
                        )

        #Add clicked card to PlayerHand scrollbox
        Ui.PlayerHand.HorizontalLayout.insertWidget(999, ClickedWholeWidget)

        #Add its resources to player
        income = ClickedCardWidget.Card.resources
        for die_to_pickup in ClickedCardWidget.Card.resources:
            Player.resources.append(die_to_pickup)

        #Hide BelowCard area prepared for PlayableStore and show the one created for PlayerHand
        ClickedCardWidget.BelowCardWidget_PlayableStore.hide()
        ClickedCardWidget.BelowCardWidget_PlayerHand.show()

        #Pick new from the deck to PlayableStore
        try:
            NewCardWidget = Ui.display_card(Card=Game.DeckPlayable.pickOneCard(), Target=Ui.PlayableStore.HorizontalLayout)
            #Assign onclick event to this new card
            NewCardWidget.mouseReleaseEvent=partial(press_the_card, NewCardWidget.parent(), NewCardWidget, Ui,  Game, self)
        except:
            #When deck is empty and player cant pick new card we are adding empty widget with size of card
            NewCardWidget = QtWidgets.QWidget()
            NewCardWidget.resize(120, 200)
            Ui.PlayableStore.HorizontalLayout.insertWidget(0, NewCardWidget)

        #Add picked card to PlayerHand
        Ui.PlayerHand.HorizontalLayout.addWidget(ClickedWholeWidget)
        Ui.PlayerHand.ScrollAreaWidgetContents.resize(Ui.PlayerHand.ScrollAreaWidgetContents.width()+130, \
                                                    Ui.PlayerHand.ScrollAreaWidgetContents.height())
    if self.popup_type == 'Harvest':
        income = ClickedCardWidget.Card.input_resources_list
        cost = ''
        for x in ClickedCardWidget.Card.input_resources_list:
            if x != '':
                Player.resources.append(x)

    if self.popup_type == 'Trade':
        income = ClickedCardWidget.Card.output_resources_list*self.multiplier
        cost = ClickedCardWidget.Card.input_resources_list*self.multiplier
        #Repeat Y times (Y is based on multiplier choosen by player)
        for y in range(0, self.multiplier):
            #Remove card cost from player resources
            for x in ClickedCardWidget.Card.input_resources_list:
                if x != '':
                    Player.resources.remove(x)
            for x in ClickedCardWidget.Card.output_resources_list:
                #Add card income to player resources
                if x != '':
                    Player.resources.append(x)

    if self.popup_type == 'Upgrade':
        income = self.upgraded_resources
        cost = self.resources_to_thorw_out
        #Remove card cost from player resources
        for x in self.upgraded_resources:
            #Add card income to player resources
            if x != '':
                Player.resources.append(x)
        for x in self.resources_to_thorw_out:
            if x != '':
                Player.resources.remove(x)

    #turn card into gray after its take effect
    if self.popup_type in ['Harvest', 'Upgrade', 'Trade']:
        ClickedCardWidget.Card.used = True
        ClickedCardWidget.setStyleSheet(
        f"#CardWidget{{background-image: url(images/{ClickedCardWidget.Card.used*'BW'}{bg_images[ClickedCardWidget.Card.card_type]}.png); background-repeat: none;}}"
        )

    if self.popup_type == 'too_much_resources':
        cost = self.resources_to_thorw_out
        income = []
        for x in self.resources_to_thorw_out:
            #We're removing one of dies choosen by player
            Player.resources.remove(x)

    #We need to hide Popup after action is finished
    self.close_popup()

    #Recalculate points and resources in playerBox
    Player.resources_count = len(Player.resources)
    Player.resources_points = Player.resources_count - Player.resources.count('k1') #every  die other than k1 gives 1 point

    #Recalculate total player points
    Player.total_points = Player.resources_points + Player.riches_points + Player.coins_points

    #Add new history note after action
    self.history_note_after_action(ClickedCardWidget=ClickedCardWidget, income=income, cost=cost)

    #Update displayed data
    update_player_box(Game=Game, Ui=Ui, Player=Player)

    #Before end of the turn we should check if player have not maximum amount of dies
    self.check_player_resources()

    #Before end of the turn we should check if player hasn't surpass maximum amount of riches
    self.check_player_riches()

    #Change turn number
    self.Game.turn_no += 1
    #Change player
    # not implemented yet

def check_player_resources(self):
    """Before end of the turn we have to check if player have not surpass maximum resource limit"""
    if self.Game.CurrentPlayer.resources_count > self.Game.resources_maximum:
        self.configure_popup(popup_type='too_much_resources', ClickedCardWidget='none')
        self.display_popup()
    pass

def check_player_riches(self):
    """Before end of the turn we have to check if player have not surpass maximum riches limit"""
    if self.Game.CurrentPlayer.riches_count >= self.Game.riches_maximum:
        print('Game is finished!')
        self.Ui.game_record(update=True, previous_record = self.Ui.record[2])
    pass

#This is also part of the popup class
def history_note_after_action(self, ClickedCardWidget='none', income=list(), cost=list()):
    display_income = False if len(income)<1 else f'[{income.count("k1")}{img("k1")}, {income.count("k2")}{img("k2")}, {income.count("k3")}{img("k3")}, {income.count("k4")}{img("k4")}]'
    display_cost = False if len(cost)<1 else f'[{cost.count("k1")}{img("k1")}, {cost.count("k2")}{img("k2")}, {cost.count("k3")}{img("k3")}, {cost.count("k4")}{img("k4")}]'
    #We re adding some coloring to make notes easier to read.
    c1 = ''
    c2 = ''
    history_notes = {
        'Harvest':
            f'has played {c1}[Harvest]{c2} card.
'
            f'Player gained {display_income}.',
        'Trade':
            f'has played {c1}Trade]{c2} card {c1}[{self.multiplier} times]{c2}.
'
            f'Player got {display_income} for {display_cost}',
        'Upgrade':
            f'has played {c1}[Upgrade]{c2} card.
'
            f'Player upgraded {display_cost} to {display_income}',
        'PlayableStore':
            f'has taken {c1}[{ClickedCardWidget.Card.card_type}]{c2} card from playable cards store.'
            f'{"
Player " if display_cost or display_income else ""}'
            f'{f"left {display_cost} in Playable Store" if display_cost else ""}'
            f'{" and " if display_cost and display_income else ""}'
            f'{f"gain {display_income} from card" if display_income else ""}',
        'BuyableStore':
            f'has buyed {c1}[Buyable]{c2} card.
'
            f'Player paid {display_cost} for this card.',
        'too_much_resources':
            f'has throwed out {display_cost} because he had too many resources'

    }
    content = history_notes[self.popup_type]
    add_to_history(Ui=self.Ui, who=self.Game.CurrentPlayer.name, HTMLtext=content)

    pass
    # for Player in self.Game.players_list:
    #     print(f'Current player is: {Player.player_number}')
    #     print(f'next player is: {next(Player).player_number}')

def update_player_box(Game, Ui, Player):
    right_label_content = {1:f'{Player.total_points} POINTS TOTAL', \
        2:f'[{Player.riches_count:2} /{Game.riches_maximum:2} ] ({Player.riches_points} POINTS)', \
        3:f'[{Player.coins_gold}G, {Player.coins_silver}S] ({Player.coins_points} POINTS)', \
        4:f'[{Player.resources_count:02}/{Game.resources_maximum:02} ({Player.resources_points} POINTS)', \
        5:f'[ \
        {Player.resources.count("k1")} {img(file_name="k1", width=14, height=16)}| \
        {Player.resources.count("k2")} {img(file_name="k2", width=14, height=16)}| \
        {Player.resources.count("k3")} {img(file_name="k3", width=14, height=16)}| \
        {Player.resources.count("k4")} {img(file_name="k4", width=14, height=16)} ]'}

    #As all players have the objects with the same name inside playerbox, we have to find their box first
    CurrentPlayerBox = Ui.Screen.findChild(QtWidgets.QWidget, f'player_{Player.player_number}_box')

    for x in range(1,6):
        #as we know CurrentPlayerBox, we now can search for specified row
        RightSideLabel = CurrentPlayerBox.findChild(QtWidgets.QWidget, f'{x}-RIGHT')
        RightSideLabel.setText(right_label_content[x])


######################################################
#
# Author: Davide Colombo
# Date: 30/12/21 15:01
# Description: INSERT HERE THE DESCRIPTION
#
######################################################
from datetime import datetime
from typing import Set, Dict, List
from airquality.database.adapter import DatabaseAdapter
from airquality.datamodel.fromdb import GeoareaLocationDM, OpenweathermapKeyDM, \
    SensorInfoDM, SensorLocationDM, SensorApiParamDM

class DatabaseGateway(object):
    def __init__(self, database_adapt: DatabaseAdapter):
        self._database_adapt = database_adapt

    def execute(self, query: str):
        self._database_adapt.execute(query)

# =========== SELECT ID QUERIES
    def _safe_fetch_id(self, query: str):
        row = self._database_adapt.fetchone(query)
        return 1 if row[0] is None else row[0] + 1

    def query_max_sensor_id_plus_one(self) -> int:
        return self._safe_fetch_id(
            query="SELECT MAX(id) FROM level0_raw.sensor;"
        )

    def query_max_mobile_packet_id_plus_one(self) -> int:
        return self._safe_fetch_id(
            query="SELECT MAX(packet_id) FROM level0_raw.mobile_measurement;"
        )

    def query_max_station_packet_id_plus_one(self) -> int:
        return self._safe_fetch_id(
            query="SELECT MAX(packet_id) FROM level0_raw.station_measurement;"
        )

# =========== SELECT SET QUERIES
    def query_poscodes_of_country(self, country_code: str) -> Set[str]:
        rows = self._database_adapt.fetchall(
            query=f"SELECT postal_code FROM level0_raw.geographical_area WHERE country_code = '{country_code}';"
        )
        return {row[0] for row in rows}

    def query_sensor_names_of_type(self, sensor_type: str) -> Set[str]:
        rows = self._database_adapt.fetchall(
            query=f"SELECT sensor_name FROM level0_raw.sensor WHERE sensor_type ILIKE '%{sensor_type}%';"
        )
        return {row[0] for row in rows}

# =========== SELECT MAPPING QUERIES
    def query_measure_param_owned_by(self, owner: str) -> Dict[str, int]:
        query = f"SELECT id, param_code FROM level0_raw.measure_param WHERE param_owner ILIKE '%{owner}%';"
        rows = self._database_adapt.fetchall(query=query)
        if len(rows) == 0:
            raise ValueError(f"Table 'level0_raw.measure_param' doesn't contain sensors owned by = '{owner}'")
        return {code: ident for ident, code in rows}

# =========== SELECT LIST QUERIES
    def query_sensor_apiparam_of_type(self, sensor_type: str) -> List[SensorApiParamDM]:
        query = "SELECT a.sensor_id, a.ch_key, a.ch_id, a.ch_name, a.last_acquisition " \
                "FROM level0_raw.sensor_api_param AS a INNER JOIN level0_raw.sensor AS s " \
                f"ON s.id = a.sensor_id WHERE s.sensor_type ILIKE '%{sensor_type}%';"
        rows = self._database_adapt.fetchall(query=query)
        if len(rows) == 0:
            raise ValueError(f"Table 'level0_raw.sensor_api_param' doesn't contain sensors of type = '{sensor_type}'")
        return [SensorApiParamDM(sid=sid, key=key, id=ident, ch=name, last=last) for sid, key, ident, name, last in rows]

    def query_openweathermap_keys(self) -> List[OpenweathermapKeyDM]:
        query = "SELECT key_value, done_req_min, max_req_min FROM level0_raw.openweathermap_key;"
        rows = self._database_adapt.fetchall(query=query)
        if len(rows) == 0:
            raise ValueError(f"Table 'level0_raw.openweathermap_key' is empty.")
        return [OpenweathermapKeyDM(key=key_val, n_done=done_r, n_max=max_r) for key_val, done_r, max_r in rows]

    def query_weather_conditions(self) -> Dict[str, int]:
        query = "SELECT id, code, icon FROM level0_raw.weather_condition;"
        rows = self._database_adapt.fetchall(query=query)
        if len(rows) == 0:
            raise ValueError(f"Table 'level0_raw.weather_condition' is empty.")
        return {f"{code}_{icon}": id_ for id_, code, icon in rows}

# =========== SELECT SINGLE ROW QUERIES
    def query_last_acquisition_of(self, sensor_id: int, ch_name: str) -> datetime:
        query = "SELECT last_acquisition FROM level0_raw.sensor_api_param " \
                f"WHERE sensor_id = {sensor_id} AND ch_name = '{ch_name}';"
        row = self._database_adapt.fetchone(query=query)
        if row is None:
            raise ValueError(f"Cannot found records corresponding to sensor_id = '{sensor_id}' and "
                             f"channel_name = '{ch_name}' in 'level0_raw.sensor_api_param' table.")
        return row[0]

    def query_place_location(self, country_code: str, place_name: str) -> GeoareaLocationDM:
        query = "SELECT id, ST_X(geom), ST_Y(geom) FROM level0_raw.geographical_area " \
                f"WHERE country_code = '{country_code}' AND place_name = '{place_name}';"
        row = self._database_adapt.fetchone(query=query)
        if row is None:
            raise ValueError(f"Cannot found a record corresponding to country_code = '{country_code}' and "
                             f"place_name = '{place_name}' in 'level0_raw.geographical_area' table")
        return GeoareaLocationDM(id=row[0], longitude=row[1], latitude=row[2])

    def query_fixed_sensor_unique_info(self, sensor_id: int):
        query = "SELECT s.id, s.sensor_name, ST_X(l.geom), ST_Y(l.geom) FROM level0_raw.sensor AS s " \
                "INNER JOIN level0_raw.sensor_at_location AS l ON s.id = l.sensor_id " \
                f"WHERE l.sensor_id = {sensor_id} ORDER BY l.valid_from DESC;"
        row = self._database_adapt.fetchone(query=query)
        if row is None:
            raise ValueError(f"Cannot found record corresponding to sensor_id = "
                             f"'{sensor_id}' in 'level0_raw.sensor_at_location' table")
        return SensorInfoDM(sensor_id=row[0], sensor_name=row[1], sensor_lng=row[2], sensor_lat=row[3])

    def query_mobile_sensor_unique_info(self, sensor_id: int):
        query = f"SELECT id, sensor_name FROM level0_raw.sensor WHERE id = {sensor_id};"
        row = self._database_adapt.fetchone(query=query)
        if row is None:
            raise ValueError(f"Cannot found record corresponding to sensor_id = "
                             f"'{sensor_id}' in 'level0_raw.sensor' table.")
        return SensorInfoDM(sensor_id=row[0], sensor_name=row[1])

    def query_purpleair_sensor_location(self, sensor_index: int) -> SensorLocationDM:
        query = "SELECT l.sensor_id, ST_X(geom), ST_Y(geom) FROM level0_raw.sensor_at_location AS l INNER JOIN " \
                "level0_raw.sensor AS s ON s.id = l.sensor_id WHERE s.sensor_type ILIKE '%purpleair%' AND " \
                f"sensor_name ILIKE '%{sensor_index}%' AND valid_to IS NULL;"
        row = self._database_adapt.fetchone(query=query)
        if row is None:
            raise ValueError(f"Cannot found a record corresponding to sensor_type = 'purpleair' which name "
                             f"contains sensor_index = '{sensor_index}' in 'level0_raw.sensor' table.")
        return SensorLocationDM(sensor_id=row[0], longitude=row[1], latitude=row[2])

    def query_hourly_forecast_records(self) -> List:
        return self._database_adapt.fetchall(query="SELECT * FROM level0_raw.hourly_forecast;")

    def query_daily_forecast_records(self) -> List:
        return self._database_adapt.fetchall(query="SELECT * FROM level0_raw.daily_forecast;")

    def exists_weather_alert_of(self, alert, geoarea_id: int) -> bool:
        row = self._database_adapt.fetchone(
            query=f"SELECT id FROM level0_raw.weather_alert WHERE geoarea_id = {geoarea_id} "
                  f"AND alert_event = '{alert.event}' AND alert_begin = '{alert.begin}';"
        )
        return False if row is None else True


from datetime import date, datetime, timezone
from pathlib import Path
from uuid import UUID

import pytest
from oes.registration.serialization.json import json_dumps

@pytest.mark.parametrize(
    "input_, expected",
    [
        ({"1", "2"}, b'["1","2"]'),
        (frozenset({2, 1}), b"[1,2]"),
        (
            UUID("534e683b-499e-4fd4-838a-f706083d4a7c"),
            b'"534e683b-499e-4fd4-838a-f706083d4a7c"',
        ),
        (
            datetime(2020, 1, 1, 12, 0, 0, tzinfo=timezone.utc),
            b'"2020-01-01T12:00:00+00:00"',
        ),
        (date(2024, 7, 4), b'"2024-07-04"'),
        (Path("/a/b/c"), b'"/a/b/c"'),
    ],
)
def test_json_defaults(input_, expected):
    result = json_dumps(input_)
    assert result == expected


"""Unit tests for reviewboard.extensions.hooks.APIExtraDataAccessHook."""

from djblets.registries.errors import AlreadyRegisteredError, RegistrationError
from kgb import SpyAgency

from reviewboard.extensions.base import Extension
from reviewboard.extensions.hooks import APIExtraDataAccessHook
from reviewboard.extensions.tests.testcases import ExtensionHookTestCaseMixin
from reviewboard.webapi.base import ExtraDataAccessLevel, WebAPIResource
from reviewboard.webapi.tests.base import BaseWebAPITestCase

class GenericTestResource(WebAPIResource):
    name = 'test'
    uri_object_key = 'test_id'
    extra_data = {}
    item_mimetype = 'application/vnd.reviewboard.org.test+json'

    fields = {
        'extra_data': {
            'type': dict,
            'description': 'Extra data as part of the test resource. '
                           'This can be set by the API or extensions.',
        },
    }

    allowed_methods = ('GET', 'PUT')

    def get(self, *args, **kwargs):
        return 200, {
            'test': {
                'extra_data': self.serialize_extra_data_field(self)
            }
        }

    def put(self, request, *args, **kwargs):
        fields = request.POST.dict()
        self.import_extra_data(self, self.extra_data, fields)

        return 200, {
            'test': self.extra_data
        }

    def has_access_permissions(self, request, obj, *args, **kwargs):
        return True

class APIExtraDataAccessHookExtension(Extension):
    """Test extension used for APIExtraDataAccessHook tests."""

    resources = [GenericTestResource()]

class EverythingPrivateHook(APIExtraDataAccessHook):
    """Hook which overrides callable to return all fields as private."""

    def get_extra_data_state(self, key_path):
        self.called = True
        return ExtraDataAccessLevel.ACCESS_STATE_PRIVATE

class InvalidCallableHook(APIExtraDataAccessHook):
    """Hook which implements an invalid callable"""

    get_extra_data_state = 'not a callable'

class APIExtraDataAccessHookTests(ExtensionHookTestCaseMixin, SpyAgency,
                                  BaseWebAPITestCase):
    """Testing APIExtraDataAccessHook."""

    extension_class = APIExtraDataAccessHookExtension
    fixtures = ['test_users']

    def setUp(self):
        super(APIExtraDataAccessHookTests, self).setUp()

        self.resource = self.extension.resources[0]
        self.url = self.resource.get_item_url(test_id=1)
        self.resource.extra_data = {
            'public': 'foo',
            'private': 'secret',
            'readonly': 'bar',
        }

    def test_register(self):
        """Testing APIExtraDataAccessHook registration"""
        APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('public',), ExtraDataAccessLevel.ACCESS_STATE_PUBLIC)
            ])

        self.assertNotEqual(list(self.resource.extra_data_access_callbacks),
                            [])

    def test_register_overridden_hook(self):
        """Testing APIExtraDataAccessHook with overridden registration for
        resource
        """
        EverythingPrivateHook(self.extension, self.resource, [])

        self.assertNotEqual(list(self.resource.extra_data_access_callbacks),
                            [])

    def test_overridden_hook_get(self):
        """Testing APIExtraDataAccessHook overrides result HTTP GET"""
        hook = EverythingPrivateHook(self.extension, self.resource, [])

        rsp = self.api_get(self.url,
                           expected_mimetype=self.resource.item_mimetype)

        # Since the hook registers the callback function on initialization,
        # which stores a pointer to the method, we can't use SpyAgency after
        # the hook has already been initialized. Since SpyAgency's spy_on
        # function requires an instance of a class, we also cannot spy on the
        # hook function before initialization. Therefore, as a workaround,
        # we're setting a variable in the function to ensure that it is in
        # fact being called.
        self.assertTrue(hook.called)
        self.assertNotIn('public', rsp['test']['extra_data'])
        self.assertNotIn('readonly', rsp['test']['extra_data'])
        self.assertNotIn('private', rsp['test']['extra_data'])

    def test_overridden_hook_put(self):
        """Testing APIExtraDataAccessHook overrides result for HTTP PUT"""
        hook = EverythingPrivateHook(self.extension, self.resource, [])

        original_value = self.resource.extra_data['readonly']
        modified_extra_fields = {
            'extra_data.public': 'modified',
        }

        rsp = self.api_put(self.url, modified_extra_fields,
                           expected_mimetype=self.resource.item_mimetype)

        # Since the hook registers the callback function on initialization,
        # which stores a pointer to the method, we can't use SpyAgency after
        # the hook has already been initialized. Since SpyAgency's spy_on
        # function requires an instance of a class, we also cannot spy on the
        # hook function before initialization. Therefore, as a workaround,
        # we're setting a variable in the function to ensure that it is in
        # fact being called.
        self.assertTrue(hook.called)
        self.assertEqual(original_value, rsp['test']['readonly'])

    def test_register_invalid_hook(self):
        """Testing APIExtraDataAccessHook registration with invalid
        get_extra_data_state
        """
        with self.assertRaises(RegistrationError):
            InvalidCallableHook(self.extension, self.resource, [])

        self.assertSetEqual(set(),
                            set(self.resource.extra_data_access_callbacks))

    def test_register_hook_already_registered(self):
        """Testing APIExtraDataAccessHook registration with already
        registered callback
        """
        hook = APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('public',), ExtraDataAccessLevel.ACCESS_STATE_PUBLIC)
            ])

        with self.assertRaises(AlreadyRegisteredError):
            hook.resource.extra_data_access_callbacks.register(
                hook.get_extra_data_state)

        self.assertNotEqual(set(),
                            set(self.resource.extra_data_access_callbacks))

    def test_public_state_get(self):
        """Testing APIExtraDataAccessHook public state GET"""
        APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('public',), ExtraDataAccessLevel.ACCESS_STATE_PUBLIC)
            ])

        rsp = self.api_get(self.url,
                           expected_mimetype=self.resource.item_mimetype)

        self.assertIn('public', rsp['test']['extra_data'])

    def test_public_state_put(self):
        """Testing APIExtraDataAccessHook public state PUT"""
        APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('public',), ExtraDataAccessLevel.ACCESS_STATE_PUBLIC)
            ])

        modified_extra_fields = {
            'extra_data.public': 'modified',
        }

        rsp = self.api_put(self.url, modified_extra_fields,
                           expected_mimetype=self.resource.item_mimetype)

        self.assertEqual(modified_extra_fields['extra_data.public'],
                         rsp['test']['public'])

    def test_readonly_state_get(self):
        """Testing APIExtraDataAccessHook readonly state get"""
        APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('readonly',),
                 ExtraDataAccessLevel.ACCESS_STATE_PUBLIC_READONLY)
            ])

        rsp = self.api_get(self.url,
                           expected_mimetype=self.resource.item_mimetype)

        self.assertIn('readonly', rsp['test']['extra_data'])

    def test_readonly_state_put(self):
        """Testing APIExtraDataAccessHook readonly state put"""
        APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('readonly',),
                 ExtraDataAccessLevel.ACCESS_STATE_PUBLIC_READONLY)
            ])

        original_value = self.resource.extra_data['readonly']
        modified_extra_fields = {
            'extra_data.readonly': 'modified',
        }

        rsp = self.api_put(self.url, modified_extra_fields,
                           expected_mimetype=self.resource.item_mimetype)

        self.assertEqual(original_value, rsp['test']['readonly'])

    def test_private_state_get(self):
        """Testing APIExtraDataAccessHook private state get"""
        APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('private',), ExtraDataAccessLevel.ACCESS_STATE_PRIVATE)
            ])

        rsp = self.api_get(self.url,
                           expected_mimetype=self.resource.item_mimetype)

        self.assertNotIn('private', rsp['test']['extra_data'])

    def test_private_state_put(self):
        """Testing APIExtraDataAccessHook private state put"""
        APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('private',), ExtraDataAccessLevel.ACCESS_STATE_PRIVATE)
            ])

        original_value = self.resource.extra_data['private']
        modified_extra_fields = {
            'extra_data.private': 'modified',
        }

        rsp = self.api_put(self.url, modified_extra_fields,
                           expected_mimetype=self.resource.item_mimetype)

        self.assertEqual(original_value, rsp['test']['private'])

    def test_unregister(self):
        """Testing APIExtraDataAccessHook unregistration"""
        hook = APIExtraDataAccessHook(
            self.extension,
            self.resource,
            [
                (('public',), ExtraDataAccessLevel.ACCESS_STATE_PUBLIC)
            ])

        hook.shutdown()

        self.assertSetEqual(set(),
                            set(self.resource.extra_data_access_callbacks))


import torch.nn as nn

class EncoderDecoder(nn.Module):
    def __init__(self):
        super(EncoderDecoder, self).__init__()

    """
        Retrieves intermediate representation's number of channels
    """

    @property
    def _encoder_channels(self):
        currentLevel, chnl_sizes, tmpParam = "_level1", [], None
        # Get the paramters from the model and their names
        for name, param in self._encoder.named_parameters():
            tmpLevel = name.split(".")[0]
            # If it is the last layer of a level, add its name and size
            if not tmpLevel == currentLevel:
                chnl_sizes.append((currentLevel, tmpParam.size()[0]))
                currentLevel = tmpLevel
            tmpParam = param

        chnl_sizes.append((tmpLevel, tmpParam.size()[0]))
        return chnl_sizes


import argparse
import os
from os import listdir
from os.path import isfile, join
import torch
import pandas
from graph_embedding.relational_graph import *

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--node_graph_dir', type=str, help='dir of the node files')
    parser.add_argument('--edge_graph_dir', type=str, help='dir of the edge files')
    parser.add_argument('--embedding_graph_dir', type=str, help='dir to save embedding graph')
    parser.add_argument('--label', type=int, help='label of the commits, 1 if the commits are buggy, 0 otherwise')
    args = parser.parse_args()

    node_graph_dir = args.node_graph_dir
    edge_graph_dir = args.edge_graph_dir
    embedding_graph_dir = args.embedding_graph_dir
    if not os.path.isdir(embedding_graph_dir):
        os.makedirs(embedding_graph_dir)
    node_files = [f for f in listdir(node_graph_dir) if isfile(join(node_graph_dir, f))]
    label = int(args.label)
    if label == 1:
        embedding_graph_dir = os.path.join(embedding_graph_dir, "VTC")
    else:
        embedding_graph_dir = os.path.join(embedding_graph_dir, "VFC")
    if not os.path.isdir(embedding_graph_dir):
        os.makedirs(embedding_graph_dir)
    for f in node_files:
        try:
            commit_id = f.split(".")[0].split("_")[-1]
            node_info = pandas.read_csv(join(node_graph_dir, f))
            edge_info = pandas.read_csv(join(edge_graph_dir, "edge_" + commit_id + ".csv"))
            edge_info = edge_info[edge_info["etype"] != "CFG"]
            data = embed_graph(commit_id, label, node_info,  edge_info)
            torch.save(data, os.path.join(embedding_graph_dir, "data_{}.pt".format(commit_id)))
        except:
            print("exception:" + commit_id)


import time
import cv2
import numpy as np
from src.analyzer import Analyzer
import sys
import time

INP = 21  # CHANGE!!!

def print_help():
    print("Line following robot for SPŠE by Plajta <3")
    print("Usage: main.py [arg1] [arg2] ...")
    print("Or: main.py -i [arg1] [arg2] ... [input]")
    print("When no args are entered the script just starts with default settings")
    print("\nArgs:")
    print("\t-h\t\tPrint this help and exits")
    print("\t-g\t\tStarts with a graphics output, if on a Raspberry Pi, automatically assumes that framebuffer should be used")
    print("\t--nofb\t\tForcibly disables framebuffer output")
    print("\t--nomotors\tForcibly disables motors")
    print("\t-m\t\tPrints frametimes after every frame")
    print("\t--hough\t\tSwitches processing from counting pixels in a column to Hough transform")
    print("\t-pi\t\tIf graphics is enabled, forces rendering of the preprocessed image for debugging use")
    print("\t-i\t\tWhen this is enabled, the last argument willbe treated like a path to an input image")
    print("\t--stop\t\tWhen enabled the robot will try to stop on the finish line")
    print("\t--colors\t\tWhen enabled the robot will try to react to colored markings")

def main(args):
    # Default flags
    running_on_rpi = True
    headless = True
    in_fb = False
    perf_metrics = False
    enable_motors = False
    use_hough = False
    do_tocka = False
    show_preprocessed_image = False
    virt_camera = False
    stop_on_line = False
    detect_colors = False
    start_speed = 0x6666
    int_speed = 0x0000
    acceleration = start_speed / 2 # Reach full speed in half a second
    radial_speed_servo = 90 # In degrees per second
    max_angle = 110
    path = ""

    try:
        with open('/sys/firmware/devicetree/base/model') as f:  # Check if running on an Raspberry Pi
            model = f.read()
            if "Raspberry" in model:
                running_on_rpi = True
                in_fb = True
                enable_motors = True
                try:
                    with open('/sys/class/graphics/fb0/virtual_size') as f:  # Get framebuffer size
                        size = f.read()
                        fb_size = size[:-1].split(",")
                        fb_size = [int(side) for side in fb_size]
                        fb_size = tuple(fb_size)
                except FileNotFoundError:
                    in_fb = False
            else:
                running_on_rpi = False
    except FileNotFoundError:  # If the file doesn't exist automatically assume a PC and disable framebuffer output
        running_on_rpi = False

    print(f"Running on a Raspberry Pi: {running_on_rpi}")

    if args is not []:  # Check all args
        if "-h" in args:
            print_help()
            sys.exit()
        if "-g" in args:
            headless = False
        if "--nofb" in args:
            in_fb = False
        if "--nomotors" in args:
            enable_motors = False
        if "-m" in args:
            perf_metrics = False
        if "--hough" in args:
            use_hough = True
        if "--tocka" in args:
            do_tocka = True
        if "-pi" in args:
            show_preprocessed_image = True
        if "-i" in args:
            virt_camera = True
        if "--stop" in args:
            stop_on_line = True
        if "--colors" in args:
            detect_colors = True

    if virt_camera:
        path = args[-1]

    # Import and init platform specific packages
    if running_on_rpi:
        import RPi.GPIO as GPIO
        if enable_motors:
            from src.motors import Motors
            motors = Motors()
            motors.enable()
            if do_tocka:
                GPIO.setup(INP, GPIO.IN)
    else:
        from src.webcam import Camera

    # Camera import
    if virt_camera:
        from src.virtcam import Camera
    else:
        if running_on_rpi:
            from src.picam import Camera
        else:
            from src.webcam import Camera

    # Init general packages
    camera = Camera(path)
    analyzer = Analyzer(perf_metrics)
    last_E = 0
    start_time = time.time()
    last_time = time.time()
    stop_time = None
    desired_speed = start_speed
    if enable_motors: motors.angle = 0
    if detect_colors:
        verdict_o_meter = [0,0,0] # Color, Number of frames with color, Number of frames from last color
        min_color_frames = 3
        max_noncolor_frames = 2

    try:
        while True:  # Main loop
            if running_on_rpi and enable_motors and do_tocka and not GPIO.input(INP):
                motors.tocka()

            frame = camera.capture()

            if use_hough:
                preprocessed_frame = analyzer.preprocessing(frame)

                lines = analyzer.detect_lines(preprocessed_frame)

                line_image = np.copy(frame)

                if headless:
                    deviation, _ = analyzer.process_lines(lines)
                else:
                    deviation, out_image = analyzer.process_lines(lines, line_image)
            else:
                preprocessed_frame, thresh = analyzer.preprocessing(frame, otsu=True, kernel_size=(5, 5))
                deviation, out_image, contour = analyzer.find_centroid(preprocessed_frame, not headless)
                if detect_colors: verdict, color = analyzer.find_colors(frame, render=not headless, otsu=True, centroid=deviation, thresh=thresh)
                if stop_on_line:
                    sf_detect = analyzer.stop_line_detect(contour, (int(frame.shape[0]*0.15), int(frame.shape[1]*0.42)), (int(frame.shape[0]*0.85), int(frame.shape[1]*0.42))) # Completely ✨ arbitrary ✨ numbers
                    if sf_detect and ((time.time() - start_time) > 10):
                        stop_time = time.time()
                    if stop_time is not None and ((time.time() - stop_time) > 0.5):
                        break
                # if not headless and detect_colors: out_image = (color[:,:,:3] + out_image)[:,:,:3]
                if not headless and detect_colors: out_image = color
                if detect_colors:
                    if verdict[0] != 0:
                        if verdict_o_meter[0] == verdict[0]:
                            verdict_o_meter[1] +=1
                        elif verdict_o_meter[0] == 0:
                            verdict_o_meter = [verdict[0],1,0]
                    if verdict_o_meter[0] != verdict[0]:
                        verdict_o_meter[2] += 1
                    if verdict_o_meter[0] != 0 and verdict_o_meter[1] >= min_color_frames and verdict_o_meter[2] >= max_noncolor_frames:
                        if verdict_o_meter[0] == 1:
                            print("Red, new desired speed")
                            desired_speed = 0x4444
                            verdict_o_meter = [0,0,0]
                        if verdict_o_meter[0] == 2:
                            desired_speed = start_speed
                            print("Green, new desired speed")
                            verdict_o_meter = [0,0,0]
                    if verdict_o_meter[0] != 0 and verdict_o_meter[1] <= min_color_frames and verdict_o_meter[2] >= max_noncolor_frames:
                        verdict_o_meter = [0,0,0]
                    # print(verdict,verdict_o_meter)
                # out_image[:,:,0] = color[:,:,0]
                # np.logical_or(color[:,:,0],out_image[:,:,0],out_image[:,:,0])
                # cv2.addWeighted(color,0.5,out_image,0.5,0)
                # out_image = frame
            if deviation is not None:
                now_time = time.time()
                # print(now_time-last_time)
                if int_speed < desired_speed:
                    int_speed += acceleration*(now_time-last_time)
                if int_speed > desired_speed:
                    int_speed = desired_speed
                int_speed = int(int_speed)
                speed = [int_speed,int_speed]
                Kp = 1.3
                Kd = 0.15
                E = 1 - abs(deviation)
                P = E * Kp
                D = ((E - last_E) / (now_time - last_time)) * Kd
                output = max(min(P + D, 1), 0)
                if deviation < 0:
                    speed[0] = round(speed[0] * output)
                else:
                    speed[1] = round(speed[1] * output)
                if enable_motors:
                    motors.speed = speed
                    motors.angle += radial_speed_servo*(now_time-last_time)
                    if motors.angle > max_angle:
                        motors.angle = max_angle
                        radial_speed_servo *= -1
                    elif motors.angle <= 0:
                        motors.angle = 0
                        radial_speed_servo *= -1
                last_time = now_time
                last_E = E
                # print(speed)

            if not headless:  # Display output
                if show_preprocessed_image: out_image = preprocessed_frame
                if in_fb:
                    frame32 = cv2.cvtColor(out_image, cv2.COLOR_BGR2BGRA)
                    fbframe = cv2.resize(frame32, fb_size)
                    with open('/dev/fb0', 'rb+') as buf:
                        buf.write(fbframe)
                else:
                    cv2.imshow('video', out_image)
                    if cv2.waitKey(1) == 27:
                        break

            if perf_metrics: print(analyzer.framecounter, analyzer.times)
    except KeyboardInterrupt:
        pass

    print("\nQuitting because of a keyboard interrupt\n")
    if running_on_rpi and enable_motors: motors.deinit()
    camera.deinit()
    if not headless and not in_fb: cv2.destroyAllWindows()
    sys.exit()

if __name__ == "__main__":
    main(sys.argv[1:])


from sys import argv, stdin, stdout, stderr, exit
import re

tokenPattern = re.compile(r"([0-9a-fA-F]{2})|(\s+)|(;.*$)", re.MULTILINE)
newlinePattern = re.compile(r"\r\n|[\n\r]")

def main(input, output):
    """
    input  : str - such as open("Example.class", "r").read()
    output : file - such as stdout or anything with a method write(str)
    return : str - error message or None
    """
    offset = 0
    lineNumber = 1 # for error reporting
    while offset < len(input):
        match = tokenPattern.match(input, offset)
        if match == None:
            return "You're doing it wrong in line %i" % lineNumber
        hexText = match.group(1)
        if hexText != None:
            output.write(chr(int(hexText, 16)))
        whitespace = match.group(2)
        if whitespace != None:
            lineNumber += len(newlinePattern.findall(whitespace))
        offset = match.end()

if __name__ == "__main__":
    if len(argv) == 1:
        input = stdin.read()
    elif len(argv) == 2:
        input = open(argv[1], "r").read()
    else:
        stderr.write("too many arguments\n")
        exit(1)

    errorMessage = main(input, stdout)
    returnCode = 0
    if errorMessage != None:
        stderr.write(errorMessage + "\n")
        returnCode = 1
    exit(returnCode)


import io

from fastapi import FastAPI, UploadFile
import tensorflow as tf
from PIL import Image
import numpy as np

IMG_SIZE = (64, 64)
model = tf.keras.models.load_model("models/model_loss_0.882523775100708_acc_0.6944937705993652.h5")

app = FastAPI()

RESULTS = ["black", "blue", "green", "yellow"]

def imageThroughIA(image: Image) -> str:
    imag = np.array(image)
    predictions = model.predict(imag[None, :, :]).argmax(axis=1)
    return RESULTS[predictions[0]]

@app.get("/")
async def root():
    return {"message": "Hello There"}

@app.post("/check-recyclable")
async def checkRecyclable(file: UploadFile):
    request_object_content = await file.read()
    img = Image.open(io.BytesIO(request_object_content)).convert('RGB').resize(IMG_SIZE)
    res = imageThroughIA(img)
    return res


import unittest

import numpy as np
import scipy.linalg as spla

class TestLinalg(unittest.TestCase):
    def test_solveh_banded(self):
        import numpy as onp
        import scipy.linalg as ospla

        num_dims = 15
        b = onp.exp(onp.random.normal(size=(num_dims, )))
        a = 0.1 * onp.random.normal(size=(num_dims-1, ))
        tri = onp.diag(b)
        tri += onp.diag(a, 1)
        tri += onp.diag(a, -1)
        rhs = onp.random.normal(size=(num_dims, ))

        ab = onp.array([
            onp.hstack((0.0, onp.diag(tri, 1))),
            onp.diag(tri)
        ])
        x = ospla.solveh_banded(ab, rhs)
        self.assertTrue(onp.allclose(tri@x, rhs))

        sol = spla.solveh_banded(ab, rhs)
        self.assertTrue(np.allclose(sol, x))
        self.assertTrue(np.allclose(tri@sol, rhs))


import os
from avocado import Test
from avocado.utils import distro, genio, linux_modules, process
from avocado.utils.software_manager.manager import SoftwareManager

class kernelLockdown(Test):
    """
    Kernel Lockdown tests for Linux
    :avocado: tags=privileged,security,lockdown
    """

    def setUp(self):
        '''
        Kernel lockdown and Guest Secure boot support is available only on
        Power10 LPAR.
        '''
        self.distro_version = distro.detect()
        smm = SoftwareManager()
        deps = []
        if self.distro_version.name in ['rhel', 'redhat']:
            deps.extend(['powerpc-utils-core'])
        if self.distro_version.name in ['SuSE']:
            deps.extend(['powerpc-utils'])
        for package in deps:
            if not smm.check_installed(package) and not smm.install(package):
                self.cancel('%s is needed for the test to be run' % package)
        val = genio.read_file("/proc/cpuinfo")
        if 'POWER10' not in val:
            self.cancel("Power10 LPAR is required to run this test.")
        # Checking whether lockdown enabled or not.
        self.lockdown_file = "/sys/kernel/security/lockdown"
        if not os.path.exists(self.lockdown_file):
            self.cancel("Lockdown not enabled, can't execute test(s)")
        lockdown = genio.read_file(self.lockdown_file).rstrip('\t\r\n\0')
        index1 = int(lockdown.index('[')) + 1
        index2 = int(lockdown.index(']'))
        sys_lockdown = lockdown[index1:index2]
        # Checking the Guest Secure Boot enabled or not.
        cmd = "lsprop  /proc/device-tree/ibm,secure-boot"
        output = process.system_output(cmd, ignore_status=True).decode()
        if '00000002' not in output:
            self.cancel("Secure boot is not enabled.")
        # List required for kernel configuration check.
        self.no_config = []

    def _check_kernel_config(self, config_option):
        # Helper function to check kernel config options
        ret = linux_modules.check_kernel_config(config_option)
        if ret == linux_modules.ModuleConfig.NOT_SET:
            self.no_config.append(config_option)

    def test_check_kernel_config(self):
        # Checking the required kernel config options for lockdown
        self._check_kernel_config('CONFIG_SECURITY_LOCKDOWN_LSM')
        self._check_kernel_config('CONFIG_SECURITY_LOCKDOWN_LSM_EARLY')
        self._check_kernel_config('CONFIG_LSM')
        if self.no_config:
            self.fail("Config options not set are: %s" % self.no_config)

    def test_lockdown_none(self):
        # Try changing the lockdown value to 'none'
        try:
            genio.write_one_line(self.lockdown_file, 'none')
        except IOError as err:
            if 'Operation not permitted' not in str(err):
                self.fail("Kernel Lockdown value changed to 'none'")

    def test_lockdown_mem(self):
        # Try read the values from /dev/mem
        try:
            genio.read_file("/dev/mem")
        except IOError as err:
            if 'Operation not permitted' not in str(err):
                self.fail("'/dev/mem' file access permitted.")

    def test_lockdown_debugfs(self):
        if self.distro_version.name == "SuSE":
            self.cancel("This test not supported on SuSE")
        # Try read the values from sysfs file
        output = process.system_output('mount', ignore_status=True).decode()
        if 'debugfs' not in output:
            self.cancel("Skip this test as 'debugfs' not mounted.")
        dbg_file = "/sys/kernel/debug/powerpc/xive"
        if os.path.exists(dbg_file):
            try:
                genio.read_file(dbg_file)
            except IOError as err:
                if 'Operation not permitted' not in str(err):
                    self.fail("Access to %s permitted." % dbg_file)
        else:
            self.cancel("%s file not exist." % dbg_file)


import re
import sys
import requests

MODULE_REGEX = r'^[_a-zA-Z][_a-zA-Z0-9]+$'

module_name = '{{ cookiecutter.project_slug}}'

if not re.match(MODULE_REGEX, module_name):
    print('ERROR: The project slug (%s) is not a valid Python module name. Please do not use a - and use _ instead' % module_name)

    #Exit to cancel project
    sys.exit(1)

prodpypi_url = 'https://pypi.org/project/' + module_name

resp = requests.get(prodpypi_url, timeout=30)

if resp.status_code == 200:
    print('ERROR: The project slug ' + module_name +
          ' already exists on Production Pypi (' + prodpypi_url +
          ') Please use a different name')
    sys.exit(2)

testpypi_url = 'https://test.pypi.org/project/' + module_name
resp = requests.get(testpypi_url, timeout=30)

if resp.status_code == 200:
    print('ERROR: The project slug ' + module_name +
          ' already exists on Test Pypi (' + testpypi_url +
          ') Please use a different name')
    sys.exit(3)