"""
Created on Wed Sep  1 16:07:35 2021

@author: John Waldo (jw922)
@author: Adam Wolfson (amw337)

HW0

Assumptions:
    Assuming that the iris data and names are in the current
    directory. If not, please update the main function with
    the proper path.

"""

from matplotlib import pyplot as plt
import math

def getFeaturePairs(data, feature1, feature2):
    '''
    Pulls the two features of interest.

    Parameters
    ----------
    Data : Matrix
        Matrix of data.
    feature1 : Int
        Index of first feature
    feature2: Int
        Index of second feature

    Returns
    -------
    firstFeatures : All datapoints of first feature
    secondFeatures : All datapoints of second feature
    '''

    firstFeatures = data[feature1]
    secondFeatures = data[feature2]

    return [firstFeatures, secondFeatures]

def getPlotDimensions(featureCount):
    '''
    Get optimal dimensions of subplots

    Parameters
    ----------
    featureCount : Int
        The total number of features.

    Returns
    -------
    plotRows : The optimal number of rows
    plotCols : The optimal number of cols

    '''

    totalPlots = (featureCount - 1)*featureCount/2

    rootSize = math.sqrt(totalPlots)

    lowerBound = math.floor(rootSize)
    upperBound = math.ceil(rootSize)

    if lowerBound*upperBound >= totalPlots:
        plotRows = lowerBound
        plotCols = upperBound
    else:
        plotRows = upperBound
        plotCols = upperBound

    return [plotRows, plotCols]

class IrisPlotter(object):
    """
    Class that handles visualization of iris data
    """

    def __init__(self, datasource, namesource):

        self.datasource = datasource
        self.namesource = namesource

    def main(self):
        '''
        Main function for this class.
        Manages pulling, parsing, and plotting the data
        '''

        irisData = self.pullData(self.datasource)

        # irisNames = pullNames(self.namesource)
        # HARD CODED NAMES:
        irisNames = ['sepal length', 'sepal width', 'petal length', 'petal width']

        self.plotPairwiseData(irisData, irisNames)

    def pullData(self,source):
        '''
        Load the raw data from the given path
        as a dictionary ordered by Iris type

        Parameters
        ----------
        source : String
            Path to data file

        Returns
        -------
        irisData : Dictionary
            Dictionary with iris type as key.
            Values are the feature data for
            instances of the given type.
        '''

        irisData = {}

        for line in open(source):
            details = line[:-2].split(",")
            if len(details) > 1:
                flower = details[-1]
                data = details[:-1]

                if flower not in irisData:
                    irisData[flower] = []

                    for d in range(len(data)):
                        irisData[flower].append([])

                for d in range(len(data)):
                    irisData[flower][d].append(float(data[d]))

        return irisData

    def plotPairwiseData(self, data, featNames):

        '''
        Plots the feature data in pairs.

        Parameters
        ----------
        data : Dictionary
            Dictionary with iris type as key.
            Values are the feature data for instances of the given type.

        featNames : List
            List of feature names

        Returns
        -------
        None

        '''

        flowers = list(data.keys())

        totalFeatures = len(data[flowers[0]])

        [rows, cols] = getPlotDimensions(totalFeatures)

        fig, axes = plt.subplots(rows, cols)

        for feat in range(len(flowers)):
            flower = flowers[feat]

            plotNumber = [0,0]

            for f1 in range(totalFeatures):
                for f2 in range(f1):
                    [firstFeatures, secondFeatures] = getFeaturePairs(data[flower], f1, f2)

                    axes[plotNumber[0],plotNumber[1]].scatter(firstFeatures,
                                                              secondFeatures,
                                                              label = flower)

                    axes[plotNumber[0],plotNumber[1]].set_xlabel(featNames[f1])
                    axes[plotNumber[0],plotNumber[1]].set_ylabel(featNames[f2])

                    plotNumber[1] += 1

                    if plotNumber[1] >= cols:
                        plotNumber[0] += 1
                        plotNumber[1] = 0

        fig.suptitle("Iris Data")
        fig.tight_layout()
        plt.legend(bbox_to_anchor=(0, -0.35, 1, 0), mode="expand", borderaxespad=0)

        plt.show()

if __name__ == "__main__":
    source = './iris.data'
    names = './iris.names'
    irisObj = IrisPlotter(source, names)
    irisObj.main()


"""Wrapper for Torch Dataset class to enable contrastive training
"""
import torch
from torch import Tensor
from torch.utils.data import Dataset
from torchaudio_augmentations import Compose
from typing import Tuple, List

class ContrastiveDataset(Dataset):
    def __init__(self, dataset: Dataset, input_shape: List[int], transform: Compose):
        self.dataset = dataset
        self.transform = transform
        self.input_shape = input_shape
        self.ignore_idx = []

    def __getitem__(self, idx) -> Tuple[Tensor, Tensor]:
        if idx in self.ignore_idx:
            return self[idx + 1]

        audio, label = self.dataset[idx]

        if audio.shape[1] < self.input_shape[1]:
            self.ignore_idx.append(idx)
            return self[idx + 1]

        if self.transform:
            audio = self.transform(audio)
        return audio, label

    def __len__(self) -> int:
        return len(self.dataset)

    def concat_clip(self, n: int, audio_length: float) -> Tensor:
        audio, _ = self.dataset[n]
        batch = torch.split(audio, audio_length, dim=1)
        batch = torch.cat(batch[:-1])
        batch = batch.unsqueeze(dim=1)

        if self.transform:
            batch = self.transform(batch)

        return batch


# -*- coding: utf-8 -*-
"""
# @Time    : 2018/12/3 下午7:53
# @Author  : zhanzecheng
# @File    : dataset.py
# @Software: PyCharm
"""
from src import nn_utils

class cached_property(object):
    """ A property that is only computed once per instance and then replaces
        itself with an ordinary attribute. Deleting the attribute resets the
        property.

        Source: https://github.com/bottlepy/bottle/commit/fa7733e075da0d790d809aa3d2f53071897e6f76
        """

    def __init__(self, func):
        self.__doc__ = getattr(func, '__doc__')
        self.func = func

    def __get__(self, obj, cls):
        if obj is None:
            return self
        value = obj.__dict__[self.func.__name__] = self.func(obj)
        return value

class Example:

    def __init__(self, confidence, label, decoder_pob, one_hot_type):
        self.confidence = confidence
        self.label = label
        self.src_sent = len(confidence)
        self.decoder_pob = decoder_pob
        self.one_hot_type = one_hot_type

class Batch:
    def __init__(self, examples, cuda=False):
        self.examples = examples
        self.cuda = cuda

        self.confidence = [e.confidence for e in self.examples]
        self.decoder_pob = [e.decoder_pob for e in self.examples]
        self.one_hot_type = [e.one_hot_type for e in self.examples]
        self.src_sents_len = [len(e.confidence) for e in self.examples]
        self.label = [e.label for e in examples]

    def __len__(self):
        return len(self.examples)

    @cached_property
    def src_sents_var(self):
        return nn_utils.to_input_variable(self.confidence,
                                          cuda=self.cuda)

    @cached_property
    def decoder_pob_car(self):
        return nn_utils.to_input_variable(self.decoder_pob,
                                          cuda=self.cuda)

    @cached_property
    def src_token_mask(self):
        return nn_utils.length_array_to_mask_tensor(self.src_sents_len,
                                             cuda=self.cuda)


# -*- coding: utf-8 -*-
# @Time    : 18/7/27 上午10:40
# @Author  : Edward
# @Site    :
# @File    : tfidf.py
# @Software: PyCharm Community Edition

from collections import Counter

import jieba
from gensim.models import TfidfModel
from gensim.corpora.dictionary import Dictionary

class TfIdf(object):
    '''
    该类适用于文本关键词抽取或同性质特征抽取任务
    该类使用TfIdf模型抽取关键词

    >>> sentences = ['a b c d', 'a b c e', 'a c c e', 'b a e d']

    >>> tfidf = TfIdf(sentences, cutter=lambda x: x.split(' '))
    >>> ret = tfidf.get_sentence_key_words('c e f g')
    >>> ret
    [('c', 0.7071067811865476), ('e', 0.7071067811865476)]
    >>> ret = tfidf.get_key_words()
    >>> ret
    [('b', 3), ('c', 3), ('e', 3)]
    '''

    def __init__(self, sentences, stop_words=set(), cutter=jieba.cut):
        '''
        初始化TfIdf特征抽取器

        :param sentences: 文本列表
        :param stop_words: 停用词表，需要为list/set/tuple
        :param cutter: 分词方式，默认为使用jieba分词处理中文，如果要处理英文或者其他分词方式，只要丢入一个分词函数就OK
        '''
        self.stop_words = set(stop_words)
        self.cutter = cutter
        self.common_texts = [
            [word for word in cutter(sentence) if word not in self.stop_words]
            for sentence in set(sentences)
            if isinstance(sentence, str)
        ]
        self.common_dictionary = Dictionary(self.common_texts)
        self.common_corpus = [self.common_dictionary.doc2bow(text) for text in self.common_texts]

        self.tfidf = TfidfModel(self.common_corpus)
        self.vectors = [
            self.tfidf[self.common_corpus[index]]
            for index in range(len(self.common_corpus))
            if self.tfidf[self.common_corpus[index]
            ]
        ]

    def get_key_words(self, top_n=10, top_word=1):
        '''
        获取初始化文本中的关键词
        计算方式是通过获取每个句子中，tfidf值最高的top_word个词。然后统计出现次数获得的
        :param top_n: 返回前top_n个关键词
        :param top_word: 每个句子的前top_word个词
        :return: 返回列表，每一项分别为(词, 词频)
        '''
        top_word_index = [
            sorted(vector, key=lambda x: -x[1])[:top_word]
            for vector in self.vectors
        ]

        # 转化为关键词并统计出现次数
        key_words_index = []
        for line in top_word_index:
            key_words_index += [item[0] for item in line]

        key_words_index = Counter(key_words_index).items()
        key_words = [(self.common_dictionary[item[0]], item[1]) for item in key_words_index]

        return sorted(key_words, key=lambda x: (-x[1], x[0]))[:top_n]

    def get_sentence_key_words(self, sentence, top_n=3):
        '''
        获取句子关键词
        :param sentence: 待抽取的文本
        :param top_n: 抽取top_n个关键词
        :return: 返回一个列表，每一项分别为(词, 词权重)
        '''
        ret = self.transform(sentence, False)
        return sorted(ret, key=lambda x: (-x[1], x[0]))[:top_n]

    def transform(self, sentence, return_word=True):
        '''
        获取句子每个词的权重
        :param sentence: 待获取文本
        :param return_word: 返回的词权重是否使用词。True则返回词，False则返回index
        :return: 返回一个列表，每一项分别为(词, 词权重)
        '''
        words_list = list(self.cutter(sentence))
        common_corpus = self.common_dictionary.doc2bow(words_list)
        words_tfidf_value = self.tfidf[common_corpus]
        return [(self.common_dictionary[item[0]], item[1]) for item in words_tfidf_value] \
            if return_word else words_tfidf_value

if __name__ == '__main__':
    import doctest
    doctest.testmod()


from Solution import Solution, ListNode
import sys
import os

def createLL(values):
    head = ListNode(values[0])
    prev = head
    for i in range(1, len(values)):
        prev.next = ListNode(values[i])
        prev = prev.next
    return head

def convertLL(node):
    res = []
    while node:
        res.append(node.val)
        node = node.next
    return res

def displayErrorMessage(testCase, head, values):
    print("Result: Failed for test case: " + testCase)
    print("Actual Output: ", convertLL(head))
    print("Expected Output: ", values)

file = open(os.path.join(sys.path[0], '../testcases.txt'), 'r')
lines = file.readlines()

isSolutionWrong = False
lineNumber = 1
solution = Solution()
for line in lines[1:]:
    line = line.strip()
    if lineNumber % 2 == 1:
        testCase = line
        values = list(map(int, [s.strip() for s in line[1:-1].split(',')]))
        ll = createLL(values)
        solution.reorderList(ll)
    else:
        values = list(map(int, [s.strip() for s in line[1:-1].split(',')]))
        head = ll
        for value in values:
            if not ll or ll.val != value:
                displayErrorMessage(testCase, head, values)
                isSolutionWrong = True
                break
            ll = ll.next
        if ll:
            displayErrorMessage(testCase, head, values)
            isSolutionWrong = True
            break
    lineNumber += 1

if not isSolutionWrong:
    print("Result: Success")


from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render

from store.models import Product, Variation

from .models import Cart, CartItem

# Create your views here.
def _cart_id(request):
    cart = request.session.session_key
    if not cart:
        cart = request.session.create()
    return cart

def _get_cart_item(request, product_id, cart_item_id):
    product = get_object_or_404(Product, id=product_id)
    if request.user.is_authenticated:
        return CartItem.objects.get(product=product, user=request.user, id=cart_item_id)
    else:
        cart = Cart.objects.get(cart_id=_cart_id(request=request))
        return CartItem.objects.get(product=product, cart=cart, id=cart_item_id)

def add_cart(request, product_id):
    current_user = request.user
    product = Product.objects.get(id=product_id)  # get the product
    product_variations = []
    if request.method == "POST":
        for param in request.POST:
            key = param
            value = request.POST[key]
            try:
                variation = Variation.objects.get(
                    product=product,
                    variation_category__iexact=key,
                    variation_value__iexact=value,
                )
                product_variations.append(variation)
            except:
                pass

    if current_user.is_authenticated:
        cart = None
        cart_items = CartItem.objects.filter(product=product, user=current_user)
    else:
        try:
            cart = Cart.objects.get(
                cart_id=_cart_id(request=request)
            )  # get the cart using the cart_id presents in the session
        except Cart.DoesNotExist:
            cart = Cart.objects.create(cart_id=_cart_id(request=request))
        cart.save()
        cart_items = CartItem.objects.filter(product=product, cart=cart)

    cart_item = None
    for single_cart_item in cart_items:
        if product_variations == list(single_cart_item.variations.all()):
            # increase the cart item quantity
            single_cart_item.quantity += 1
            single_cart_item.save()
            cart_item = single_cart_item
            break

    # if nothing existing found - create a new item
    if cart_item is None:
        if current_user.is_authenticated:
            cart_item = CartItem.objects.create(
                product=product, quantity=1, user=current_user
            )
        else:
            cart_item = CartItem.objects.create(product=product, quantity=1, cart=cart)

    if len(product_variations) > 0:
        cart_item.variations.add(*product_variations)

    cart_item.save()
    return redirect("cart")

def remove_cart(request, product_id, cart_item_id):
    cart_item = _get_cart_item(
        request=request, product_id=product_id, cart_item_id=cart_item_id
    )
    if cart_item.quantity > 1:
        cart_item.quantity -= 1
        cart_item.save()
    else:
        cart_item.delete()
    return redirect("cart")

def remove_cart_item(request, product_id, cart_item_id):
    cart_item = _get_cart_item(
        request=request, product_id=product_id, cart_item_id=cart_item_id
    )
    cart_item.delete()
    return redirect("cart")

def cart(request, total=0, quantity=0, cart_items=None):
    try:
        if request.user.is_authenticated:
            cart_items = CartItem.objects.filter(user=request.user, is_active=True)
        else:
            cart = Cart.objects.get(cart_id=_cart_id(request=request))
            cart_items = CartItem.objects.filter(cart=cart, is_active=True)
        for cart_item in cart_items:
            total += cart_item.product.price * cart_item.quantity
            quantity += cart_item.quantity
        tax = (2 * total) / 100
        grand_total = total + tax
    except ObjectDoesNotExist:
        grand_total = 0
        tax = 0
    context = {
        "total": total,
        "quantity": quantity,
        "tax": tax,
        "grand_total": grand_total,
        "cart_items": cart_items,
    }
    return render(request=request, template_name="store/cart.html", context=context)

@login_required(login_url="login")
def checkout(request, total=0, quantity=0, cart_items=None):
    try:
        if request.user.is_authenticated:
            cart_items = CartItem.objects.filter(user=request.user, is_active=True)
        else:
            cart = Cart.objects.get(cart_id=_cart_id(request=request))
            cart_items = CartItem.objects.filter(cart=cart, is_active=True)

        for cart_item in cart_items:
            total += cart_item.product.price * cart_item.quantity
            quantity += cart_item.quantity
        tax = (2 * total) / 100
        grand_total = total + tax
    except ObjectDoesNotExist:
        grand_total = 0
        tax = 0
    context = {
        "total": total,
        "quantity": quantity,
        "tax": tax,
        "grand_total": grand_total,
        "cart_items": cart_items,
    }
    return render(request, "store/checkout.html", context)


import pygame

pygame.init()
WIDTH = 1000
HEIGHT = 900
screen = pygame.display.set_mode([WIDTH, HEIGHT])
pygame.display.set_caption('Chess')
font = pygame.font.Font('freesansbold.ttf', 20)
medium_font = pygame.font.Font('freesansbold.ttf', 40)
big_font = pygame.font.Font('freesansbold.ttf', 50)
timer = pygame.time.Clock()
FPS = 60

white_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook',
                'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn']
white_locations = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0),
                   (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)]
black_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook',
                'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn']
black_locations = [(0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7),
                   (0, 6), (1, 6), (2, 6), (3, 6), (4, 6), (5, 6), (6, 6), (7, 6)]
captured_pieces_white = []
captured_pieces_black = []
# 0 - ход белых, фигура не выбрана; 1 - ход белых, фигура выбрана;
# 2 - ход чёрных, фигура не выбрана; 3 - ход чёрных, фигура не выбрана
turn_step = 0
# 100 - никакая фигура не выбрана, для каждой фигуры своё число
selection = 100
valid_moves = []
# загрузка картиночек
black_queen = pygame.image.load('assets/images/black queen.svg')
black_queen = pygame.transform.scale(black_queen, (80, 80))
black_queen_small = pygame.transform.scale(black_queen, (45, 45))
black_king = pygame.image.load('assets/images/black king.svg')
black_king = pygame.transform.scale(black_king, (80, 80))
black_king_small = pygame.transform.scale(black_king, (45, 45))
black_rook = pygame.image.load('assets/images/black rook.svg')
black_rook = pygame.transform.scale(black_rook, (80, 80))
black_rook_small = pygame.transform.scale(black_rook, (45, 45))
black_bishop = pygame.image.load('assets/images/black bishop.svg')
black_bishop = pygame.transform.scale(black_bishop, (80, 80))
black_bishop_small = pygame.transform.scale(black_bishop, (45, 45))
black_knight = pygame.image.load('assets/images/black knight.svg')
black_knight = pygame.transform.scale(black_knight, (80, 80))
black_knight_small = pygame.transform.scale(black_knight, (45, 45))
black_pawn = pygame.image.load('assets/images/black pawn.svg')
black_pawn = pygame.transform.scale(black_pawn, (80, 80))
black_pawn_small = pygame.transform.scale(black_pawn, (45, 45))
white_queen = pygame.image.load('assets/images/white queen.svg')
white_queen = pygame.transform.scale(white_queen, (80, 80))
white_queen_small = pygame.transform.scale(white_queen, (45, 45))
white_king = pygame.image.load('assets/images/white king.svg')
white_king = pygame.transform.scale(white_king, (80, 80))
white_king_small = pygame.transform.scale(white_king, (45, 45))
white_rook = pygame.image.load('assets/images/white rook.svg')
white_rook = pygame.transform.scale(white_rook, (80, 80))
white_rook_small = pygame.transform.scale(white_rook, (45, 45))
white_bishop = pygame.image.load('assets/images/white bishop.svg')
white_bishop = pygame.transform.scale(white_bishop, (80, 80))
white_bishop_small = pygame.transform.scale(white_bishop, (45, 45))
white_knight = pygame.image.load('assets/images/white knight.svg')
white_knight = pygame.transform.scale(white_knight, (80, 80))
white_knight_small = pygame.transform.scale(white_knight, (45, 45))
white_pawn = pygame.image.load('assets/images/white pawn.svg')
white_pawn = pygame.transform.scale(white_pawn, (80, 80))
white_pawn_small = pygame.transform.scale(white_pawn, (45, 45))
white_images = [white_pawn, white_queen, white_king, white_knight, white_rook, white_bishop]
small_white_images = [white_pawn_small, white_queen_small, white_king_small, white_knight_small,
                      white_rook_small, white_bishop_small]
black_images = [black_pawn, black_queen, black_king, black_knight, black_rook, black_bishop]
small_black_images = [black_pawn_small, black_queen_small, black_king_small, black_knight_small,
                      black_rook_small, black_bishop_small]
piece_list = ['pawn', 'queen', 'king', 'knight', 'rook', 'bishop']

counter = 0
winner = ''
game_over = False
white_castling_short = True
white_castling_long = True
black_castling_short = True
black_castling_long = True
white_promotion = False
black_promotion = False

# рисует доску
def draw_board():
    for i in range(32):
        column = i % 4
        row = i // 4
        if row % 2 == 0:
            pygame.draw.rect(screen, 'light gray', [600 - (column * 200), row * 100, 100, 100])
        else:
            pygame.draw.rect(screen, 'light gray', [700 - (column * 200), row * 100, 100, 100])
        pygame.draw.rect(screen, 'gray', [0, 800, WIDTH, 100])
        pygame.draw.rect(screen, 'gold', [0, 800, WIDTH, 100], 5)
        pygame.draw.rect(screen, 'gold', [800, 0, 200, HEIGHT], 5)
        status_text = ['White: Select a Piece to Move!', 'White: Select a Destination!',
                       'Black: Select a Piece to Move!', 'Black: Select a Destination!']
        screen.blit(big_font.render(status_text[turn_step], True, 'black'), (20, 820))
        for j in range(9):
            pygame.draw.line(screen, 'black', (0, 100 * j), (800, 100 * j), 2)
            pygame.draw.line(screen, 'black', (100 * j, 0), (100 * j, 800), 2)
        screen.blit(medium_font.render('RESIGN', True, 'black'), (820, 830))

# рисует фигуры на доске
def draw_pieces():
    for i in range(len(white_pieces)):
        index = piece_list.index(white_pieces[i])
        screen.blit(white_images[index], (white_locations[i][0] * 100 + 10, white_locations[i][1] * 100 + 10))
        if turn_step < 2:
            if selection == i:
                pygame.draw.rect(screen, 'red', [white_locations[i][0] * 100 + 1, white_locations[i][1] * 100 + 1,
                                                 100, 100], 2)
    for i in range(len(black_pieces)):
        index = piece_list.index(black_pieces[i])
        screen.blit(black_images[index], (black_locations[i][0] * 100 + 10, black_locations[i][1] * 100 + 10))
        if turn_step >= 2:
            if selection == i:
                pygame.draw.rect(screen, 'blue', [black_locations[i][0] * 100 + 1, black_locations[i][1] * 100 + 1,
                                                 100, 100], 2)

# возвращает список с возможными ходами для каждой фигуры
def check_options(pieces, locations, turn):
    moves_list = []
    all_moves_list = []
    for i in range(len(pieces)):
        location = locations[i]
        piece = pieces[i]
        if piece == 'pawn':
            moves_list = check_pawn(location, turn)
        elif piece == 'rook':
            moves_list = check_rook(location, turn)
        elif piece == 'knight':
            moves_list = check_knight(location, turn)
        elif piece == 'bishop':
            moves_list = check_bishop(location, turn)
        elif piece == 'queen':
            moves_list = check_queen(location, turn)
        elif piece == 'king':
            moves_list = check_king(location, turn)
        all_moves_list.append(moves_list)
    return all_moves_list

# проверяет возможные ходы короля
def check_king(position, color):
    moves_list = []
    if color == 'white':
        friends_list = white_locations
    else:
        friends_list = black_locations
    targets = [(1, 0), (1, 1), (1, -1), (-1, 0), (-1, 1), (-1, -1), (0, 1), (0, -1)]
    for i in range(8):
        target = (position[0] + targets[i][0], position[1] + targets[i][1])
        if target not in friends_list and 0 <= target[0] <= 7 and 0 <= target[1] <= 7:
            moves_list.append(target)
    return moves_list

# проверяет возможные ходы ферзя
def check_queen(position, color):
    moves_list = check_bishop(position, color)
    second_list = check_rook(position, color)
    for i in range(len(second_list)):
        moves_list.append(second_list[i])
    return moves_list

# проверяет возможные ходы слона
def check_bishop(position, color):
    moves_list = []
    if color == 'white':
        enemies_list = black_locations
        friends_list = white_locations
    else:
        enemies_list = white_locations
        friends_list = black_locations
    for i in range(4):
        path = True
        chain = 1
        if i == 0:
            x = 1
            y = -1
        elif i == 1:
            x = -1
            y = -1
        elif i == 2:
            x = 1
            y = 1
        else:
            x = -1
            y = 1
        while path:
            if (position[0] + (chain * x), position[1] + (chain * y)) not in friends_list and \
                    0 <= position[0] + (chain * x) <= 7 and 0 <= position[1] + (chain * y) <= 7:
                moves_list.append((position[0] + (chain * x), position[1] + (chain * y)))
                if (position[0] + (chain * x), position[1] + (chain * y)) in enemies_list:
                    path = False
                chain += 1
            else:
                path = False
    return moves_list

# проверяет возможные ходы ладьи
def check_rook(position, color):
    moves_list = []
    if color == 'white':
        enemies_list = black_locations
        friends_list = white_locations
    else:
        enemies_list = white_locations
        friends_list = black_locations
    for i in range(4):
        path = True
        chain = 1
        if i == 0:
            x = 0
            y = 1
        elif i == 1:
            x = 0
            y = -1
        elif i == 2:
            x = 1
            y = 0
        else:
            x = -1
            y = 0
        while path:
            if (position[0] + (chain * x), position[1] + (chain * y)) not in friends_list and \
                    0 <= position[0] + (chain * x) <= 7 and 0 <= position[1] + (chain * y) <= 7:
                moves_list.append((position[0] + (chain * x), position[1] + (chain * y)))
                if (position[0] + (chain * x), position[1] + (chain * y)) in enemies_list:
                    path = False
                chain += 1
            else:
                path = False
    return moves_list

# проверяет возможные ходы коня
def check_knight(position, color):
    moves_list = []
    if color == 'white':
        friends_list = white_locations
    else:
        friends_list = black_locations
    targets = [(1, 2), (1, -2), (2, 1), (2, -1), (-1, 2), (-1, -2), (-2, 1), (-2, -1)]
    for i in range(8):
        target = (position[0] + targets[i][0], position[1] + targets[i][1])
        if target not in friends_list and 0 <= target[0] <= 7 and 0 <= target[1] <= 7:
            moves_list.append(target)
    return moves_list

# проверяет возможные ходы пешки
def check_pawn(position, color):
    moves_list = []
    if color == 'white':
        # ход на 1 клетку
        if (position[0], position[1] + 1) not in white_locations and \
                (position[0], position[1] + 1) not in black_locations and position[1] < 7:
            moves_list.append((position[0], position[1] + 1))
        # ход на 2 клетки
        if (position[0], position[1] + 2) not in white_locations and \
                (position[0], position[1] + 1) not in white_locations and \
                (position[0], position[1] + 2) not in black_locations and \
                (position[0], position[1] + 1) not in black_locations and position[1] == 1:
            moves_list.append((position[0], position[1] + 2))
        # взятие
        if (position[0] + 1, position[1] + 1) in black_locations:
            moves_list.append((position[0] + 1, position[1] + 1))
        if (position[0] - 1, position[1] + 1) in black_locations:
            moves_list.append((position[0] - 1, position[1] + 1))
    else:
        # ход на 1 клетку
        if (position[0], position[1] - 1) not in white_locations and \
                (position[0], position[1] - 1) not in black_locations and position[1] > 0:
            moves_list.append((position[0], position[1] - 1))
        # ход на 2 клетки
        if (position[0], position[1] - 2) not in white_locations and \
                (position[0], position[1] - 1) not in white_locations and \
                (position[0], position[1] - 1) not in black_locations and \
                (position[0], position[1] - 2) not in black_locations and position[1] == 6:
            moves_list.append((position[0], position[1] - 2))
        # взятие
        if (position[0] + 1, position[1] - 1) in white_locations:
            moves_list.append((position[0] + 1, position[1] - 1))
        if (position[0] - 1, position[1] - 1) in white_locations:
            moves_list.append((position[0] - 1, position[1] - 1))
    return moves_list

# проверяет вохможные ходы для выбранной фигуры
def check_valid_moves():
    if turn_step < 2:
        options_list = white_options
    else:
        options_list = black_options
    valid_options = options_list[selection]
    return valid_options

# рисует возможные ходы на доске
def draw_valid(moves):
    if turn_step < 2:
        color = 'red'
    else:
        color = 'blue'
    for i in range(len(moves)):
        pygame.draw.circle(screen, color, (moves[i][0] * 100 + 50, moves[i][1] * 100 + 50), 5)

# рисует съеденные фигуры с краю
def draw_captured():
    for i in range(len(captured_pieces_white)):
        captured_piece = captured_pieces_white[i]
        index = piece_list.index(captured_piece)
        screen.blit(small_black_images[index], (825, 5 + 50 * i))
    for i in range(len(captured_pieces_black)):
        captured_piece = captured_pieces_black[i]
        index = piece_list.index(captured_piece)
        screen.blit(small_white_images[index], (925, 5 + 50 * i))

# рисует окошко конца игры
def draw_game_over():
    pygame.draw.rect(screen, 'black', [200, 350, 400, 70])
    screen.blit(font.render(f'{winner} won the game!', True, 'white'), (302, 360))
    screen.blit(font.render('press ENTER to restart!', True, 'white'), (290, 390))

# рисует мигающую обводку вокруг короля, когда тот под шахом
def draw_check():
    if turn_step < 2:
        if 'king' in white_pieces:
            king_index = white_pieces.index('king')
            king_location = white_locations[king_index]
            for i in range(len(black_options)):
                if king_location in black_options[i]:
                    if counter < 15:
                        pygame.draw.rect(screen, 'dark red', [white_locations[king_index][0] * 100 + 1,
                                                              white_locations[king_index][1] * 100 + 1, 100, 100], 5)
    else:
        if 'king' in black_pieces:
            king_index = black_pieces.index('king')
            king_location = black_locations[king_index]
            for i in range(len(white_options)):
                if king_location in white_options[i]:
                    if counter < 15:
                        pygame.draw.rect(screen, 'dark blue', [black_locations[king_index][0] * 100 + 1,
                                                               black_locations[king_index][1] * 100 + 1, 100, 100], 5)

# проверяет возможные варианты для рокировки
def check_castling():
    castling_options = []
    white_options_1d = []
    black_options_1d = []
    all_locations = white_locations + black_locations
    for i in range(len(white_pieces)):
        for j in white_options[i]:
            white_options_1d.append(j)
    for i in range(len(black_pieces)):
        for j in black_options[i]:
            black_options_1d.append(j)

    if white_castling_short and (1, 0) not in black_options_1d and \
            (2, 0) not in black_options_1d and (3, 0) not in black_options_1d and \
            (1, 0) not in all_locations and (2, 0) not in all_locations:
        castling_options.append((1, 0))
    if white_castling_long and (5, 0) not in black_options_1d and \
            (4, 0) not in black_options_1d and (3, 0) not in black_options_1d and \
            (4, 0) not in all_locations and (5, 0) not in all_locations and (6, 0) not in all_locations:
        castling_options.append((5, 0))
    if black_castling_short and (1, 7) not in white_options_1d and \
            (2, 7) not in white_options_1d and (3, 7) not in white_options_1d and \
            (1, 7) not in all_locations and (2, 7) not in all_locations:
        castling_options.append((1, 7))
    if black_castling_long and (5, 7) not in white_options_1d and \
            (4, 7) not in white_options_1d and (3, 7) not in white_options_1d and \
            (4, 7) not in all_locations and (5, 7) not in all_locations and (6, 7) not in all_locations:
        castling_options.append((5, 7))
    return castling_options

black_options = check_options(black_pieces, black_locations, 'black')
white_options = check_options(white_pieces, white_locations, 'white')
run = True
while run:
    timer.tick(FPS)
    # штучка для мигания клетки
    if counter < 30:
        counter += 1
    else:
        counter = 0
    screen.fill('dark gray')
    draw_board()
    draw_pieces()
    draw_captured()
    draw_check()
    castling_squares = check_castling()
    # проверка на потерю прав для рокировки
    if (3, 0) in white_locations and (0, 0) in white_locations:
        if white_pieces[white_locations.index((3, 0))] != 'king' or white_pieces[white_locations.index((0, 0))] != 'rook':
            white_castling_short = False
    else:
        white_castling_short = False
    if (3, 0) in white_locations and (7, 0) in white_locations:
        if white_pieces[white_locations.index((3, 0))] != 'king' or white_pieces[white_locations.index((7, 0))] != 'rook':
            white_castling_long = False
    else:
        white_castling_long = False
    if (3, 7) in black_locations and (0, 7) in black_locations:
        if black_pieces[black_locations.index((3, 7))] != 'king' or black_pieces[black_locations.index((0, 7))] != 'rook':
            black_castling_short = False
    else:
        black_castling_short = False
    if (3, 7) in black_locations and (7, 7) in black_locations:
        if black_pieces[black_locations.index((3, 7))] != 'king' or black_pieces[black_locations.index((7, 7))] != 'rook':
            black_castling_long = False
    else:
        black_castling_long = False
    if selection != 100:
        valid_moves = check_valid_moves()
        draw_valid(valid_moves)
    # вывод окошка выбора фигуры при проведении пешки
    if white_promotion:
        pygame.draw.rect(screen, 'black', [200, 350, 400, 50])
        screen.blit(white_queen_small, (230, 350))
        screen.blit(white_rook_small, (330, 350))
        screen.blit(white_knight_small, (430, 350))
        screen.blit(white_bishop_small, (530, 350))
    if black_promotion:
        pygame.draw.rect(screen, 'black', [200, 350, 400, 50])
        screen.blit(black_queen_small, (230, 350))
        screen.blit(black_rook_small, (330, 350))
        screen.blit(black_knight_small, (430, 350))
        screen.blit(black_bishop_small, (530, 350))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1 and not game_over:
            x_coord = event.pos[0] // 100
            y_coord = event.pos[1] // 100
            click_coords = (x_coord, y_coord)
            # выбор фигуры для превращения пешки
            if white_promotion:
                if click_coords == (2, 3):
                    white_pieces[promoted_pawn] = "queen"
                elif click_coords == (3, 3):
                    white_pieces[promoted_pawn] = "rook"
                elif click_coords == (4, 3):
                    white_pieces[promoted_pawn] = "knight"
                elif click_coords == (5, 3):
                    white_pieces[promoted_pawn] = "bishop"
                white_promotion = False
                black_options = check_options(black_pieces, black_locations, 'black')
                white_options = check_options(white_pieces, white_locations, 'white')
                turn_step = 2
                selection = 100
                valid_moves = []
                break
            if black_promotion:
                if click_coords == (2, 3):
                    black_pieces[promoted_pawn] = "queen"
                elif click_coords == (3, 3):
                    black_pieces[promoted_pawn] = "rook"
                elif click_coords == (4, 3):
                    black_pieces[promoted_pawn] = "knight"
                elif click_coords == (5, 3):
                    black_pieces[promoted_pawn] = "bishop"
                black_promotion = False
                black_options = check_options(black_pieces, black_locations, 'black')
                white_options = check_options(white_pieces, white_locations, 'white')
                turn_step = 0
                selection = 100
                valid_moves = []
                break
            if turn_step <= 1:
                # проверка на нажатие кнопки "сдаться"
                if click_coords == (8, 8) or click_coords == (9, 8):
                    winner = 'black'
                if click_coords in white_locations:
                    selection = white_locations.index(click_coords)
                    if turn_step == 0:
                        turn_step = 1
                if turn_step == 1:
                    # рокировка
                    if click_coords in castling_squares and white_pieces[selection] == 'king':
                        if click_coords == (1, 0):
                            white_locations[selection] = click_coords
                            white_locations[0] = (2, 0)
                        elif click_coords == (5, 0):
                            white_locations[selection] = click_coords
                            index = white_locations.index((7, 0))
                            white_locations[index] = (4, 0)
                        black_options = check_options(black_pieces, black_locations, 'black')
                        white_options = check_options(white_pieces, white_locations, 'white')
                        turn_step = 2
                        selection = 100
                        valid_moves = []
                if click_coords in valid_moves and selection != 100:
                    white_locations[selection] = click_coords
                    # достижение пешкой последней линии
                    if click_coords[1] == 7 and white_pieces[selection] == 'pawn':
                        white_promotion = True
                        promoted_pawn = selection
                        if click_coords in black_locations:
                            black_piece = black_locations.index(click_coords)
                            captured_pieces_white.append(black_pieces[black_piece])
                            if black_pieces[black_piece] == 'king':
                                winner = 'white'
                            black_pieces.pop(black_piece)
                            black_locations.pop(black_piece)
                        break
                    # взятие вражеской фигуры
                    if click_coords in black_locations:
                        black_piece = black_locations.index(click_coords)
                        captured_pieces_white.append(black_pieces[black_piece])
                        if black_pieces[black_piece] == 'king':
                            winner = 'white'
                        black_pieces.pop(black_piece)
                        black_locations.pop(black_piece)
                    black_options = check_options(black_pieces, black_locations, 'black')
                    white_options = check_options(white_pieces, white_locations, 'white')
                    turn_step = 2
                    selection = 100
                    valid_moves = []

            elif turn_step > 1:
                # роверка на нажатие кнопки "сдаться"
                if click_coords == (8, 8) or click_coords == (9, 8):
                    winner = 'white'
                if click_coords in black_locations:
                    selection = black_locations.index(click_coords)
                    if turn_step == 2:
                        turn_step = 3
                if turn_step == 3:
                    # рокировка
                    if click_coords in castling_squares and black_pieces[selection] == 'king':
                        if click_coords == (1, 7):
                            black_locations[selection] = click_coords
                            black_locations[0] = (2, 7)
                        elif click_coords == (5, 7):
                            black_locations[selection] = click_coords
                            index = black_locations.index((7, 7))
                            black_locations[index] = (4, 7)
                        black_options = check_options(black_pieces, black_locations, 'black')
                        white_options = check_options(white_pieces, white_locations, 'white')
                        turn_step = 0
                        selection = 100
                        valid_moves = []
                if click_coords in valid_moves and selection != 100:
                    black_locations[selection] = click_coords
                    # достижение пешкой последней линии
                    if click_coords[1] == 0 and black_pieces[selection] == 'pawn':
                        black_promotion = True
                        promoted_pawn = selection
                        if click_coords in white_locations:
                            white_piece = white_locations.index(click_coords)
                            captured_pieces_black.append(white_pieces[white_piece])
                            if white_pieces[white_piece] == 'king':
                                winner = 'black'
                            white_pieces.pop(white_piece)
                            white_locations.pop(white_piece)
                        break
                    # взятие вражеской фигуры
                    if click_coords in white_locations:
                        white_piece = white_locations.index(click_coords)
                        captured_pieces_black.append(white_pieces[white_piece])
                        if white_pieces[white_piece] == 'king':
                            winner = 'black'
                        white_pieces.pop(white_piece)
                        white_locations.pop(white_piece)
                    black_options = check_options(black_pieces, black_locations, 'black')
                    white_options = check_options(white_pieces, white_locations, 'white')
                    turn_step = 0
                    selection = 100
                    valid_moves = []
        # перезапуск игры
        if event.type == pygame.KEYDOWN and game_over:
            if event.key == pygame.K_RETURN:
                game_over = False
                winner = ''
                white_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook',
                                'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn']
                white_locations = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0),
                                   (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)]
                black_pieces = ['rook', 'knight', 'bishop', 'king', 'queen', 'bishop', 'knight', 'rook',
                                'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn', 'pawn']
                black_locations = [(0, 7), (1, 7), (2, 7), (3, 7), (4, 7), (5, 7), (6, 7), (7, 7),
                                   (0, 6), (1, 6), (2, 6), (3, 6), (4, 6), (5, 6), (6, 6), (7, 6)]
                captured_pieces_white = []
                captured_pieces_black = []
                turn_step = 0
                selection = 100
                valid_moves = []
                black_options = check_options(black_pieces, black_locations, 'black')
                white_options = check_options(white_pieces, white_locations, 'white')
                white_castling_short = True
                white_castling_long = True
                black_castling_short = True
                black_castling_long = True
                white_promotion = False
                black_promotion = False
    if winner != '':
        game_over = True
        draw_game_over()
    pygame.display.flip()
pygame.quit()


from collections import defaultdict
import sys
from queue import Empty, PriorityQueue

class Graph:
    def __init__(self):
        self.G = defaultdict(list)

    def __str__(self):
        text = "Graph: %d vertices\n" % (len(self.G))
        for node in self.G.keys():
           text += "[node: %s] -> %s\n" % (node,self.G[node])

        return text

    def addEdge(self,u,v,d):
        self.G[u].append((v,d))

    def shortestPath (self,u):
        dist = [sys.maxsize] * (len(self.G) + 1)
        dist[u] = 0
        pq = []
        import heapq
        heapq.heappush(pq,(0,u))
        prev = {}

        while pq:
            u = heapq.heappop(pq)[1]
            for vd in self.G[u]:
                v = vd[0]
                d = vd[1]

                du = dist[u]
                if dist[v] > du + d:
                    dist[v] = du+d
                    heapq.heappush(pq,(dist[v],v))
                    prev[v] = u

        #self.printSolution(dist)
        return dist,prev

    def printSolution(self,dist):

        for node in self.G.keys():
            print (node,"   :   ",dist[node])

"""
      [1]  -1- [3]
   1 /             \1
[0]                 [5]
   2 \             /2
      [2]  -2-  [4]

"""
g = Graph()
g.addEdge(0,1,1)
g.addEdge(0,2,2)
#g.addEdge(0,5,1)
g.addEdge(2,4,2)
g.addEdge(1,3,1)
g.addEdge(3,5,1)
g.addEdge(4,5,2)

print (g)
d,p = g.shortestPath(0)
print (d)
g.printSolution(d)

target = 5
print ("Caminho para o node %d: " % (target))

def printPath(p,target):
    if target in p:
        printPath(p,p[target])
    else:
        return

    print (p[target],end="-> ")

printPath(p,target)


# -*- coding: utf-8 -*-
"""
Created on Fri Aug 13 17:05:15 2021

@author: liuhaolin
"""

import os,time
import requests
import re
from selenium import webdriver
from selenium.common.exceptions import UnexpectedAlertPresentException
from selenium.webdriver import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains  #鼠标动作
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
import selenium.common.exceptions  #支持浏览器插件
import pandas as pd
from datetime import date,datetime, timedelta
import random
from tqdm import tqdm

#浏览器相关
def driver_options():
    global driver
    global wait
    # 设置get直接返回，不再等待界面加载完成
    desired_capabilities = DesiredCapabilities.CHROME
    desired_capabilities["pageLoadStrategy"] = "none"
    options = webdriver.ChromeOptions()

    # 附带本地插件
    # extension_path = r'D:\Reports\Tools\SellerSprite2.7.0_0.crx'
    # options.add_extension(extension_path)

    # 启用本地带插件的浏览器 chrome://version/  个人资料路径
    options.add_argument("--user-data-dir="+r"D:/Program Files/GoogleCache/Chrome/UserData/")
    # options.add_argument("--user-data-dir="+r"C:/Users/liuhaolin/AppData/Local/Google/Chrome/User Data/")

    # 无窗口模式
    # options.add_argument('--headless')

    # 禁止硬件加速，避免严重占用cpu
    options.add_argument('--disable-gpu')
    # 关闭安全策略
    options.add_argument("disable-web-security")
    # 禁止图片加载
    # options.add_experimental_option('prefs', {'profile.managed_default_content_settings.images': 2})
    # 隐藏Chrome正在受到自动软件的控制
    options.add_argument('disable-infobars')
    # 设置开发者模式启动，该模式下webdriver属性为正常值
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    #指定浏览器分辨率
    options.add_argument('window-size=1920x1080')

    # 模拟移动设备
    # options.add_argument('user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"')

    #需要指定Google驱动的文件位置,chromedriver_Home     下载地址：http://npm.taobao.org/mirrors/chromedriver/
    driver = webdriver.Chrome(chrome_options=options,executable_path="D:/Reports/Tools/chromedriver")
    # 返回驱动等待的变量
    # wait = WebDriverWait(driver, 15)
    driver.maximize_window()

if __name__ == '__main__':

    # SITE = 'https://www.sif.com/search'
    # SITE = 'https://app.isellerpal.com/data/asinreverse'
    SITE = 'https://members.helium10.com/cerebro?'

    #ASIN列表Excel地址以及一次多少条
    path = r"C:\Users\liuhaolin\Desktop\666.xlsx"
    LoadBunch = 10

    driver_options()

    Now_Time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

    i = 0

    df = pd.read_excel(path, sheet_name = 0)
    #ASIN列转列表
    AsinList = df['ASIN'].values.tolist()[:200]
    StepByLoadBunch = [AsinList[i:i+LoadBunch] for i in range(0,len(AsinList),LoadBunch)]

    for y,x in enumerate(tqdm(StepByLoadBunch)):

        time.sleep(random.randint(5,10))

        Try_Count = 0
        while Try_Count <=3:
            try:
                driver.get(SITE)

                #打乱下ASIN顺序以免某些狗掉的ASIN导致无法搜索
                random.shuffle(x)

                ASINs = " ".join(x) + ' '

                # #SIF版本
                # time.sleep(random.randint(5,10))
                # AsinSearch = driver.find_element_by_xpath('//*[@placeholder="输入ASIN，多个请使用逗号分隔"]')
                # AsinSearch.clear()
                # AsinSearch.send_keys(ASINs)

                # driver.find_element_by_xpath("//*[contains(text(),'搜 索')]").click()

                # time.sleep(3)
                # driver.find_element_by_xpath("//*[@class='batch']/*[contains(text(),'批量下载流量词')]").click()

                # time.sleep(3)
                # driver.find_element_by_xpath("//*[@class='el-checkbox__input']").click()

                # time.sleep(3)
                # driver.find_element_by_xpath("//*[@class='batch']/*[contains(text(),'下载流量词')]").click()

                # #isellerpal版本
                # time.sleep(random.randint(5,10))
                # driver.find_element_by_xpath("//*[@class='el-popover__reference-wrapper']//*[contains(text(),'热门搜索词')]").click()
                # time.sleep(0.5)
                # driver.find_element_by_xpath("//*[@class='el-dropdown-menu__item']//*[contains(text(),'全部关键词')]").click()
                # time.sleep(0.5)
                # AsinSearch = driver.find_element_by_xpath('//*[@placeholder="请输入ASIN"]')
                # AsinSearch.send_keys(ASINs)
                # time.sleep(1)
                # driver.find_element_by_xpath("//*[@type='button']//*[@class='el-icon-search']").click()

                # time.sleep(random.randint(5,10))
                # driver.find_element_by_xpath("//*[@type='button']/*[contains(text(),'下载')]").click()

                # #Helium10版本
                WebDriverWait(driver, 72).until(ec.visibility_of_element_located((By.XPATH,"//*[@class='cerebro-search-form']//*[contains(text(),'Get Keywords')]")))

                time.sleep(1)

                AsinSearch = driver.find_element_by_xpath("//*[@class='multi-asin-search-container']//input")
                AsinSearch.send_keys(ASINs)

                time.sleep(2)
                driver.find_element_by_xpath("//*[@class='cerebro-search-form']//*[contains(text(),'Get Keywords')]").click()

                time.sleep(2)
                try:
                    driver.find_element_by_xpath("//*[@class='sa-button-container']//*[contains(text(),'New Search')]").click()

                finally:
                    WebDriverWait(driver, 72).until(ec.visibility_of_element_located((By.XPATH,"//*[@class='dropdown float-right']//button")))

                    time.sleep(1)

                    driver.find_element_by_xpath("//*[@class='dropdown float-right']//button").click()
                    time.sleep(1)
                    driver.find_element_by_xpath("//*[@class='dropdown float-right show']//*[@data-format='xlsx']").click()

                    WebDriverWait(driver, 72, 0.5).until(ec.visibility_of_element_located((By.XPATH,"//*[@class='tooltipster-box']//*[contains(text(),'Exported!')]")))
                    time.sleep(random.randint(1,3))
                    i += 1
                    break

            except:
                Try_Count += 1
                print("获取失败,第%s次尝试刷新"%Try_Count)
                driver.refresh()
                time.sleep(5)
                continue

driver.quit()

print('搞完了，最后一个ASIN：%s'%x[:-1])

# End_Time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

# # 发送到钉钉群
# json_data = {
#           "msgtype": "text",
#           "text": {
#               "content": "AMZ(SearchTerm)\n启动时间：{0}\n结束时间：{1}\n数据量：{2}\最后ASIN：{3}".format(Now_Time,End_Time,i*10,ASINs[:-1])  # 发送内容
#           },
#           "at": {
#               "atMobiles": [
#               ],
#               "isAtAll": False  # 是否要@某位用户
#           }
#       }

# ding_url = 'https://oapi.dingtalk.com/robot/send?access_token=' \
#                     '66571ff131625d3a0f9f8a053333939a571ff902ee1f9a8a5af8a8dc5de04b9f'
#                     # 公司钉钉群 '314ba5ccba18c377ec9d688543a6b5afcb2baf6319023e29878278453f3ab96c'
#                     # GOGO哒     '4d7674403085618ece3003a8166f5f7bce07f160851e496f78e2abc4c5026e4a'
#                     # 执行记录    '66571ff131625d3a0f9f8a053333939a571ff902ee1f9a8a5af8a8dc5de04b9f'

# requests.post(url=ding_url, json=json_data)
# print('信息发送成功。')


from gym.spaces import Box
import numpy as np
import torch

from reinforcement_learning.common import discount_rewards
from reinforcement_learning.reinforce import (
    ReinforceTrainer, BasicPPO)

class MLPValueModule(torch.nn.Module):
    def __init__(self, env, hidden_units):
        if not isinstance(env.observation_space, Box):
            raise ValueError(
                'Unsupported observation space {}'.format(
                    env.observation_space))
        if len(env.observation_space.shape) != 1:
            raise ValueError(
                'Unsupported observation space rank != 1 {}'.format(
                    env.observation_space.shape))
        super().__init__()
        self.hidden_units = hidden_units
        last_layer = torch.nn.Linear(self.hidden_units, 1, bias=False)
        last_layer.weight.data.zero_()
        self.model = torch.nn.Sequential(
            torch.nn.Linear(env.observation_space.shape[0], self.hidden_units,),
            torch.nn.LeakyReLU(),
            torch.nn.Linear(self.hidden_units, self.hidden_units,),
            torch.nn.LeakyReLU(),
            last_layer,
        )

    def forward(self, inputs):
        return self.model(inputs)[:, 0]

class AdvantageMixin:
    def __init__(
            self, env, agent, value_module,
            value_num_trainings_per_batch, **kwargs):
        super().__init__(env=env, agent=agent, **kwargs)
        self.value_module = value_module
        self.value_optimizer = torch.optim.Adam(
            self.value_module.parameters(), lr=1e-3)
        self.value_num_trainings_per_batch = value_num_trainings_per_batch

    def _extra_buffer_kwargs(
            self, observations, actions, rewards, discounted_rewards):
        current_observations = observations[:-1]
        future_observations = observations[1:]
        with torch.no_grad():
            current_state_values = self.value_module(
                torch.tensor(current_observations, dtype=torch.float32)).numpy()
            next_state_values = self.value_module(
                torch.tensor(
                    future_observations, dtype=torch.float32)).numpy()
        advantage = (
            rewards +
            self.reward_discount * next_state_values -
            current_state_values
        ).tolist()
        discounted_advantage = discount_rewards(
            advantage, self.reward_discount * 0.97)
        return {
            **super()._extra_buffer_kwargs(
                observations, actions, rewards, discounted_rewards),
            'advantage': advantage,
            'discounted_advantage': discounted_advantage,
        }

    def _train_on_replay_buffer(self, replay_buffer_sample):
        observations = replay_buffer_sample['current_state']
        discounted_rewards = replay_buffer_sample['discounted_reward']
        first_l2_loss = None
        for _ in range(self.value_num_trainings_per_batch):
            expected_rewards = self.value_module(
                torch.tensor(observations, dtype=torch.float32))
            l2_loss = torch.nn.functional.mse_loss(
                expected_rewards, torch.tensor(discounted_rewards))
            if first_l2_loss is None:
                first_l2_loss = l2_loss.item()
            self.value_optimizer.zero_grad()
            l2_loss.backward()
            self.value_optimizer.step()
        advantage = replay_buffer_sample['discounted_advantage']
        advantage -= np.mean(advantage)
        advantage /= np.std(advantage) + 1e-6
        replay_buffer_sample = {
            **replay_buffer_sample,
            'discounted_reward': advantage}
        print('l2_loss', first_l2_loss, l2_loss.item())
        return super()._train_on_replay_buffer(replay_buffer_sample)


import scrapy
import os
import pandas as pd
from twisted.internet import reactor
from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging
from functions import verify, verify_folder, transform_data, error_message

#Paginas de dolar-pesos

# investing = https://es.investing.com/currencies/usd-cop

USD_COL = {'mataf': 'https://www.mataf.net/es/cambio/divisas-USD-COP', 'dolar_colombia':'https://www.dolar-colombia.com/',
'cotizacion':'https://www.cotizacion.co/colombia/precio-del-dolar.php','dolar_web':'https://dolar.wilkinsonpc.com.co/'}

#Paginas de dolar-bitcoin

# 1 investing = https://es.investing.com/crypto/bitcoin

USD_BTC = {'coinmarketcap':'https://coinmarketcap.com/es/currencies/bitcoin/','coin_telegraph':'https://cointelegraph.com/bitcoin-price',
'marketwatch':'https://www.marketwatch.com/investing/cryptocurrency/btcusd', 'yahoo_finance':'https://finance.yahoo.com/quote/BTC-USD'}

#Paginas de dolar-bolivares

# 1 investing = https://es.investing.com/currencies/usd-vef

USD_VES = {'valutafx':'https://es.valutafx.com/USD-VES.htm', 'exchange':'https://es.exchange-rates.org/Rate/USD/VES'}

WDIR = os.getcwd()[:-24] if os.getcwd()[-7:] == 'spiders' else os.getcwd()
TRANSFORM = os.path.join(WDIR,'transform')
RAW_PATH = os.path.join(TRANSFORM,'raw_data')

class usd_cop(scrapy.Spider):
    name = 'usd_cop'
    start_urls = [
        'https://es.investing.com/currencies/usd-cop'
    ]

    def parse(self, response):
        investing_currency = response.xpath('//div[contains(@class,"instrument-price")]/span[@data-test="instrument-price-last" and @class="text-2xl"]/text()').get()
        if investing_currency:
            yield response.follow(USD_COL['mataf'], callback=self.mataf, cb_kwargs={'name':['investing'],'value':[investing_currency]})
        else:
            error_message('usd_cop','parse','https://es.investing.com/currencies/usd-cop')
            yield response.follow(USD_COL['mataf'], callback=self.mataf, cb_kwargs={'name':['investing'],'value':['not available']})

    def mataf(self, response, **kwargs):
        mataf_currency = response.xpath('//div[@class="table-responsive"]/table/tbody[not(@class)]/tr[@itemprop="mainEntity"][1]/td[4]/span/meta[@itemprop="value"]/@content').get()
        if mataf_currency:
            mataf_currency = mataf_currency.replace(' ',',')
            kwargs['name'].append('mataf')
            kwargs['value'].append(mataf_currency)
            yield response.follow(USD_COL['dolar_colombia'], callback=self.dolar_colombia ,cb_kwargs=kwargs)
        else:
            error_message('usd_cop','mataf',USD_COL['mataf'])
            kwargs['name'].append('mataf')
            kwargs['value'].append('not available')
            yield response.follow(USD_COL['dolar_colombia'], callback=self.dolar_colombia ,cb_kwargs=kwargs)

    def dolar_colombia(self,response, **kwargs):
        dolar_colombia_currency = response.xpath('//div[@class="box"]/div[@class="box__content"]/h2/span/text()').get()
        if dolar_colombia_currency:
            kwargs['name'].append('dolar_colombia')
            kwargs['value'].append(dolar_colombia_currency)
            yield response.follow(USD_COL['cotizacion'], callback=self.cotizacion, cb_kwargs=kwargs)
        else:
            error_message('usd_cop','dolar_colombia',USD_COL['dolar_colombia'])
            kwargs['name'].append('dolar_colombia')
            kwargs['value'].append('not available')
            yield response.follow(USD_COL['cotizacion'], callback=self.cotizacion, cb_kwargs=kwargs)

    def cotizacion(self, response, **kwargs):
        cotizacion_currency = response.xpath('//div[contains(@class,"col-xs-12")]/p/span/span[@id="convertido-dol-ch"]/text()').get()
        if cotizacion_currency:
            kwargs['name'].append('cotizacion.co')
            kwargs['value'].append(cotizacion_currency)
            yield response.follow(USD_COL['dolar_web'], callback=self.dolar_web, cb_kwargs=kwargs)
        else:
            error_message('usd_cop','cotizacion',USD_COL['cotizacion'])
            kwargs['name'].append('cotizacion.co')
            kwargs['value'].append('not available')
            yield response.follow(USD_COL['dolar_web'], callback=self.dolar_web, cb_kwargs=kwargs)

    def dolar_web(self,response,**kwargs):
        dolar_web = response.xpath('//div[@class="row"]//span[@class="valor"]/a/h2/span[@class="sube-numero"]/text()').get()
        dolar_web1 = response.xpath('//div[@class="row"]/div/span/a/h2/span[@class="baja-numero"]/text()').get()

        if dolar_web:
            kwargs['name'].append('dolar_web')
            kwargs['value'].append(dolar_web)

        else:
            kwargs['name'].append('dolar_web')
            kwargs['value'].append(dolar_web1)

        df = pd.DataFrame(kwargs)
        df.to_csv(os.path.join(RAW_PATH,'raw_usd_cop.csv'))

class usd_btc(scrapy.Spider):
    name = 'usd_btc'
    start_urls = [
        'https://es.investing.com/crypto/bitcoin'
    ]

    def parse(self, response):
        investing_currency_btc = response.xpath('//div[@class="inlineblock"]/div[contains(@class,"top bold")]/span/span/text()').get()
        if investing_currency_btc:
            yield response.follow(USD_BTC['coinmarketcap'], callback= self.coinmarketcap, cb_kwargs={'name':['investing'],'value':[investing_currency_btc]})
        else:
            error_message('usd_btc','parse',USD_BTC['https://es.investing.com/crypto/bitcoin'])
        yield response.follow(USD_BTC['coinmarketcap'], callback= self.coinmarketcap, cb_kwargs={'name':['investing'],'value':['not available']})

    def coinmarketcap(self, response, **kwargs):
        coinmarket_currency_btc = response.xpath('//div[contains(@class,"sc")]/div[contains(@class,"priceValue")]/span/text()').get()
        if coinmarket_currency_btc:
            kwargs['name'].append('coinmarketcap')
            kwargs['value'].append(coinmarket_currency_btc)
            yield response.follow(USD_BTC['coin_telegraph'], callback = self.coin_telegraph, cb_kwargs=kwargs)
        else:
            error_message('usd_btc','coinmarketcap',USD_BTC['coinmarketcap'])
            kwargs['name'].append('coinmarketcap')
            kwargs['value'].append('not available')
            yield response.follow(USD_BTC['coin_telegraph'], callback = self.coin_telegraph, cb_kwargs=kwargs)

    def coin_telegraph(self, response, **kwargs):
        coin_telegraph_currency_btc = response.xpath('//span[@class="price-value" and contains(text(),"$")]/text()').get()
        if coin_telegraph_currency_btc:
            kwargs['name'].append('coin_telegraph')
            kwargs['value'].append(coin_telegraph_currency_btc)
            yield response.follow(USD_BTC['marketwatch'], callback = self.market_watch, cb_kwargs= kwargs)
        else:
            error_message('usd_btc','coin_telegraph',USD_BTC['coin_telegraph'])
            kwargs['name'].append('coin_telegraph')
            kwargs['value'].append('not_available')
            yield response.follow(USD_BTC['marketwatch'], callback = self.market_watch, cb_kwargs= kwargs)

    def market_watch(self, response, **kwargs):
        market_watch_currency_btc = response.xpath('//div[@class="intraday__data"]/h2/bg-quote/text()').get()
        if market_watch_currency_btc:
            kwargs['name'].append('market_watch')
            kwargs['value'].append(market_watch_currency_btc)
            yield response.follow(USD_BTC['yahoo_finance'], callback = self.yahoo_finance, cb_kwargs= kwargs)
        else:
            error_message('usd_btc','marketwatch',USD_BTC['marketwatch'])
            kwargs['name'].append('market_watch')
            kwargs['value'].append('not available')
            yield response.follow(USD_BTC['yahoo_finance'], callback = self.yahoo_finance, cb_kwargs= kwargs)

    def yahoo_finance(self, response, **kwargs):
        yahoo_finance_currency_btc = response.xpath('//fin-streamer[@data-symbol="BTC-USD" and @value and @data-test="qsp-price"]/@value').get()
        kwargs['name'].append('yahoo_finance')
        kwargs['value'].append(yahoo_finance_currency_btc)

        df = pd.DataFrame(kwargs)
        df.to_csv(os.path.join(RAW_PATH,'raw_usd_btc.csv'))

class usd_ves(scrapy.Spider):
    name = 'usd_ves'
    start_urls = [
        'https://es.investing.com/currencies/usd-vef'
    ]

    def parse(self, response):
        investing_currency_ves = response.xpath('//div[contains(@class,"instrument-price")]/span[@data-test="instrument-price-last" and @class="text-2xl"]/text()').get()
        if investing_currency_ves:
            yield response.follow(USD_VES['valutafx'], callback = self.valutafx, cb_kwargs={'name':['investing'],'value':[investing_currency_ves]})
        else:
            error_message('usd_ves','parse',USD_VES['https://es.investing.com/currencies/usd-vef'])
            yield response.follow(USD_VES['valutafx'], callback = self.valutafx, cb_kwargs={'name':['investing'],'value':['not available']})

    def valutafx(self, response, **kwargs):
        valuta_currency_ves = response.xpath('//div[@class="converter-result"]/div[@class="rate-value"]/text()').get()
        if valuta_currency_ves:
            kwargs['name'].append('valuta')
            kwargs['value'].append(valuta_currency_ves)
            yield response.follow(USD_VES['exchange'], callback = self.exchange_rates, cb_kwargs= kwargs)
        else:
            error_message('usd_ves','valutafx',USD_VES['valutafx'])
            kwargs['name'].append('valuta')
            kwargs['value'].append('not available')
            yield response.follow(USD_VES['exchange'], callback = self.exchange_rates, cb_kwargs= kwargs)

    def exchange_rates(self, response, **kwargs):
        exchange_rates_ves = response.xpath('//div[@class="table-responsive"]/table/tbody/tr[1]/td[contains(@class,"result")]/text()').get()
        kwargs['name'].append('exchange_rate')
        kwargs['value'].append(exchange_rates_ves)

        df = pd.DataFrame(kwargs)
        df.to_csv(os.path.join(RAW_PATH,'raw_usd_ves.csv'))

if __name__ == '__main__':
    verify_folder()
    verify()

    configure_logging()
    runner = CrawlerRunner(
        {
        'USER_AGENT': "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36",
        }
    )

    runner.crawl(usd_cop)
    runner.crawl(usd_btc)
    runner.crawl(usd_ves)

    d = runner.join()
    d.addBoth(lambda _: reactor.stop())

    reactor.run()

    transform_data()


'''
Created on 26 Jul 2013

@author: hicksj
'''
from datetime import datetime
from operator import attrgetter
from utils.text import TextUtils

class TeamFixturesReport:

    def getSortedMatches(self):
        return sorted(self.matches, key=attrgetter("datetime", "opponentName"))

class MatchInReport:
    pass

class TeamFixturesReportGenerator():
    '''
    classdocs
    '''

    def getReport(self, rootElement, teamId):
        answer = TeamFixturesReport()
        answer.matches = []
        leagueElement = self.getLeagueElement(rootElement, teamId)
        teams = self.getTeams(leagueElement)
        matchElements = self.getMatchElements(leagueElement, teamId)
        answer.teamId = teamId
        answer.teamName = teams[teamId]
        answer.leagueId = leagueElement.get('id')
        answer.leagueName = leagueElement.find('name').text
        for matchElement in matchElements:
            answer.matches.append(self.getMatch(matchElement, teamId, teams))
        return answer

    def getMatch(self, matchElement, teamId, teams):
        answer = MatchInReport()
        self.setOpponentInfo(teamId, matchElement, answer, teams)
        self.setWinLossInfo(teamId, matchElement, answer)
        answer.court = matchElement.find("pitch").text
        answer.datetime = datetime.strptime(matchElement.find("date").text, "%Y-%m-%d.%H:%M")
        return answer

    def setOpponentInfo(self, teamId, matchElement, match, teams):
        homeTeam = matchElement.find("homeTeam")
        awayTeam = matchElement.find("awayTeam")
        match.home = (homeTeam.get('id') == teamId)
        opponent = awayTeam if match.home else homeTeam
        match.opponentId = opponent.get('id')
        match.opponentName = teams[match.opponentId]

    def setWinLossInfo(self, teamId, matchElement, match):
        match.result = None
        match.margin = None
        if not self.setWinLossInfoGamePlayed(teamId, matchElement, match):
            self.setWinLossInfoGameAwarded(teamId, matchElement, match)

    def setWinLossInfoGamePlayed(self, teamId, matchElement, match):
        playedMatchElement = matchElement.find('playedMatch')
        answer = playedMatchElement != None
        if answer:
            ourScore = None
            ourWickets = None
            batFirst = None
            theirScore = None
            theirWickets = None
            for teamInMatchElement in playedMatchElement.findall("teamInMatch"):
                tRef = teamInMatchElement.find("teamRef").get("id")
                inns = teamInMatchElement.find("innings")
                if tRef == teamId:
                    batFirst = teamInMatchElement.find("battingFirst").text == "true"
                    ourScore = int(inns.find("runsScored").text)
                    wktsElement = inns.find("wicketsLost")
                    ourWickets = 6 if wktsElement == None else int(wktsElement.text)
                else:
                    theirScore = int(inns.find("runsScored").text)
                    wktsElement = inns.find("wicketsLost")
                    theirWickets = 6 if wktsElement == None else int(wktsElement.text)
            if ourScore > theirScore:
                match.result = "Won"
            elif ourScore < theirScore:
                match.result = "Lost"
            else:
                match.result = "Tied"
            if batFirst:
                match.margin = self.getMargin(ourScore, theirScore, theirWickets)
            else:
                match.margin = self.getMargin(theirScore, ourScore, ourWickets)
        return answer

    def getMargin(self, batFirstScore, batSecondScore, batSecondWickets):
        answer = None
        runsDifference = batFirstScore - batSecondScore
        if runsDifference > 0:
            answer = "{0} {1}".format(runsDifference, TextUtils.getGrammaticalNumber(runsDifference, "run", "runs"))
        elif runsDifference < 0:
            wicketsInHand = 6 - batSecondWickets
            answer = "{0} {1}".format(wicketsInHand, TextUtils.getGrammaticalNumber(wicketsInHand, "wicket", "wickets"))
        return answer

    def setWinLossInfoGameAwarded(self, teamId, matchElement, match):
        awardedMatchElement = matchElement.find('awardedMatch')
        answer = awardedMatchElement != None
        if answer:
            won = awardedMatchElement.find("winner").get("id") == teamId
            match.result = "Won" if won else "Lost"
            match.margin = "default"
        return answer

    def getLeagueElement(self, modelElement, teamId):
        answer = None
        for l in modelElement.findall("league"):
            for t in l.findall("team"):
                if t.get("id") == teamId:
                    answer = l
                    break;
                if answer is not None:
                    break
            if answer is not None:
                break
        return answer

    def getTeams(self, leagueElement):
        answer = {}
        for elem in leagueElement.findall("team"):
            answer[elem.get('id')] = elem.find("name").text
        return answer

    def getMatchElements(self, leagueElement, teamId):
        answer = []
        for m in leagueElement.findall("match"):
            match = None
            for ha in ["homeTeam", "awayTeam"]:
                if m.find(ha).get("id") == teamId:
                    match = m
                    break
            if match is not None:
                answer.append(match)
        return answer


from logging import Filter
from re import A
import string
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import *
import json
import logging

#token
Token = "5529993642:AAFJkMvsan_Iusk14f7JwmUTcb1AlkcqSWw"

# Enable logging
logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)
user_anno = 0

ANNO, MATERIA, INFORMAZIONI = range(3)

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    """Inizia la conversazione e chiede all'utente che anno frequenta."""
    reply_keyboard = [["Primo", "Secondo", "Terzo"]]

    await update.message.reply_text(
        "Benvenuto! Io sono il Bot che ti permette di prenotare il posto a Lezione."
        "Invia /cancel per smettere di parlare con me.\n\n"
        "Che anno frequenti?",
        reply_markup=ReplyKeyboardMarkup(
            reply_keyboard, one_time_keyboard=True, input_field_placeholder="Primo, Secondo o Terzo ?"
        ),
    )
    return ANNO

async def anno(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    """" Chiede all'utente quale materia vuole prenotare """
    global user_anno
    user = update.message.from_user
    logger.info("Anno di corso di %s: %s", user.full_name, update.message.text)
    testo = update.message.text.lower()

    f = open('tabelle.json')
    data = json.load(f)

    if  "primo" in testo :
        user_anno = 1
        reply_keyboard = [["Analisi Matematica 1", "Matematica Discreta 1", "Programmazione 1", "Logica e Reti Logiche"]]
        await update.message.reply_text(
            "Fai il Primo Anno."
            "Scegli la materia che vuoi seguire.",
            reply_markup=ReplyKeyboardMarkup(
                reply_keyboard, one_time_keyboard=True, input_field_placeholder="Analisi Matematica,Matematica Discreta,Programmazione 1,Logica e Reti Logiche"
            ),
        )
        for i in data['orario_1']:
            await update.message.reply_text(json.dumps(i, indent=4))

    if "secondo" in testo:
        user_anno = 2
        reply_keyboard = [["Algoritmi e Strutture Dati", "Calcolo delle Probabilita'","Calcolo Numerico"]]
        await update.message.reply_text(
            "Fai il Secondo Anno."
            "Scegli la materia che vuoi seguire.",
            reply_markup=ReplyKeyboardMarkup(
                reply_keyboard, one_time_keyboard=True, input_field_placeholder="Algoritmi e Strutture Dati,Calcolo delle Probabilita', Calcolo Numerico"
            ),
        )
        for i in data['orario_2']:
            await update.message.reply_text(json.dumps(i, indent=4))

    if "terzo" in testo:
        user_anno = 3
        reply_keyboard = [["Archittetura Reti", "Base di Dati"]]
        await update.message.reply_text(
            "Fai il Terzo Anno."
            "Scegli la materia che vuoi seguire.",
            reply_markup=ReplyKeyboardMarkup(
                reply_keyboard, one_time_keyboard=True, input_field_placeholder="Archittetura Reti,Base di Dati"
            ),
        )
        for i in data['orario_3']:
            await update.message.reply_text(json.dumps(i, indent=4))

    return MATERIA

async def prenotazione(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    """"" Qui verra' salvata la prenotazione dell'utente per la materia scelta """
    user = update.message.from_user
    logger.info("%s vuole prenotare: %s",user.full_name, update.message.text)
    user_materia = update.message.text

    with open('tabelle.json', 'r', encoding='utf-8') as f:
        data = json.load(f)

    if user_anno == 1:
        for i in data["orario_1"]:
            if user_materia in i["Nome"]:
                if i["posti"] > 0 :
                    await update.message.reply_text("C'e' ancora posto...")
                    i["posti"] = i["posti"]-1
                    break
                else:
                    await update.message.reply_text("Non ci sono posti disponibili ...\nRiprova settimana prossima per questa materia o prenotane un'altra.")
                    return

    if user_anno == 2:
        for i in data["orario_2"]:
            if user_materia in i["Nome"]:
                if i["posti"] > 0 :
                    await update.message.reply_text("C'e' ancora posto...")
                    i["posti"] = i["posti"]-1
                    break
                else:
                    await update.message.reply_text("Non ci sono posti disponibili ...\nRiprova settimana prossima per questa materia o prenotane un'altra.")
                    return

    if user_anno == 3:
        for i in data["orario_3"]:
            if user_materia in i["Nome"]:
                if i["posti"] > 0 :
                    await update.message.reply_text("C'e' ancora posto...")
                    i["posti"] = i["posti"]-1
                    break
                else:
                    await update.message.reply_text("Non ci sono posti disponibili ...\nRiprova settimana prossima per questa materia o prenotane un'altra.")
                    return

    lunghezza = len ( data[user_materia])
    for pos in range(lunghezza):
        if "vuoto" in data[user_materia][pos]["Nome"]:
            await update.message.reply_text("Hai prenotto il tuo posto in aula.\n\nAprendo la KEYBOARD delle materie potrai prenotare un'altra materia.")
            data[user_materia][pos]["Nome"] = user.full_name
            data[user_materia][pos]["posto"] = pos + 1
            with open('tabelle.json', 'w', encoding='utf-8') as g:
                json.dump(data, g, ensure_ascii=False, indent=4)
            file = open(user_materia,"a")
            file.write(user.full_name + "   " +  str(user.id) +  '\n')
            file.close()
            break
        elif user.full_name in data[user_materia][pos]["Nome"]:
            await update.message.reply_text("Hai gia prenotato il tuo posto in aula per questa materia.")
            break

async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
    """Cancella la conversazione."""
    user = update.message.from_user
    logger.info("Utente: %s ha cancellato la conversazione.", user.first_name)
    await update.message.reply_text(
    "Bye! Ci sentiamo un altro giorno.", reply_markup=ReplyKeyboardRemove()
    )

def main() -> None:
    """Run the bot."""
    # Create the Application and pass it your bot's token.
    application = Application.builder().token(Token).build()

    application.add_handler(ConversationHandler( entry_points=[CommandHandler("start", start)],
        states={
            ANNO: [MessageHandler(filters.Regex("^(Primo|Secondo|Terzo)$"), anno)],
            MATERIA: [MessageHandler(filters.Regex("^(Analisi Matematica 1|Matematica Discreta 1|Programmazione 1|Logica e Reti Logiche|Algoritmi e Strutture Dati|Calcolo delle Probabilita'|Calcolo Numerico|Archittetura Reti|Base di Dati)$"), prenotazione)],
        },
        fallbacks=[CommandHandler('cancel', cancel)]))

    # Run the bot until the user presses Ctrl-C
    application.run_polling()

if __name__ == "__main__":
    main()


"""
This script evaluates the MRR, Precision@K and Recall@K for automatic triple alignment. It takes two arguments:
  * The generation file
  * The test file
"""
from sys import argv

GENERATIONS_FILENAME = argv[1]
TEST_SET_FILENAME = argv[2]

goldstandard = dict()
with open(TEST_SET_FILENAME) as f:
    for line in f:
        line = line.strip().strip("<|endoftext|>").split("[SEP]")
        if len(line) != 2:
            continue
        if line[0] not in goldstandard:
            goldstandard[line[0]] = []
        goldstandard[line[0]].append(line[1])

res = []
with open(GENERATIONS_FILENAME) as f:
    for line in f:
        line = line.strip().split("\t")
        original = line[0].replace(",", "\t")
        if original not in goldstandard:
            continue
        truth = goldstandard[original]
        temp_res = []
        for i, pred in enumerate(line[1:]):
            pred_tab = pred.replace(",", "\t")
            if pred_tab in truth:
                temp_res.append(i)
        res.append((temp_res, len(truth)))

mrrs = []
for pred, _ in res:
    temp = 0
    for rank in pred:
        temp = 1.0 / (rank + 1.0)
        break
    mrrs.append(temp)

print("MRR:", sum(mrrs) / len(mrrs))

for at in range(10):
    recall = []
    precision = []
    for pred, size in res:
        p_temp = 0
        for rank in pred:
            if rank <= at:
                p_temp += 1
        precision.append(p_temp / (at + 1))
        recall.append(p_temp / size)
    print("Precision at", at + 1, ":", sum(precision) / len(precision) * 100, "%")
    print("Recall at", at + 1, ":", sum(recall) / len(recall) * 100, "%")


import math
import random
import pygame
pygame.init()

class Spot():
    def __init__(self, i, j):
        self.i = i
        self.j = j
        self.neighbors = []
        self.previous = None
        self.f = 0
        self.g = 0
        self.h = 0
        self.wall = False
        self.isUserCreatedWall = False
        self.randomNum = random.randint(0, 9)
        if self.randomNum <= 3:
            self.wall = True
    #neighbors = []

    def showSpot(self, color):
        if self.wall == True:
            color = (0, 0, 0)
        pygame.draw.rect(gameDisplay, color, [self.i * w, self.j * h,  w,  h])

    def addNeighbors(self, grid):
        self.i = i
        self.j = j
        if i < columns - 1:
            self.neighbors.append(grid[i + 1][j])
        if i > 0:
            self.neighbors.append(grid[i - 1][j])
        if j < rows - 1:
            self.neighbors.append(grid[i][j + 1])
        if j > 0:
            self.neighbors.append(grid[i][j - 1])
        if i > 0 and j > 0:
            self.neighbors.append(grid[i - 1][j - 1])
        if i < columns - 1 and j > 0:
            self.neighbors.append(grid[i + 1][j - 1])
        if i > 0 and j < rows - 1:
            self.neighbors.append(grid[i - 1][j + 1])
        if i < columns - 1 and j < rows - 1:
            self.neighbors.append(grid[i + 1][j + 1])

def heuristic(a, b):
    distance = math.sqrt((b.i - a.i)**2 + (b.j - a.j)**2)
    return distance

#pygame stuff
displayX = 1000
displayY = 1000
gameDisplay = pygame.display.set_mode((displayX, displayY))
gameDisplay.fill((255,255,255))
clock = pygame.time.Clock()
gameExit = False

userInputGridSize = int(input("Enter a scale (1, 2, 3, 4, or 5) for the grid/matrix \n(where 1 is the smallest scaling, and 5 is the largest)\n"))
toggleArrayScaleValue = userInputGridSize - 1
matrixSizesArray = [10, 20, 25, 50, 100]
rows = matrixSizesArray[toggleArrayScaleValue]
columns = matrixSizesArray[toggleArrayScaleValue]
path = []

white = (255, 255, 255)
black = (0, 0, 0)

w = int(displayX / columns)
h = int(displayY / rows)

grid = []
def createGrid(someGrid, col, row):
    for i in range(0, col):
        someGrid.append([])
        for j in range(0, row):
            newSpot = Spot(i, j)
            someGrid[i].append(newSpot)

createGrid(grid, columns, rows)

def deleteArrayContents(someArr):
    gridLength = len(someArr) - 1
    for i in range(0, gridLength):
        someArr.pop(0)

for i in range(0, columns):
    for j in range(0, rows):
        #addNeighbors(grid[i][j])
        grid[i][j].addNeighbors(grid)
        #print("the neighbors of node ", i, ", ", j, "are ")
        #if i <= 1:
            #for k in range(0, len(grid[i][j].neighbors)):
             #   print("the length of node ",i, ", ", j, " 's neighbors list is ", len(grid[i][j].neighbors))
             #print(grid[i][j].neighbors[k].i, " ", grid[i][j].neighbors[k].j)

openSet = []
closedSet = []

startNode = grid[0][0]
startNode.showSpot((255, 14, 93))
endNode = grid[columns - 1][rows - 1]
endNode.showSpot((0, 150, 200))
startNode.wall = False
endNode.wall = False
noSolution = False

openSet.append(startNode)

stopLooping = True
mouseIsClicked = False
OptimalPathFound = False
gridScaleWasAdjusted = False

stopText = False
font = pygame.font.SysFont(None, w + 5)
def text_to_screen(msg, locX, locY, width):
    screen_text = font.render(msg, True, (0, 0, 0))
    gameDisplay.blit(screen_text, [(locX * width) + int(width/4), locY * h])

BigFont = pygame.font.SysFont(None, int(displayX/20))
def text_to_screen_big(msg, locX, locY, color):
    screen_text = BigFont.render(msg, True, color)
    gameDisplay.blit(screen_text, [locX, locY])

#main game loop to draw grid
while not gameExit:

    pygame.draw.rect(gameDisplay, white, [displayX, displayY, 0, 0])

    startNode.wall = False
    endNode.wall = False

    mouseLocX = math.floor(pygame.mouse.get_pos()[0] / w)
    mouseLocY = math.floor(pygame.mouse.get_pos()[1] / h)

    for event in pygame.event.get():
        if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
            gameExit = True
        if event.type == pygame.MOUSEBUTTONDOWN:
            mouseIsClicked = True
        if event.type == pygame.MOUSEBUTTONUP:
            mouseIsClicked = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_1: #option to start with random generated walls
                print("Starting A* search - option 1 pressed")
                stopLooping = False

            if event.key == pygame.K_2: #option to start with just user generated walls
                print("Starting A* search - option 2 pressed")
                stopLooping = False

                for i in range(0, columns):
                    for j in range(0, rows):
                        if not grid[i][j].isUserCreatedWall:
                            grid[i][j].wall = False

            # if event.key == pygame.K_o:
            #     if toggleArrayScaleValue != 0:
            #         deleteArrayContents(grid)
            #         pygame.draw.rect(gameDisplay, white, [endNode.i * w, endNode.j * h, w, h])
            #         toggleArrayScaleValue = toggleArrayScaleValue - 1
            #         rows = matrixSizesArray[toggleArrayScaleValue]
            #         columns = matrixSizesArray[toggleArrayScaleValue]
            #         w = int(displayX / columns)
            #         h = int(displayY / rows)
            #         createGrid(grid, rows, columns)
            #         endNode = grid[columns - 1][rows - 1]
            #         gridScaleWasAdjusted = True
            #
            # if event.key == pygame.K_p:
            #     if toggleArrayScaleValue < len(matrixSizesArray) - 1:
            #         deleteArrayContents(grid)
            #         pygame.draw.rect(gameDisplay, white, [endNode.i * w, endNode.j * h, w, h])
            #         toggleArrayScaleValue = toggleArrayScaleValue + 1
            #         rows = matrixSizesArray[toggleArrayScaleValue]
            #         columns = matrixSizesArray[toggleArrayScaleValue]
            #         w = int(displayX / columns)
            #         h = int(displayY / rows)
            #         createGrid(grid, rows, columns)
            #         endNode = grid[columns - 1][rows - 1]
            #         gridScaleWasAdjusted = True

            if event.key == pygame.K_s: #option to place starting node elsewhere from default (which is top left)
                startNode.showSpot((white))
                startNode = grid[mouseLocX][mouseLocY]
                openSet.pop()
                openSet.append(startNode)

            elif event.key == pygame.K_e: #option to place end node elsewhere from default (which is bottom right)
                endNode.showSpot((white))
                endNode = grid[mouseLocX][mouseLocY]

    if mouseIsClicked: #creating walls on mouse click + drag
        grid[mouseLocX][mouseLocY].wall = True
        grid[mouseLocX][mouseLocY].isUserCreatedWall = True
        pygame.draw.rect(gameDisplay, (0, 0, 0), [mouseLocX * w, mouseLocY * h,  w,  h])

    if len(openSet) > 0 and not stopLooping: #keep going - openSet still has nodes to visit
        lowestIndex = 0
        for i in range(0, len(openSet)):
            if openSet[i].f < openSet[lowestIndex].f:
                lowestIndex = i

        current = openSet[lowestIndex]

        if current == endNode: #finished, now find the optimal path backwards
            stopLooping = True
            OptimalPathFound = True
            print("Open set is now empty; all paths checked. Optimal path is as follows.")

        openSet.remove(current)
        closedSet.append(current)

        newNeighbors = current.neighbors
        for i in range(0, len(newNeighbors)):
            #print("Length of neighbors is currently: ", len(newNeighbors))
            neighbor = newNeighbors[i]
            if closedSet.count(neighbor) == 0 and not neighbor.wall: #if the closed set does NOT include neighbor
                tempG = current.g + 1

                newPath = False
                if openSet.count(neighbor) >= 1:
                    if tempG < neighbor.g:
                        neighbor.g = tempG
                        newPath = True
                else:
                    neighbor.g = tempG
                    newPath = True
                    openSet.append(neighbor)

                if newPath:
                    neighbor.h = heuristic(neighbor, endNode)   #euclidean distance or manhattan distance
                    neighbor.f = neighbor.g + neighbor.h
                    neighbor.previous = current
                #print("Just checked node ", neighbor.i, ", ", neighbor.j, "which has an f value of ", neighbor.f)

        for i in range(0, rows):#draw the white ("empty") spaces first
            for j in range(0, columns):
                grid[i][j].showSpot((white))

        path = []
        tempNode = current
        path.append(tempNode.previous)
        while tempNode.previous:
            path.append(tempNode.previous)
            tempNode = tempNode.previous

        for i in range(0, len(closedSet)):
            closedSet[i].showSpot((255, 99, 71))

        for i in range(0, len(openSet)):
            openSet[i].showSpot((79, 200, 120))

        for i in range(0, len(path)):
            if path[i] != None:
                path[i].showSpot((106, 90, 205))

    else:  #no solution
        if not noSolution and not OptimalPathFound and len(openSet) == 0:
            print("There is no route to the destination node")
            noSolution = True

    x = 0
    y = 0

    # if gridScaleWasAdjusted:
    #     pygame.draw.rect(gameDisplay, white, [endNode.i * w, endNode.j * h,  w,  h])
    #     startNode.showSpot((white))
    #     gridScaleWasAdjusted = False
    #     endNode = grid[columns - 1][rows - 1]
    #     #print("Start node is at ", startNode.i, " ",startNode.j, " and end node is at ", endNode.i, " ",endNode.j)

    endNode.showSpot((0, 150, 200))
    text_to_screen("e", endNode.i, endNode.j, w)
    startNode.showSpot((255, 140, 0))
    text_to_screen("s", startNode.i, startNode.j, w)

    z = 0
    for i in range(0, rows):
        #vertical lines
        pygame.draw.line(gameDisplay, black, [w + z, 0], [w + z, displayY], 1)
        #horizontal lines
        pygame.draw.line(gameDisplay, black, [0, h + z], [displayX, h + z], 1)
        z = z + w

    magenta = (255, 0, 255)
    if (stopLooping or noSolution or OptimalPathFound) and not stopText:
        text_to_screen_big("Visualization and User Interaction of A* Search", 100, 200, magenta)
        text_to_screen_big("-Created by Sean de Mesa-", 120, 250, magenta)
        text_to_screen_big("Click & hold mouse to create walls", 100, 500, magenta)
        text_to_screen_big("(S) + (hover mouse) to change starting node", 100, 600, magenta)
        text_to_screen_big("(top left is default)", 100, 650, (255, 140, 0))
        text_to_screen_big("(E) + (hover mouse) to change end node", 100, 700, magenta)
        text_to_screen_big("(bottom right is default)", 100, 750, (0, 150, 200))
        text_to_screen_big("Press 1 or 2 to start", 100, 800, magenta)
        text_to_screen_big("1 - Randomly generated walls + user-created walls", 100, 850, (125, 125, 60))
        text_to_screen_big("2 - Begin w/ user-created walls, if any", 100, 900, (125, 125, 60))
        stopText = True

    pygame.display.update()
    clock.tick(60)

print("end")