from ETRIDataset.visualization import Visualizer
from utils.functions import *
from helper import load_datasetloader, load_solvers

def main():
    parser = argparse.ArgumentParser()

    parser.add_argument('--exp_id', type=int, default=1331)
    parser.add_argument('--gpu_num', type=int, default=0)
    parser.add_argument('--model_name', type=str, default='autove')
    parser.add_argument('--start_frm_idx', type=int, default=0)
    parser.add_argument('--best_k', type=int, default=10)
    parser.add_argument('--map_size', type=int, default=1024)
    parser.add_argument('--t_skip', type=int, default=1)
    parser.add_argument('--scene_range', type=float, default=60)
    parser.add_argument('--is_save', type=int, default=0) # update, 220216
    parser.add_argument('--is_target_only', type=int, default=1)  # update, 220216
    args = parser.parse_args()
    test(args)

def return_target_scenes():

    # update, 220217
    target_scenes = []

    # logid : 0075
    target_scenes += [i for i in range(0, 4+1)]
    target_scenes += [i for i in range(15, 19+1)]
    target_scenes += [i for i in range(180, 184+1)]
    target_scenes += [i for i in range(193, 197+1)]
    target_scenes += [i for i in range(200, 204+1)]

    # logid : 0043
    target_scenes += [i for i in range(215, 219 + 1)]
    target_scenes += [i for i in range(240, 249 + 1)]
    target_scenes += [i for i in range(280, 289 + 1)]
    target_scenes += [i for i in range(350, 354 + 1)]
    target_scenes += [i for i in range(420, 424 + 1)]
    target_scenes += [i for i in range(450, 454 + 1)]
    target_scenes += [i for i in range(465, 469 + 1)]
    target_scenes += [i for i in range(480, 484 + 1)]
    target_scenes += [i for i in range(525, 529 + 1)]

    # logid : 0006
    target_scenes += [i for i in range(615, 619 + 1)]

    # logid : 0033
    target_scenes += [i for i in range(795, 799 + 1)]
    target_scenes += [i for i in range(840, 844 + 1)]

    # logid : 0016
    target_scenes += [i for i in range(970, 974 + 1)]
    target_scenes += [i for i in range(995, 999 + 1)]
    target_scenes += [i for i in range(1104, 1108 + 1)]
    # target_scenes += [i for i in range(1274, 1278 + 1)]
    target_scenes += [i for i in range(1300, 1304 + 1)]
    target_scenes += [i for i in range(1330, 1334 + 1)]

    # logid : 0110
    target_scenes += [i for i in range(1395, 1399 + 1)]
    target_scenes += [i for i in range(1410, 1414 + 1)]
    target_scenes += [i for i in range(1594, 1598 + 1)]

    return target_scenes

def test(args):

    # parent of working directory is base
    abspath = os.path.dirname(os.path.realpath(__file__))
    os.chdir(Path(abspath).parent.absolute())

    # CUDA setting
    os.environ["CUDA_VISIBLE_DEVICES"] = str(int(args.gpu_num))

    # type definition
    long_dtype, float_dtype = get_dtypes(useGPU=True)

    folder_name = 'ETRI_' + args.model_name + '_model' + str(args.exp_id)
    path = os.path.join('./saved_models/', folder_name)

    # load parameter setting
    with open(os.path.join(path, 'config.pkl'), 'rb') as f:
        saved_args = pickle.load(f)
    saved_args.best_k = args.best_k
    saved_args.is_train_w_nuscenes = 0
    saved_args.limit_range = 50 # important ------
    saved_args.dataset_type = 'ETRI'
    print_training_info(saved_args)

    # load test data
    data_loader, _ = load_datasetloader(args=saved_args, isTrain=False, dtype=torch.FloatTensor)

    # define network
    solver = load_solvers(saved_args, data_loader.num_test_scenes, float_dtype)
    ckp_idx = save_read_latest_checkpoint_num(os.path.join(solver.save_dir), 0, isSave=False)
    _ = solver.load_pretrained_network_params(ckp_idx)
    solver.mode_selection(isTrain=False)

    # evaluation setting
    t_skip = args.t_skip
    obs_len = int(saved_args.past_horizon_seconds * saved_args.target_sample_period)
    pred_len = int(saved_args.future_horizon_seconds * saved_args.target_sample_period)
    saved_args.best_k = args.best_k
    saved_args.batch_size = 1
    obs_len_ = obs_len

    # sub-sample trajs
    target_index_obs = np.array([-1 * _ for _ in range(0, obs_len, t_skip)])[::-1] + (obs_len-1)
    target_index_pred = np.array([_ for _ in range(t_skip - 1, pred_len, t_skip)])

    obs_len = len(target_index_obs)
    pred_len = len(target_index_pred)

    # scene range
    map_size = args.map_size
    x_range = (-1 * args.scene_range, args.scene_range)
    y_range = (-1 * args.scene_range, args.scene_range)
    z_range = (-3, 2)

    # visualizer
    vs = Visualizer(args=saved_args, map=data_loader.map,  x_range=x_range, y_range=y_range,
                    z_range=z_range, map_size=map_size, obs_len=obs_len, pred_len=pred_len)

    # update, 220216
    folder_path = './Captures/capture_%d' % saved_args.exp_id
    if (args.is_save == 1):
        if (os.path.exists('./Captures') == False):
            os.mkdir('./Captures')

        if (os.path.exists(folder_path) == False):
            os.mkdir(folder_path)

    target_scenes = return_target_scenes()

    auto_play = False
    dataset_len = data_loader.num_test_scenes
    current_frame_idx = args.start_frm_idx
    while True:

        # update, 220217
        if (args.is_target_only == 1 and current_frame_idx not in target_scenes):
            current_frame_idx += 1
            if (current_frame_idx == dataset_len):
                sys.exit()
            continue

        # data loading
        data = data_loader.next_sample(current_frame_idx, mode='test')

        # inference
        obs_traj, future_traj, pred_trajs, agent_ids, scene, valid_scene_flag = solver.test(data, float_dtype, args.best_k)

        if (valid_scene_flag == False):
            current_frame_idx+=1
            continue

        # debug ---
        # vs.show_around_view_images(scene.sample_token)

        obs_traj_valid = obs_traj[target_index_obs, :, :]
        future_traj_valid = future_traj[target_index_pred, :, :]
        overall_traj = np.concatenate([obs_traj_valid, future_traj_valid], axis=0)
        pred_trajs_valid = pred_trajs[:, target_index_pred, :, :]

        # draw point cloud topivew
        fig, ax = plt.subplots()
        img = 255 * np.ones(shape=(map_size, map_size, 3))
        ax.imshow(img.astype('float') / 255.0, extent=[0, map_size, 0, map_size])

        # draw hdmap
        ax = vs.topview_hdmap(ax, scene.agent_dict['EGO'].pose, x_range, y_range, map_size)

        # draw bbox
        num_agents = agent_ids.shape[0]
        for a in range(num_agents):
            a_token = scene.id_2_token_lookup[agent_ids[a]]
            agent = scene.agent_dict[a_token]
            if (agent.track_id == 'EGO'):
                continue
            ax = vs.topview_bbox(ax, agent, (0.5, 0.5, 0.5))

        # draw trajs
        if (saved_args.model_mode == 'pedestrian'):
            ego_traj = scene.agent_dict['EGO'].trajectory[:, 1:3]
            ax = vs.topview_trajectory(ax, ego_traj, [])

        num_agents = agent_ids.shape[0]
        for a in range(num_agents):

            if (a == 0):
                continue

            a_token = scene.id_2_token_lookup[agent_ids[a]]
            agent = scene.agent_dict[a_token]

            if (agent.track_id != 'EGO'):
                ax = vs.topview_bbox(ax, agent, (1, 0, 0))

            gt_traj = overall_traj[:, a, :]
            for k in range(args.best_k):
                est_traj = pred_trajs_valid[k, :, a, :]
                ax = vs.topview_trajectory(ax, gt_traj, est_traj)

        plt.axis([0, map_size, 0, map_size])
        # plt.show()

        img = vs.fig_to_nparray(fig, ax)
        text = '[Log ID %s, Scene # %d]' % (scene.log_token, current_frame_idx)
        cv2.putText(img, text, (20, 20), cv2.FONT_HERSHEY_PLAIN, 2, (0, 0, 255))

        # update, 220216
        if (args.is_save == 1):
            file_name = 'img_%04d.png' % (current_frame_idx)
            cv2.imwrite(os.path.join(folder_path, file_name), img)
            current_frame_idx += 1
            if (current_frame_idx == dataset_len):
                sys.exit()

        else:
            # show image
            cv2.imshow('', img)

            # key actions
            if auto_play:
                k = cv2.waitKey(1) & 0xFF
                current_frame_idx = current_frame_idx + 1
            else:
                k = cv2.waitKey(0) & 0xFF

            if k == 27:  # esc key
                cv2.destroyAllWindows()
                return False
            elif k == 32:  # Space key
                if auto_play:
                    auto_play = False
                else:
                    auto_play = True

            if k == ord('e'):  # jump actions
                if current_frame_idx + 10 < dataset_len:
                    current_frame_idx = current_frame_idx + 10
                else:
                    current_frame_idx = dataset_len - 1
            if k == ord('q'):
                if current_frame_idx - 10 >= 0:
                    current_frame_idx = current_frame_idx - 10
                else:
                    current_frame_idx = 0
            if k == ord('/'):
                current_frame_idx = 0

            if not auto_play:
                if k == 83 or k == ord('d'):  # '->' key
                    if not current_frame_idx >= dataset_len:
                        current_frame_idx = current_frame_idx + 1
                elif k == 81 or k == ord('a'):  # '<-' key
                    if current_frame_idx - 1 >= 0:
                        current_frame_idx = current_frame_idx - 1

            if current_frame_idx >= dataset_len:
                current_frame_idx = dataset_len - 1

if __name__ == '__main__':
    main()


import torch
import numpy as np
from torch import Tensor
from tools.tree_tools import get_parent_children_combo_from_tree, parentchild_ids_to_idx, tokentree_to_ete
from typing import List, Callable, Dict, Tuple, Optional, DefaultDict
from conllu import TokenList
import os
from collections import defaultdict

get_ids_from_sent: Callable[[TokenList], List[str]] = lambda sent: [word['id'] for word in sent]
get_pos_from_sent: Callable[[TokenList], List[str]] = lambda sent: [word['upostag'] for word in sent]
get_tokens_from_sent: Callable[[TokenList], List[str]] = lambda sent: [word['form'] for word in sent]

def fetch_pos_tags(
    ud_parses: List[TokenList],
    pos_vocab: Optional[DefaultDict[str, int]] = None,
    corrupted=False,
    corrupted_pos_tags: Optional[Dict[str, str]] = None
)-> Tuple[List[Tensor], DefaultDict]:
    """
    Converts `ud_parses` into a tensor of POS tags.
    """
    # If `pos_vocab` is not known, make one based on all POS tokens in `ud_parses`
    if (pos_vocab is None):
        print('get all tokens')
        all_pos_tokens = set([pos for sent in ud_parses for pos in get_pos_from_sent(sent)])
        print('get all pos2i')
        pos2i: dict = {'<pad>': 0, '<unk>': 1, **{pos.strip(): i + 2 for i, pos in enumerate(all_pos_tokens)}}
        pos_vocab = defaultdict(lambda: pos2i["<unk>"])
        pos_vocab.update(pos2i)

    pos_tokens_result: List[Tensor] = []
    sent: TokenList

    for sent in ud_parses:
        # If corrupted, let the target value be the corrupted tokens
        if corrupted:
            pos_tokens = torch.tensor([pos_vocab[corrupted_pos_tags[word]] for word in get_tokens_from_sent(sent)])
        else:
            pos_tokens = torch.tensor([pos_vocab[pos] for pos in get_pos_from_sent(sent)])
        pos_tokens_result.append(pos_tokens)

    return pos_tokens_result, pos_vocab

def create_struct_gold_distances(corpus) -> List[Tensor]:
    """
    Creates gold distances for the strucutal task
    """
    all_distances: List[Tensor] = []

    for sent in corpus:
        tokentree = sent.to_tree()
        ete_tree = tokentree_to_ete(tokentree)

        sen_len = len(ete_tree.search_nodes())
        distances = torch.zeros((sen_len, sen_len))

        # 🏁
        token_ids = get_ids_from_sent(sent)

        # Go over all the token ids, as row and as columns
        for i, token_id_A in enumerate(token_ids):
            for j, token_id_B in enumerate(token_ids):

                # Set distance to 0 if they are equal
                if token_id_A == token_id_B:
                    distances[i, j] = 0
                else:
                    # Else use `.get_distance` to calculate the distance for row A and column B
                    A = str(token_id_A)
                    B = str(token_id_B)
                    distances[i, j] = ete_tree.get_distance(A, B)

        all_distances.append(distances)

    return all_distances

def create_dep_parent_gold_distances(
    corpus: List[TokenList],
    corrupted: bool = False,
    vocab: Dict[str, int] = None
) -> List[Tensor]:
    """
    Assigns for each sentence the index of the parent node.
    If node is -1, then that node has no parent (should be ignored).

    Input:
        - corpus: list of TokenLists
    Output:
        List of Tensors(tensor is )
    """
    all_edges: List[Tensor] = []

    for sent in corpus:
        sent_tree = sent.to_tree()
        sent_id2idx = {i['id']: idx for idx, i in enumerate(sent)}

        # Calculate tuples of (parent, child), and then map their ID to their respective indices
        parent_child_tuples = get_parent_children_combo_from_tree(sent_tree)
        parent_child_tuples = parentchild_ids_to_idx(sent_id2idx, parent_child_tuples)

        # Initialize our matrix
        sen_len = len(sent)
        edges = torch.zeros((sen_len))
        root_idx = sent_id2idx[sent_tree.token['id']]

        # For each edge, assign in the corresponding index the parent index, and -1 for root
        for parent_edge in parent_child_tuples:
            parent_idx, child_idx = parent_edge

            if corrupted:
                corrupted_choices = [0, child_idx, sen_len]
                child_token = sent[child_idx]['form']
                corrupted_choice_idx = vocab[child_token]
                edges[child_idx] = corrupted_choices[corrupted_choice_idx]
            else:
                edges[child_idx] = parent_idx

            edges[root_idx] = -1

        all_edges.append(edges)

    return all_edges

def create_corrupted_dep_vocab(corpora: List[TokenList]) -> Dict[str, str]:
    # Get sentences from all data sets
    possible_targets_distr = [0, 1, 2]

    corrupted_word_type = defaultdict(lambda: 0)
    # Get a corrupted POS tag for each word
    for sentence in corpora:
        for token in sentence:
            corrupted_behaviour = np.random.choice(possible_targets_distr, 1).item()

            if token['form'] not in corrupted_word_type:
                corrupted_word_type[token['form']] = corrupted_behaviour

    return corrupted_word_type


#need to look at subarrays of the nums array, whose lengths are = k and return the
#highest average derived from the sub   arrays

def max_sub(nums, k):
    left = 0
    right = k
    highest_avg = 0
    while right <= len(nums):
        avg = sum(nums[left:right])/k
        if avg > highest_avg:
            highest_avg = avg
        left += 1
        right += 1
    return highest_avg

print(max_sub([5],1))


# https://leetcode.com/problems/summary-ranges/

# Given a sorted integer array without duplicates, return the summary of its ranges.

# For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"].

class Solution(object):
    def summaryRanges(self, nums):
        """
        :type nums: List[int]
        :rtype: List[str]
        """

        if not nums: return []

        last = [nums[0], nums[0]]
        results = []

        # traverse
        for n in nums[1:]:
            if n == last[1]+1:
                last[1] = n
            else:
                if last[0] == last[1]:
                    results.append("%i" % (last[0]))
                else:
                    results.append("%i->%i" % (last[0], last[1]))
                last = [n, n]

        # finishing
        if last[0] == last[1]:
            results.append("%i" % (last[0]))
        else:
            results.append("%i->%i" % (last[0], last[1]))

        return results

    def test(self):
        cases = [
            [],
            [0,3,4,5,10,11],
            [0,1,2,4,5,7],
            [1,2],
            [10,11,15],
        ]
        for c in cases:
            res = self.summaryRanges(c)
            print(c, res)

# Solution().test()


import json
import csv
import time
import requests
from io import StringIO
from datetime import datetime
from .models import Post, ChatRoom, User

from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async

class BOT:
    def __init__(self):
        self.name = 'bot'
        self.queue = []
    def stock(self, param):
        r = requests.get('https://stooq.com/q/l/?s={}&f=sd2t2ohlcv&h&e=csv%E2%80%8B'.format(param))
        row = next( csv.DictReader( StringIO(r.text) ) )
        if row['Close'] == 'N/D':
            return 'Error: Command not have quote'
        else:
            return '{} quote is ${} per share'.format(row['Symbol'], row['Close'])
    def deploy(self, command):
        stock_cmd = command.split("=")
        current_time = datetime.now()
        response = {
            'user_name': self.name,
            'created_date': current_time.strftime('%Y-%m-%d'),
            'created_time': current_time.strftime('%H:%M')
        }

        if len(stock_cmd) != 2:
            response['message'] = 'Error: Wrong command'
        else:
            if stock_cmd[0] == 'stock' and len(stock_cmd[1]) > 1:
                job_id = len(self.queue) - 1
                self.queue.append( [job_id, stock_cmd[1], 'created'] )
                if len(self.queue) >= 2:
                    while self.queue[job_id - 1][0] == 'created':
                        time.sleep(0.5)
                    self.queue[job_id][2] = 'finished'
                    response['message'] = self.stock(stock_cmd[1])
                elif len(self.queue) == 1:
                    self.queue[0][2] = 'finished'
                    response['message'] = self.stock(stock_cmd[1])
            else:
                response['message'] = 'Error: Wrong command {}'.format(stock_cmd[0])
        return response

bot = BOT()

class Server(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_id = self.scope['url_route']['kwargs']['room_id']
        self.room_group = 'chat_%s' % self.room_id
        await self.channel_layer.group_add(self.room_group, self.channel_name)
        await self.accept()

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(self.room_group, self.channel_name)

    async def receive(self, text_data):
        data = json.loads(text_data)
        out = await self.save_post(data['user_name'], data['user_id'], data['room_id'], data['message'])
        await self.channel_layer.group_send( self.room_group,
            {
                'type': 'send_message',
                'message': out['message'],
                'user_name': out['user_name'],
                'created_date': out['created_date'],
                'created_time': out['created_time']
            }
        )

    async def send_message(self, event):
        await self.send(text_data=json.dumps({
            'message': event['message'],
            'user_name': event['user_name'],
            'created_date': event['created_date'],
            'created_time': event['created_time']
        }))

    @sync_to_async
    def save_post(self, user_name, user_id, room_id, message):
        if message[:1] == '/': # maybe bot
            return bot.deploy(message[1:])
        else:
            room = ChatRoom.objects.get(pk=room_id)
            user = User.objects.get(pk=user_id)
            post = Post.objects.create(room=room, msn=message, created_by=user)
            post.save()
            return {
                'message': message,
                'user_name': user_name,
                'created_date': post.created.strftime('%Y-%m-%d'),
                'created_time': post.created.strftime('%H:%M')
            }


# coding=utf-8

from cms_support.utils.constants import CteSAM as CteSAM
from cms_support.utils.site_utils import AbstractCMSSST
import re

class SiteReadiness(AbstractCMSSST):
    def __init__(self, time_class, target="", blacklist_regex=""):
        super().__init__(time_class, CteSAM.REF_SR_METRIC, target=target, blacklist_regex=blacklist_regex)

    @staticmethod
    def site_enabled(dict_site, metric):
        site_enabled = True
        if metric in dict_site.keys():
            status = dict_site[metric]
            if status != "enabled":
                site_enabled = False
        return site_enabled

    def get_not_enabled_sites(self, metric=""):
        rows, metrics = [], CteSAM.REF_METRICS_SR

        if metric:
            desired_metrics = [sr_m for m in metric.split("|") for sr_m in CteSAM.REF_METRICS_SR if re.search(m, sr_m)]
            if desired_metrics:
                metrics = desired_metrics
        # for site in self.sites_list:
        dict_attr = {"name": self.target}
        kibana_query_all = self.get_kibana_query(dict_attr=dict_attr)
        response_kibana_cmssst = self.get_direct_response(kibana_query=kibana_query_all)

        studied_sites = []
        for response in reversed(response_kibana_cmssst):
            data_response = response["data"]
            data_response["life_status"] = data_response.pop("status")  # change key to keep structure <metric>_status
            site_name = data_response["name"]
            is_blacklisted = self.is_blacklisted(site_name, self.blacklist_regex)

            if site_name not in studied_sites and not is_blacklisted:
                studied_sites.append(site_name)
                site_with_issues = False

                for metric in metrics:
                    if not self.site_enabled(data_response, metric):
                        site_with_issues = True
                        break
                if site_with_issues:
                    rows.append(data_response)
        return rows

if __name__ == "__main__":
    from cms_support.utils.query_utils import Time
    time_ss = Time(hours=CteSAM.HOURS_RANGE)
    sam = SiteReadiness(time_ss, target="T2")
    rows = sam.get_not_enabled_sites(metric="prod|life")
    columns = ["name"] + CteSAM.REF_METRICS_SR + ["detail"]

#     from cms_support.utils.site_utils import write_excel
#     write_excel(rows, columns=columns, name_ref="testing" + "SiteReadiness")
#     print()


#!/usr/bin/env python3
from pyrogram import Client, errors
from termcolor import colored
from time import localtime, strftime
import sys
import os
import re

count = False
get_names = False

def get_channels(argv):
	channels = []
	for x in argv:
		if not x.startswith('-'):
			if x.startswith('@'): channels.append(x[1:])
			else: channels.append(x)
	return channels

def process_flags(argv):
	if '--help' in argv or '-h' in argv:
		help_msg = '''USAGE: ./download.py channel(s) [FLAGS]

FLAGS:
--help    | -h -- Print this message and exit.
--count   | -c -- Simply count up all the chat/channel's documents.
--names   | -n -- Iterate through the chat/channel and print file names with no downloads.
--nocolor -- Disable colored output.
--cleanup -- Clear the vault and exit.

GETTING AN API DATA:
1. Go to <my.telegram.org> ang log in;
2. Register new app in "API development tools" section;
3. Copy values from first and second fields;

ISSUES: <github.com/asciid/tg_grabber/issues>'''

		print(help_msg)
		sys.exit()

	elif '--cleanup' in argv:
		r = input('This action wipes all stored data. Are you sure? [y/n]: ')
		if r.lower() == 'y':
			os.system('rm -rf vault/ amount.txt output.txt')
		sys.exit()

	elif '--nocolor' in argv:
		def colored(a, b, **attrs): return a

	elif '--count' in argv or '-c' in argv:
		global count
		count = True

	elif '--names' in argv or '-n' in argv:
		global get_names
		get_names = True

# Error handling

args = sys.argv[1:]
process_flags(args)
channels = get_channels(args)

if len(channels) == 0:
	print('Error: Chat or channel to download is omitting.\nRun ./download.py -h for some info.')
	sys.exit()

# Getting data to start
if os.path.exists('grabber.ini'):
	app = Client(session_name='grabber', config_file='grabber.ini')
else:
	api_id = input('Enter your API ID: ')
	api_hash = input('Enter your API hash: ')

	with open('grabber.ini', 'w') as config:
		ini = """[pyrogram]
api_id = {0}
api_hash = {1}""".format(api_id, api_hash)
		config.writelines(ini)
	print('grabber.ini config file has been created.')

	app = Client(session_name='grabber', api_id=api_id, api_hash=api_hash)

app.start()

for entity in channels:
	try:
		data = app.get_chat(entity)
		if data.type not in ('group', 'channel', 'supergroup'):
			app.stop()
			print('Error: Given link refers to a user or a bot.')
			sys.exit()
	except (errors.exceptions.bad_request_400.UsernameNotOccupied, errors.exceptions.bad_request_400.UsernameInvalid):
		app.stop()
		print('Error: Given chat/channel does not exist.')
		sys.exit()

	downloaded = 0
	amount = 0
	path = os.getcwd() + '/vault/' + entity + '/'

	if not count and not get_names:
		if not os.path.exists('vault'): os.mkdir('vault')
		if not os.path.exists('vault/' + entity): os.mkdir('vault/' + entity)

		files = os.listdir(path)

	if not count:
		if data.description == None:
			print(colored('{} ({})'.format(entity, data.title), 'magenta', attrs=['bold']))
		else:
			print(colored('{} ({}): {}'.format(entity, data.title, data.description), 'magenta', attrs=['bold']))

	prev_date = 0
	curr_date = 0
	copies = 1

	for message in app.iter_history(entity):
		if message.media and message.document:

			curr_date = message.date
			date_string = strftime('%Y-%m-%d (%H:%M)', localtime(curr_date))

			if count:
				amount += 1

			elif get_names:
				file_name = message.document.file_name
				print(file_name)

			else:
				file_name = message.document.file_name
				date = message.date

				lenght = message.document.file_size

				os.chdir(path)

				skip = False

				for file in files:
					if file.startswith(file_name+'(COPY'): skip = True

				if not skip:
					if os.path.exists(file_name):
						if os.path.getsize(file_name) == lenght:
							print(colored("File already exists: {};".format(file_name), 'yellow'))
						elif curr_date != prev_date:
							print(colored("[{}]".format(date_string), 'yellow'), colored('Downloading:', 'green'), file_name + ' -- COPY')
							app.download_media(message, file_name=path+file_name+'(COPY {})'.format(copies))
							copies += 1
							downloaded += 1
					else:
						print(colored("[{}]".format(date_string), 'yellow'), colored('Downloading:', 'green'), file_name)
						app.download_media(message, file_name=path + file_name)
						downloaded += 1
						copies = 1

			prev_date = curr_date

	if count:
		print('Total file amount:', amount)
	elif not get_names:
		if downloaded == 0:
			print('Resource is already stored.')
		else:
			print('Files proceed:', downloaded)

	os.chdir('../../')

app.stop()


__metaclass__ = type

# let's try to keep path imports to a minimum...
from os.path import dirname, split as splitpath

import sys
import zipimport
import inspect
import warnings
import re
try:
    import ast
except ImportError:
    ast = None

from zope.interface import Interface, implements

from exocet._filepath import UnlistableError, FilePath
from exocet._zippath import  ZipArchive

from exocet._reflect import namedAny
from exocet._components import registerAdapter

_nothing = object()

PYTHON_EXTENSIONS = ['.py']
OPTIMIZED_MODE = __doc__ is None
if OPTIMIZED_MODE:
    PYTHON_EXTENSIONS.append('.pyo')
else:
    PYTHON_EXTENSIONS.append('.pyc')
PYTHON_EXTENSIONS.extend([".so", ".pyd"])

def _isPythonIdentifier(string):
    """
    cheezy fake test for proper identifier-ness.

    @param string: a str which might or might not be a valid python identifier.

    @return: True or False
    """
    if string == '':
        return True
    try:
        return re.match('[a-zA-Z_][a-zA-Z0-9_]*$', string) is not None
    except TypeError:
        return False

class NotLoadedError(Exception):
    """
    Attempt to access a value that hasn't been loaded yet.

    @since: 10.2
    """

def _isPackagePath(fpath):
    # Determine if a FilePath-like object is a Python package.  TODO: deal with
    # __init__module.(so|dll|pyd)?
    extless = fpath.splitext()[0]
    basend = splitpath(extless)[1]
    return basend == "__init__"

class _ModuleIteratorHelper:
    """
    This mixin provides common behavior between python module and path entries,
    since the mechanism for searching sys.path and __path__ attributes is
    remarkably similar.
    """

    def iterModules(self):
        """
        Loop over the modules present below this entry or package on PYTHONPATH.

        For modules which are not packages, this will yield nothing.

        For packages and path entries, this will only yield modules one level
        down; i.e. if there is a package a.b.c, iterModules on a will only
        return a.b.  If you want to descend deeply, use walkModules.

        @return: a generator which yields PythonModule instances that describe
        modules which can be, or have been, imported.
        """
        yielded = {}
        if not self.filePath.exists():
            return

        for placeToLook in self._packagePaths():
            try:
                children = placeToLook.children()
            except UnlistableError:
                continue

            children.sort()
            for potentialTopLevel in children:
                ext = potentialTopLevel.splitext()[1]
                potentialBasename = potentialTopLevel.basename()[:-len(ext)]
                if ext in PYTHON_EXTENSIONS:
                    # TODO: this should be a little choosier about which path entry
                    # it selects first, and it should do all the .so checking and
                    # crud
                    if not _isPythonIdentifier(potentialBasename):
                        continue
                    modname = self._subModuleName(potentialBasename)
                    if modname.split(".")[-1] == '__init__':
                        # This marks the directory as a package so it can't be
                        # a module.
                        continue
                    if modname not in yielded:
                        yielded[modname] = True
                        pm = PythonModule(modname, potentialTopLevel, self._getEntry())
                        assert pm != self
                        yield pm
                else:
                    if (ext or not _isPythonIdentifier(potentialBasename)
                        or not potentialTopLevel.isdir()):
                        continue
                    modname = self._subModuleName(potentialTopLevel.basename())
                    for ext in PYTHON_EXTENSIONS:
                        initpy = potentialTopLevel.child("__init__"+ext)
                        if initpy.exists():
                            yielded[modname] = True
                            pm = PythonModule(modname, initpy, self._getEntry())
                            assert pm != self
                            yield pm
                            break

    def walkModules(self, importPackages=False):
        """
        Similar to L{iterModules}, this yields self, and then every module in my
        package or entry, and every submodule in each package or entry.

        In other words, this is deep, and L{iterModules} is shallow.
        """
        yield self
        for package in self.iterModules():
            for module in package.walkModules(importPackages=importPackages):
                yield module

    def _subModuleName(self, mn):
        """
        This is a hook to provide packages with the ability to specify their names
        as a prefix to submodules here.
        """
        return mn

    def _packagePaths(self):
        """
        Implement in subclasses to specify where to look for modules.

        @return: iterable of FilePath-like objects.
        """
        raise NotImplementedError()

    def _getEntry(self):
        """
        Implement in subclasses to specify what path entry submodules will come
        from.

        @return: a PathEntry instance.
        """
        raise NotImplementedError()

    def __getitem__(self, modname):
        """
        Retrieve a module from below this path or package.

        @param modname: a str naming a module to be loaded.  For entries, this
        is a top-level, undotted package name, and for packages it is the name
        of the module without the package prefix.  For example, if you have a
        PythonModule representing the 'twisted' package, you could use::

            twistedPackageObj['python']['modules']

        to retrieve the Twisted-supplied version of this module.

        @raise: KeyError if the module is not found.

        @return: a PythonModule.
        """
        for module in self.iterModules():
            if module.name == self._subModuleName(modname):
                return module
        raise KeyError(modname)

    def __iter__(self):
        """
        Implemented to raise NotImplementedError for clarity, so that attempting to
        loop over this object won't call __getitem__.

        Note: in the future there might be some sensible default for iteration,
        like 'walkEverything', so this is deliberately untested and undefined
        behavior.
        """
        raise NotImplementedError()

if ast is not None:
    _iefBase = ast.NodeVisitor
else:
    _iefBase = object

class _ImportExportFinder(_iefBase):
    """
    Find names of imports and exports (via __all__).

    @ivar imports: A set of (source, name) pairs describing an
                   imported name. if the source is None, the name
                   is an import from the top level.

    @ivar exports: A list of names defined in __all__ in this
                   module, or None if the module has no __all__
                   attribute.

    @ivar definedNames: A set of names created by assignment,
                        class definitions, or function definitions
                        at the top level of this module.
    """

    def __init__(self):
        self.imports = set()
        self.exports = None
        self.definedNames = set()

    def visit_Import(self, node):
        """
        Collect names for all import statements.
        """
        for alias in node.names:
            self.imports.add((None, alias.name))

    def visit_ImportFrom(self, node):
        """
        Collect names and source modules from "import x from y" statements.
        """
        if node.names[0].name == "*":
            raise SyntaxError("Code containing 'import *' cannot be statically analyzed.")
        for name in node.names:
            self.imports.add((node.module, name.name))

    def visit_Module(self, node):
        """
        Look for top-level name bindings and __all__ in a module.
        """
        def collectNames(target, value):
            if isinstance(target, ast.Name):
                collectSingleName(value, target.id)
            if isinstance(target, (ast.List, ast.Tuple)):
                if not (isinstance(value, (ast.List, ast.Tuple))
                        and len(value.elts) == len(target.elts)):
                    value = None
                nameNodes = target.elts
                for (i, n) in enumerate(nameNodes):
                    if value is not None:
                        v = value.elts[i]
                    else:
                        v = None
                    collectNames(n, v)

        def collectSingleName(value, name):
            if name == '__all__':
                checkAll(value)
            else:
                self.definedNames.add(name)

        def checkAll(allval):
            if self.exports is not None:
                    raise SyntaxError("__all__ can only be defined once")
            try:
                self.exports = set(ast.literal_eval(allval))
            except ValueError:
                raise SyntaxError("__all__ must only contain literal Python identifier strings")
            for exp in self.exports:
                if not _isPythonIdentifier(exp):
                    raise SyntaxError("__all__ must only contain literal Python identifier strings")
        for stmt in node.body:
            self.visit(stmt)
            if isinstance(stmt, ast.Assign):
                collectNames(stmt.targets[0], stmt.value)
            elif isinstance(stmt, (ast.FunctionDef, ast.ClassDef)):
                self.definedNames.add(stmt.name)

class PythonAttribute:
    """
    I represent a function, class, or other object that is present.

    @ivar name: the fully-qualified python name of this attribute.

    @ivar onObject: a reference to a PythonModule or other PythonAttribute that
    is this attribute's logical parent.

    @ivar name: the fully qualified python name of the attribute represented by
    this class.
    """
    def __init__(self, name, onObject, loaded, pythonValue):
        """
        Create a PythonAttribute.  This is a private constructor.  Do not construct
        me directly, use PythonModule.iterAttributes.

        @param name: the FQPN
        @param onObject: see ivar
        @param loaded: always True, for now
        @param pythonValue: the value of the attribute we're pointing to.
        """
        self.name = name
        self.onObject = onObject
        self._loaded = loaded
        self.pythonValue = pythonValue

    def __repr__(self):
        return 'PythonAttribute<%r>'%(self.name,)

    def isLoaded(self):
        """
        Return a boolean describing whether the attribute this describes has
        actually been loaded into memory by importing its module.
        """
        return self._loaded

    def load(self, default=_nothing):
        """
        Load the value associated with this attribute.

        @return: an arbitrary Python object, or 'default' if there is an error
        loading it.
        """
        if not self.isLoaded():
            mod = self.onObject.load()
            self.pythonValue = getattr(mod, self.name.split('.')[-1], default)
            self._loaded = True
        return self.pythonValue

    def iterAttributes(self):
        """
        Iterate over the attributes of the value named by this
        object. Only works when the module is loaded.

        @raise NotImplementedError: when the module is not loaded.
        """
        if not self.isLoaded():
            raise NotImplementedError("Static inspection of attributes doesn't"
                                      " go beyond the top level of the module.")
        for name, val in inspect.getmembers(self.load()):
            yield PythonAttribute(self.name + '.' + name, self, True, val)

class PythonModule(_ModuleIteratorHelper):
    """
    Representation of a module which could be imported from sys.path.

    @ivar name: the fully qualified python name of this module.

    @ivar filePath: a FilePath-like object which points to the location of this
    module.

    @ivar pathEntry: a L{PathEntry} instance which this module was located
    from.

    @ivar _finder: an L{_ImportExportFinder}, or None. Used to
    discover names used and defined in a module by inspecting its AST.
    """

    def __init__(self, name, filePath, pathEntry):
        """
        Create a PythonModule.  Do not construct this directly, instead inspect a
        PythonPath or other PythonModule instances.

        @param name: see ivar
        @param filePath: see ivar
        @param pathEntry: see ivar
        """
        assert not name.endswith(".__init__")
        self.name = name
        self.filePath = filePath
        self.parentPath = filePath.parent()
        self.pathEntry = pathEntry

        self._finder = None

    def _getEntry(self):
        return self.pathEntry

    def __repr__(self):
        """
        Return a string representation including the module name.
        """
        return 'PythonModule<%r>' % (self.name,)

    def isLoaded(self):
        """
        Determine if the module is loaded into sys.modules.

        @return: a boolean: true if loaded, false if not.
        """
        return self.pathEntry.pythonPath.moduleDict.get(self.name) is not None

    def _maybeLoadFinder(self):
        """
        Scan a module for imports, exports, and attributes.
        """
        if self._finder is None:
            try:
                tree = ast.parse(self.filePath.getContent())
            except TypeError:
                raise ValueError("Static analysis of module attributes can only be done on Python source.")
            self._finder = _ImportExportFinder()
            self._finder.visit(tree)

    def iterAttributes(self):
        """
        List all the attributes defined in this module.

        On Python 2.6 and later this method can list attributes on a
        module without loading it, via AST inspection. On earlier
        Python versions, they must be loaded. This method will use
        inspect.getmembers on all Python versions if the module is loaded.

        @raise NotImplementedError: if this module is not loaded and
        AST inspection is not possible.

        @return: a generator yielding PythonAttribute instances describing the
        attributes of this module.
        """
        if not self.isLoaded():
            if ast is None:
                raise NotImplementedError("Static analysis of module attributes"
                                          " requires the 'ast' module,"
                                          " found in Python 2.6 or later.")
            self._maybeLoadFinder()
            if self._finder.exports:
                attrs = (set([x[1] for x in self._finder.imports]) | self._finder.definedNames) & self._finder.exports
            else:
                attrs = self._finder.definedNames
            for name in attrs:
                yield PythonAttribute(self.name + '.' + name, self, False, _nothing)
        else:
            for name, val in inspect.getmembers(self.load()):
                yield PythonAttribute(self.name + '.' + name, self, True, val)

    def iterImportNames(self):
        """
        List all the fully-qualified names imported in this module.

        @raise NotImplementedError: if this module is not loaded and
        AST inspection is not possible.

        @return: a generator yielding fully qualified name strings for
                 each name imported into this module.

        @since: 10.2
        """
        if ast is None:
            raise NotImplementedError("Static analysis of module attributes"
                                      " requires the 'ast' module, found in"
                                      " Python 2.6 or later.")

        self._maybeLoadFinder()
        for (origin, name) in self._finder.imports:
            if origin is not None:
                yield origin+ '.' + name
            else:
                yield name

    def iterExportNames(self):
        """
        List all the names exported by this module. If the module
        defines __all__ as a list of literal strings, those names will
        be treated as the module's exports. Otherwise, all names
        defined at the top level of the module will be regarded as
        exports.

        @raise NotImplementedError: if this module is not loaded and
        AST inspection is not possible.

        @return: an iterable of names of attributes of this module.

        @since: 10.2
        """
        if ast is None:
            raise NotImplementedError("Static analysis of module attributes"
                                      " requires the 'ast' module, found in"
                                      " Python 2.6 or later.")
        self._maybeLoadFinder()
        return self._finder.exports or self._finder.definedNames

    def isPackage(self):
        """
        Returns true if this module is also a package, and might yield something
        from iterModules.
        """
        return _isPackagePath(self.filePath)

    def load(self, default=_nothing):
        """
        Load this module.

        @param default: if specified, the value to return in case of an error.

        @return: a genuine python module.

        @raise: any type of exception.  Importing modules is a risky business;
        the erorrs of any code run at module scope may be raised from here, as
        well as ImportError if something bizarre happened to the system path
        between the discovery of this PythonModule object and the attempt to
        import it.  If you specify a default, the error will be swallowed
        entirely, and not logged.

        @rtype: types.ModuleType.
        """
        try:
            return self.pathEntry.pythonPath.moduleLoader(self.name)
        except:                 # this needs more thought...
            if default is not _nothing:
                return default
            raise

    def __eq__(self, other):
        """
        PythonModules with the same name are equal.
        """
        if not isinstance(other, PythonModule):
            return False
        return other.name == self.name

    def __ne__(self, other):
        """
        PythonModules with different names are not equal.
        """
        if not isinstance(other, PythonModule):
            return True
        return other.name != self.name

    def walkModules(self, importPackages=False):
        if importPackages and self.isPackage():
            self.load()
        return super(PythonModule, self).walkModules(importPackages=importPackages)

    def _subModuleName(self, mn):
        """
        submodules of this module are prefixed with our name.
        """
        return self.name + '.' + mn

    def _packagePaths(self):
        """
        Yield a sequence of FilePath-like objects which represent path segments.
        """
        if not self.isPackage():
            return
        if self.isLoaded():
            load = self.load()
            if hasattr(load, '__path__'):
                for fn in load.__path__:
                    if fn == self.parentPath.path:
                        # this should _really_ exist.
                        assert self.parentPath.exists()
                        yield self.parentPath
                    else:
                        smp = self.pathEntry.pythonPath._smartPath(fn)
                        if smp.exists():
                            yield smp
        else:
            yield self.parentPath

class PathEntry(_ModuleIteratorHelper):
    """
    I am a proxy for a single entry on sys.path.

    @ivar filePath: a FilePath-like object pointing at the filesystem location
    or archive file where this path entry is stored.

    @ivar pythonPath: a PythonPath instance.
    """
    def __init__(self, filePath, pythonPath):
        """
        Create a PathEntry.  This is a private constructor.
        """
        self.filePath = filePath
        self.pythonPath = pythonPath

    def _getEntry(self):
        return self

    def __repr__(self):
        return 'PathEntry<%r>' % (self.filePath,)

    def _packagePaths(self):
        yield self.filePath

class IPathImportMapper(Interface):
    """
    This is an internal interface, used to map importers to factories for
    FilePath-like objects.
    """
    def mapPath(self, pathLikeString):
        """
        Return a FilePath-like object.

        @param pathLikeString: a path-like string, like one that might be
        passed to an import hook.

        @return: a L{FilePath}, or something like it (currently only a
        L{ZipPath}, but more might be added later).
        """

class _DefaultMapImpl:
    """ Wrapper for the default importer, i.e. None.  """
    implements(IPathImportMapper)
    def mapPath(self, fsPathString):
        return FilePath(fsPathString)
_theDefaultMapper = _DefaultMapImpl()

class _ZipMapImpl:
    """ IPathImportMapper implementation for zipimport.ZipImporter.  """
    implements(IPathImportMapper)
    def __init__(self, importer):
        self.importer = importer

    def mapPath(self, fsPathString):
        """
        Map the given FS path to a ZipPath, by looking at the ZipImporter's
        "archive" attribute and using it as our ZipArchive root, then walking
        down into the archive from there.

        @return: a L{zippath.ZipPath} or L{zippath.ZipArchive} instance.
        """
        za = ZipArchive(self.importer.archive)
        myPath = FilePath(self.importer.archive)
        itsPath = FilePath(fsPathString)
        if myPath == itsPath:
            return za
        # This is NOT a general-purpose rule for sys.path or __file__:
        # zipimport specifically uses regular OS path syntax in its pathnames,
        # even though zip files specify that slashes are always the separator,
        # regardless of platform.
        segs = itsPath.segmentsFrom(myPath)
        zp = za
        for seg in segs:
            zp = zp.child(seg)
        return zp

registerAdapter(_ZipMapImpl, zipimport.zipimporter, IPathImportMapper)

def _defaultSysPathFactory():
    """
    Provide the default behavior of PythonPath's sys.path factory, which is to
    return the current value of sys.path.

    @return: L{sys.path}
    """
    return sys.path

class PythonPath:
    """
    I represent the very top of the Python object-space, the module list in
    sys.path and the modules list in sys.modules.

    @ivar _sysPath: a sequence of strings like sys.path.  This attribute is
    read-only.

    @ivar moduleDict: a dictionary mapping string module names to module
    objects, like sys.modules.

    @ivar sysPathHooks: a list of PEP-302 path hooks, like sys.path_hooks.

    @ivar moduleLoader: a function that takes a fully-qualified python name and
    returns a module, like twisted.python.reflect.namedAny.
    """

    def __init__(self,
                 sysPath=None,
                 moduleDict=sys.modules,
                 sysPathHooks=sys.path_hooks,
                 importerCache=sys.path_importer_cache,
                 moduleLoader=namedAny,
                 sysPathFactory=None):
        """
        Create a PythonPath.  You almost certainly want to use
        modules.theSystemPath, or its aliased methods, rather than creating a
        new instance yourself, though.

        All parameters are optional, and if unspecified, will use 'system'
        equivalents that makes this PythonPath like the global L{theSystemPath}
        instance.

        @param sysPath: a sys.path-like list to use for this PythonPath, to
        specify where to load modules from.

        @param moduleDict: a sys.modules-like dictionary to use for keeping
        track of what modules this PythonPath has loaded.

        @param sysPathHooks: sys.path_hooks-like list of PEP-302 path hooks to
        be used for this PythonPath, to determie which importers should be
        used.

        @param importerCache: a sys.path_importer_cache-like list of PEP-302
        importers.  This will be used in conjunction with the given
        sysPathHooks.

        @param moduleLoader: a module loader function which takes a string and
        returns a module.  That is to say, it is like L{namedAny} - *not* like
        L{__import__}.

        @param sysPathFactory: a 0-argument callable which returns the current
        value of a sys.path-like list of strings.  Specify either this, or
        sysPath, not both.  This alternative interface is provided because the
        way the Python import mechanism works, you can re-bind the 'sys.path'
        name and that is what is used for current imports, so it must be a
        factory rather than a value to deal with modification by rebinding
        rather than modification by mutation.  Note: it is not recommended to
        rebind sys.path.  Although this mechanism can deal with that, it is a
        subtle point which some tools that it is easy for tools which interact
        with sys.path to miss.
        """
        if sysPath is not None:
            sysPathFactory = lambda : sysPath
        elif sysPathFactory is None:
            sysPathFactory = _defaultSysPathFactory
        self._sysPathFactory = sysPathFactory
        self._sysPath = sysPath
        self.moduleDict = moduleDict
        self.sysPathHooks = sysPathHooks
        self.importerCache = importerCache
        self.moduleLoader = moduleLoader

    def _getSysPath(self):
        """
        Retrieve the current value of the module search path list.
        """
        return self._sysPathFactory()

    sysPath = property(_getSysPath)

    def _findEntryPathString(self, modobj):
        """
        Determine where a given Python module object came from by looking at path
        entries.
        """
        topPackageObj = modobj
        while '.' in topPackageObj.__name__:
            topPackageObj = self.moduleDict['.'.join(
                    topPackageObj.__name__.split('.')[:-1])]
        if _isPackagePath(FilePath(topPackageObj.__file__)):
            # if package 'foo' is on sys.path at /a/b/foo, package 'foo's
            # __file__ will be /a/b/foo/__init__.py, and we are looking for
            # /a/b here, the path-entry; so go up two steps.
            rval = dirname(dirname(topPackageObj.__file__))
        else:
            # the module is completely top-level, not within any packages.  The
            # path entry it's on is just its dirname.
            rval = dirname(topPackageObj.__file__)

        # There are probably some awful tricks that an importer could pull
        # which would break this, so let's just make sure... it's a loaded
        # module after all, which means that its path MUST be in
        # path_importer_cache according to PEP 302 -glyph
        if rval not in self.importerCache:
            warnings.warn(
                "%s (for module %s) not in path importer cache "
                "(PEP 302 violation - check your local configuration)." % (
                    rval, modobj.__name__),
                stacklevel=3)

        return rval

    def _smartPath(self, pathName):
        """
        Given a path entry from sys.path which may refer to an importer,
        return the appropriate FilePath-like instance.

        @param pathName: a str describing the path.

        @return: a FilePath-like object.
        """
        importr = self.importerCache.get(pathName, _nothing)
        if importr is _nothing:
            for hook in self.sysPathHooks:
                try:
                    importr = hook(pathName)
                except ImportError:
                    pass
            if importr is _nothing: # still
                importr = None
        return IPathImportMapper(importr, _theDefaultMapper).mapPath(pathName)

    def iterEntries(self):
        """
        Iterate the entries on my sysPath.

        @return: a generator yielding PathEntry objects
        """
        for pathName in self.sysPath:
            fp = self._smartPath(pathName)
            yield PathEntry(fp, self)

    def __getitem__(self, modname):
        """
        Get a python module by its given fully-qualified name.

        @param modname: The fully-qualified Python module name to load.

        @type modname: C{str}

        @return: an object representing the module identified by C{modname}

        @rtype: L{PythonModule}

        @raise KeyError: if the module name is not a valid module name, or no
            such module can be identified as loadable.
        """
        # See if the module is already somewhere in Python-land.
        moduleObject = self.moduleDict.get(modname)
        if moduleObject is not None:
            # we need 2 paths; one of the path entry and one for the module.
            pe = PathEntry(
                self._smartPath(
                    self._findEntryPathString(moduleObject)),
                self)
            path = inspect.getsourcefile(moduleObject)
            if path is None:
                path = moduleObject.__file__
            mp = self._smartPath(path)
            return PythonModule(modname, mp, pe)

        # Recurse if we're trying to get a submodule.
        if '.' in modname:
            pkg = self
            for name in modname.split('.'):
                pkg = pkg[name]
            return pkg

        # Finally do the slowest possible thing and iterate
        for module in self.iterModules():
            if module.name == modname:
                return module
        raise KeyError(modname)

    def __repr__(self):
        """
        Display my sysPath and moduleDict in a string representation.
        """
        return "PythonPath(%r,%r)" % (self.sysPath, self.moduleDict)

    def iterModules(self):
        """
        Yield all top-level modules on my sysPath.
        """
        for entry in self.iterEntries():
            for module in entry.iterModules():
                yield module

    def walkModules(self, importPackages=False):
        """
        Similar to L{iterModules}, this yields every module on the path, then every
        submodule in each package or entry.
        """
        for package in self.iterModules():
            for module in package.walkModules(importPackages=False):
                yield module

theSystemPath = PythonPath()

def walkModules(importPackages=False):
    """
    Deeply iterate all modules on the global python path.

    @param importPackages: Import packages as they are seen.
    """
    return theSystemPath.walkModules(importPackages=importPackages)

def iterModules():
    """
    Iterate all modules and top-level packages on the global Python path, but
    do not descend into packages.

    @param importPackages: Import packages as they are seen.
    """
    return theSystemPath.iterModules()

def getModule(moduleName):
    """
    Retrieve a module from the system path.
    """
    return theSystemPath[moduleName]


## All pairs shortest path problem
## uses dp
## Key idea is for 0-k, at each step,
## update min distance by chekcing distance
## without including vertex "k" and
## with including it

def floyd_warshall(A,n):
    '''
    :param A: Adjacency matrix
    :param n: no of nodes
    :return: dp table with shortest paths from i-j
    '''

    dp = [[None]*n for _ in range(n)]
    next = [[None] * n for _ in range(n)]
    for i in range(n):
        for j in range(n):
            dp[i][j] = A[i][j]
            if A[i][j]!=float('inf'):
                next[i][j] = j

    for k in range(n):
        for i in range(n):
            for j in range(n):
                if dp[i][k]+ dp[k][j] < dp[i][j]:
                    dp[i][j] = dp[i][k]+ dp[k][j]
                    next[i][j] = next[i][k]

    ## update negative cycles (similar step as BF, repeat FW)
    for k in range(n):
        for i in range(n):
            for j in range(n):
                if dp[i][k]+ dp[k][j] < dp[i][j]:
                    dp[i][j] = float('-inf')
                    next[i][j] = -1

    return dp

## Testing .. avoiding for time constraints

## Time complexity O(V^3) when adjacency matrix is used.


from rest_framework.fields import CharField
from rest_framework.relations import HyperlinkedRelatedField, HyperlinkedIdentityField
from rest_framework.serializers import HyperlinkedModelSerializer
from models import Album, AlbumReview

class AlbumSerializer(HyperlinkedModelSerializer):
    uri = HyperlinkedIdentityField(view_name='waifufmapp:album-detail')
    albumreview_set = HyperlinkedRelatedField(many=True, read_only=True,
                                                   view_name='waifufmapp:albumreview-detail')

    class Meta:
        model = Album
        fields = ('uri', 'name', 'year', 'albumreview_set')

class AlbumReviewSerializer(HyperlinkedModelSerializer):
    uri = HyperlinkedIdentityField(view_name='waifufmapp:albumreview-detail')
    album = HyperlinkedRelatedField(view_name='waifufmapp:album-detail', read_only=True)
    user = CharField(read_only=True)

    class Meta:
        model = AlbumReview
        fields = ('uri', 'rating', 'comment', 'user', 'date', 'userlocation', 'album')


#! /usr/bin/env python3
"""
Problem 23 - Project Euler
http://projecteuler.net/index.php?section=problems&id=023
"""

def is_abundant(x: int) -> bool:
    sum_div = 0
    i = 1
    while i * i <= x:
        if x % i == 0:
            sum_div += i
            m = x // i
            if m != i and x != m:
                sum_div += x // i
        i += 1

    return x < sum_div

if __name__ == "__main__":
    limit = 28123
    abundant_nums = list(filter(is_abundant, range(12, limit + 1)))
    sum_of_two_ab = set(
        x + y
        for i, x in enumerate(abundant_nums)
        for y in abundant_nums[i:]
        if x + y < limit
    )
    print(sum(set(range(1, limit)) - sum_of_two_ab))


import logging
from typing import List, Optional, Tuple
import torch
from fvcore.nn import sigmoid_focal_loss_jit
from torch import nn
from torch.nn import functional as F

from detectron2.layers import ShapeSpec, batched_nms
from detectron2.structures import Boxes, ImageList, Instances, pairwise_point_box_distance
from detectron2.utils.events import get_event_storage

from ..anchor_generator import DefaultAnchorGenerator
from ..backbone import Backbone
from ..box_regression import Box2BoxTransformLinear, _dense_box_regression_loss
from .dense_detector import DenseDetector
from .retinanet import RetinaNetHead

__all__ = ["FCOS"]

logger = logging.getLogger(__name__)

class FCOS(DenseDetector):
    """
    Implement FCOS in :paper:`fcos`.
    """

    def __init__(
        self,
        *,
        backbone: Backbone,
        head: nn.Module,
        head_in_features: Optional[List[str]] = None,
        box2box_transform=None,
        num_classes,
        center_sampling_radius: float = 1.5,
        focal_loss_alpha=0.25,
        focal_loss_gamma=2.0,
        test_score_thresh=0.2,
        test_topk_candidates=1000,
        test_nms_thresh=0.6,
        max_detections_per_image=100,
        pixel_mean,
        pixel_std,
    ):
        """
        Args:
            center_sampling_radius: radius of the "center" of a groundtruth box,
                within which all anchor points are labeled positive.
            Other arguments mean the same as in :class:`RetinaNet`.
        """
        super().__init__(
            backbone, head, head_in_features, pixel_mean=pixel_mean, pixel_std=pixel_std
        )

        self.num_classes = num_classes

        # FCOS uses one anchor point per location.
        # We represent the anchor point by a box whose size equals the anchor stride.
        feature_shapes = backbone.output_shape()
        fpn_strides = [feature_shapes[k].stride for k in self.head_in_features]
        self.anchor_generator = DefaultAnchorGenerator(
            sizes=[[k] for k in fpn_strides], aspect_ratios=[1.0], strides=fpn_strides
        )

        # FCOS parameterizes box regression by a linear transform,
        # where predictions are normalized by anchor stride (equal to anchor size).
        if box2box_transform is None:
            box2box_transform = Box2BoxTransformLinear(normalize_by_size=True)
        self.box2box_transform = box2box_transform

        self.center_sampling_radius = float(center_sampling_radius)

        # Loss parameters:
        self.focal_loss_alpha = focal_loss_alpha
        self.focal_loss_gamma = focal_loss_gamma

        # Inference parameters:
        self.test_score_thresh = test_score_thresh
        self.test_topk_candidates = test_topk_candidates
        self.test_nms_thresh = test_nms_thresh
        self.max_detections_per_image = max_detections_per_image

    def forward_training(self, images, features, predictions, gt_instances):
        # Transpose the Hi*Wi*A dimension to the middle:
        pred_logits, pred_anchor_deltas, pred_centerness = self._transpose_dense_predictions(
            predictions, [self.num_classes, 4, 1]
        )
        anchors = self.anchor_generator(features)
        gt_labels, gt_boxes = self.label_anchors(anchors, gt_instances)
        return self.losses(
            anchors, pred_logits, gt_labels, pred_anchor_deltas, gt_boxes, pred_centerness
        )

    @torch.no_grad()
    def _match_anchors(self, gt_boxes: Boxes, anchors: List[Boxes]):
        """
        Match ground-truth boxes to a set of multi-level anchors.

        Args:
            gt_boxes: Ground-truth boxes from instances of an image.
            anchors: List of anchors for each feature map (of different scales).

        Returns:
            torch.Tensor
                A tensor of shape `(M, R)`, given `M` ground-truth boxes and total
                `R` anchor points from all feature levels, indicating the quality
                of match between m-th box and r-th anchor. Higher value indicates
                better match.
        """
        # Naming convention: (M = ground-truth boxes, R = anchor points)
        # Anchor points are represented as square boxes of size = stride.
        num_anchors_per_level = [len(x) for x in anchors]
        anchors = Boxes.cat(anchors)  # (R, 4)
        anchor_centers = anchors.get_centers()  # (R, 2)
        anchor_sizes = anchors.tensor[:, 2] - anchors.tensor[:, 0]  # (R, )

        lower_bound = anchor_sizes * 4
        lower_bound[: num_anchors_per_level[0]] = 0
        upper_bound = anchor_sizes * 8
        upper_bound[-num_anchors_per_level[-1] :] = float("inf")

        gt_centers = gt_boxes.get_centers()

        # FCOS with center sampling: anchor point must be close enough to
        # ground-truth box center.
        center_dists = (anchor_centers[None, :, :] - gt_centers[:, None, :]).abs_()
        sampling_regions = self.center_sampling_radius * anchor_sizes[None, :]

        match_quality_matrix = center_dists.max(dim=2).values < sampling_regions

        pairwise_dist = pairwise_point_box_distance(anchor_centers, gt_boxes)
        pairwise_dist = pairwise_dist.permute(1, 0, 2)  # (M, R, 4)

        # The original FCOS anchor matching rule: anchor point must be inside GT.
        match_quality_matrix &= pairwise_dist.min(dim=2).values > 0

        # Multilevel anchor matching in FCOS: each anchor is only responsible
        # for certain scale range.
        pairwise_dist = pairwise_dist.max(dim=2).values
        match_quality_matrix &= (pairwise_dist > lower_bound[None, :]) & (
            pairwise_dist < upper_bound[None, :]
        )
        # Match the GT box with minimum area, if there are multiple GT matches.
        gt_areas = gt_boxes.area()  # (M, )

        match_quality_matrix = match_quality_matrix.to(torch.float32)
        match_quality_matrix *= 1e8 - gt_areas[:, None]
        return match_quality_matrix  # (M, R)

    @torch.no_grad()
    def label_anchors(self, anchors: List[Boxes], gt_instances: List[Instances]):
        """
        Same interface as :meth:`RetinaNet.label_anchors`, but implemented with FCOS
        anchor matching rule.

        Unlike RetinaNet, there are no ignored anchors.
        """

        gt_labels, matched_gt_boxes = [], []

        for inst in gt_instances:
            if len(inst) > 0:
                match_quality_matrix = self._match_anchors(inst.gt_boxes, anchors)

                # Find matched ground-truth box per anchor. Un-matched anchors are
                # assigned -1. This is equivalent to using an anchor matcher as used
                # in R-CNN/RetinaNet: `Matcher(thresholds=[1e-5], labels=[0, 1])`
                match_quality, matched_idxs = match_quality_matrix.max(dim=0)
                matched_idxs[match_quality < 1e-5] = -1

                matched_gt_boxes_i = inst.gt_boxes.tensor[matched_idxs.clip(min=0)]
                gt_labels_i = inst.gt_classes[matched_idxs.clip(min=0)]

                # Anchors with matched_idxs = -1 are labeled background.
                gt_labels_i[matched_idxs < 0] = self.num_classes
            else:
                matched_gt_boxes_i = torch.zeros_like(Boxes.cat(anchors).tensor)
                gt_labels_i = torch.full(
                    (len(matched_gt_boxes_i),),
                    fill_value=self.num_classes,
                    dtype=torch.long,
                    device=matched_gt_boxes_i.device,
                )

            gt_labels.append(gt_labels_i)
            matched_gt_boxes.append(matched_gt_boxes_i)

        return gt_labels, matched_gt_boxes

    def losses(
        self, anchors, pred_logits, gt_labels, pred_anchor_deltas, gt_boxes, pred_centerness
    ):
        """
        This method is almost identical to :meth:`RetinaNet.losses`, with an extra
        "loss_centerness" in the returned dict.
        """
        num_images = len(gt_labels)
        gt_labels = torch.stack(gt_labels)  # (M, R)

        pos_mask = (gt_labels >= 0) & (gt_labels != self.num_classes)
        num_pos_anchors = pos_mask.sum().item()
        get_event_storage().put_scalar("num_pos_anchors", num_pos_anchors / num_images)
        normalizer = self._ema_update("loss_normalizer", max(num_pos_anchors, 1), 300)

        # classification and regression loss
        gt_labels_target = F.one_hot(gt_labels, num_classes=self.num_classes + 1)[
            :, :, :-1
        ]  # no loss for the last (background) class
        loss_cls = sigmoid_focal_loss_jit(
            torch.cat(pred_logits, dim=1),
            gt_labels_target.to(pred_logits[0].dtype),
            alpha=self.focal_loss_alpha,
            gamma=self.focal_loss_gamma,
            reduction="sum",
        )

        loss_box_reg = _dense_box_regression_loss(
            anchors,
            self.box2box_transform,
            pred_anchor_deltas,
            gt_boxes,
            pos_mask,
            box_reg_loss_type="giou",
        )

        ctrness_targets = self.compute_ctrness_targets(anchors, gt_boxes)  # (M, R)
        pred_centerness = torch.cat(pred_centerness, dim=1).squeeze(dim=2)  # (M, R)
        ctrness_loss = F.binary_cross_entropy_with_logits(
            pred_centerness[pos_mask], ctrness_targets[pos_mask], reduction="sum"
        )
        return {
            "loss_fcos_cls": loss_cls / normalizer,
            "loss_fcos_loc": loss_box_reg / normalizer,
            "loss_fcos_ctr": ctrness_loss / normalizer,
        }

    def compute_ctrness_targets(self, anchors: List[Boxes], gt_boxes: List[torch.Tensor]):
        anchors = Boxes.cat(anchors).tensor  # Rx4
        reg_targets = [self.box2box_transform.get_deltas(anchors, m) for m in gt_boxes]
        reg_targets = torch.stack(reg_targets, dim=0)  # NxRx4
        if len(reg_targets) == 0:
            return reg_targets.new_zeros(len(reg_targets))
        left_right = reg_targets[:, :, [0, 2]]
        top_bottom = reg_targets[:, :, [1, 3]]
        ctrness = (left_right.min(dim=-1)[0] / left_right.max(dim=-1)[0]) * (
            top_bottom.min(dim=-1)[0] / top_bottom.max(dim=-1)[0]
        )
        return torch.sqrt(ctrness)

    def forward_inference(
        self,
        images: ImageList,
        features: List[torch.Tensor],
        predictions: List[List[torch.Tensor]],
    ):
        pred_logits, pred_anchor_deltas, pred_centerness = self._transpose_dense_predictions(
            predictions, [self.num_classes, 4, 1]
        )
        anchors = self.anchor_generator(features)

        results: List[Instances] = []
        for img_idx, image_size in enumerate(images.image_sizes):
            scores_per_image = [
                # Multiply and sqrt centerness & classification scores
                # (See eqn. 4 in https://arxiv.org/abs/2006.09214)
                torch.sqrt(x[img_idx].sigmoid_() * y[img_idx].sigmoid_())
                for x, y in zip(pred_logits, pred_centerness)
            ]
            deltas_per_image = [x[img_idx] for x in pred_anchor_deltas]
            results_per_image = self.inference_single_image(
                anchors, scores_per_image, deltas_per_image, image_size
            )
            results.append(results_per_image)
        return results

    def inference_single_image(
        self,
        anchors: List[Boxes],
        box_cls: List[torch.Tensor],
        box_delta: List[torch.Tensor],
        image_size: Tuple[int, int],
    ):
        """
        Identical to :meth:`RetinaNet.inference_single_image.
        """
        pred = self._decode_multi_level_predictions(
            anchors,
            box_cls,
            box_delta,
            self.test_score_thresh,
            self.test_topk_candidates,
            image_size,
        )
        keep = batched_nms(
            pred.pred_boxes.tensor, pred.scores, pred.pred_classes, self.test_nms_thresh
        )
        return pred[keep[: self.max_detections_per_image]]

class FCOSHead(RetinaNetHead):
    """
    The head used in :paper:`fcos`. It adds an additional centerness
    prediction branch on top of :class:`RetinaNetHead`.
    """

    def __init__(self, *, input_shape: List[ShapeSpec], conv_dims: List[int], **kwargs):
        super().__init__(input_shape=input_shape, conv_dims=conv_dims, num_anchors=1, **kwargs)
        # Unlike original FCOS, we do not add an additional learnable scale layer
        # because it's found to have no benefits after normalizing regression targets by stride.
        self._num_features = len(input_shape)
        self.ctrness = nn.Conv2d(conv_dims[-1], 1, kernel_size=3, stride=1, padding=1)
        torch.nn.init.normal_(self.ctrness.weight, std=0.01)
        torch.nn.init.constant_(self.ctrness.bias, 0)

    def forward(self, features):
        assert len(features) == self._num_features
        logits = []
        bbox_reg = []
        ctrness = []
        for feature in features:
            logits.append(self.cls_score(self.cls_subnet(feature)))
            bbox_feature = self.bbox_subnet(feature)
            bbox_reg.append(self.bbox_pred(bbox_feature))
            ctrness.append(self.ctrness(bbox_feature))
        return logits, bbox_reg, ctrness


import sqlite3
import hashlib
import random
import datetime
import json
import os

DATABASE_NAME= "game.db"

# DATABASE_NAME= os.path.abspath("Tombola_Bingo/game.db")

# Connects to a database and creates a cursor object

def connect_Sqlite():
    global conn,c
    conn = sqlite3.connect(DATABASE_NAME)
    c = conn.cursor()

### RETURNS SHA1 hash of the string ###

def get_sha1(input_string):
    sha1 = hashlib.sha1()
    sha1.update(input_string.encode('utf-8'))
    return sha1.hexdigest()

class Game():

    ## Method for inserting a new game object into the database

    def insert_row(self):
        SQL_INSERT_QUERY = "INSERT INTO numbers_played (serial, numbers, date, stars) VALUES (?, ?, ?, ?)"
        connect_Sqlite()

    # Convert the dictionary to a JSON string for database compatibility

        dict_As_Json = json.dumps(self.numbers)
        self.date= json.dumps(datetime.datetime.now().timestamp())
        c.execute(SQL_INSERT_QUERY, (self.Serial, dict_As_Json, self.date, self.starsArray))

        conn.commit()
        conn.close()

    ## Reads the database to see the last number and encrypts the input data

    def add_id(self):
        GET_ID_QUERY = "SELECT id FROM numbers_played ORDER BY id DESC LIMIT 1"
        connect_Sqlite()
        c.execute(GET_ID_QUERY)
        try: max_Id = c.fetchone()[0]
        except TypeError: max_Id= 0 #Because we need this for the first time initialization

        if max_Id:
            self.id = max_Id + 1
            new_Id = max_Id + 1
            new_Id = get_sha1(str(new_Id)+get_sha1("SECRET_KEY"))

        else:
            self.id = 0
            new_Id = 0
            new_Id = get_sha1(str(new_Id)+get_sha1("SECRET_KEY"))

        self.Serial = new_Id
        print(self.Serial)
        conn.close()

    ## Generates the game numbers in a dictionary with multipliers

    def generate_numbers(self):
        numbers = list(range(1, 49))
        random.shuffle(numbers)
        arrayWinnings=["First","Second","Third","Forth","Fifth",10000,7500,5000,2500,1000,500,300,200,150,100,90,80,70,60,50,40,30,25,20,15,10,9,8,7,6,5,4,3,2,1]
        numbersRandom= numbers[:35]
        dictionary = dict(zip(arrayWinnings, numbersRandom))
        self.numbers= dictionary

    ## Method for generating star multipliers

    def generate_stars(self):
        arrayMultipliers=[i for i in range(7,36)]
        starsArray=[]
        while len(starsArray) < 2:
            i= random.choice(arrayMultipliers)
            if i in starsArray: pass
            else: starsArray.append(i)
        self.starsArray= json.dumps(starsArray)

    def __init__(self):
        connect_Sqlite()
        self.generate_numbers()
        self.generate_stars()
        self.add_id()
        self.insert_row()
        #print("Success!")

    def __str__(self):
        return f"Game object with id {self.id} and numbers {self.numbers}"


from sqlalchemy.orm import Session
from datetime import datetime

from ..shared import models, schemas
from .users import download_delete_picture

def download_picture(db: Session, picture_id: int, requestor_id: int):
    """
    Create request to download picture
    :param db: database session
    :param picture_id: picture id
    :param requestor_id: requestor id
    :return: id of picture
    """
    # Verify the picture exists
    picture = db.query(models.Picture).filter(
        models.Picture.id == picture_id).first()
    if picture is None:
        return {"download": False}
    # Verify the request doesn't exist
    download = db.query(models.Download).filter(
        models.Download.requestor_id == requestor_id,
        models.Download.picture_id == picture_id,
    ).first()
    # If request exists change status to requested
    if download is not None:
        download.status = 'requested'
        download.created_at = datetime.now()
        db.commit()
        return {"pictureId": picture_id}
    # Create download request
    download = {
        "requestor_id": requestor_id,
        "owner_id": picture.album.user_id,
        "album_id": picture.album.id,
        "picture_id": picture_id,
        "created_at": datetime.now(),
        "status": "requested",
    }
    # Convert request to model
    db_download = models.Download(**download)
    db.add(db_download)
    db.commit()
    return {"pictureId": picture_id}

def get_album_pictures(db: Session, album_id: int):
    """
    Get all pictures from album
    :param db: database session
    :param album_id: id of album
    :return: pictures
    """
    return db.query(models.Picture).filter(
        models.Picture.album_id == album_id).all()

def get_picture(db: Session, picture_id: int):
    """
    Get picture by id
    :param db: database session
    :param picture_id: picture id
    :return: picture
    """
    return db.query(models.Picture).filter(
        models.Picture.id == picture_id).first()

def create_picture(db: Session, picture: schemas.PictureCreate):
    """
    Create a new picture
    :param db: database session
    :param picture: picture data
    :return: picture
    """
    # Convert picture to model
    db_picture = models.Picture(**picture.dict())
    db_picture.created_at = datetime.now()
    db.add(db_picture)
    db.commit()
    # Sync picture from database
    db.refresh(db_picture)
    return db_picture

def delete_picture(db: Session, picture_id: int):
    """
    Delete a picture
    :param db: database session
    :param picture_id: picture id
    """
    picture = db.query(models.Picture).filter(
        models.Picture.id == picture_id).first()
    if picture:
        download_delete_picture(db, picture_id=picture_id)
        db.delete(picture)
        db.commit()

def update_picture(db: Session, picture_id: int, picture: schemas.Picture):
    """
    Update picture data
    :param db: database session
    :param picture_id: picture id
    :param picture: picture data
    :return: updated picture
    """
    # Find picture
    db_picture = get_picture(db, picture_id)
    if not db_picture:
        return NameError
    # Update data
    db_picture.title = picture.title
    db_picture.description = picture.description
    db_picture.image = picture.image
    db_picture.filename = picture.filename
    db.commit()
    # Sync picture from database
    db.refresh(db_picture)
    return db_picture


"""empty message

Revision ID: 17c7b4e8abaa
Revises: 60d3a9067ff8
Create Date: 2019-03-14 16:31:20.295359

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = '17c7b4e8abaa'
down_revision = '60d3a9067ff8'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('roles',
                    sa.Column('id', mysql.INTEGER(display_width=11),
                              autoincrement=True, nullable=False),
                    sa.Column('name', mysql.VARCHAR(
                        length=100), nullable=True),
                    sa.PrimaryKeyConstraint('id'),
                    mysql_default_charset='utf8',
                    mysql_engine='InnoDB'
                    )
    op.create_table('users',
                    sa.Column('id', mysql.INTEGER(display_width=11),
                              autoincrement=True, nullable=False),
                    sa.Column('is_active', mysql.BOOLEAN(),
                              autoincrement=False, nullable=True),
                    sa.Column('email', mysql.VARCHAR(
                        length=255), nullable=True),
                    sa.Column('email_confirmed_at',
                              mysql.TIMESTAMP(), nullable=True),
                    sa.Column('username', mysql.VARCHAR(
                        length=200), nullable=True),
                    sa.Column('password', mysql.VARCHAR(
                        length=260), nullable=True),
                    sa.Column('first_name', mysql.VARCHAR(
                        length=120), nullable=True),
                    sa.Column('last_name', mysql.VARCHAR(
                        length=120), nullable=True),
                    sa.PrimaryKeyConstraint('id'),
                    mysql_default_charset='utf8',
                    mysql_engine='InnoDB'
                    )
    op.create_table('user_roles',
                    sa.Column('id', mysql.INTEGER(display_width=11),
                              autoincrement=True, nullable=False),
                    sa.Column('user_id', mysql.INTEGER(display_width=11),
                              autoincrement=False, nullable=True),
                    sa.Column('role_id', mysql.INTEGER(display_width=11),
                              autoincrement=False, nullable=True),
                    sa.PrimaryKeyConstraint('id'),
                    mysql_default_charset='utf8',
                    mysql_engine='InnoDB'
                    )
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('user_roles')
    op.drop_table('users')
    op.drop_table('roles')
    # ### end Alembic commands ###


#!/usr/bin/env python3

import logging
from . import serverconf
from . import benchmark
from dateutil.parser import parse

def get_constraint(cursor, table_name):
    if table_name is not None:
        query = "SELECT TABLE_NAME, TABLE_SCHEMA, COLUMN_NAME, " \
                "CONSTRAINT_NAME FROM " \
                "INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE"
        sql_response = execute_request(cursor, query, [])
        for i in sql_response:
            if i['CONSTRAINT_NAME'].find("PK__") != -1:
                if i['TABLE_NAME'] == table_name.replace(
                                i['TABLE_SCHEMA'] + ".", "", 1):
                    logging.debug(i['COLUMN_NAME'])
                    return i['COLUMN_NAME']
        logging.warn("Primary key not found! Table is in read only mode.")
    return ""

def is_date(string):
    try:
        a = parse(string)
        try:
            number = int(string)
            return False
        except Exception as e:
            pass
        return a
    except ValueError:
        return False

def check_type(key, params):
    typename = type(params[key]).__name__
    if params[key] == "":
        return ""
    if typename == "int":
        log.debug("YALA")
        return key + " LIKE " + str(params[key])
    elif typename == "str":
        log.debug("YOLO")
        return key + " LIKE '" + params[key] + "'"
    return False

def offset(params):
    if "limit" in params.keys():
        final = "OFFSET " + params["offset"] + " ROWS FETCH NEXT " + params[
            "limit"] + " ROWS ONLY"
    else:
        final = "OFFSET " + params["offset"] + " ROWS FETCH NEXT 20 ROWS ONLY"
    return final

def order_by(params):
    final = " ORDER BY "
    values = params["order"].split(",")
    for value in values:
        elems = value.split(".")
        for elem in elems:
            final += elem + " "
        final += ", "
    final = final[:-2]
    return final

def get_views(cursor, name, param):
    arguments = []
    query = "SELECT * FROM sys.views"
    return execute_request(cursor, query, arguments)

def get_columns(cursor, table_name, param):
    arguments = []
    query = "SELECT * FROM INFORMATION_SCHEMA.columns WHERE TABLE_NAME = ?"
    arguments.append(table_name.split('.')[1])
    return execute_request(cursor, query, arguments)

def get_tables(cursor, name, param):
    query = "select table_schema, table_name from INFORMATION_SCHEMA.TABLES " \
            "where TABLE_TYPE = 'BASE TABLE'"
    return execute_request(cursor, query, [])

def execute_request(cursor, query, args):
    query = query.replace("--", "")
    query = query.replace("#", "")
    logging.debug(query + " | {}".format(args))
    if serverconf.is_benchmark():
        benchmark.delay_start()     # Benchmarking delay
    try:
        cursor.execute(query, *args)
    except Exception as e:
        logging.error(e)
        return {'success': False}
    if serverconf.is_benchmark():
        benchmark.delay_stop()  # Benchmarking delay
    keys = []
    for elem in cursor.description:
        keys.append(elem[0])
    result = []
    for row in cursor:
        i = 0
        value = {}
        for elem in row:
            value[keys[i]] = elem
            i = i + 1
        result.append(value)
    return result

def function_call(cursor, function_name, params):
    arguments = []
    request = "SELECT * FROM " + function_name + "(" + params.get("arg") + ")"
    logging.debug(request, arguments)
    return execute_request(cursor, request, arguments)

def where(params):
    final = " WHERE "
    a = False
    special_words = ["select", "order", "group", "limit", "offset"]
    tab = {
        "eq": "LIKE", "gte": ">=", "gt": ">", "lte": "<=", "lt": "<",
        "neq": "NOT LIKE", "like": "LIKE", "is": "IS", "between": "BETWEEN"
    }
    for key in params.keys():
        if key in special_words:
            continue
        split = params[key].split(',')
        for elem in split:
            a = True
            value = elem.split('.')
            if len(value) >= 2:
                final += key + " " + tab[value[0]] + " "
                i = 1
                while i < len(value):
                    final += value[i] + " and "
                    i += 1
            else:
                value[0] = value[0].replace("'", "\\'")
                value[0] = value[0].replace('"', '\\"')
                final += key + " LIKE '" + value[0] + "' and "
    if a is True:
        final = final[:-5]
    else:
        final = final[:-6]
    return final

def separate_select_params(params):
    all_params = []
    join = False
    tmp = ""
    for c in params:
        if c == ',' and not join:
            all_params.append(tmp)
            tmp = ""
        else:
            tmp += c
        if c == '{' or c == '}':
            join = not join

    all_params.append(tmp)

    select_params = []
    join_params = {}
    for elem in all_params:
        if elem.find('{') == -1:
            select_params.append(elem)
        else:
            elem = elem.split('{')
            name = elem[0]
            value = elem[1].strip('}')
            tmp = []
            for val in value.split(','):
                tmp.append(val)
            join_params[name] = tmp

    return select_params, join_params

def inner_join(table_name, join_params):
    query = ""
    if len(join_params) == 0:
        return query
    for key, value in join_params.items():
        query += " INNER JOIN (SELECT "
        for val in value:
            query += val + ","
        if len(value) != 0:
            query = query[:-1]
        query += " FROM " + key + ") on " + table_name + ".id = " + key + \
                 ".fk_id"
    return query

def select(cursor, table_name, params):
    arguments = []
    select_query = "SELECT "
    join_params = {}
    select_params = []
    if "limit" in params.keys() and "offset" not in params.keys():
        select_query += "TOP(?)"
        arguments.append(params["limit"])
    if 'select' in params.keys():
        select_params, join_params = separate_select_params(params["select"])
    if len(select_params) == 0:
        select_query += "*,"
    row = False
    for param in select_params:
        if param == "ROW_NUMBER":
            row = True
        else:
            select_query += param + ","
    select_query = select_query[:-1]
    if row is False:
        select_query += " FROM " + table_name
    else:
        select_query += " FROM (select *, ROW_NUMBER() OVER (ORDER BY Id) " \
                        "ROW_NUMBER from " + table_name + ") AS A "
    select_query += where(params)

    if "order" in params.keys():
        select_query += order_by(params)
    elif "offset" in params.keys():
        select_query += " ORDER BY (SELECT 0) "
    if "offset" in params.keys():
        select_query += offset(params)

    select_query += inner_join(table_name, join_params)
    return execute_request(cursor, select_query, arguments)

def delete(cursor, table, params):
    query = "DELETE FROM " + table + " WHERE "
    for key, value in params.items():
        query += key + "=" + value + " and "
    if len(params) != 0:
        query = query[:-5]
    logging.debug(query)
    try:
        cursor.execute(query)
    except Exception as e:
        return {"success": False}
    return {"success": True}

def update(cursor, table, params):
    arguments = []
    guid = get_constraint(cursor, table)
    query = "UPDATE " + table + " SET "
    for key, value in params.items():
        value = value.replace("'", "\\'")
        value = value.replace('"', '\\"')
        if key == "fieldId" or key == guid:
            continue
        a = is_date(value)
        if a:
            value = a
        query += key + " = ?,"
        arguments.append(value)
    if len(params) != 0:
        query = query[:-1]
    query += " FROM " + table
    query += " WHERE " + guid + "=" + params["fieldId"]
    logging.debug(query + " | ", arguments)
    try:
        cursor.execute(query, *arguments)
    except Exception as e:
        logging.error(e)
        return {"success": False, "message": e}
    return {"success": True}

def store_procedure(cursor, name, params):
    # PROTECT FROM SQLI !!!!
    query = params["query"]
    try:
        cursor.execute(query)
    except Exception as e:
        logging.error(e)
        return {"success": False}
    return {"success": True}

def get_stored_procedure_name(cursor, p2, p3):
    try:
        cursor.execute("SELECT name FROM dbo.sysobjects WHERE (TYPE = 'P')")
    except Exception as e:
        logging.error(e)
        return {"success": False}
    code = []
    for row in cursor:
        a = row[0].split('\n')
        for line in a:
            if len(line) > 0:
                code.append(line)
    return {"names": code}

def get_stored_procedure_code(cursor, procName, p3):
    try:
        cursor.execute("EXEC sp_helptext N'" + procName + "'")
    except Exception as e:
        logging.error(e)
        return {"success": False}
    code = []
    for row in cursor:
        a = row[0].split('\n')
        for line in a:
            if len(line) > 0:
                code.append(line)
    return {procName: code}


import pygame
from pygame.locals import *
import pygameMenu
from data.parser import Parser
from ui.config import Config
from ui.cardboard import Cardboard
from ui.menu import Menu

class Main:

    @classmethod
    def init(cls):
        # set font config
        cls.fontconfig = Config.font_vars["large"]

        cls.parser = Parser()
        cls.parser.parse("questions.json")
        pygame.init()
        cls.screen = pygame.display.set_mode((Config.display_width, Config.display_height))

        # display cards
        cls.screen.fill(Config.niceblue)
        cls.font = pygame.font.Font(Config.font_setting[0], cls.fontconfig[0])
        pools = cls.parser.get_pools()

        cls.cardboard = Cardboard(cls.switch_menu)
        cls.menu = Menu(cls.screen, Config.font_setting[0], pools, cls.switch_cardboard)
        pygame.display.flip()

        cls.main()

    @classmethod
    def main(cls):
        while True:
            events = pygame.event.get()
            cls.menu.mainloop(events)
            cls.cardboard.mainloop(events, cls.screen)
        cls.quit()

    @classmethod
    def switch_cardboard(cls, get_pool_id):
        cls.menu.disable()
        cls.cardboard.enable(cls.screen, cls.parser.get_pool(get_pool_id()), cls.fontconfig)

    @classmethod
    def switch_menu(cls):
        cls.cardboard.disable(cls.screen)
        cls.menu.enable()

    @classmethod
    def quit(cls):
        pygame.quit()
        quit()

    @classmethod
    def log(cls, msg):
        if Config.debug:
            print(msg)

if __name__ == '__main__':
    Main.init()


import re

m = re.compile(r'((\d{2}\.{3}){3}\d{2})|((\d{2}-){3}\d{2})|((\d{2}:){3}\d{2})')
f = open('texto.txt', 'r')
nMatriculas = 0

for line in f:
    lista = m.findall(line)
    if(lista):
        nMatriculas += 1

print("Encontradas %d matrículas" % (nMatriculas))


from flask import Blueprint, render_template, request, flash, jsonify, redirect, url_for
from flask_login import login_required, current_user
from .models import Kursy
from . import db
from .models import Admin,Mecz,Klient,Kursy,Kupon,Zaklad,Portfel
from sqlalchemy import select, update, insert, delete,distinct,between
import json
from datetime import datetime,date

views = Blueprint('views', __name__)

@views.route('/', methods=['GET', 'POST'])
@login_required
def home():
    flash('Welcme to SQLBET!', category='success')

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

@views.route('/admin', methods=['GET', 'POST'])
def home_admin():
    return render_template("home_admin.html", user=current_user)

@views.route('/historia', methods=['GET', 'POST'])
def historia():
    conn = db.engine.connect()
    sql = select(Kupon.id_kuponu, Kupon.data_zakonczenia, Kupon.kwota, Kupon.kurs, Kupon.potencjalna_wygrana,
                 Kupon.stan).where(Kupon.Klient_id_user == current_user.id_user)
    kupony = conn.execute(sql).fetchall()
    #sql = select(Mecz.id_meczu, Mecz.data, Mecz.dr1, Mecz.dr2)

    for kupon in kupony:
        sql = select(Zaklad.id_zakladu, Zaklad.typ, Zaklad.kurs, Zaklad.Mecz_id_meczu).where(Zaklad.Kupon_id_kuponu == kupon.id_kuponu)
        zaklady = conn.execute(sql).fetchall()
        wyniki = []

        for zaklad in zaklady:
            print("ZALAD",zaklad)
            sql = select(Mecz.id_meczu, Mecz.wynik_meczu).where(Mecz.id_meczu == zaklad.Mecz_id_meczu)
            wyn = conn.execute(sql).fetchall()
            wyniki.append(wyn[0])

        if wyniki[0][1] == None:
            print(wyniki[0][1])
            if kupon.stan == "Dodany":
                stan = "Aktywny"
                sql = update(Kupon).where(Kupon.id_kuponu == kupon.id_kuponu).values(stan=stan)
                conn.execute(sql)
                return redirect(url_for('views.historia'))

            if kupon.stan == "Dodany":
                    stan = "Aktywny"
                    sql = update(Kupon).where(Kupon.id_kuponu == kupon.id_kuponu).values(stan=stan)
                    conn.execute(sql)
            if kupon.data_zakonczenia < datetime.date.today():
                #print(stan)
                #print(kupon.kurs,kupon.kwota,kupon.potencjalna_wygrana)

                if kupon.stan == "Aktywny":
                    print(kupon)
                elif kupon.stan == "Do odebrania":
                    stan = "Odebrany"
                    #sql = update(Kupon).where(Kupon.id_kuponu == kupon.id_kuponu).values(stan=stan)
                #conn.execute(sql)
                #print(kupon)
            #print(kupon)
    return render_template("historia.html", user=current_user,kupony=kupony,type=0)

@views.route('/usunsmecz', methods=['GET', 'POST'])
def usun_mecz():
    conn = db.engine.connect()
    sql = select(Mecz.id_meczu, Mecz.liga, Mecz.data_meczu, Mecz.dr1, Mecz.dr2,Mecz.wynik_meczu).where(Mecz.data_meczu > date.today(),Mecz.wynik_meczu == None).order_by(Mecz.data_meczu)
    ligi = conn.execute(sql).fetchall()

    if request.method == 'POST':
        id = request.form.get("game")
        sql = select(Kursy.id_kursu, Kursy.Mecz_id_meczu).where(Kursy.Mecz_id_meczu == id)
        kursy = conn.execute(sql).fetchall()
        emty = []
        if kursy != emty:
            print(kursy)
            flash('Nie można usunąć meczu, ponieważ istnieją kursy na ten mecz!', category='error')
            return redirect(url_for('views.home_admin'))
        else:

            sql = delete(Mecz).where(Mecz.id_meczu == id)
            conn.execute(sql)
            return redirect(url_for('views.home_admin'))

    return render_template("usun_mecz.html", user=current_user,Mecze=ligi,type=1)