import os, sys, random
import numpy as np
from tqdm import tqdm

import torch
from torch.utils.data import DataLoader

from transformers import AutoConfig
from transformers import LongformerModel, LongformerTokenizer
import argparse

from utils import collate_fn_bert_single_row
from utils import get_single_row_scene_classification_datasets_with_test as get_datasets
from models import LongformerSingleRowClassifier

os.environ["CUDA_VISIBLE_DEVICES"]="0"

# set seed
seed = 0
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False

def load_data(args, tokenizer):
    D_tr_list, D_dev_list, D_test_list, label_dict = get_datasets(
                                                        args.data_dir,
                                                        max_seq_len=args.max_seq_len,
                                                        max_sent_num=args.max_sent_num,
                                                        reverse=False,
                                                        fill_empty=False,
                                                        min_num_row=1,
                                                        tokenizer=tokenizer,
                                                    )
    show_id_map = {key: i for i, key in enumerate(label_dict.keys())}
    D_tr_list_ = {}
    D_dev_list_ = {}
    D_test_list_ = {}
    for showname in D_tr_list.keys():
        D_tr_ = DataLoader(D_tr_list[showname], batch_size=args.batch_size, shuffle=True,
                        collate_fn=collate_fn_bert_single_row)
        D_dev_ = DataLoader(D_dev_list[showname], batch_size=args.batch_size, shuffle=False,
                            collate_fn=collate_fn_bert_single_row)
        D_test_ = DataLoader(D_test_list[showname], batch_size=args.batch_size, shuffle=False,
                            collate_fn=collate_fn_bert_single_row)
        D_tr_list_[showname] = D_tr_
        D_dev_list_[showname] = D_dev_
        D_test_list_[showname] = D_test_
    print('[*] Loaded TV Shows: {}'.format(list(show_id_map.keys())))

    return D_tr_list_, D_dev_list_, D_test_list_, show_id_map

def compute_loss(args, labels, pred_logits, c_masks):
    sup_loss = 0.
    sample_count = 0
    for inst_id in range(pred_logits.size(0)):
        log_pred_probs = torch.log_softmax(pred_logits[inst_id][:len(labels[inst_id])], dim=1)
        y_mask = torch.sum(c_masks[inst_id], dim=1)
        for c_id in range(len(labels[inst_id])):
            loss = -log_pred_probs[c_id][labels[inst_id][c_id]] / args.gradient_accumulation_steps
            if y_mask[c_id] != 0:
                sup_loss += loss
                sample_count += 1
    sup_loss = sup_loss / sample_count
    return sup_loss

def compute_accu(labels, pred_logits):
    acc = 0
    sample_count = 0
    for inst_id in range(len(labels)):
        for c_id in range(len(labels[inst_id])):
            max_score = torch.min(pred_logits[inst_id][c_id]).cpu().item()
            pred = -1
            for choice in labels[inst_id]:
                if pred_logits[inst_id][c_id][choice] > max_score:
                    max_score = pred_logits[inst_id][c_id][choice]
                    pred = choice
            if pred == labels[inst_id][c_id]:
                acc += 1
            sample_count += 1

    acc /= sample_count
    return acc

def evaluate(model, data_dict, split_name, show_id_map):
    model.eval()
    print('========== Evaluation on {} =========='.format(split_name))
    with torch.no_grad():
        num_sample = 0
        correct = 0.
        num_person = 0
        correct_person = 0.

        for showname in data_dict.keys():
            show_num_sample = 0
            show_correct = 0.
            show_num_person = 0
            show_correct_person = 0.
            show_id = show_id_map[showname]
            for i_batch, data in enumerate(data_dict[showname]):
                x = data["xs"].cuda()
                mask = data["masks"].cuda()
                c = data['c_masks'].cuda()
                y = data["y"]
                scene_id = data["scene_id"]

                pred_logits = model(x, mask, c, show_id)

                acc = 0
                sample_count = 0
                for inst_id in range(x.size(0)):
                    scene_acc = 0
                    scene_sample_count = 0
                    for c_id in range(len(y[inst_id])):
                        max_score = torch.min(pred_logits[inst_id][c_id]).cpu().item()
                        pred = -1
                        for choice in y[inst_id]:
                            if pred_logits[inst_id][c_id][choice] > max_score:
                                max_score = pred_logits[inst_id][c_id][choice]
                                pred = choice
                        if pred == y[inst_id][c_id]:
                            acc += 1
                            scene_acc += 1
                        sample_count += 1
                        scene_sample_count += 1
                    scene_acc /= scene_sample_count
                    correct += scene_acc
                    show_correct += scene_acc
                    num_sample += 1
                    show_num_sample += 1

                correct_person += acc
                show_correct_person += acc
                num_person += sample_count
                show_num_person += sample_count

            print('[*] SHOW NAME - {}:'.format(showname))
            # print('    Scene-Level {} Acc:  {:.4f}'.format(split_name.capitalize(), show_correct / show_num_sample))
            print('    Person-Level {} Acc: {:.4f}'.format(split_name.capitalize(), show_correct_person / show_num_person))
            # print('    Number of scenes:\t ', show_num_sample)
            # print('    Number of characters:', show_num_person)

        if split_name.lower() == 'dev':
            # print('[*] Average Scene-Level {} Acc:  {:.4f}'.format(split_name.capitalize(), correct/num_sample))
            print('[*] Average Person-Level {} Acc: {:.4f}'.format(split_name.capitalize(), correct_person/num_person))
        else:
            # print('[*] Average Scene-Level {} Acc: {:.4f}'.format(split_name.capitalize(), correct / num_sample))
            print('[*] Average Person-Level {} Acc: {:.4f}'.format(split_name.capitalize(), correct_person / num_person))
        # print('[*] Number of scenes:\t ', num_sample)
        # print('[*] Number of characters:', num_person)
    print('========== END of Evaluation ==========')
    return correct/num_sample, correct_person/num_person

def main():
    parser = argparse.ArgumentParser(description='Process some integers.')
    parser.add_argument('--data_dir', type=str,
                        required=True,
                        help='The directory where the merged json files locate.')
    parser.add_argument('--splits', nargs='+',
                        default=[],
                        help='The directory where the merged json files locate.')
    parser.add_argument('--from_pretrained', type=str,
                        default=None,
                        help='The model to load.')
    parser.add_argument('--max_seq_len', type=int,
                        default=2000,
                        help='The maximum length of the input sequence.')
    parser.add_argument('--max_sent_num', type=int,
                        default=12,
                        help='The maximum number of dialogue utterances/sentences included in the context.')
    parser.add_argument('--attention_window', type=int,
                        default=256,
                        help='The attention window size in Longformer.')
    parser.add_argument('--gradient_accumulation_steps', type=int,
                        default=1,
                        help='Number of updates steps to accumulate before performing a backward/update pass.')
    parser.add_argument('--num_epochs', type=int,
                        default=40,
                        help='The total number of training epochs.')
    parser.add_argument('--batch_size', type=int,
                        default=4,
                        help='The batch size.')
    parser.add_argument('--lr', type=float,
                        default=2e-5,
                        help='Learning rate.')
    parser.add_argument('--output_dir', type=str,
                        default='trained_models/',
                        help='The directory where the trained model will be saved.')
    parser.add_argument('--train', action='store_true',
                        help='To enable training.')
    parser.add_argument('--test', action='store_true',
                        help='To enable evaluation.')
    args = parser.parse_args()

    # load tokenizer and data
    tokenizer = LongformerTokenizer.from_pretrained('allenai/longformer-base-4096')
    train_data, dev_data, test_data, show_id_map = load_data(args, tokenizer)

    # load model
    config = AutoConfig.from_pretrained('allenai/longformer-base-4096')
    config.attention_window = args.attention_window
    pretrained_longformer = LongformerModel.from_pretrained('allenai/longformer-base-4096', config=config)
    args.num_classes = 6
    args.num_shows = len(show_id_map)
    model = LongformerSingleRowClassifier(args, bert_model=pretrained_longformer, fine_tuning=True, max_length=512)
    if args.from_pretrained is not None:
        model.load_state_dict(torch.load(args.from_pretrained))
    model = model.to('cuda')

    # optimization
    pred_optimizer = torch.optim.Adam(model.pred_vars() , lr=args.lr)

    # training
    if args.train:
        best_F1s = [0., 0., 0., 0.]
        best_dev = 0.
        best_dev_person = 0.
        show_list = list(show_id_map.keys())
        for i_epoch in range(args.num_epochs):
            print("================")
            print("   epoch: {:02}".format(i_epoch))
            print("================")

            model.train()
            train_accs = {}
            train_losses = {}
            for showname in train_data.keys():
                train_accs[showname] = []
                train_losses[showname] = []

            step = 0
            pred_optimizer.zero_grad()

            for i_batch in tqdm(range(len(train_data['The_Office']))):
                random.shuffle(show_list)
                for showname in show_list:
                    show_id = show_id_map[showname]
                    data = next(iter(train_data[showname]))

                    x = data["xs"].to('cuda')
                    mask = data["masks"].to('cuda')
                    c = data['c_masks'].to('cuda')
                    y = data["y"]
                    scene_id = data["scene_id"]
                    pred_logits = model(x, mask, c, show_id)

                    sup_loss = compute_loss(args, y, pred_logits, c)
                    train_losses[showname].append(sup_loss.cpu().item())
                    sup_loss.backward()

                    acc = compute_accu(y, pred_logits)
                    train_accs[showname].append(acc)

                    if (step + 1) % args.gradient_accumulation_steps == 0:
                        pred_optimizer.step()
                        pred_optimizer.zero_grad()
                        step = 0
                    else:
                        step += 1

                # print training accuracy
                if (i_batch + 1) % 500 == 0:
                    print('[*] Training Stats:')
                    for showname in train_data.keys():
                        print("    {:<20} => Train batch: {:<5} step: {:<4} loss: {:07.4f}   acc: {:.4f}".format(
                                    showname,
                                    i_batch,
                                    step,
                                    np.mean(train_losses[showname]),
                                    np.mean(train_accs[showname]))
                                )
                    for showname in train_data.keys():
                        train_accs[showname] = []
                        train_losses[showname] = []

                # evaluate on dev set
                if (i_batch + 1) % 600 == 0 or (i_batch+1) == len(train_data['The_Office']):
                    scene_score_mean, person_score_mean = evaluate(model, dev_data, 'dev', show_id_map)
                    ## scene_score > person_score
                    ## But we use person_score as our metrics in the paper
                    if person_score_mean > best_dev_person:
                        best_dev_person = person_score_mean
                        print('[*] Saving the checkpoint with best dev {:.4f}'.format(best_dev_person))
                        torch.save(model.state_dict(), args.output_dir + 'pytorch_model.pt')

    # testing
    if args.test:
        if 'dev' in args.splits:
            evaluate(model, dev_data, 'dev', show_id_map)
        if 'test' in args.splits:
            evaluate(model, test_data, 'test', show_id_map)

if __name__ == '__main__':
    main()


# -------------------------------------------------------------

from AI_intro_project.Coordinate_and_Move \
                import Coordinate, Move

from random import choice

import matplotlib.pyplot as plt

class State():
    '''a state of the game'''

    def __init__(self) -> None:
        '''
        Each state is composed by 4 components, which are:
        - board_size: a tuple (m, n)
        - walked_moves: a list of instances of Move,
          each instance is represented by (x, y,
          direction)
        - current_pos: Coordinate(x, y)
        - current_tax: a real number
        Properties:
        Methods:
        - initialize_4x4_default
        - initialize_6x6_default
        - initialize_8x8_default
        - initialize_mxn_default: pick a random state in the state
          directory
        - _plt_prepare: prepare matplotlib.pyplot for the game
          visualizer
        - visualize: plot the board using matplotlib.pyplot (no
          subplot involved)
        - random_play: legally play several random moves
        - undo_last_move: undo last move
        - check_duplicate_move: check if a move is available
          for later walk
        - available_moves_list: a list of avalable moves
        - tax_after_move: the tax after a specified move
        - move_on_move: (wtf name) move the pilgrim on a
          move specified
        - move_to_direction: move the pilgrim to a specified
          direction (R, L, U, D)
        '''
        self.initialize_4x4_default()

    def __repr__(self) -> str:
        return f'State: (size={self.board_size}, #moved={len(self.walked_moves)}, \
curr-pos={self.current_pos}, curr-tax={self.current_tax})'

    def initialize_mxn_blank(self, size=(4,4)) -> None:
        '''Initialize the state without moves'''
        self.board_size = size
        self.walked_moves = list()
        self.current_pos = Coordinate(0, 0)
        self.current_tax = 0.0

    def initialize_4x4_default(self) -> None:
        '''
        Initialize the state which is the same as the
        TED-Ed's video: https://youtu.be/6sBB-gRhfjE
        '''
        self.initialize_mxn_blank()

        # move to the right twice
        for _ in range(2):
            self.move_to_direction('R')

    def initialize_6x6_default(self) -> None:
        '''Initialize the state'''
        self.initialize_mxn_blank((6, 6))

        # move to the right twice
        for _ in range(3):
            self.move_to_direction('R')

    def initialize_8x8_default(self) -> None:
        '''Initialize the state'''
        self.initialize_mxn_blank((8, 8))

        # move to the right twice
        for _ in range(4):
            self.move_to_direction('R')

    def initialize_mxn_random(self) -> None:
        '''Initialize the state by a randomized state'''
        from AI_intro_project._Utilities import _Utilities
        s = _Utilities().load_randomly(
                sizes=[(i,j) for i in range(4,9) for j in range(4,9)],
                directory='AI_intro_project/randomized_states',
                extension='state'
            )

        self.board_size = s.board_size
        self.walked_moves = s.walked_moves
        self.current_pos = s.current_pos
        self.current_tax = s.current_tax

    def _plt_prepare(self, show_move_numbers=True) -> None:
        '''
        Prepare matplolib.pyplot for plotting
        Used to visualize the current state in matplotlib
        Most of the things below are reversed in some way,
        since the x coordinate of the game is the y
        coordinate in math, etc.
        '''
        # move x axis to the top
        plt.rcParams['xtick.bottom'] = \
            plt.rcParams['xtick.labelbottom'] = False
        plt.rcParams['xtick.top'] = \
            plt.rcParams['xtick.labeltop'] = True

        # black board
        for i in range(self.board_size[1] + 1):
            plt.plot(
                    [i,i],
                    [0,self.board_size[0]],
                    color='silver'
            )
        for i in range(self.board_size[0] + 1):
            plt.plot(
                    [0,self.board_size[1]],
                    [i,i],
                    color='silver'
            )

        # moves
        for index, move in enumerate(self.walked_moves):
            plt.plot(
                [move.coordinate_start.y,
                        move.coordinate_end.y],
                [move.coordinate_start.x,
                        move.coordinate_end.x],
                color='red'
            )
            if show_move_numbers:
                plt.text(move.coordinate_start.y/2 + move.coordinate_end.y/2,
                        move.coordinate_start.x/2 + move.coordinate_end.x/2,
                        index,
                        ha='center',
                        va='center',
                        fontfamily='monospace',
                        color='blue'
                        )
        # current tax text
        plt.text(
                self.board_size[1]/2,
                self.board_size[0]+3/4,
                f'Current tax: {self.current_tax}',
                ha='center',
                va='center',)

        # limit the plot by board size
        plt.xlim(-1, self.board_size[1] + 1)
        plt.ylim(-1, self.board_size[0] + 1)

        # invert y axis (oriented downward)
        plt.gca().invert_yaxis()

        # scale axes equally, so squares are displayed
        plt.gca().set_aspect('equal', adjustable='box')

        # show every value on the axes, and exclude -1
        plt.xticks([x for x in range(self.board_size[1] + 1)])
        plt.yticks([y for y in range(self.board_size[0] + 1)])

        # show
        plt.plot()

    def visualize(self, show_move_numbers=True) -> None:
        '''
        Visualize the current state in matplotlib
        '''
        self._plt_prepare(show_move_numbers=show_move_numbers)
        plt.show()

    def random_play(self, number_of_moves=20, silent=False) -> None:
        '''
        Randomly continue playing the current state
        for the given number of moves if the moves is
        possible
        Print the moves if silent is False
        '''
        for i in range(number_of_moves):
            if len(self.available_moves_list()) != 0:
                move = choice(self.available_moves_list())
                self.move_on_move(move)
                if not silent:
                    print(f'{move.__str__(show_coordinate_end=True)}, tax after move = {self.current_tax}')

    def undo_last_move(self) -> None:
        '''Undo the last move'''
        assert self.walked_moves, \
                'NO MOVE LEFT TO UNDO'
        last_move = self.walked_moves.pop(-1)
        recover_direction = last_move.reverse_direction()
        self.move_to_direction(recover_direction)
        self.walked_moves.pop(-1)

    def check_not_duplicate_move(self, move) -> bool:
        '''
        Check if a move is available for later walk, by
        checking if the move is already in walked_moves
        of the current state, return False if it
        is duplicated
        '''
        for walked_move in self.walked_moves:
            if walked_move == move:
                return False
        return True

    def available_moves_list(self) -> list():
        '''
        Return a list of instances of Move, which are the
        moves that the pilgrim can walk in the current state,
        by checking all 4 directions around the current_pos.
        '''
        result = list()
        for direction in ['L', 'U', 'R', 'D']:
            move = Move(self.current_pos.x,
                        self.current_pos.y,
                        direction)
            if (self.check_not_duplicate_move(move)
                    and move.check_inside(*self.board_size)):
                result.append(move)
        return result

    def tax_after_move(self, move) -> None:
        '''Return the tax after a move'''
        if move.direction == 'R':
            return self.current_tax + 2
        elif move.direction == 'L':
            return self.current_tax - 2
        elif move.direction == 'U':
            return self.current_tax / 2
        elif move.direction == 'D':
            return self.current_tax * 2

    def move_on_move(self, move) -> None:
        '''perform the move on a Move instance'''
        assert move in self.available_moves_list(), \
                f'{move}: CANNOT MOVE THIS WAY'

        self.walked_moves.append(move)
        self.current_pos = move.coordinate_end
        self.current_tax = self.tax_after_move(move)

    def move_to_direction(self, direction) -> None:
        '''
        perform the move from the current position
        to a direction
        '''
        self.move_on_move(
                Move(
                        self.current_pos.x,
                        self.current_pos.y,
                        direction
                )
        )

# Run this file to randomly move 20 times if available,
# print the moves, then visualize the final state
if __name__ == '__main__':
    s = State()
    s.random_play()
    print(repr(s))
    s.visualize()


from rest_framework.schemas import AutoSchema

from Apps.common.services import Params, BaseService

class GoogleMobility_Service(BaseService):
    def __init__(self):
        self.dropped_keys = []
        self.single_keys = ['CountryName', 'CountryCode']

        self.params = [
            Params(name='regionCode', dtype=str, required=True,
                   location='query', description="Country code (ISO3)"),
            Params(name='startDate', dtype=str, required=True,
                   location='query', description="Query start date (format: %Y-%m-%d)"),
            Params(name='offset', dtype=int, required=True,
                   location='query', description="The number of dates from startDate."),

            # Params(name='retail_and_recreation', dtype=bool, required=True,
            #        location='header', description="requesting retail and recreation data"),
            # Params(name='grocery_and_pharmacy', dtype=bool, required=True,
            #        location='header', description="requesting grocery and pharmacy data"),
            # Params(name='parks', dtype=bool, required=True,
            #        location='header', description="requesting parks data"),
            # Params(name='transit_stations', dtype=bool, required=True,
            #        location='header', description="requesting transit stations data"),
            # Params(name='workplaces', dtype=bool, required=True,
            #        location='header', description="requesting workplaces data"),
            # Params(name='residential', dtype=bool, required=True,
            #        location='header', description="requesting residential data"),
        ]
        self.methods = ['get']

        super(GoogleMobility_Service, self).__init__(params=self.params, methods=self.methods,
                                                     dropped_keys=self.dropped_keys, single_keys=self.single_keys)
        self.schema = GoogleMobility_Schema(self.fields)

class GoogleMobility_Schema(AutoSchema):
    manual_fields = []  # common fields

    def __init__(self, fields):
        super().__init__()
        self.manual_fields = fields

    def get_manual_fields(self, path, method):
        super().get_manual_fields(path, method)
        custom_fields = []

        return self.manual_fields + custom_fields


#!/usr/bin/python3

program = 'getObsFiles'
author  = 'Helge Rottmann'
version = '0.2'
verdate = '20230727'

import os
import sys

baseURLs = ["ftp://vlbeer.ira.inaf.it/vlb_arc/ftp/vlbi_arch/", "http://www.vlba.nrao.edu/astro/VOBS/astronomy/"]
#baseURLs = ["http://www.vlba.nrao.edu/astro/VOBS/astronomy/"]
localDir = "FILES"

def printUsage():

        print ('\n%s ver. %s  %s %s' % (program, version, author, verdate))
        print ('\nA program to retrieve the observation files (logs, vex etc.)')
        print ('from the Bologna and NRAO servers.')

        print ("\nUsage: \n")
        print (sys.argv[0] + " <experiment> <session> \n\n")

        print ("experiment:     experiment code to retrieve logs files for")
        print ("session:                session of the observation (e.g. mar10, nov09)\n")

        print ("Files are downloaded to the %s subdirectory\n" % (localDir))

        exit(1)

if len(sys.argv) < 3:
        printUsage()

exp = str.lower(sys.argv[1])
date = sys.argv[2]

try:
        os.mkdir("./%s" % (localDir))
except:
        print ("Directory %s exists." % localDir)
        print ("Continuing will download new files, existing files will not be updated.")
        answer = ""
        while answer not in ["y", "n"]:
            answer = input("Do you want to continue [y/n]? ").lower()

        if answer == "n":
            exit(1)

os.chdir("./%s" % (localDir))

for baseURL in baseURLs:

        print ("Downloading files from: %s" % baseURL)
        if "ira.inaf" in baseURL:
                url = baseURL + date + "/"
                wget = 'wget -r -nd -nc --no-parent -nv -A' + exp + '* -e robots=off ' + url
                os.system(wget)

                urlLatest = url + ".latest/"
                wgetLatest = 'wget -r -nd --no-parent -nv -A' + exp + '* -e robots=off ' + urlLatest
                os.system(wgetLatest)

        if "vlba" in baseURL:
                url = baseURL + date + "/" + exp + "/"
                wget = 'wget -r -nd -nc --no-parent --level=1 -nv '
                wget += '-A' + exp + '.*,'+ exp + 'cal.vlba,'+ exp + 'log.vlba ' # <exp>cal.vlba has VLBA Tsys and everything else
                wget += '-Rindex* -e robots=off ' + url
                #print (wget)
                os.system(wget)


import pandas as pd
import ast

df = pd.read_csv('booksummaries.txt', delimiter="\t", names=["WID", "BookName", "Author", "Date", "Tags", "Summary"],
                 encoding="UTF-8")

emptyDf = df[df['Tags'].isna()]
validDf = df.dropna(subset=['Tags'], how='all')

indx = 0
for i in validDf["Tags"]:
    i = ast.literal_eval(i)
    validDf.iat[indx, 4] = i
    indx += 1

validChangedDate = pd.DataFrame(columns=["WID", "BookName", "Author", "Date", "Tags", "Summary"])

counter = 0
for i in range(len(validDf)):
    for j in validDf.iloc[i].Tags:
        validChangedDate.loc[counter] = [validDf.iloc[i].WID, validDf.iloc[i].BookName, validDf.iloc[i].Author, validDf.iloc[i].Date, validDf.iloc[i].Tags[j], validDf.iloc[i].Summary]
        counter += 1

validChangedDate.to_csv('validChangedDate.txt', sep='\t')


# from pudb import set_trace; set_trace()
from typing import List, Tuple
import math

class Solution1:
    def longestPath(self, parent: List[int], s: str) -> int:
        """LeetCode 2246

        I am glad that this solution was almost exactly the same as the updated
        one last time I encountered this problem in April 2022.

        Direct DFS. The return of dfs(idx) is the longest path that satisfies
        the question starting from idx. For each idx, we can also compute a
        potential result, which is the longest path of its child plus the second
        longest path of its child plus one.

        O(NlogN), 1829 ms, faster than 83.81%
        """
        graph = [[] for _ in range(len(s))]
        for i, p in enumerate(parent[1:], 1):
            graph[p].append(i)
        self.res = 0

        def dfs(idx) -> int:
            max_lens = [0, 0]
            for nex in graph[idx]:
                l = dfs(nex)
                if s[nex] != s[idx]:
                    max_lens.append(l)
            max_lens.sort()
            self.res = max(self.res, max_lens[-1] + 1 + max_lens[-2])
            return max_lens[-1] + 1

        dfs(0)
        return self.res

class Solution2:
    def longestPath(self, parent: List[int], s: str) -> int:
        """Remove the sort. Use two variables to keep track the largest and
        second largest.

        O(N), 1589 ms, faster than 95.34%
        """
        graph = [[] for _ in range(len(s))]
        for i, p in enumerate(parent[1:], 1):
            graph[p].append(i)
        self.res = 0

        def dfs(idx) -> int:
            l1, l2 = 0, 0  # max, second max
            for nex in graph[idx]:
                l = dfs(nex)
                if s[nex] != s[idx]:
                    if l > l1:
                        l2, l1 = l1, l
                    elif l > l2:
                        l2 = l
            self.res = max(self.res, l1 + l2 + 1)
            return l1 + 1

        dfs(0)
        return self.res

sol = Solution2()
tests = [
    ([-1,0,0,1,1,2], "abacbe", 3),
    ([-1,0,0,0], "aabc", 3),
    ([-1,0,1], "aab", 2),
]

for i, (parent, s, ans) in enumerate(tests):
    res = sol.longestPath(parent, s)
    if res == ans:
        print(f'Test {i}: PASS')
    else:
        print(f'Test {i}; Fail. Ans: {ans}, Res: {res}')


import cv2
import matplotlib.pyplot as plt

def main():
    windowName="Live Webcam Video Feed Capture"
    cv2.namedWindow(windowName)

    cap = cv2.VideoCapture(0)

    filename='C:\\Users\\ASH\\Desktop\\New folder\\456.avi'

    codec= cv2.VideoWriter_fourcc('X','V','I','D')
    framerate=30
    resolution = (640,480)
#codec examples => WMV2,WMV1,MJPG,DIVX,XVID,H264

    VideoFileOutput=cv2.VideoWriter(filename,codec,framerate,resolution)

    if cap.isOpened():          #check if camera is opened or not
        ret,frame=cap.read()
    else:
        ret=False

    while ret:
        ret,frame=cap.read()

        frame=cv2.cvtColor(frame,cv2.COLOR_BGR2RGB) #to swap blue green color of video

        VideoFileOutput.write(frame)

        cv2.imshow(windowName,frame)
        if cv2.waitKey(1)==27:
            break

    cap.release()       #turn off webcam

    cv2.destroyAllWindows()

if __name__=="__main__":
    main()


from kafka import KafkaProducer
import time
import json

producer = KafkaProducer(bootstrap_servers='192.168.33.50:9092')

topic = 'test'
i = 0
while True:
    i += 1
    json_data = {
        "msg": "my kafka {}".format(i),
        "count": i,
        "create_time": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    }
    post_data = json.dumps(json_data).encode()

    producer.send(topic, post_data)
    print('producer - {0}'.format(post_data))
    time.sleep(8)


import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from xgboost import XGBClassifier
import logging
from typing import List, Tuple, Dict
import pickle

logger = logging.getLogger(__name__)

def load_data(data_file: str) -> pd.DataFrame:
    """
    Loads the data from a CSV file.

    Parameters:
    - data_file (str): The path to the data file.

    Returns:
    - A pandas DataFrame with the data.
    """
    logger.info(f"Loading data from file {data_file}")
    return pd.read_csv(data_file)

def preprocess_data(X: pd.DataFrame) -> (pd.DataFrame, ColumnTransformer):
    """
    Preprocesses the data by scaling numeric features and one-hot-encoding categorical features.

    Parameters:
    - X (pd.DataFrame): The input data.

    Returns:
    - A tuple containing the preprocessed data and the ColumnTransformer used to preprocess it.
    """
    logger.info("Preprocessing data")
    df_index = pd.DataFrame(X.dtypes).reset_index()

    categorical_cols = df_index.loc[df_index[0]=='object']['index'].to_list()
    numeric_cols = df_index.loc[df_index[0]=='int64']['index'].to_list()
    numeric_transformer = StandardScaler()
    categorical_transformer = OneHotEncoder()
    preprocessor = ColumnTransformer(transformers=[
        ('num', numeric_transformer, numeric_cols),
        ('cat', categorical_transformer, categorical_cols)])
    X_preprocessed = preprocessor.fit_transform(X)
    return X_preprocessed, preprocessor

def train_model(X: pd.DataFrame, y: pd.Series) -> XGBClassifier:
    """
    Trains a model to predict heart disease.

    Parameters:
    - X (pd.DataFrame): The preprocessed input data.
    - y (pd.Series): The target variable.

    Returns:
    - The trained XGBClassifier model.
    """
    logger.info("Training model")
    model = XGBClassifier(learning_rate=0.01, n_estimators=100, max_depth=4)
    model.fit(X, y)
    return model

def save_models(model: XGBClassifier, preprocessor: ColumnTransformer, model_file: str,
                scaler_file: str, encoder_file: str) -> None:
    """
    Saves the trained model and its preprocessing transformers to disk.

    Parameters:
    - model (XGBClassifier): The trained model.
    - preprocessor (ColumnTransformer): The preprocessing ColumnTransformer.
    - model_file (str): The filename to use for the model file.
    - scaler_file (str): The filename to use for the scaler file.
    - encoder_file (str): The filename to use for the encoder file.
    """
    logger.info(f"Saving model to file {model_file}")
    model.save_model(model_file)

    logger.info(f"Saving scaler to file {scaler_file}")
    with open(scaler_file, 'wb') as f:
        pickle.dump(preprocessor.named_transformers_['num'], f)

    logger.info(f"Saving encoder to file {encoder_file}")
    with open(encoder_file, 'wb') as f:
        pickle.dump(preprocessor.named_transformers_['cat'], f)

def load_models(scaler_file: str, encoder_file: str, model_file: str) -> Tuple:
    """
    Load the scaler, encoder, and XGBoost model from disk.

    Parameters:
    - scaler_file (str): The path to the file containing the scaler object.
    - encoder_file (str): The path to the file containing the encoder object.
    - model_file (str): The path to the file containing the XGBoost model.

    Returns:
    - A tuple containing the scaler, encoder, and XGBoost model objects.
    """
    with open(scaler_file, 'rb') as f:
        scaler = pickle.load(f)

    with open(encoder_file, 'rb') as f:
        encoder = pickle.load(f)

    model = XGBClassifier()
    model.load_model(model_file)

    return scaler, encoder, model

def predict(data: pd.DataFrame, scaler: StandardScaler, encoder: OneHotEncoder, model: XGBClassifier, numerical_features: List[str], categorical_features: List[str]) -> Dict[str, List[float]]:
    """
    Makes predictions using a saved machine learning model.

    Parameters:
    - data (pd.DataFrame): The data to make predictions on.
    - scaler (StandardScaler): The trained scaler used to scale the data.
    - encoder (OneHotEncoder): The trained encoder used to encode categorical features.
    - model (XGBClassifier): The trained machine learning model.
    - numerical_features (List[str]): The names of the numerical features in the input data.
    - categorical_features (List[str]): The names of the categorical features in the input data.

    Returns:
    - A dictionary containing the predicted class and probability for each sample in the input data.
    """

    scaled_data = scaler.transform(data[numerical_features])
    encoded_data = encoder.transform(data[categorical_features]).toarray()
    preprocessed_data = np.concatenate([scaled_data, encoded_data], axis=1)
    probabilities = model.predict_proba(preprocessed_data)
    predictions = model.predict(preprocessed_data)

    return {"predictions": predictions, "probabilities": probabilities[:, 1].tolist()}

def main():
    # Load data
    data = load_data("models/heart.csv")

    # Preprocess data
    X, preprocessor = preprocess_data(data.drop("HeartDisease", axis=1))
    y = data["HeartDisease"]

    # Train model
    model = train_model(X, y)

    # Save models
    save_models(model, preprocessor, "models/model.json", "models/scaler.pkl", "models/encoder.pkl")

    # Load models
    scaler, encoder, model = load_models("models/scaler.pkl", "models/encoder.pkl", "models/model.json")

    # Make predictions
    df_index = pd.DataFrame(data.drop("HeartDisease", axis=1).dtypes).reset_index()
    numerical_features = df_index.loc[df_index[0]=='int64']['index'].to_list()
    categorical_features = df_index.loc[df_index[0]=='object']['index'].to_list()
    new_data = pd.DataFrame(data.drop("HeartDisease", axis=1).loc[0]).T
    predictions = predict(new_data, scaler, encoder, model, numerical_features, categorical_features)
    print(predictions)

if __name__ == "__main__":
    main()


# from pudb import set_trace; set_trace()
from typing import List
from functools import lru_cache

class Solution1:
    def findPaths(self, m: int, n: int, maxMove: int, startRow: int, startColumn: int) -> int:
        """LeetCode 576

        Not very difficult. A typical DP problem. We record the number of
        ways to move out of bound for each consecutive moves. For instance, with
        move 1, we have all the edges eligible to move out of bound. We record
        the number of ways each eligible cell can move out of bound (basically
        everyone on the edge has one way to move out of bound, except for the
        four corners, which have two ways). Then we consider the second move.
        We go through each cell and see if a cell's next move can end up at a
        cell that is eligible for one-move out of bound. If it's possible, we
        increment the number of ways for the two-move eligible cell with the
        number of ways in the one-move eligible cell. We continue this operation
        until reaching maxMove.

        At each round, we increment the result by adding the number of ways at
        location startRow, startColumn for the current move.

        The tricky part that got to me was that I forgot to consider the zero
        move situation. But it was resolved by simply setting up a check at the
        very beginning for maxMove == 0.

        O(KMN), where K = maxMove, M is the number of rows in the grid, and N
        the numbre of columns. 364 ms, 18% ranking.
        """
        if not maxMove:
            return 0
        pre = [[0] * n for _ in range(m)]
        for j in range(n):  # base case for one move
            pre[0][j] += 1
            pre[-1][j] += 1
        for i in range(m):
            pre[i][0] += 1
            pre[i][-1] += 1
        res = pre[startRow][startColumn]
        for _ in range(maxMove - 1):
            cur = [[0] * n for _ in range(m)]
            for i in range(m):
                for j in range(n):
                    for di, dj in [(-1, 0), (0, 1), (1, 0), (0, -1)]:
                        ni, nj = i + di, j + dj
                        if 0 <= ni < m and 0 <= nj < n and pre[ni][nj]:
                            cur[i][j] += pre[ni][nj]
            res += cur[startRow][startColumn]
            pre = cur
        return res % 1000000007

class Solution2:
    def findPaths(self, m: int, n: int, maxMove: int, startRow: int, startColumn: int) -> int:
        """The recursive solution. Courtesy of:

        https://leetcode.com/problems/out-of-boundary-paths/discuss/1293727/Python-Short-dp-%2B-educational-matrix-exponentiation-explained

        However, as I was trying to write it myself, I got massively blocked by
        the terminating case. I was checking for numMove first, and then the
        i and j. This is not correct, because i and j can be out of bound for
        multiple moves and eventually end up at the right position that I want.
        Yet this is not a correct case. E.g. we want to take three moves to get
        to (-1, 0), and we have (0, 0) -> (-1, 0) -> (-2, 0) -> (-1, 0). So we
        have achieved going from (0, 0) to (-1, 0) in three moves. This shall
        count as a way, right? No, because we went out of bound for multiple
        moves, which is not allowed.

        Therefore, the correct terminating case is to check for out of bound
        first. As long as we go out of bound for the first time, that is a valid
        way. After that, we check for numMoves.

        One more thing to mention is the speed. This solution has the same
        complexity as Solution1, but it runs 124 ms, much faster. This is most
        likely due to lru_cache being more optimized than preparing the DP table
        ourselves.
        """

        @lru_cache(maxsize=None)
        def dfs(i: int, j: int, numMove: int) -> int:
            if i < 0 or i >= m or j < 0 or j >= n:
                return 1
            if numMove == 0:
                return 0
            return sum(dfs(i + di, j + dj, numMove - 1) for di, dj in [(-1, 0), (0, 1), (1, 0), (0, -1)])

        return dfs(startRow, startColumn, maxMove) % 1000000007

sol = Solution2()
tests = [
    # (2, 2, 2, 0, 0, 6),
    (1, 3, 3, 0, 1, 12),
    # (3, 8, 0, 2, 0, 0),
]

for i, (m, n, maxMove, startRow, startColumn, ans) in enumerate(tests):
    res = sol.findPaths(m, n, maxMove, startRow, startColumn)
    if res == ans:
        print(f'Test {i}: PASS')
    else:
        print(f'Test {i}; Fail. Ans: {ans}, Res: {res}')


#!/usr/bin/env python3

import libtcodpy as libtcod

from functools import reduce
import re # for sub

from interfaces import Carryable, Activatable, Activator, CountUp, Mappable, TurnTaker, StatusEffect, LightSource
from ui import UI, HBar, Message
from errors import InvalidMoveError

class Item(Carryable, Activatable, Mappable):
    # for item generation
    awesome_rank    = 2   # out of 5. 0 can't be returned by .random()
    awesome_weight  = 1.0 # 0.0 never occur; 1.0 normal; 2.0 twice normal ... choices also sorted by weight within each rank
    AWESOME_MAP     = None

    def __init__(self, owner, power, colour, symbol='!'):
        pos = None
        if not isinstance(owner, Activator):
            pos   = owner
            owner = None
        self.power = power
        Mappable.__init__(self,pos,symbol,colour)
        Activatable.__init__(self,owner)
        if pos is None:
            self.is_visible = False
        self.is_chargable = False

        # to trigger any on-pickup behaviour
        if not self.owner is None:
            self.take_by(self.owner)

    def __str__(self):
        if self.owner is None:
            return "%s at %s"%(self.__class__.__name__,self.pos)
        else:
            return "%s held by %s"%(self.__class__.__name__,self.owner)

    def draw_ui(self,pos,max_width=40):
        pass

    def drop_at(self,pos):
        self.owner = None
        self.pos = pos
        self.is_visible = True

    def take_by(self,owner):
        self.owner = owner
        self.pos = None
        self.is_visible = False

    def charge(self,amount=1):
        """returns true if item is charged by more than 0"""
        return False

    @staticmethod
    def random(rng,pos,ranks=range(1,4),weight=1.0):
        """random item at pos using rng. fixing a rank will limit choice to that rank. raising weight increases probability of a good item"""
        # build cache of item ranks and weights
        if Item.AWESOME_MAP is None:
            Item.__GEN_AWESOME_MAP()

        if isinstance(ranks,int):
            ranks = [ranks]

        elif isinstance(ranks,list):
            ranks.sort()

        # calculate weighted range
        awesome_range = reduce( lambda a,b: a + b, [A[1][-1].awesome_acc_weight for A in Item.AWESOME_MAP.items() if A[0] in ranks], 0.0 )

        # roll die and weight by parameter
        # NB. weighting can push t out of bounds!
        t = awesome_range + 1.0
        while t >= awesome_range:
            t = libtcod.random_get_float(rng,0.0,awesome_range) * weight

        #print("Range = 0.0 - %f  =>  %f" % (awesome_range,t))

        # find rank that was rolled
        rank = ranks[0]
        while t > Item.AWESOME_MAP[rank][-1].awesome_acc_weight:
            t    -= Item.AWESOME_MAP[rank][-1].awesome_acc_weight
            rank += 1

        #print("Rank = %d  =>  %s   %s" %(rank,Item.AWESOME_MAP[rank],[C.awesome_acc_weight for C in Item.AWESOME_MAP[rank]]))

        # find item that was rolled
        item_idx = 0
        while t > Item.AWESOME_MAP[rank][item_idx].awesome_acc_weight:
            item_idx += 1

        # calculate item power (higher in range => more power)
        item_power = 2 * (Item.AWESOME_MAP[rank][item_idx].awesome_acc_weight-t) / Item.AWESOME_MAP[rank][item_idx].awesome_weight

        #print("Got %s (%d) at power %f" % (Item.AWESOME_MAP[rank][item_idx],item_idx,item_power))

        return Item.AWESOME_MAP[rank][item_idx](pos,item_power)

    @staticmethod
    def __GEN_AWESOME_MAP():
        Item.AWESOME_MAP = {}
        for i in range(1,6):
            Item.AWESOME_MAP[i] = [] # need empty entries even if no rank
        for C in (MemoryWipe,Tangler,TangleMine,HandTeleport,Cloaker,DoorRelease,LevelMap,XRaySpecs,LabCoat,NinjaSuit,EmergencyHammer,RemoteControl,AnalysisSpecs,TorchHelmet,InfraSpecs,NightVisionGoggles):
            Item.AWESOME_MAP[C.awesome_rank].append(C)
        for CL in Item.AWESOME_MAP.values():
            CL.sort(key=lambda x: x.awesome_weight)
            last = 0.0
            for C in CL:
                # generate a corrected cumulative weight, where high rank items are rarer
                C.awesome_acc_weight = (C.awesome_weight + last)/C.awesome_rank
                last += C.awesome_weight

    @staticmethod
    def get_item_by_name(name):
        for CL in Item.AWESOME_MAP.values():
            for C in CL:
                if C.__name__.lower() == name.lower() or re.sub("([a-z])([A-Z])",r'\1 \2',C.__name__).lower() == name.lower():
                    return C
        raise NameError(name)

class SlotItem(Item):
    awesome_rank   = 3
    awesome_weight = 1.0

    HEAD_SLOT = 'Head'
    BODY_SLOT = 'Body'
    FEET_SLOT = 'Feet'

    def __init__(self,owner,item_power,valid_slot,item_colour=libtcod.cyan,bar_colour=libtcod.dark_cyan):
        Item.__init__(self,owner,item_power,item_colour,'[')
        self.valid_slot = valid_slot

class RunDownItem(SlotItem, CountUp, TurnTaker):
    def __init__(self,owner,item_power,valid_slot,item_colour=libtcod.cyan,bar_colour=libtcod.dark_cyan):
        self.bar = HBar(None, None, bar_colour, libtcod.dark_grey, True, False, str(self), str.ljust)
        self.bar.is_visible = False

        SlotItem.__init__(self,owner,item_power,valid_slot,item_colour,bar_colour)
        count_to = int( 50 + 100*item_power )
        CountUp.__init__(self,count_to)
        TurnTaker.__init__(self,100,False)

        self.is_active = False
        self.is_chargable = True

    def take_turn(self):
        assert self.is_active, "Taking turns on inactive RunDownItem %s" % self

        # sanity: if left active and dropped, deactivate
        if not self.owner:
            self.activate()
            return False

        # if run out of charge, deactivate
        if self.inc():
            self.activate()
            return False

        return True

    def activate(self,activator=None):
        if self.is_active:
            # deactivate an active item
            self.is_active = False
            TurnTaker.clear_turntaker(self)
            return True

        elif self.full():
            # can't activate one that's run out
            return False

        else:
            self.is_active = True
            TurnTaker.add_turntaker(self)
            self.inc(4) # activation costs 4 + 1 for the first turn; discouraging flickering
            self.take_turn() # so takes effect straight away if any turn taking behaviour
            return True

    def charge(self,amount=1):
        if self.is_chargable:
            return self.dec(amount)

    # TODO: refactor these, plus the bar, into the base class
    def draw_ui(self,pos,max_width=40):
        self.bar.pos = pos
        self.bar.size = max_width
        self.bar.value = self.count_to-self.count
        self.bar.max_value = self.count_to
        self.bar.is_visible = True

    def drop_at(self,pos):
        Item.drop_at(self,pos)
        self.bar.is_visible = False

    def take_by(self,owner):
        Item.take_by(self,owner)
        self.bar.is_visible = True

class CoolDownItem(Item, CountUp, TurnTaker):
    awesome_rank   = 2
    awesome_weight = 1.0

    def __init__(self,owner,item_power,item_colour=libtcod.green,bar_colour=libtcod.dark_green):
        count_to = int( 30 - 10*item_power )
        self.bar = HBar(None, None, bar_colour, libtcod.dark_grey, True, False, str(self), str.ljust)
        self.bar.is_visible = False
        Item.__init__(self,owner,item_power,item_colour)
        CountUp.__init__(self,count_to,count_to)
        TurnTaker.__init__(self,100,False)
        self.is_chargable = True

    def take_turn(self):
        if self.inc():
            TurnTaker.clear_turntaker(self)
            return True
        return False

    def activate(self,activator=None):
        if not self.full():
            print ("%s still on cooldown, %d turns remaining"%(self,self.count_to-self.count))
            # still on cooldown
            return False
        self.reset(0) # was -1 because we immediately inc()
        TurnTaker.add_turntaker(self)
        return True

    def draw_ui(self,pos,max_width=40):
        self.bar.pos = pos
        self.bar.size = max_width
        self.bar.value = self.count
        self.bar.max_value = self.count_to
        self.bar.is_visible = True

    def drop_at(self,pos):
        Item.drop_at(self,pos)
        self.bar.is_visible = False

    def take_by(self,owner):
        Item.take_by(self,owner)
        self.bar.is_visible = True

    def charge(self,amount=1):
        if self.is_chargable:
            return not self.inc(amount)

class LimitedUsesItem(Item):
    awesome_rank   = 1
    awesome_weight = 1.0

    def __init__(self,owner,item_power=1.0,item_colour=libtcod.orange,bar_colour=libtcod.red):
        self.bar = HBar(None, None, bar_colour, libtcod.dark_grey, True, False, str(self), str.ljust)
        self.bar.is_visible = False
        Item.__init__(self,owner,item_power,item_colour)
        uses = int(1 + 3*item_power)
        self.max_uses = uses
        self.uses = uses

    def draw_ui(self,pos,max_width=40):
        self.bar.pos = pos
        self.bar.size = max_width
        self.bar.value = self.uses
        self.bar.max_value = self.max_uses
        self.bar.is_visible = True

    def activate(self,activator=None):
        if self.uses == 0:
            return False

        self.uses -= 1
        return True

    def drop_at(self,pos):
        Item.drop_at(self,pos)
        self.bar.is_visible = False

    def take_by(self,owner):
        Item.take_by(self,owner)
        self.bar.is_visible = True

class HandTeleport(CoolDownItem):
    awesome_weight = 0.5

    def __str__(self):
        return "Hand Teleport"

    def activate(self,activator=None):
        if not CoolDownItem.activate(self):
            return False

        try:
            self.owner.move_to(self.owner.map.find_random_clear())
        except InvalidMoveError:
            print("Can't teleport from %s" % self.owner.pos)
            return False
        self.owner.reset_fov()
        return True

class Cloaker(CoolDownItem):
    awesome_weight = 1.2

    def __init__(self,owner,item_power=1.0):
        CoolDownItem.__init__(self,owner,item_power,libtcod.light_blue,libtcod.dark_blue)
        self.hidden_at = None

    def __str__(self):
        return "Cloaker"

    def activate(self,activator=None):
        if not CoolDownItem.activate(self):
            return False
        self.owner.is_visible = False
        self.hidden_at = self.owner.pos
        return True

    def take_turn(self):

        # only run cooldown whilst effect inactive
        if self.hidden_at is None:
            CoolDownItem.take_turn(self)

        # player moved; unhide them
        elif self.hidden_at != self.owner.pos:
            self.owner.is_visible = True
            self.hidden_at = None

class RemoteTimer(LimitedUsesItem):
    pass # TODO: same as R/C but counts down from activation

class RemoteControl(LimitedUsesItem):
    awesome_weight = 0.8

    def __init__(self,owner,item_power,item_colour=libtcod.orange,bar_colour=libtcod.red):
        # only a few uses permitted!
        self.connected_to = None
        LimitedUsesItem.__init__(self,owner,item_power*0.5,item_colour=item_colour,bar_colour=bar_colour)

    def __str__(self):
        if self.connected_to is None:
            return "Remote Control"
        else:
            return "R/C for %s" % self.connected_to

    def activate(self,activator=None):
        # sanity
        if self.owner is None or self.uses == 0:
            print("sanity failed")
            return False

        # set something to activate
        if self.connected_to is None:
            activatables = [a for a in self.owner.map.find_all_at_pos(self.owner.pos) if isinstance(a,Activatable) and a.can_be_remote_controlled]
            if len(activatables)>0:
                self.connected_to = activatables[0]
                self.bar.text = str(self)
                self.bar.show_numerator = False # because it doesn't fit
                return True
            return False

        # activate the thing
        else:
            t = self.connected_to.activate(self.owner)
            if t:
                self.connected_to = None
                self.bar.text = str(self)
                self.bar.show_numerator = True
                return LimitedUsesItem.activate(self,self.owner)
            return False

from tangling import Tanglable, Tangle
from monsters import Monster

class Tangler(LimitedUsesItem):
    awesome_weight = 1.5

    def __str__(self):
        return "Tangler"

    def activate(self,activator=None):
        # TODO: make this find the nearest untangled tanglable
        m = self.owner.map.find_nearest(self.owner,Tanglable,Monster)
        if isinstance(m, Tanglable) and not m.is_tangled() and LimitedUsesItem.activate(self):
            t = Tangle()
            t.add(m)
            return True

        return False

class TangleMine(LimitedUsesItem):
    awesome_weight = 1.2

    def __str__(self):
        return "Tangle Mine"

    def activate(self,activator=None):
        if LimitedUsesItem.activate(self):
            t = Tangle(self.owner.pos)
            t.tangle_counter = 10 # stays until something collides with it
            self.owner.map.add(t)
            return True

        return False

class MemoryWipe(LimitedUsesItem):
    awesome_weight = 0.8
    def __str__(self):
        return "Memory Wipe"

    def activate(self,activator=None):
        ms = self.owner.map.find_all_within_r(self.owner, Monster, 30, False)
        if len(ms)>0 and LimitedUsesItem.activate(self):
            for m in ms:
                m.reset_state()
            return True
        return False

from tiles import Tile, Door, Window
class DoorRelease(LimitedUsesItem):
    awesome_weight = 0.7

    def __str__(self):
        return "Door Release"

    def activate(self,activator=None):
        d = self.owner.map.find_nearest(self.owner,Door,Tile)
        if not d is None and LimitedUsesItem.activate(self):
            d.to_closing()
            return True
        return False

class EmergencyHammer(LimitedUsesItem):
    awesome_weight = 0.8

    def __str__(self):
        return "Emergency Hammer"

    def activate(self,activator=None):
        for w in self.owner.map.find_all_within_r(self.owner,Window,3):
            if not w.is_smashed and LimitedUsesItem.activate(self):
                w.smash()
                return True
        return False

class LevelMap(LimitedUsesItem):
    awesome_weight = 0.4
    def __init__(self,owner,item_power,item_colour=libtcod.orange,bar_colour=libtcod.red):
        # only a few uses permitted!
        LimitedUsesItem.__init__(self,owner,item_power*0.3,item_colour=item_colour,bar_colour=bar_colour)

    def __str__(self):
        return "Map"

    def activate(self,activator=None):
        if LimitedUsesItem.activate(self):
            for t in self.owner.map.find_all(Tile):
                t.has_been_seen = True
            return True
        return False

class Evidence(Item):
    awesome_rank = 0

    def __str__(self):
        return "Evidence"

    def __init__(self,pos):
        Item.__init__(self,pos,0.0,libtcod.yellow)

class TorchHelmet(RunDownItem):
    def __init__(self,owner,item_power=1.0):
        RunDownItem.__init__(self,owner,item_power*3.0,SlotItem.HEAD_SLOT)
        self.old_intensity = None
        self.old_radius    = None
        self.intensity     = 1.2
        self.radius        = 8

    def activate(self,activator=None):
        if not isinstance(self.owner,LightSource):
            return False

        if not RunDownItem.activate(self):
            return False

        if self.is_active:
            self.old_intensity   = self.owner.intensity
            self.old_radius      = self.owner.radius
            self.owner.intensity = self.intensity
            self.owner.radius    = self.radius

        else:
            self.owner.intensity = self.old_intensity
            self.owner.radius    = self.old_radius

        #self.owner.map.recalculate_lighting(statics=False)
        return True

    def __str__(self):
        return "Torch Helmet"

## implemented as a light source (overkill!!)
#class TorchHelmet(RunDownItem,LightSource):
#    def activate(self,activator=None):
#        if not RunDownItem.activate(self):
#            return False
#
#        if self.is_active:
#            if isinstance(self.owner,LightSource):
#                self.owner.light_enabled = False
#            self.light_enabled = True
#            self.pos = self.owner.pos
#            self.map = self.owner.map
#            self.is_visible = False
#            self.map.add(self)
#
#        else:
#            if isinstance(self.owner,LightSource):
#                self.owner.light_enabled = True
#            self.light_enabled = False
#            self.map.remove(self)
#            self.is_visible = True
#            self.pos = None
#            self.map = None
#
#        self.owner.map.recalculate_lighting(statics=False)
#        return True
#
#    def reset_map(self,pos=None):
#        self.move_to(self.owner.pos)
#        return LightSource.reset_map(self,pos)

class XRaySpecs(RunDownItem):
    def __init__(self,owner,item_power=1.0):
        RunDownItem.__init__(self,owner,item_power,SlotItem.HEAD_SLOT)

    def __str__(self):
        return "X-Ray Specs"

    def activate(self,activator=None):
        if not RunDownItem.activate(self):
            return False

        if self.is_active:
            self.owner.add_effect(StatusEffect.X_RAY_VISION)
            self.owner.reset_fov()

        else:
            self.owner.remove_effect(StatusEffect.X_RAY_VISION)
            self.owner.reset_fov()

        return True

class InfraSpecs(RunDownItem):
    def __init__(self,owner,item_power=1.0):
        RunDownItem.__init__(self,owner,item_power,SlotItem.HEAD_SLOT)

    def __str__(self):
        return "Infra Specs"

    def activate(self,activator=None):
        if not RunDownItem.activate(self):
            return False

        if self.is_active:
            self.owner.add_effect(StatusEffect.INFRAVISION)

        else:
            self.owner.remove_effect(StatusEffect.INFRAVISION)

        return True

class NightVisionGoggles(RunDownItem):
    def __init__(self,owner,item_power=1.0):
        RunDownItem.__init__(self,owner,item_power,SlotItem.HEAD_SLOT)

    def __str__(self):
        return "Night Vision Goggles"

    def activate(self,activator=None):
        if not RunDownItem.activate(self):
            return False

        if self.is_active:
            self.owner.add_effect(StatusEffect.NIGHT_VISION)

        else:
            self.owner.remove_effect(StatusEffect.NIGHT_VISION)

        return True

class AnalysisSpecs(RunDownItem):
    SYM_W_E   = '-'
    SYM_N_S   = '|'
    SYM_NW_SE = '\\'
    SYM_NE_SW = '/'

    def __init__(self,owner,item_power=1.0):
        RunDownItem.__init__(self,owner,item_power,SlotItem.HEAD_SLOT)
        self.messages = []

    def __str__(self):
        return "Analysis Specs"

    def activate(self,activator=None):
        if self.is_active: # i.e. about to be deactivated
            self.messages = []
        return RunDownItem.activate(self,activator)

    def take_turn(self):
        self.messages = []

        if not RunDownItem.take_turn(self):
            return False

        # show the heading of each monster as a line
        ms = self.owner.map.find_all(Monster,Monster)
        for m in ms:
            if m.last_pos is None or m.last_pos == m.pos or not self.owner.map._drawing_can_see(m.pos):
                continue # nothing to do here
            v = m.pos-m.last_pos

            # calculate symbol
            s = self.SYM_NE_SW
            if v.y == 0:
                s = self.SYM_W_E
            elif v.x == 0:
                s = self.SYM_N_S
            elif v.x == v.y:
                s = self.SYM_NW_SE

            g = Message(m.pos+v, s, colour=UI.COLCTRL_GREEN)
            g.is_visible = True
            g.timeout    = 5.0
            self.messages.append(g)

        return True

class RunningShoes(RunDownItem):
    def __init__(self,owner,item_power=1.0):
        RunDownItem.__init__(self,owner,item_power*0.5,SlotItem.FEET_SLOT)

    def __str__(self):
        return "Running Shoes"

    def activate(self,activator=None):
        if not RunDownItem.activate(self):
            return False

        if self.is_active:
            TurnTaker.add_turntaker(self.owner)

        else:
            TurnTaker.clear_turntaker(self.owner)

        return True

class PassiveItem(SlotItem):
    awesome_rank   = 3
    awesome_weight = 1.0

    def __init__(self,owner,item_power,valid_slot,item_colour=libtcod.cyan,bar_colour=libtcod.grey):
        self.bar = HBar(None, None, bar_colour, libtcod.dark_grey, False, False, str(self), str.ljust)
        self.bar.is_visible = False
        SlotItem.__init__(self,owner,item_power,valid_slot,item_colour)

    def draw_ui(self,pos,max_width=40):
        self.bar.pos = pos
        self.bar.size = max_width
        self.bar.is_visible = True

    def drop_at(self,pos):
        SlotItem.drop_at(self,pos)
        self.bar.is_visible = False

    def take_by(self,owner):
        SlotItem.take_by(self,owner)
        self.bar.is_visible = True

    def activate(self,activator=None):
        return False

class LabCoat(PassiveItem):
    def __init__(self,owner,item_power=1.0):
        PassiveItem.__init__(self,owner,0.0,SlotItem.BODY_SLOT)

    def __str__(self):
        return "Lab Coat"

class NinjaSuit(PassiveItem):
    def __init__(self,owner,item_power=1.0):
        PassiveItem.__init__(self,owner,0.0,SlotItem.BODY_SLOT)

    def __str__(self):
        return "Ninja Suit"

    def drop_at(self,pos):
        if isinstance(self.owner,StatusEffect):
            self.owner.remove_effect(StatusEffect.HIDDEN_IN_SHADOW)
        PassiveItem.drop_at(self,pos)

    def take_by(self,owner):
        PassiveItem.take_by(self,owner)
        if isinstance(owner,StatusEffect):
            owner.add_effect(StatusEffect.HIDDEN_IN_SHADOW)


file = open('file1.txt')
res = open('res1.txt', 'a')

def clear_file():
    try:
        res.truncate(0)
    except Exception as e:
        print(e)
        print(e.__doc__)
        exit(1)

def clear_line():
    try:
        res.write('\n')
    except Exception as e:
        print(e)
        print(e.__doc__)
        exit(1)

def z1():
    try:
        print('Вычесления для первой формулы: ')
        values_str = file.readline().split(' ')
        values = []
        for i in values_str:
            values.append(int(i))
        for i in values:
            a = i
            if (1 + a + a**2 == 0) or (2*a + a**2 == 0) or (1-a+a**2 == 0) or (2*a-a**2 == 0):
                print("Z1" + str(a) + ": " + 'ОДЗ!!!')
                res.write("Z1: " + str(a) + ": " + 'ОДЗ!!!' + '\n')
            else:
                z = (((1 + a + a ** 2) / (2*a + a**2)) + 2 - ((1-a+a**2)/(2*a-a**2))) * (5 - 2*a**2)
                print(str(a) + ": " + str(z))
                res.write("Z1: " + str(a) + ": " + str(z) + '\n')
    except Exception as e:
        print(e)
        print(e.__doc__)
        exit(1)

def z2():
    try:
        print('Выяисления для второй формулы: ')
        values_str = file.readline().split(' ')
        values = []
        for i in values_str:
            values.append(int(i))
        for i in values:
            a = i
            if 4 - a**2 == 0:
                print(str(a) + ": " + 'ОДЗ!!!')
                res.write("Z2: " + str(a) + ": " + 'ОДЗ!!!' + '\n')
            else:
                z = (4 - a**2) / 2
                print(str(a) + ": " + str(z))
                res.write("Z2: " + str(a) + ": " + str(z) + '\n')

        print('Выяисления для второй формулы завершены: ')
    except Exception as e:
        print(e)
        print(e.__doc__)
        exit(1)

try:
    clear_file()
    z1()
    clear_line()
    z2()
except Exception as e:
    print(e)
    print(e.__doc__)
    exit(1)


import asyncio

import DiscordUtils
from discord.ext import commands
from discord.ext.commands import Cog

import config
from db.src import db_strings
from modules.leaderboard_helper import gen_leaderboard_embed, MAIN_LEADERBOARD_LIM, LEADERBOARD_SIZE

LEADERBOARD_UPDATE_TIME = (60 * 60)  # 60 min, or 1 hour

class Leaderboard(Cog):
    def __init__(self, bot):
        self.bot = bot
        self.db = self.bot.db
        self.global_lb_mes = None  # the message that contains the global leaderboard

        self.bot.loop.create_task(self.leaderboard_update())

    async def leaderboard_update(self):
        await self.bot.wait_until_ready()
        await asyncio.sleep(5)  # Sometimes the bot won't actually be ready, so an extra 5 sec helps
        while not self.bot.is_closed():
            print("[LPBot] Updating global leaderboard...")

            db_settings = self.db.execute_query(db_strings.GET_SETTINGS, config.launchpoint_server_id)[0]
            db_curr_season = db_settings[4]
            db_leaderboard = db_settings[3]

            members = await self.bot.get_guild(config.launchpoint_server_id).fetch_members(limit=1000).flatten()
            member_ids = [user.id for user in members]

            leaderboard = self.db.execute_query_no_arg(db_strings.GET_LEADERBOARD)
            embed = gen_leaderboard_embed(leaderboard, 0, db_curr_season, False, member_ids)

            # embed is none iff there's no one on the leaderboard
            if embed is not None:
                # on first run or on reboot, get the db entry (also check if internal lb id ≠ db id at season change.
                if self.global_lb_mes is None or self.global_lb_mes.id is not db_leaderboard:
                    # if it doesn't exist, make a new one and safe that as the global leaderboard
                    if db_leaderboard is None or db_leaderboard is 0:
                        self.global_lb_mes = await self.bot.get_channel(config.launchpoint_leaderboard_id).send(
                                                                                embed=embed)
                        self.db.execute_commit_query(db_strings.UPDATE_LEADERBOARD, (self.global_lb_mes.id,
                                                                                config.launchpoint_server_id))
                    else:  # otherwise use the existing one as the leaderboard and exit
                        self.global_lb_mes = await self.bot.get_channel(config.launchpoint_leaderboard_id).\
                            fetch_message(db_leaderboard)
                        await self.global_lb_mes.edit(embed=embed)
                else:  # if we have the message update the leaderboard
                    await self.global_lb_mes.edit(embed=embed)
            await asyncio.sleep(LEADERBOARD_UPDATE_TIME)

    @commands.command(case_insensitive=True, aliases=["l", "rank", "ranks"])
    async def leaderboard(self, ctx):
        embeds = []
        leaderboard = self.db.execute_query_no_arg(db_strings.GET_LEADERBOARD)

        db_settings = self.db.execute_query(db_strings.GET_SETTINGS, config.launchpoint_server_id)[0]
        db_curr_season = db_settings[4]

        if len(leaderboard) == 0:
            overwrite_empty = False
        else:
            overwrite_empty = True

        members = await self.bot.get_guild(config.launchpoint_server_id).fetch_members(limit=1000).flatten()
        member_ids = [user.id for user in members]

        # Makes embeds for pagination, we want 5 10-player sized embeds sorta like the global leaderboard
        for i in range(0, LEADERBOARD_SIZE, MAIN_LEADERBOARD_LIM):

            embeds.append(gen_leaderboard_embed(leaderboard, i, db_curr_season, overwrite_empty, member_ids))

            if not overwrite_empty:
                break

        # Sets up pagination, thank you libraries
        paginator = DiscordUtils.Pagination.CustomEmbedPaginator(ctx=ctx, remove_reactions=True, auto_footer=True)
        paginator.add_reaction('⏮', "first")
        paginator.add_reaction('⏪', "back")
        paginator.add_reaction('🛑', "lock")
        paginator.add_reaction('⏩', "next")
        paginator.add_reaction('⏭', "last")
        await paginator.run(embeds)

def setup(bot):
    bot.add_cog(Leaderboard(bot))


import hashlib
import yaml

import url_utils
import config

def tokenize_string(string):
    tokens = []
    cur_token = ""

    for char in string:
        if char in config.settings["ALLOWED_AN_CHARS"]:
            cur_token += char
        else:
            if cur_token:
                tokens.append(cur_token)
                cur_token = ""
            else:
                pass
    if cur_token:
        tokens.append(cur_token)
    return tokens

def get_base_filename(url):
    tokens = url_utils.tokenize_url(url)
    md5 = hashlib.md5(url.encode("utf-8")).hexdigest()
    tokens.append(md5)
    base_filename = "-".join(tokens)
    return base_filename


''' A Dynamic Programming based Python
  Program for 0-1 Knapsack problem
  Returns the maximum value that can
  be put in a knapsack of capacity W '''

def knapSack(W, wt, val, n):
	K = [[0 for x in range(W + 1)] for x in range(n + 1)]

	# Build table K[][] in bottom up manner
	for i in range(n + 1):
		for w in range(W + 1):
			if i == 0 or w == 0:
				K[i][w] = 0
			elif wt[i-1] <= w:
				K[i][w] = max(val[i-1] + K[i-1][w-wt[i-1]], K[i-1][w])
			else:
				K[i][w] = K[i-1][w]

	selected = []
	w = W
	for i in range(n,0,-1):
		if K[i][w]!= K[i-1][w]:
			selected.insert(0,i-1)
			w -= wt[i-1]

	return selected

# Driver program to test above function
'''val = [4,4,2,2,2,4]
wt =  [2,2,1,1,1,2]
W = 7
n = len(val)
selected = knapSack(W, wt, val, n)
print(selected)'''

# This code is contributed by Bhavya Jain


import numpy as np
import matplotlib as mlp
mlp.use('TkAgg')
import matplotlib.pyplot as plt

x = np.arange(0, 6, 0.1)
y1 = np.sin(x)
y2 = np.cos(x)

# graph
plt.plot(x, y1, label="sin")
plt.plot(x, y2, linestyle="--", label="cos")
plt.xlabel("x")
plt.xlabel("y")
plt.title("sin & cos")
plt.legend()
plt.show()


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

from hanabi_learning_environment.agents.rainbow.run_experiment import ObservationStacker
from pathlib import Path

import time

from hanabi_learning_environment.agents.rainbow.third_party.dopamine import checkpointer
from hanabi_learning_environment.agents.rainbow.third_party.dopamine import iteration_statistics
#import dqn_agent
import gin.tf
from hanabi_learning_environment import rl_env
import numpy as np
from hanabi_learning_environment.agents.rainbow import rainbow_agent
from hanabi_learning_environment.agents.rainbow import dqn_agent
import tensorflow as tf

from hanabi_live_bot.hanabi_client import HanabiClient
from hanabi_live_bot.constants import ACTION, MAX_CLUE_NUM, MAX_TOKENS
from hanabi_live_bot.connection import establishConnection
from hanabi_learning_environment.agents.rainbow.run_experiment import format_legal_moves
LENIENT_SCORE = False

# to get the environment file for agent login

def load_gin_configs(gin_files, gin_bindings):
    """Loads gin configuration files.

    Args:
      gin_files: A list of paths to the gin configuration files for this
        experiment.
      gin_bindings: List of gin parameter bindings to override the values in the
        config files.
    """
    gin.parse_config_files_and_bindings(gin_files,
                                        bindings=gin_bindings,
                                        skip_unknown=False)

class HanabiLiveRainbowAgent(HanabiClient):
    def __init__(self, agent, environment, obs_stacker, url, cookie):
        HanabiClient.__init__(self, url, cookie)
        self.agent = agent
        self.environment = environment
        self.obs_stacker = obs_stacker
        self.obs_stacker.reset_stack()
        self.max_pile = {1: 3, 2: 2, 3: 2, 4: 2, 5: 1}
        self.actionEncoding = {'play': 0, 'discard': 1, 'strike': 0, 'clue': 2}

    def GetMoveUid(self, table_id, move_type, card_index, suit, rank):
        target_offset = 1
        state = self.games[table_id]
        if move_type == 1:
            return card_index
        elif move_type == 0:
            return len(state.hands[state.our_index]) + card_index
        elif move_type == 2:
            return 5 + 5 + (target_offset - 1) * 5 + suit
        elif move_type == 3:
            return 5+5 + 5 + (target_offset - 1) * 5 + rank
        else:
            return -1

    # def run_one_episode(self, agent, environment, obs_stacker):
    def extractCurrentObservationAndLegalActions(self, table_id):
        # build directly vectorized form of observation from game state
        state = self.games[table_id]
        vectorizedObs = [0]*658
        currOffset = 0
        # encode hands
        numColors = 5
        numRanks = 5
        bits_per_card = numColors * numRanks
        # build card vector, only one opponent, pick values of other player
        handOfOtherPlayer = state.hands[(state.our_index+1) % 2]
        for item in handOfOtherPlayer:
            # we do not know if the handOfOtherPlayer has the cards in order
            #
            offsetCard = self.findCardIndex(
                handOfOtherPlayer, item['order'])*bits_per_card
            if offsetCard < 0:
                print('error: unable to find card with order ' + str(order) + ' in'
                      'the hand of player ' + str(seat))
                return None
            offsetSuit = item['suit']
            # 0: Red, 1:Yellow ,2: Green, 3: Blue, 4: Purple
            offsetRank = item['rank']-1
            vectorizedObs[offsetCard+offsetSuit*5+offsetRank] = 1
        # since hands can have less than 5 cards, leave 0s by moving offset
        currOffset += 5*bits_per_card
        # bit that tells if hand is full or not (1 = not full)
        vectorizedObs[currOffset] = 0 if len(
            state.hands[state.our_index]) == 5 else 1
        vectorizedObs[currOffset +
                      1] = 0 if len(state.hands[(state.our_index+1) % 2]) == 5 else 1
        currOffset += 2
        print(currOffset)
        # encode board
        # fill remaining deck size as thermometer (as many 1's as cards)
        vectorizedObs[currOffset:currOffset +
                      state.num_cards_deck] = [1]*state.num_cards_deck
        currOffset += 40 # for two players, general: (max_deck_size - hand_size * num_players)
        # fill fireworks (cards placed correctly), fireworks = play_stacks
        for i in range(numColors):
            # fireworks[color] is the number of successfully played <color> cards.
            # If some were played, one-hot encode the highest (0-indexed) rank played
            if len(state.play_stacks[i]) > 0:
                vectorizedObs[currOffset +
                              len(state.play_stacks[i])] = 1
            currOffset += numRanks # num_ranks
        # fill information tokens aka clues 8 in thermometer style
        vectorizedObs[currOffset:currOffset +
                      state.clue_tokens] = [1]*state.clue_tokens
        currOffset += MAX_CLUE_NUM  # max num of clue tokens
        # fill in remaining life tokens
        vectorizedObs[currOffset:currOffset +
                      state.life_tokens] = [1]*state.life_tokens
        currOffset += MAX_TOKENS # maxliftokens
        print(currOffset)
        # encode discard stack
        # for each color
        # // 3 cards of lowest rank (1), 1 card of highest rank (5), 2 of all else. So each color would be
        #  ordered like so:
        #  LLL      H
        #   1100011101
        # enconding means: two low ones are on the pile, the highest, one 4 and both 3
        for suit in range(5):
            for rank in range(1, 6):
                vectorizedObs[currOffset:currOffset+len(state.discard_pile[suit][rank])] = [
                    1] * len(state.discard_pile[suit][rank])
                currOffset += self.max_pile[rank]
        print(currOffset)
        # for action encoding enum Type { kPlay, kDiscard, kRevealColor, kRevealRank };
        # set index of player that played last action
        index_last_player = 0
        if state.turn > 0:
            if (state.last_action['who'] != state.our_index):
                index_last_player = 1
            vectorizedObs[currOffset+index_last_player] = 1
        currOffset += 2
        # encode action
        actionCode = -1
        if state.turn > 0:
            actionCode = self.actionEncoding[state.last_action['type']]
            if (actionCode == 2):  # clue action needs further refinement
                actionCode += state.last_action['clue']['type']
            vectorizedObs[currOffset+actionCode] = 1
        currOffset += 4
        # reveal action, encode target player in that case (one-hot)
        if actionCode >= 2:
            if state.last_action['target'] == state.our_index:
                vectorizedObs[currOffset] = 1
            else:
                vectorizedObs[currOffset+1] = 1
        currOffset += 2
        # in case of color clue, encode color
        if actionCode == 2:
            vectorizedObs[currOffset+state.last_action['clue']['value']] = 1
        currOffset += numColors
        # in case of rank clue, encode rank
        if actionCode == 3:
            # ranks are encoded 1-5  --> -1 to get index
            vectorizedObs[currOffset+state.last_action['clue']['value']-1] = 1
        currOffset += numRanks
        # encode reveal outcome, which cards on the hand were hinted
        if actionCode >= 2:
            listTargetClue = state.last_action['list']
            hand = state.hands[state.last_action['target']]
            for clueTarget in listTargetClue:
                card_index = super().findCardIndex(hand, clueTarget)
                if card_index != -1:
                    vectorizedObs[currOffset+card_index] = 1
                else:
                    print('error: unable to find card with order ' + str(order) + ' in'
                          'the hand of player ' + str(seat))
        currOffset += 5
        # encode played/discarded card in case action was play/discard
        card = None
        if actionCode == 0 or actionCode == 1:
            card_index = -1
            if state.last_action['type'] != 'play':
                # find card on discard pile
                searchForOrder = -1
                if actionCode == 0:
                    searchForOrder = state.last_action['order']
                else:
                    searchForOrder = state.last_action['which']['order']
                for suit in state.discard_pile:
                    for rank in suit:
                        for listItem in suit[rank]:
                            if listItem['order'] == searchForOrder:
                                card = listItem
                                break
                    # cardOrder = state.last_action['which']['order']
                    # handSeat = state.last_action['which']['index']
                card_index = card['hand_index']
            else:
                # find card on play_stacks pile
                cardOrder = state.last_action['which']['order']
                for stacks in state.play_stacks:
                    for cards in stacks:
                        if cards['order'] == cardOrder:
                            card_index = cards['hand_index']
                        if card_index != -1:
                            break
            if card_index != -1:
                vectorizedObs[currOffset+card_index] = 1
            else:
                print('error: unable to find card with order line 537')
        currOffset += 5
        # encode card
        if (actionCode == 0 or actionCode == 1) and card is not None:
            offsetSuit = card['suit']
            offsetRank = card['rank']-1
            assert offsetRank > 0, "Offset should not be negative"
            vectorizedObs[currOffset+offsetSuit*5+offsetRank] = 1
        currOffset += bits_per_card
        if actionCode == 0 and state.last_action['type'] != 'strike':
            vectorizedObs[currOffset] = 1
        if actionCode == 1:
            vectorizedObs[currOffset+1] = 1
        currOffset += 2
        print(currOffset)
        # encode clue knowledge
        listHandsOurOrder = [state.hands[state.our_index],
                             state.hands[(state.our_index+1) % 2]]
        for handI in range(len(listHandsOurOrder)):
            hand = listHandsOurOrder[handI]
            for i in range(len(hand)):
                vectorizedObs[currOffset:currOffset +
                              len(hand[i]['knowledge'])] = hand[i]['knowledge']
                currOffset += len(hand[i]['knowledge'])
                vectorizedObs[currOffset:currOffset +
                              len(hand[i]['clue'][0])] = hand[i]['clue'][0]
                currOffset += len(hand[i]['clue'][0])
                vectorizedObs[currOffset:currOffset +
                              len(hand[i]['clue'][1])] = hand[i]['clue'][1]
                currOffset += len(hand[i]['clue'][1])
        print("Offset: ",currOffset)
        self.obs_stacker.add_observation(vectorizedObs, 0)
        observation_vector = self.obs_stacker.get_observation_stack(0)
        legal_moves, legal_move_list_integer = self.computeLegalMoves(state)
        return observation_vector, legal_moves, legal_move_list_integer

    def computeLegalMoves(self, state):
        # MaxDiscardMoves() + MaxPlayMoves() + MaxRevealColorMoves() + MaxRevealRankMoves();
        num_actions = 5 + 5 + 5 + 5
        maxDiscard = 5
        maxPlay = 5
        maxReveal = 5
        numColors = 5
        numRanks = 5

        legal_move_list = []
        # play moves
        for i in range(5):
            legal_move_list.append({
                'action_type': ACTION.PLAY,
                'card_index': i
            })
        if state.clue_tokens is not MAX_CLUE_NUM:
            # discard moves
            for i in range(5):
                legal_move_list.append({
                    'action_type': ACTION.DISCARD,
                    'card_index': i
                })
            # clue moves
        handPartner = state.hands[(state.our_index+1) % 2]
        listColors = []
        listRanks = []
        for card in handPartner:
            listColors.append(card['suit'])
            listRanks.append(card['rank'])
        setColor = set(listColors)
        setRanks = set(listRanks)
        if state.clue_tokens > 0:
            for suit in setColor:
                legal_move_list.append({'action_type': ACTION.COLOR_CLUE,
                                        'value': suit,
                                        'target_offset': 1})
            for rank in setRanks:
                legal_move_list.append({'action_type': ACTION.RANK_CLUE,
                                        'value': rank,
                                        'target_offset': 1})
        # format to integers
        legal_move_list_integer = []
        legal_move_dict = {}
        for item in legal_move_list:
            move_uid = -1
            if item['action_type']==ACTION.DISCARD: #HanabiMove::kDiscard:
                move_uid = item['card_index'] # return card_index;
            if item['action_type']==ACTION.PLAY:
                move_uid = (maxDiscard + item['card_index']) #return MaxDiscardMoves() + card_index;
            if item['action_type']== ACTION.COLOR_CLUE:  #case HanabiMove::kRevealColor:
                move_uid = (maxDiscard + maxPlay + \
                    (item['target_offset']-1)*numColors+item['value']) # return MaxDiscardMoves() + MaxPlayMoves() +
                    #(target_offset - 1) * NumColors() + color;
            if item['action_type']== ACTION.RANK_CLUE: #case HanabiMove::kRevealRank:
                move_uid = (maxDiscard + maxPlay + maxReveal + \
                    (item['target_offset']-1)*numRanks+item['value']-1) #return MaxDiscardMoves() + MaxPlayMoves() + MaxRevealColorMoves() +
                    # (target_offset - 1) * NumRanks() + rank;
            legal_move_list_integer.append(move_uid)
            legal_move_dict[move_uid] = item
        # format to something else used by the agent
        legal_moves = format_legal_moves(legal_move_list_integer, num_actions)
        return legal_moves, legal_move_dict

    def actionToMessage(self, action, table_id):
        state = self.games[table_id]
        message_dict = {
            'tableID': table_id,
            'type': action['action_type']
        }
        if action['action_type'] == ACTION.PLAY or action['action_type'] == ACTION.DISCARD:
            myHand = state.hands[state.our_index]
            message_dict['target'] = myHand[action['card_index']]['order']
            print(myHand[action['card_index']])
        else:
            message_dict['target'] = (action['target_offset']+state.our_index) % 2
            message_dict['value'] = action['value']
        return message_dict

    def decide_action(self, table_id):
        observation, legal_actions, legal_move_dict = self.extractCurrentObservationAndLegalActions(table_id)
        action = self.agent._select_action(observation, legal_actions)
        print(legal_actions, legal_move_dict)
        print(legal_move_dict[action])
        #super().decide_action(table_id)
        # action = agent._select_action(observation, legal_actions)
        print(self.actionToMessage(legal_move_dict[action], table_id))
        super().send('action', self.actionToMessage(legal_move_dict[action], table_id))

@gin.configurable
def start_experiment(agent,
                     environment,
                     start_iteration,
                     obs_stacker,
                     experiment_logger,
                     experiment_checkpointer,
                     checkpoint_dir,
                     num_iterations=200,
                     training_steps=5000,
                     logging_file_prefix='log',
                     log_every_n=10,
                     checkpoint_every_n=1):
    """Runs the agent that can connect to Hanabi-Live and play one game."""
    tf.logging.info('Beginning playing...')
    # statistics defined in run_one_iteration
    env_path = Path('.') / '.env'
    url, cookie = establishConnection(env_path)
    HanabiLiveRainbowAgent(agent, environment, obs_stacker, url, cookie).start_server()
    # for iteration in range(start_iteration, num_iterations):
    #   start_time = time.time()
    #   statistics = run_one_iteration(agent, environment, obs_stacker, iteration,
    #                                  training_steps)
    #   tf.logging.info('Iteration %d took %d seconds', iteration,
    #                   time.time() - start_time)
    #   start_time = time.time()
    #   log_experiment(experiment_logger, iteration, statistics,
    #                  logging_file_prefix, log_every_n)
    #   tf.logging.info('Logging iteration %d took %d seconds', iteration,
    #                   time.time() - start_time)
    #   start_time = time.time()
    #   checkpoint_experiment(experiment_checkpointer, agent, experiment_logger,
    #                         iteration, checkpoint_dir, checkpoint_every_n)
    #   tf.logging.info('Checkpointing iteration %d took %d seconds', iteration,
    #                   time.time() - start_time)


# -*- coding: utf-8 -*-
# @Time    : 2019/8/21 9:00
# @Author  : Youpeng Li
# @Site    :
# @File    : 0179_largestNumber.py
# @Software: PyCharm

'''
179. Largest Number

Given a list of non negative integers, arrange them such that they form the largest number.

Example 1:
Input: [10,2]
Output: "210"

Example 2:
Input: [3,30,34,5,9]
Output: "9534330"
Note: The result may be very large, so you need to return a string instead of an integer.
'''

import functools

class Solution(object):
    def largestNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: str
        """
        if not nums or len(nums) <= 0:
            return ""
        nums = list(map(str, nums))
        # 在python3.x中已经没有cmp函数，要是用operator函数进行比较，cmp函数就是比较输入两个字符串之间大小的数字
        # cmp(x,y) 函数用于比较2个对象，如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1。
        # 是两两对象之间的比较，排序默认是从小到大，在这个函数内部实现的两两排序
        def cmp(x, y):
            if x + y < y + x:
                return -1
            if x + y > y + x:
                return 1
            return 0

        nums.sort(key=functools.cmp_to_key(cmp), reverse=True)
        res = ''.join(nums).lstrip('0')
        return res or '0'

if __name__  == "__main__":
    a = Solution()
    nums = [10, 2]
    print(a.largestNumber(nums))
    nums = [3, 30, 34, 5, 9]
    print(a.largestNumber(nums))


from django.shortcuts import render, redirect, render_to_response
from django.views.generic import TemplateView, View
from django.http import HttpResponse, HttpResponseRedirect
from django.views.generic.edit import UpdateView
from .forms import EventForm
from .models import Event
from django.contrib.auth.models import User
from django.template import RequestContext
from django.core.urlresolvers import reverse_lazy
# Create your views here.
def update_event(request, event_id):
    event = Event.objects.get(id=event_id)
    print(event)
    event_form = EventForm(instance=event, initial={'title': event.title})
    if request.method == 'POST':
        event_form.save()
        return redirect('/ngo/profile/')
    return render(request, 'update_event.html', {'event_form': event_form,
                                                 'event': event})

class UpdateEvent(UpdateView):
    template_name = 'update_event.html'
    form_class = EventForm
    model = Event

def ngopro(request):
    events_fil = Event.objects.filter(user=request.user)
    template_name = 'ngopro.html'
    return render(request, template_name, {'events_fil': events_fil})

def event_del(request, event_id):
    try:
        event = Event.objects.filter(id=int(event_id))
        event.delete()
    except Exception as e:
        print(e)
        return redirect('ngo/profile')
    return HttpResponseRedirect('/ngo/profile')

"""class add_event(View):
    form_class = EventForm
    template_name = 'add_event.html'

    def get(self, request):
        form = self.form_class(None)

        return render(request, self.template_name, {'form': form})

    def post(self, request):
        form = self.form_class(request.POST, request.FILES)
        image = request.FILES.get('image')

        if form.is_valid():
            title = form.cleaned_data['title']
            place = form.cleaned_data['place']
            description = form.cleaned_data['description']
            contact = form.cleaned_data['contact']
            user_id = request.user
            event = Event(user=user_id, image=image, title=title, description=description, place=place, contact=contact)
            event.save()

            return HttpResponse('your event has been saved')

        return render(request, self.template_name, {'form': form})"""

def add_event(request):
    if request.method == 'GET':
        form = EventForm()
        return render(request, 'add_event.html', {'form': form})
    else:
        title = request.POST['title']
        place = request.POST['place']
        description = request.POST['description']
        contact = request.POST['contact']
        image = request.POST['image']

        event = Event()
        event.user = request.user
        event.image = image
        event.title = title
        event.place = place
        event.description = description
        event.contact = contact

        event.save()
        return HttpResponse('your event has been saved Click here')

def event_full(request, event_id):
    template_name = 'event_full.html'
    event = Event.objects.get(id=int(event_id))
    list_users = event.users.split('&')
    list_users = list_users[:-1]
    regd_users = User.objects.filter(id__in=list_users)
    return render(request, template_name, {'regd_users': regd_users,
                                           'event': event})


from fastapi import APIRouter, HTTPException, Depends
from typing import List

from src.api import codes
from src.api.errors import APIValidationError
from src.auth.middleware import user_id_authorization
from src.api.errors import error_response
from src.organization.service import get_organization_by_id
from src.service.model import Service, UserService
from src.service.schema import CreateServiceRequest
from src.service.service import get_service_by_id, get_services_by_organization_id, \
    create_service, create_user_service
from src.user.service import get_user_by_id, get_user_by_id_and_organization

r = APIRouter()

@r.get("", response_model=List[Service])
def get_services(organization_id: str):
    services = get_services_by_organization_id(organization_id)
    return services

@r.get("/{id}", response_model=Service)
def get_service_by_id(id: str):
    service = get_service_by_id(id)
    if service is None:
        raise HTTPException(status_code=404, detail=error_response(
            code=codes.SERVICE_NOT_FOUND,
            message="Service not found",
        ))
    return service

@r.post("", response_model=Service)
def create_service(req: CreateServiceRequest, user_id: str = Depends(user_id_authorization)):
    # Get user
    user = get_user_by_id(user_id)
    if user is None:
        raise HTTPException(status_code=401, detail=error_response(
            code=codes.EXPIRED_TOKEN,
            message="Token expired",
        ))
    # User has to be an admin
    if user.role != "admin":
        raise HTTPException(status_code=403, detail=error_response(
            code=codes.FORBIDDEN,
            message="Forbidden",
        ))
    # Get user's organization
    if user.organization_id == "":
        raise HTTPException(status_code=400, detail=error_response(
            code=codes.USER_HAS_NO_ORGANIZATION,
            message="User has no organization",
        ))
    organization = get_organization_by_id(user.organization_id)
    if organization is None:
        raise HTTPException(status_code=404, detail=error_response(
            code=codes.ORGANIZATION_NOT_FOUND,
            message="Organization not found",
        ))
    # Validations
    try:
        req.check()
    except APIValidationError as e:
        raise HTTPException(status_code=400, detail=error_response(
            code=e.code,
            message=e.message,
            detail=e.detail,
        ))
    # Check if all appointees are in the organization
    for appointee_id in req.appointees:
        u = get_user_by_id_and_organization(appointee_id, user.organization_id)
        if u is None:
            raise HTTPException(status_code=400, detail=error_response(
                code=codes.SERVICE_APPOINTEE_NOT_FOUND,
                message="Appointee not found",
                detail=f"Appointee {appointee_id} is not in organization",
            ))
    # Create service
    service = Service(
        organization_id=user.organization_id,
        title=req.title,
        description=req.description,
        category=req.category,
        timezone=req.timezone,
        start_time=req.start_time,
        end_time=req.end_time,
        duration=req.duration,
        gap=req.gap,
        break_time=req.break_time,
        break_duration=req.break_duration,
        break_days=",".join(str(day.value) for day in req.break_days),
        price=req.price,
        slot_per_session=req.slot_per_session,
    )
    create_service(service)

    # Create user services
    for appointee_id in req.appointees:
        user_service = UserService(
            user_id=appointee_id,
            service_id=service.id,
        )
        create_user_service(user_service)
    return service


"""
https://leetcode.com/problems/spiral-matrix-iii/
"""

class Solution:
    def spiralMatrixIII(
            self,
            rows: int,
            cols: int,
            rStart: int,
            cStart: int) -> list[list[int]]:
        """
        1. The walk steps follows 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, ..., so
            in order to generate such sequence, we use a counter to stand for
            the index of this sequence and we could find that when index is
            odd, we increase the curret walk steps by 1.
        2. The spiral walks towards four directions from east, south, west,
            north. When any time we step onto a valid cell on the grid, we
            add it to the final results.
        """
        DIRECTIONS = [(0, 1), (1, 0), (0, -1), (-1, 0)]
        rslt = [(rStart, cStart)]
        cnt, walkSteps, toward = 0, 1, 0
        r, c = rStart, cStart
        while len(rslt) < rows * cols:
            dr, dc = DIRECTIONS[toward]
            for _ in range(1, walkSteps + 1):
                r += dr
                c += dc
                if 0 <= r < rows and 0 <= c < cols:
                    rslt.append((r, c))

            if cnt & 1:
                walkSteps += 1

            cnt += 1
            toward = (toward + 1) % 4

        return rslt