import argparse
from datetime import datetime, timedelta
import torch
from torch import nn
import torch.backends.cudnn as cudnn
from torch.utils.tensorboard import SummaryWriter
from tqdm import tqdm
import model.RAIN as net
from dataset.data_generator_RAIN import DataGenerator
from utils.utils import get_checkpoints
from utils.timer import timeit

print("Device name: {}".format(torch.cuda.get_device_name(0)))
start_time = datetime.now()
max_duration = 24 * 3600 - 5 * 60
print("torch version: {}".format(torch.__version__))
print("device count: {}".format(torch.cuda.device_count()))
print('device name: {}'.format(torch.cuda.get_device_name(0)))

cudnn.benchmark = True

torch.autograd.set_detect_anomaly(True)

def adjust_learning_rate(optimizer, iteration_count):
    """Imitating the original implementation"""
    lr = args.lr / (1.0 + args.lr_decay * iteration_count)
    for param_group in optimizer.param_groups:
        param_group['lr'] = lr

parser = argparse.ArgumentParser()
# Basic options
parser.add_argument('--content', type=str, default='bssfp',
                    help='the modality for content')  # bssfp, t2 or lge
parser.add_argument('--style', type=str, default='t2',
                    help='the modality for content')

parser.add_argument('--lr', type=float, default=1e-4)
parser.add_argument('--lr_decay', type=float, default=5e-5)
parser.add_argument('--batch_size', type=int, default=16)
parser.add_argument('--ns', type=int, default=700)
parser.add_argument('--epochs', type=int, default=200)
parser.add_argument('--augmentation', action='store_true')
parser.add_argument('--lw', action='store_true')
parser.add_argument('--crop', type=int, default=224)
parser.add_argument('--vgg', help='the path to the directory of the weight', type=str,
                    default='pretrained/vgg_normalised.pth')
parser.add_argument('--style_weight', type=float, default=1.0)
parser.add_argument('--content_weight', type=float, default=1.0)
parser.add_argument('--latent_weight', type=float, default=1.0)
parser.add_argument('--recons_weight', type=float, default=5.0)
parser.add_argument('--save_every_epochs', type=int, default=0)
args = parser.parse_args()
print('weight_dir: {}'.format(args.vgg))

def get_appendix():
    appendix = args.content + "2" + args.style + '.lr{}'.format(args.lr) + \
               '.sw{}'.format(args.style_weight) + '.cw{}'.format(args.content_weight) + \
               '.lw{}'.format(args.latent_weight) + '.rw{}'.format(args.recons_weight)
    if args.augmentation:
        appendix += '.aug'
    return appendix

appendix = get_appendix()
print(appendix)
device = torch.device('cuda')

@timeit
def main():
    decoder = net.decoder
    vgg = net.encoder
    fc_encoder = net.fc_encoder
    fc_decoder = net.fc_decoder

    vgg.load_state_dict(torch.load(args.vgg))
    vgg = nn.Sequential(*list(vgg.children())[:31])

    start_epoch = 0
    if args.lw:
        decoder_model_dir = 'weights/decoder.{}.pt'.format(appendix)
        fc_encoder_dir = 'weights/fc_encoder.{}.pt'.format(appendix)
        fc_decoder_dir = 'weights/fc_decoder.{}.pt'.format(appendix)
        decoder.load_state_dict(torch.load(decoder_model_dir)['model_state_dict'])
        fc_encoder.load_state_dict(torch.load(fc_encoder_dir)['model_state_dict'])
        fc_decoder.load_state_dict(torch.load(fc_decoder_dir)['model_state_dict'])
        start_epoch = torch.load(decoder_model_dir)['epoch']
    print('start epoch: {}'.format(start_epoch))
    network = net.Net(vgg, decoder, fc_encoder, fc_decoder)
    network.train()
    network.to(device)

    decoder_checkpoint, fc_encoder_checkpoint, fc_decoder_checkpoint = get_checkpoints(apdx=appendix,
                                                                                n_epochs=args.epochs,
                                                                                save_every_epochs=args.save_every_epochs)

    content_iter = iter(
        DataGenerator(modality=args.content, crop_size=args.crop, n_samples=args.ns, batch_size=args.batch_size,
                      augmentation=args.augmentation))
    style_iter = iter(
        DataGenerator(modality=args.style, crop_size=args.crop, n_samples=args.ns, batch_size=args.batch_size,
                      augmentation=args.augmentation))

    optimizer = torch.optim.Adam(network.decoder.parameters(), lr=args.lr)
    optimizer_fc_encoder = torch.optim.Adam(network.fc_encoder.parameters(), lr=args.lr)
    optimizer_fc_decoder = torch.optim.Adam(network.fc_decoder.parameters(), lr=args.lr)

    loss_c_mean_list, loss_s_mean_list, loss_l_mean_list, loss_r_mean_list = [], [], [], []
    decoder_lr = []
    fc_encoder_lr = []
    fc_decoder_lr = []
    max_epoch_time = 0
    for i in tqdm(range(start_epoch, args.epochs)):
        epoch_start = datetime.now()
        loss_c_list, loss_s_list, loss_l_list, loss_r_list = [], [], [], []

        adjust_learning_rate(optimizer, iteration_count=i)
        adjust_learning_rate(optimizer_fc_encoder, iteration_count=i)
        adjust_learning_rate(optimizer_fc_decoder, iteration_count=i)

        decoder_lr.append(optimizer.param_groups[0]['lr'])
        fc_encoder_lr.append(optimizer_fc_encoder.param_groups[0]['lr'])
        fc_decoder_lr.append(optimizer_fc_decoder.param_groups[0]['lr'])

        for (content_images, _), (style_images, _) in zip(content_iter, style_iter):
            for param in network.fc_encoder.parameters():
                param.requires_grad = True
            for param in network.fc_decoder.parameters():
                param.requires_grad = True
            loss_c, loss_s, loss_l, loss_r = network.forward(torch.from_numpy(content_images).cuda(),
                                                             torch.from_numpy(style_images).cuda())

            # collect losses
            loss_c_list.append(loss_c.item())
            loss_s_list.append(loss_s.item())
            loss_l_list.append(loss_l.item())
            loss_r_list.append(loss_r.item())

            loss_l = args.latent_weight * loss_l
            loss_r = args.recons_weight * loss_r
            loss_fc = loss_l + loss_r
            optimizer_fc_encoder.zero_grad()
            optimizer_fc_decoder.zero_grad()
            loss_fc.backward(retain_graph=True)

            for param in network.fc_encoder.parameters():
                param.requires_grad = False
            for param in network.fc_decoder.parameters():
                param.requires_grad = False

            loss_c = args.content_weight * loss_c
            loss_s = args.style_weight * loss_s
            optimizer.zero_grad()
            loss_de = loss_c + loss_s
            loss_de.backward()
            optimizer.step()
            optimizer_fc_encoder.step()
            optimizer_fc_decoder.step()
            print("{}, {}, {}, {}, {}".format("0:>12".format('epoch: {}'.format(i)), loss_c.item(), loss_s.item(),
                                              loss_l.item(), loss_r.item()))

        mean_loss_c = sum(loss_c_list) / len(loss_c_list)
        mean_loss_s = sum(loss_s_list) / len(loss_s_list)
        mean_loss_l = sum(loss_l_list) / len(loss_l_list)
        mean_loss_r = sum(loss_r_list) / len(loss_r_list)
        loss_c_mean_list.append(mean_loss_c)
        loss_s_mean_list.append(mean_loss_s)
        loss_l_mean_list.append(mean_loss_l)
        loss_r_mean_list.append(mean_loss_r)
        if (datetime.now() - start_time).seconds > max_duration - max_epoch_time:
            i = args.epochs - 1

        monitor = args.latent_weight * mean_loss_l + args.recons_weight * mean_loss_r + \
                  args.content_weight * mean_loss_c + args.style_weight * mean_loss_s
        monitor = round(monitor, 3)

        decoder_checkpoint.step(monitor=monitor, model=network.decoder, epoch=i + 1)
        fc_encoder_checkpoint.step(monitor=monitor, model=network.fc_encoder, epoch=i + 1)
        fc_decoder_checkpoint.step(monitor=monitor, model=network.fc_decoder, epoch=i + 1)

        if (datetime.now() - start_time).seconds > max_duration - max_epoch_time:
            print("training time elapsed: {}".format(datetime.now() - start_time))
            print("max_epoch_time: {}".format(timedelta(seconds=max_epoch_time)))
            break
        max_epoch_time = max((datetime.now() - epoch_start).seconds, max_epoch_time)

    writer = SummaryWriter(comment=appendix + 'Scr{}'.format(decoder_checkpoint.best_result))
    print("write a training summary")
    i = 1
    for loss_c, loss_s, loss_l, loss_r, d_lr, fc_e_lr, fc_d_lr in zip(loss_c_mean_list, loss_s_mean_list,
                                                                      loss_l_mean_list, loss_r_mean_list,
                                                                      decoder_lr, fc_encoder_lr, fc_decoder_lr):
        writer.add_scalars('Loss', {'Content': loss_c, 'Style': loss_s, 'KL': loss_l, 'Reconstruct': loss_r,
                                    'Combine': args.latent_weight * loss_l + args.recons_weight * loss_r +
                                               args.content_weight * loss_c + args.style_weight * loss_s}, i)
        writer.add_scalars('Lr', {'Decoder': d_lr, 'FC_encoder': fc_e_lr, 'FC_decoder': fc_d_lr}, i)
        i += 1
    writer.close()

if __name__ == '__main__':
    main()
    print('Time elapsed: {}'.format(datetime.now() - start_time))
    print('program finish')


from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport
from collections import OrderedDict
from operator import getitem
import time, math

########## Configuration String ##########

GRAPHQL_URL = "https://defi-kingdoms-community-api-gateway-co06z8vi.uc.gateway.dev/graphql"
ADDRESS  = "0xD688F76E844f2982a776cBf59235fa2aB79cF726"
HERO_SHOWN = 6 #number of heroes shown in results in each category
TQ_HEROES = ['1353','1759','73659','180273','43371','700','58270','63009','102956','177124','23915'] #heroes id which falls under training quests category

##########################################

# Select your transport with a defined url endpoint
transport = AIOHTTPTransport(url=GRAPHQL_URL)

# Create a GraphQL client using the defined transport
client = Client(transport=transport, fetch_schema_from_transport=True)

# Provide a GraphQL query
graphQuery = """
{
heroes(where: {owner: "ADDRESS"}) {
    xp
    level
    id
    staminaFullAt
    stamina
    currentQuest
    mainClass
    profession
    }
}
"""

def getXpNeeded(currentLevel):
  xpNeeded = 0
  nextLevel = currentLevel + 1;

  if currentLevel < 6:
    xpNeeded = nextLevel * 1000
  elif currentLevel < 9:
    xpNeeded = 4000 + (nextLevel - 5) * 2000
  elif currentLevel < 16:
    xpNeeded = 12000 + (nextLevel - 9) * 4000
  elif currentLevel < 36:
    xpNeeded = 40000 + (nextLevel - 16) * 5000
  elif currentLevel < 56:
      xpNeeded = 140000 + (nextLevel - 36) * 7500
  elif currentLevel >= 56:
      xpNeeded = 290000 + (nextLevel - 56) * 10000;
  return xpNeeded

def getCurrentStamina(id, staminaFullAt,stamina):
  ts = time.time()
  currentStamina = stamina - ((staminaFullAt-ts) / (20*60))
  return currentStamina

def getTimerCD(stamina):
    if stamina < 20:
        return ' (' + str(math.ceil((20 - stamina) * 20)) + ' min)'
    else:
        return ''

def printDetails(heroes,entries):
    for x in range(min(len(heroes),entries)):
      print(str(heroes[x]['id']) , ', ',
      str(heroes[x]['xpLeft']) , ', ' ,
      '{0:.2f}'.format(heroes[x]['currentStamina']) ,
      getTimerCD(heroes[x]['currentStamina']) , ', ',
      str(heroes[x]['status']), ', ',
      heroes[x]['mainClass'] , ' (' , heroes[x]['profession'] ,')' ,
      sep='')

graphQuery = graphQuery.replace("ADDRESS",ADDRESS)

query = gql(
    graphQuery
)

# Execute the query on the transport
result = client.execute(query)
for item in result['heroes']:
    xpNeeded = getXpNeeded(item['level'])
    xpLeft = xpNeeded - item ['xp']
    currentStamina = getCurrentStamina(item['id'], item['staminaFullAt'], item['stamina'])
    item.update( {"xpNeeded":xpNeeded})
    item.update( {"xpLeft":xpLeft})
    item.update( {"currentStamina":currentStamina})
    if item['currentQuest'] == '0x0000000000000000000000000000000000000000':
        item.update( {"status":"idle"})
    else:
        item.update( {"status":"questing"})
    if item['id'] in TQ_HEROES:
        item.update( {"isTQ":"true"})
    else:
        item.update( {"isTQ":"false"})

print("=== Experience  ===")
print("ID , XP NEEDED , CURRENT STAMINA , STATUS , HERO CLASS (PROFESSION)")
heroes = result['heroes']
heroes.sort(key=lambda x: x.get('xpLeft'))
printDetails(heroes,HERO_SHOWN)

print("\n\n=== Gardening Heroes  ===")
TimerQuestHeroes = list(filter(lambda x: x.get('currentQuest') == '0x0000000000000000000000000000000000000000' and x.get('profession') in ('gardening') and x.get('isTQ') == 'false', heroes))
TimerQuestHeroes.sort(key=lambda x: x.get('currentStamina'), reverse=True)
printDetails(TimerQuestHeroes,HERO_SHOWN)

print("\n\n=== Mining Heroes  ===")
TimerQuestHeroes = list(filter(lambda x: x.get('currentQuest') == '0x0000000000000000000000000000000000000000' and x.get('profession') in ('mining') and x.get('isTQ') == 'false', heroes))
TimerQuestHeroes.sort(key=lambda x: x.get('currentStamina'), reverse=True)
printDetails(TimerQuestHeroes,HERO_SHOWN)

print("\n\n=== Fishing Heroes  ===")
idleHeroes = list(filter(lambda x: x.get('currentQuest') == '0x0000000000000000000000000000000000000000' and x.get('profession') in ('fishing') and x.get('isTQ') == 'false', heroes))
idleHeroes.sort(key=lambda x: x.get('currentStamina'), reverse=True)
printDetails(idleHeroes,HERO_SHOWN)

print("\n\n=== Foraging Heroes  ===")
idleHeroes = list(filter(lambda x: x.get('currentQuest') == '0x0000000000000000000000000000000000000000' and x.get('profession') in ('foraging') and x.get('isTQ') == 'false', heroes))
idleHeroes.sort(key=lambda x: x.get('currentStamina'), reverse=True)
printDetails(idleHeroes,HERO_SHOWN)

print("\n\n=== Training Quest Heroes  ===")
idleHeroes = list(filter(lambda x: x.get('currentQuest') == '0x0000000000000000000000000000000000000000' and x.get('isTQ') == 'true', heroes))
idleHeroes.sort(key=lambda x: x.get('currentStamina'), reverse=True)
printDetails(idleHeroes,HERO_SHOWN)


from django.contrib import admin
from .models import Wallpaper
from django.contrib.auth.models import Group
class WallpaperAdmin(admin.ModelAdmin):
    list_display = ('title', 'created_date', 'is_free', 'image_thumb')
    list_filter = ('created_date', 'is_free')
    list_editable = ('is_free', )
    list_per_page = 100

admin.site.register(Wallpaper, WallpaperAdmin)
admin.site.unregister(Group)


from django.shortcuts import render, redirect, HttpResponse
from django.contrib import messages
from datetime import datetime
from .models import *
from ..log_reg.models import User

from django.http import JsonResponse

from django.views.generic import View
from django.views.generic import ListView

# Create your views here.
def index(View):
    def get(self, request):
        if 'logged_user' not in request.session:
            return redirect('/')
        else:
            context = {
                'logged_user': User.objects.get(id=request.session['logged_user']),
                'collections': Collection.objects.all().order_by("due_date"),
                'assignments': Assignment.objects.all().order_by("due_date"),

                # 'all_trips': Trip.objects.all(),
                # 'excluded_trips': Trip.objects.exclude(trips_joined=request.session['logged_user']),
            }
            test = Assignment.objects.all()
            print(test)
        return render(request, "base.html", context)

class add_assignment(View):
    def  get(self, request):
        user = User.objects.get(id=request.session['logged_user'])
        collection = Collection.objects.get(id=request.GET['collection_id'])
        this_assignment = Assignment.objects.create(
            creator=user,
            collection=collection,
            name=request.GET['assignment_name'],
            description=request.GET['description'],
            due_date=request.GET['due_date'],
            min_hours=request.GET['min_hours'],
            max_hours=request.GET['max_hours'],
            priority=request.GET['priority'],
            completed=request.GET.get('completed', False),
        )
        this_assignment.save()
        new_assignment = {
            'creator': this_assignment.creator.id,
            'collection': this_assignment.collection.name,
            'name': this_assignment.name,
            'description': this_assignment.description,
            'due_date': this_assignment.due_date,
            'min_hours': this_assignment.min_hours,
            'max_hours': this_assignment.max_hours,
            'priority': this_assignment.priority,
            'completed': this_assignment.completed,
        }
        data = {
            'new_assignment': new_assignment,
        }
        return JsonResponse(data)

# def get_collection_form(request):
#     context = {
#         'collections': Collection.objects.all().order_by("due_date"),
#     }
#     return render(request, 'collection_form.html', context)

# def get_assignment_form(request):
#     context = {
#         'assignments': Assignment.objects.all().order_by("due_date"),
#     }
#     return render(request, 'assignment_form.html', context)

# def add_collection(request):
#     errors = Collection.objects.collection_validator(request.POST)

#     if errors:
#         for k, v in errors.items():
#             messages.error(request, v)
#         return redirect('/main/index/')
#     else:
#         user = User.objects.get(id=request.session['logged_user'])
#         this_collection = Collection.objects.create(
#             name=request.POST['collection_name'],
#             description=request.POST['description'],
#             due_date=request.POST['due_date'],
#             priority=request.POST['priority'],
#             completed=request.POST.get('completed', False),
#             creator=user,
#         )
#         this_collection.save()
#         context = {
#             'collection': this_collection,
#         }
#         return render(request, "add_collection_form.html", context)

# def add_assignment(request):
#     errors = Assignment.objects.assignment_validator(request.POST)

#     if errors:
#         for k, v in errors.items():
#             messages.error(request, v)
#         return redirect('/main/index/')
#     else:
#         # possible Checkbox Bug Fix
#         # if request.POST['completed'] = "on":
#         #     completed=True
#         user = User.objects.get(id=request.session['logged_user'])
#         collection = Collection.objects.get(id=request.POST['collection_id'])
#         this_assignment = Assignment.objects.create(
#             creator=user,
#             collection=collection,
#             name=request.POST['assignment_name'],
#             description=request.POST['description'],
#             due_date=request.POST['due_date'],
#             min_hours=request.POST['min_hours'],
#             max_hours=request.POST['max_hours'],
#             priority=request.POST['priority'],
#             completed=request.POST.get('completed', False),
#         )
#         this_assignment.save()
#         context ={
#             'assignment': this_assignment
#         }
#         return render(request, 'add_assignment_form.html', context)

# def update_assignment(request, assignment_id):
#     errors = Assignment.objects.assignment_validator(request.POST)

#     if errors:
#         for k, v in errors.items():
#             messages.error(request, v)
#         return redirect('/main/index/')
#     else:
#         assignment_form = Assignment.objects.get(id=request.POST['assignment_id'])
#         new_collection_id = Collection.objects.get(id=request.POST['collection'])
#         assignment_form.collection=new_collection_id,
#         assignment_form.name=request.POST['assignment_name'],
#         assignment_form.description=request.POST['description'],
#         assignment_form.due_date=request.POST['due_date'],
#         assignment_form.min_hours=request.POST['min_hours'],
#         assignment_form.max_hours=request.POST['max_hours'],
#         assignment_form.priority=request.POST['priority'],
#         assignment_form.completed=request.POST.get('completed', False)
#         assignment_form.save()
#         success = True
#         console.log(success)
#         context = {
#             'assignments': Assignment.objects.all().order_by("due_date"),
#         }
#         return render(request, 'assignment_form.html', context)

# def update_collection(request):
#     pass


# -*- coding: utf-8 -*-
from __future__ import print_function

__author__= "Luis C. Pérez Tato (LCPT) and Ana Ortega (AO_O)"
__copyright__= "Copyright 2015, LCPT and AO_O"
__license__= "GPL"
__version__= "3.0"
__email__= "l.pereztato@ciccp.es ana.ortega@ciccp.es"

import geom
pto=geom.Pos3d(-1.,1.,0.)

fromPoint=geom.Pos3d(-1.,1.,0.)
ptoDest=geom.Pos3d(1.,1.,0.)
r1=geom.Line3d(fromPoint,ptoDest)

svd1=geom.SlidingVectorsSystem3d()
ptoAplic=geom.Pos3d(1,1,0)
vectorDir=geom.Vector3d(0,0,1)
vec=geom.SlidingVector3d(ptoAplic,vectorDir)
svd1+=vec
ptoAplic=geom.Pos3d(-1,1,0)
vec=geom.SlidingVector3d(ptoAplic,vectorDir)
svd1+=vec
ptoAplic=geom.Pos3d(-1,-1,0)
vec=geom.SlidingVector3d(ptoAplic,vectorDir)
svd1+=vec
ptoAplic=geom.Pos3d(1,-1,0)
vec=geom.SlidingVector3d(ptoAplic,vectorDir)
svd1+=vec

Res=svd1.getResultant()
Mom=svd1.getMoment()
MomP=svd1.getMoment(pto)
MomR=svd1.getMoment(r1) #devuelve el valor con signo (en función del sentido de la recta), probablemente sea mejor ignorar el signo

##print("Res.x =", Res.x)
##print("Res.y =", Res.y)
##print("Res.z =", Res.z)
##print("Mom.x =", Mom.x)
##print("Mom.y =", Mom.y)
##print("Mom.z =", Mom.z)
##print("MomR =", MomR)
##print("MomP.x =", MomP.x)
##print("MomP.y =", MomP.y)

import os
from misc_utils import log_messages as lmsg
fname= os.path.basename(__file__)
if Res.x == 0 and Res.y == 0 and Res.z == 4 and Mom.x == 0 and Mom.y == 0 and Mom.z == 0 and MomR == -4 and MomP.x == -4 and MomP.y == -4:
    print('test: '+fname+': ok.')
else:
    lmsg.error('test: '+fname+' ERROR.')


from data_settings import SettingVal
from data_store import *
from trip_data import *
from const import *

filename = b'goal.cfg'

class GoalData(DataStore, TripData):
    def __init__(self, settings):
        TripData.__init__(self, 0)
        self.target_time_min = SettingVal(60, 1, 500)
        self.target_dist_km = SettingVal(30, 1, 300, True)
        self.target_average_km_h = SettingVal(30, 10, 45, True)
        self.remaining_distance_km = 0
        self.remaining_time_sec = 0
        self.optimal_distance_km = 0
        self.calc_required_average_km_h = 0
        self.is_finished = False
        self.is_started = False

    def calculate_time(self, val, closed):
        if closed:
            self.target_time_min.value = 60 * self.target_dist_km.value / self.target_average_km_h.value

    def calculate_avg(self, val, closed):
        if closed:
            self.target_average_km_h.value = 60 * self.target_dist_km.value / self.target_time_min.value

    def calculate_progress(self):
        if self.is_started:
            self.remaining_distance_km = max(0, self.target_dist_km.value - self.trip_distance)
            self.remaining_time_sec = max(0, 3600 * (self.target_dist_km.value - (self.target_average_km_h.value * self.trip_duration_sec / 3600)) / self.target_average_km_h.value)
            if self.remaining_distance_km > 0:
                if self.remaining_time_sec > 0:
                    self.calc_required_average_km_h = min(Limits.goal_max_required_speed, 3600 * self.remaining_distance_km / self.remaining_time_sec)
                else:
                    self.calc_required_average_km_h = Limits.goal_max_required_speed
                self.is_finished = False
            else:
                if not self.is_finished:
                    self.is_finished = True
                    self.calc_required_average_km_h = self.speed_avg
                    self.is_started = False

            self.optimal_distance_km = self.target_average_km_h.value * self.trip_duration_sec / 3600
            pass

    @property
    def is_behind(self): #ut
        return self.trip_distance < self.optimal_distance_km

    def get_all_attributes(self):
        return [attr for attr in dir(self) if not callable(getattr(self, attr)) and not attr.startswith("__")]

    def save(self):
        DataStore.save(self, filename)

    def load(self):
        DataStore.load(self, filename)

    def process_data(self, cd):
        TripData.process_data(self, cd)
        self.calculate_progress()

    def enable(self, enabled):
        TripData.enable(self, enabled)
        if enabled:
            self.calculate_progress()


# _*_ coding:utf-8 _*_
import tensorflow as tf
import config
import network
import os

def train(args, sess, model):
    # Adam optimizers are used instead of AdaDelta
    # parser.add_argument('--learning_rate', dest='learning_rate', default=0.001, help='learning rate of the optimizer')
    # parser.add_argument('--momentum', dest='momentum', default=0.5, help='momentum of the optimizer')
    """
    :param args: 预先设置的一些参数，学习率
    :param sess:
    :param model: 模型
    :return:
    """
    d_optimizer = tf.train.AdamOptimizer(args.learning_rate, beta1=args.momentum, name="AdamOptimizer_D").minimize(model.d_loss, var_list=model.d_vars)
    c_optimizer = tf.train.AdamOptimizer(args.learning_rate, beta1=args.momentum, name="AdamOptimizer_C").minimize(model.recon_loss, var_list=model.c_vars)

    global_optimizer = tf.train.AdamOptimizer(args.learning_rate, beta1=args.momentum, name="AdamOptimizer_C").minimize(model.loss_all, var_list=model.c_vars)

    epoch = 0
    step = 0
    global_step = 0

    # saver
    # 创建saver对象实例用来保存训练好的模型和调用已保存的模型
    saver = tf.train.Saver()

    # 默认continue_training设置的是false
    if args.continue_training:
        tf.local_variables_initializer().run()
        last_ckpt = tf.train.latest_checkpoint(args.checkpoints_path)
        saver.restore(sess, last_ckpt)
        ckpt_name = str(last_ckpt)
        print ("Loaded model file from " + ckpt_name)
        epoch = int(ckpt_name.split('-')[-1])
    else:
        # init = tf.initialize_all_variables()
        '''替换上面的函数,作用是返回一个初始化所有全局变量的操作(op),要是你把图投放到一个session后,你可以通过run
        操作来初始化所有的全局变量,本质相当于variable_initializers(global_variables())
        '''
        tf.global_variables_initializer().run()
        '''
        返回一个初始化所有局部变量的操作(op),要是你把图投放到一个session之中,你就能通过run这个操作来初始化所有的
        局部变量,本质相当有variable_initliazers(local_variables())
        '''
        tf.local_variables_initializer().run()
    '''
    tensorflow的session是支持多线程的,可以在同一个session中创建多个线程,并行执行.在Session中的所有线程都必须能够
    同步终止,异常都必须能正确捕获并报告,session终止的时候,队列必须能被正确的关闭.tensorflow提供了两个类来实现对
    session中多线程的管理:tf.Coordinator和tf.QueueRunner,这两个类往往一起使用
    Coordinator类用来管理在Session中的多线程,可以用来同时停止多个工作线程并且向那个在等待所有工作线程终止的程序报告
    异常,该线程捕获到这个异常之后就会终止所有的线程.使用tf.train.Coordinator()来创建一个线程管理器(协调器)对象
    QueueRunner类来启动tensor的入队线程,可以用来启动多个工作线程同时将多个tensor推入到文件名称队列中,具体的执行函数是
    tf.train.start_queue_runners,只有调用该函数之后才会真正把tensor推入到内存序列中,供计算单元调用,否则会由于内存
    序列为空,数据流程图会处于一直等待状态
    https://blog.csdn.net/dcrmg/article/details/79780331
    '''
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    # summary init
    all_summary = tf.summary.merge([model.recon_loss_sum,
                                    model.d_loss_sum,
                                    model.loss_all_sum,
                                    model.input_img_sum,
                                    model.real_img_sum,
                                    model.recon_img_sum,
                                    model.g_local_imgs_sum,
                                    model.r_local_imgs_sum])
    writer = tf.summary.FileWriter(args.graph_path, sess.graph)

    # training starts here

    # first train completion network
    while epoch < args.train_step:

        # Training Stage 1 (Completion Network)
        if epoch < args.Tc:
            summary, c_loss, _ = sess.run([all_summary, model.recon_loss, c_optimizer])
            if epoch%200 == 0:
                writer.add_summary(summary, global_step)
                global_step += 1
            print ("Epoch [%d] Step [%d] C Loss: [%.4f]" % (epoch, step, c_loss))
        elif epoch < args.Tc + args.Td:
            # Training Stage 2 (Discriminator Network)
            summary, d_loss, _ = sess.run([all_summary, model.d_loss, d_optimizer])
            if epoch%200 == 0:
                writer.add_summary(summary, global_step)
                global_step += 1
            print ("Epoch [%d] Step [%d] D Loss: [%.4f]" % (epoch, step, d_loss))
        else:
            # Training Stage 3 (Completion Network)
            summary, g_loss, _ = sess.run([all_summary, model.loss_all, global_optimizer])
            if epoch%200 == 0:
                writer.add_summary(summary, global_step)
                global_step += 1
            print ("Epoch [%d] Step [%d] G Loss: [%.4f]" % (epoch, step, g_loss) )
        # Check Test image results every time epoch is finished
        if step*args.batch_size >= model.data_count:
            saver.save(sess, args.checkpoints_path + "/model")
            # global_step=epoch)

            # res_img = sess.run(model.test_res_imgs)

            # save test img result
            # img_tile(epoch, args, res_img)
            step = 0
            epoch += 1

        step += 1
    coord.request_stop()
    coord.join(threads)
    sess.close()
    print("Done.")

def main(args):
    run_config = tf.ConfigProto()
    run_config.gpu_options.allow_growth = True

    # create graph, images, and checkpoints folder if they don't exist
    if not os.path.exists(args.checkpoints_path):
        os.makedirs(args.checkpoints_path)
    if not os.path.exists(args.graph_path):
        os.makedirs(args.graph_path)
    if not os.path.exists(args.images_path):
        os.makedirs(args.images_path)

    with tf.Session(config=run_config) as sess:
        # network模块中有network对象，用来定义网络结构
        model = network.network(args)

        print('Start Training...')
        train(args, sess, model)

main(config.args)

# Still Working....


import pandas as pd
import numpy as np
import glob
import fit_velocities, get_coordinates, fit_tide_gauge

def fit_all_velocities(folder, glob_pattern, file_type):

    """
    The function accepts a folder name, a 'glob' pattern, and a string that either denotes a 'GNSS' or 'tide' string and returns a
    pandas data frame with the site name, coordinates, velocities and uncertainties.
    It uses the modules 'fit_velocities', 'get_coordinates', and fit_tide_gauge.
    param a: folder as a string
    param b: a 'glob' pattern that searches for the file of interest.
    param c: takes in the string 'GNSS' or 'tide' file and estimates rates for specified file.
    returns: a pandas dataframe with the site name, coordinates, velocities, and uncertainties for GNSS files and the rate of change
    and uncertainty for tide data.
    """

    if file_type == 'GNSS':

        filename_list = []
        sitename_list = []
        csv_files = glob.glob(f"{folder}/{glob_pattern}")

        #Iterates through the glob and extracts the filename and stores in a list
        for i in csv_files:
            filename = i.split('\\')[-1]
            sitename = filename.split('/')[-1].split('.')[0]
            sitename_list.append(sitename)

        velocities = [fit_velocities.fit_velocities(file) for file in csv_files]
        coordinates = [get_coordinates.get_coordinates(file) for file in csv_files]

        #Create individual dataframes
        site_name = pd.DataFrame({'site name':sitename_list})
        veloc = pd.DataFrame(velocities)
        coord = pd.DataFrame(coordinates)

        new_df = pd.DataFrame(data = {'latitude': coord[0], 'longitude': coord[1], 'elevation': coord[2],
                                    'east component velocity': veloc.iloc[:, 0].apply(lambda x: x[0]), 'north component velocity': veloc.iloc[:, 0].apply(lambda x: x[1]),
                                    'up component velocity': veloc.iloc[:, 0].apply(lambda x: x[2]),'east component uncertainty': veloc.iloc[:, 1].apply(lambda x: x[0]),
                                    'north component uncertainty': veloc.iloc[:, 1].apply(lambda x: x[1]), 'up component uncertainty': veloc.iloc[:, 1].apply(lambda x:x[2])})

        #Combine the dataframes
        final_df = pd.concat([site_name, new_df], axis = 1)

        return(final_df)

    else:
        filename_list = []
        sitename_list = []
        csv_files = glob.glob(f"{folder}/{glob_pattern}")

        for i in csv_files:
            filename = i.split('\\')[-1]
            sitename = filename.split('.')[0]
            sitename_list.append(sitename)

        velocities = [fit_tide_gauge.fit_tide_gauge(file) for file in csv_files]

        #Create individual dataframes
        site_name = pd.DataFrame({'site name':sitename_list})
        veloc = pd.DataFrame(velocities)

        new_df = pd.DataFrame(data = {'velocity': veloc[0], 'uncertainty': veloc[1]})

        #Combine the dataframes
        final_df = pd.concat([site_name, new_df], axis = 1)

        return(final_df)


from multiprocessing import Process,Queue
from data_set.data_gen import get_batch_inception
from config.cfg import config_instace as config
import time
gen = get_batch_inception(config.batch_size,image_size=config.image_size[0])

def new_get_data(quene):
    while True:
        org_im, box, label,r_match,r_box = next(gen)
        quene.put([org_im, box, label,r_match,r_box])

numT = 4
q = Queue(numT)
ps = []
for p in range(numT):
    ps.append(Process(target=new_get_data,args=(q,)))
for pd in ps:
    pd.start()


import inspect
import warnings
from typing import List, Optional, Union

import torch
import numpy as np
from tqdm.auto import tqdm
from transformers import CLIPFeatureExtractor, CLIPTextModel, CLIPTokenizer

from diffusers.models import AutoencoderKL, UNet2DConditionModel
from diffusers.pipeline_utils import DiffusionPipeline
from diffusers.schedulers import DDIMScheduler, LMSDiscreteScheduler, PNDMScheduler
# from diffusers import StableDiffusionSafetyChecker
from PIL import Image
from io import BytesIO
import requests
import pandas as pd
import xlwings as xw
import random

class StableDiffusionPipeline(DiffusionPipeline):
    def __init__(
        self,
        vae: AutoencoderKL,
        text_encoder: CLIPTextModel,
        tokenizer: CLIPTokenizer,
        unet: UNet2DConditionModel,
        scheduler: Union[DDIMScheduler, PNDMScheduler, LMSDiscreteScheduler],
        safety_checker,
        feature_extractor: CLIPFeatureExtractor,
    ):
        super().__init__()
        scheduler = scheduler.set_format(format)
        self.register_modules(
            vae=vae,
            text_encoder=text_encoder,
            tokenizer=tokenizer,
            unet=unet,
            scheduler=scheduler,
            safety_checker=safety_checker,
            feature_extractor=feature_extractor,
        )

    @torch.no_grad()
    def __call__(
        self,
        prompt: Union[str, List[str]],
        height: Optional[int] = 512,
        width: Optional[int] = 512,
        num_inference_steps: Optional[int] = 50,
        guidance_scale: Optional[float] = 7.5,
        eta: Optional[float] = 0.0,
        generator: Optional[torch.Generator] = None,
        latents: Optional[torch.FloatTensor] = None,
        output_type: Optional[str] = "pil",
        **kwargs,
    ):
        if "torch_device" in kwargs:
            device = kwargs.pop("torch_device")
            warnings.warn(
                "`torch_device` is deprecated as an input argument to `__call__` and will be removed in v0.3.0."
                " Consider using `pipe.to(torch_device)` instead."
            )

            # Set device as before (to be removed in 0.3.0)
            if device is None:
                device = "cuda" if torch.cuda.is_available() else "cpu"
            self.to(device)

        onnx = False
        if "execution_provider" in kwargs:
            onnx = True
            self.scheduler = self.scheduler.set_format("np")
            ep = kwargs.pop("execution_provider")
            import onnxruntime as ort
            so = ort.SessionOptions()
            so.enable_mem_pattern=False
            unet_sess = ort.InferenceSession("onnx/unet.onnx", so, providers=[ep])
            post_quant_conv_sess = ort.InferenceSession("onnx/post_quant_conv.onnx", so, providers=[ep])
            decoder_sess = ort.InferenceSession("onnx/decoder.onnx", so, providers=[ep])
            encoder_sess = ort.InferenceSession("onnx/encoder.onnx", so, providers=[ep])

        if isinstance(prompt, str):
            batch_size = 1
        elif isinstance(prompt, list):
            batch_size = len(prompt)
        else:
            raise ValueError(f"`prompt` has to be of type `str` or `list` but is {type(prompt)}")

        if height % 8 != 0 or width % 8 != 0:
            raise ValueError(f"`height` and `width` have to be divisible by 8 but are {height} and {width}.")

        # get prompt text embeddings
        text_input = self.tokenizer(
            prompt,
            padding="max_length",
            max_length=self.tokenizer.model_max_length,
            truncation=False,
            return_tensors="pt",
        )

        if onnx: text_embeddings = encoder_sess.run(None, {"text_input": text_input.input_ids.numpy()})[0]
        else: text_embeddings = self.text_encoder(text_input.input_ids.to(self.device))[0]

        # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)
        # of the Imagen paper: https://arxiv.org/pdf/2205.11487.pdf . `guidance_scale = 1`
        # corresponds to doing no classifier free guidance.
        do_classifier_free_guidance = guidance_scale > 1.0
        # get unconditional embeddings for classifier free guidance
        if do_classifier_free_guidance:
            max_length = text_input.input_ids.shape[-1]
            uncond_input = self.tokenizer(
                [""] * batch_size, padding="max_length", max_length=max_length, truncation=False, return_tensors="pt"
            )

            # For classifier free guidance, we need to do two forward passes.
            # Here we concatenate the unconditional and text embeddings into a single batch
            # to avoid doing two forward passes
            if onnx:
                uncond_embeddings = encoder_sess.run(None, {"text_input": uncond_input.input_ids.numpy()})[0]
                text_embeddings = np.concatenate([uncond_embeddings, text_embeddings])
            else:
                uncond_embeddings = self.text_encoder(uncond_input.input_ids.to(self.device))[0]
                text_embeddings = torch.cat([uncond_embeddings, text_embeddings])

        # get the initial random noise unless the user supplied it
        latents_shape = (batch_size, self.unet.in_channels, height // 8, width // 8)
        if latents is None:
            latents = torch.randn(latents_shape, generator=generator, device=self.device)
        else:
            if latents.shape != latents_shape:
                raise ValueError(f"Unexpected latents shape, got {latents.shape}, expected {latents_shape}")
            latents = latents.to(self.device)
        if onnx: latents = latents.numpy() # use pytorch rand to get consistent results

        # set timesteps
        accepts_offset = "offset" in set(inspect.signature(self.scheduler.set_timesteps).parameters.keys())
        extra_set_kwargs = {}
        if accepts_offset:
            extra_set_kwargs["offset"] = 1

        self.scheduler.set_timesteps(num_inference_steps, **extra_set_kwargs)

        # if we use LMSDiscreteScheduler, let's make sure latents are mulitplied by sigmas
        if isinstance(self.scheduler, LMSDiscreteScheduler):
            latents = latents * self.scheduler.sigmas[0]

        # prepare extra kwargs for the scheduler step, since not all schedulers have the same signature
        # eta (η) is only used with the DDIMScheduler, it will be ignored for other schedulers.
        # eta corresponds to η in DDIM paper: https://arxiv.org/abs/2010.02502
        # and should be between [0, 1]
        accepts_eta = "eta" in set(inspect.signature(self.scheduler.step).parameters.keys())
        extra_step_kwargs = {}
        if accepts_eta:
            extra_step_kwargs["eta"] = eta

        for i, t in tqdm(enumerate(self.scheduler.timesteps)):
            # expand the latents if we are doing classifier free guidance
            if onnx and do_classifier_free_guidance: latent_model_input = np.concatenate([latents] * 2)
            else: latent_model_input = torch.cat([latents] * 2) if do_classifier_free_guidance else latents

            if isinstance(self.scheduler, LMSDiscreteScheduler):
                sigma = self.scheduler.sigmas[i]
                latent_model_input = latent_model_input / ((sigma**2 + 1) ** 0.5)
                if onnx: latent_model_input = latent_model_input.astype('float32')

            # predict the noise residual
            if onnx:
                inp = {"latent_model_input": latent_model_input,
                       "t": np.array([t], dtype=np.int64),
                       "encoder_hidden_states": text_embeddings}
                noise_pred = unet_sess.run(None, inp)[0]
            else:
                noise_pred = self.unet(latent_model_input, t, encoder_hidden_states=text_embeddings)

            # perform guidance
            if do_classifier_free_guidance:
                if onnx: noise_pred_uncond, noise_pred_text = np.array_split(noise_pred, 2)
                else: noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
                noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)

            # compute the previous noisy sample x_t -> x_t-1
            if isinstance(self.scheduler, LMSDiscreteScheduler):
                latents = self.scheduler.step(noise_pred, i, latents, **extra_step_kwargs)["prev_sample"]
            else:
                latents = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs)["prev_sample"]

        # scale and decode the image latents with vae
        latents = 1 / 0.18215 * latents
        if onnx:
            latents = post_quant_conv_sess.run(None, {"latents": latents.astype("float32")})[0]
            image = decoder_sess.run(None, {"latents": latents})[0]
            image = np.clip((image / 2 + 0.5), 0, 1)
            image = np.transpose(image, (0, 2, 3, 1))
        else:
            image = self.vae.decode(latents)
            image = (image / 2 + 0.5).clamp(0, 1)
            image = image.cpu().permute(0, 2, 3, 1).numpy()

        # run safety checker
        safety_cheker_input = self.feature_extractor(self.numpy_to_pil(image), return_tensors="pt").to(self.device)
        # image, has_nsfw_concept = self.safety_checker(images=image, clip_input=safety_cheker_input.pixel_values)

        if output_type == "pil":
            image = self.numpy_to_pil(image)

        return {"sample": image,}# "nsfw_content_detected": has_nsfw_concept}

if __name__ == '__main__':
    #img_url = r'C:\Users\jay\Desktop\PythonInOffice\stable_diffusion_amd\diffusers-dml\examples\inference\test2.jpg'
    #url = "https://raw.githubusercontent.com/CompVis/stable-diffusion/main/assets/stable-samples/img2img/sketch-mountains-input.jpg"
    #response = requests.get(url)
    #init_image = Image.open(BytesIO(response.content)).convert("RGB")
    #init_image = init_image.resize((768, 512))

    # init_image = Image.open(img_url)
    # init_image = init_image.resize((512,512))

    df_prompts = pd.read_csv(r'C:\Users\jay\Desktop\stable_diffusion\stable-diffusion-main\scripts\prompts.csv')
    img_files = r'C:\Users\jay\Desktop\stable_diffusion\stable-diffusion-main\outputs\txt2img-samples\multiple'
    prompts = df_prompts['prompts']
    num =3
    wb = xw.Book()
    ws = wb.sheets[0]
    letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

    lms = LMSDiscreteScheduler(beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear")
    pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", scheduler=lms, use_auth_token=True)

    ws.range(1,1).value = 'Prompts'
    ws.range(f"2:{len(prompts)+1}").row_height = 130
    ws.range(f'B:{letters[num]}').column_width = 30

    r = 2
    for p in prompts:
        c = 2
        for s in range(1,num+1):
            seed = random.randint(0,4294967295)
            torch.manual_seed(seed)
            #seed = 100
            image = pipe(prompt, height=512, width=512, num_inference_steps=30, guidance_scale=7.5, eta=0.0, execution_provider="DmlExecutionProvider")["sample"][0]
            image.save(f"{r}_{c}.png")
            ws.range(r,1).value = p
            ws.range(r,c).value = seed
            ws.pictures.add(rf'{img_files}\{r}_{c}.png', left = ws.range(r,c).left, top = ws.range(r,c).top, scale = 0.3)
            c += 1
        r += 1

    wb.save(r'C:\Users\jay\Desktop\stable_diffusion\stable-diffusion-main\scripts\prompts_grid_amd.xlsx')

    #torch.manual_seed(42)

    # prompt = ["""background dark, block houses, eastern Europe, city highly detailed oil painting,
    # unreal 5 render, rhads, bruce pennington, studio ghibli, tim hildebrandt, digital art,
    # octane render, beautiful composition, trending on artstation, award-winning photograph, masterpiece"""]

    # image2 = pipe(prompt, height=512, width=512, num_inference_steps=50, guidance_scale=7.5, eta=0.0, execution_provider="DmlExecutionProvider")["sample"][1]
    # image.save("Dml_02.png")
    # Works on AMD Windows platform
    # Image width and height is set to 512x512
    # If you need images of other sizes (size must be divisible by 8), make sure to save the model with that size in save_onnx.py
    # For example, if you need height=512 and width=768, change create_onnx.py with height=512 and width=768 and run the prompt below with height=512 and width=768
    # Default values are height=512, width=512, num_inference_steps=50, guidance_scale=7.5, eta=0.0, execution_provider="DmlExecutionProvider"

    # prompt = "a photo of an astronaut riding a horse on mars"
    # image = pipe(prompt, height=512, width=768, num_inference_steps=50, guidance_scale=7.5, eta=0.0, execution_provider="DmlExecutionProvider")["sample"][0]
    # image.save("Dml_1.png")


import argparse
import os
import sys
from datetime import datetime

import requests
import piexif
from rich.progress import track
from rich.console import Console

from aulaclient import AulaClient

class Arguments:
    def __init__(self):
        parser = argparse.ArgumentParser(description='Download images from aula.dk.')
        parser.add_argument(
            '--outputFolder',
            required=True,
            default='output',
            help='Download images in this folder')
        parser.add_argument(
            '--cutoffDate',
            required=True,
            help='Download images posted on or after this date (format: "YYYY-MM-DD")')
        parser.add_argument(
            '--tags',
            required=False,
            nargs='+',
            help='Download images having at least one of these tags')
        args = parser.parse_args()

        self.cutoff_date = datetime.fromisoformat(args.cutoffDate).date()
        self.tags_to_find = args.tags
        self.output_directory = args.outputFolder

    def print_arguments(self):
        param_style = "cyan"
        console.print("Parameters:", style=param_style)
        console.print(f"  outputDirectory: {self.output_directory}", style=param_style)
        console.print(f"  cutoffDate: {self.cutoff_date.strftime('%Y-%m-%d')}", style=param_style)
        if self.tags_to_find:
            console.print(f"  tags: {self.tags_to_find}", style=param_style)
        console.print()

class AlbumToDownload:
    def __init__(self, name, album_type, creation_date, pictures):
        self.name = name
        self.album_type = album_type
        self.creation_date = creation_date
        self.pictures = pictures

    def __str__(self):
        return f"Type: {self.album_type}, CreationDate: {self.creation_date}, '\
            'Pictures: {len(self.pictures)}, Name: {self.name}"

def parse_date(date_string):
    return datetime.strptime(date_string.split('T')[0], '%Y-%m-%d').date()

def parse_datetime(date_string):
    return datetime.strptime(date_string, '%Y-%m-%dT%H:%M:%S%z')

def clean_title(title):
    return title.strip().replace('/', '_').replace(':', '_').replace('?', '_')

def picture_has_tags(picture, tags):
    if not picture['tags']:
        return False

    picture_tags = list(map(lambda t: t['name'], picture['tags']))
    for tag in tags:
        if tag in picture_tags:
            return True
    return False

def add_exif_creation_time(image_path, creation_time):
    is_jpeg = image_path.lower().endswith(('.jpg', '.jpeg'))
    if is_jpeg:
        zeroth_ifd = {
            piexif.ImageIFD.DateTime: creation_time.strftime('%Y:%m:%d %H:%M:%S'),
        }
        exif_ifd = {
            piexif.ExifIFD.DateTimeOriginal: creation_time.strftime('%Y:%m:%d %H:%M:%S'),
        }
        exif_dict = {"0th": zeroth_ifd, "Exif": exif_ifd}
        exif_bytes = piexif.dump(exif_dict)
        piexif.insert(exif_bytes, image_path)

def get_albums_from_gallery(institution_profile_ids, cutoff_date):
    print('Get Albums...')
    additional_params = {'limit': 1000}
    albums_to_download = []
    albums = client.get_albums(institution_profile_ids, additional_params)
    albums_with_id = filter_list_with_property(albums, 'id')
    for album in albums_with_id:
        creation_date = parse_date(album['creationDate'])
        is_album_created_after_cutoff_date = creation_date >= cutoff_date
        if not is_album_created_after_cutoff_date:
            continue
        pictures = client.get_pictures(institution_profile_ids, album['id'], additional_params)
        if pictures:
            name = clean_title(album['title'])
            album = AlbumToDownload(name, "Album", creation_date, pictures)
            albums_to_download.append(album)
    return albums_to_download

def filter_list_with_property(list_to_filter, property_name: str):
    return list(filter(lambda a: a[property_name] is not None, list_to_filter))

def get_albums_from_posts(institution_profile_ids, children_ids, cutoff_date):
    print('Get Posts...')
    additional_params = {'limit': 1000}
    albums_to_download = []
    get_posts_institution_profile_ids = institution_profile_ids + children_ids
    posts = client.get_posts(get_posts_institution_profile_ids, additional_params)
    for post in posts:
        creation_date = parse_date(post['publishAt'])
        is_post_after_cutoff_date = creation_date >= cutoff_date
        if not is_post_after_cutoff_date:
            continue
        attachments_with_media = filter_list_with_property(post['attachments'], 'media')
        if attachments_with_media:
            name = clean_title(post['title'])
            pictures = list(map(lambda x: x['media'], attachments_with_media))
            if pictures:
                album = AlbumToDownload(name, "Post", creation_date, pictures)
                albums_to_download.append(album)
    return albums_to_download

def get_albums_from_messages(cutoff_date):
    print('Get Threads...')
    albums_to_download = []
    threads = get_threads(cutoff_date)
    for thread in threads:
        thread_id = thread['id']
        thread_latest_message_time = parse_datetime(thread['latestMessage']['sendDateTime'])
        is_thread_updated_after_cutoff_date = thread_latest_message_time.date() >= cutoff_date
        if not is_thread_updated_after_cutoff_date:
            break  # Following threads won't be updated either, exit
        messages_with_attachments = get_messages_with_attachments_in_thread(thread_id)
        for message_index, message in enumerate(messages_with_attachments):
            attachments_with_media = filter_list_with_property(message['attachments'], 'media')
            name = f"{clean_title(thread['subject'])}_{message_index:02d}"
            creation_date = parse_date(thread['startedTime'])
            pictures = list(map(lambda x: x['media'], attachments_with_media))
            if pictures:
                album = AlbumToDownload(name, "Message", creation_date, pictures)
                albums_to_download.append(album)
    return albums_to_download

def get_threads(cutoff_date):
    threads_page_param = {'page': 0}
    threads_response = client.get_threads(threads_page_param)
    threads = threads_response['threads']
    while threads_response['moreMessagesExist']:
        threads_page_param['page'] += 1
        threads_response = client.get_threads(threads_page_param)
        threads += threads_response['threads']
        last_thread_update_time = parse_datetime(threads[-1]['latestMessage']['sendDateTime'])
        if last_thread_update_time.date() < cutoff_date:
            break
    return threads

def get_messages_with_attachments_in_thread(thread_id):
    page_param = {'page': 0}
    messages_response = client.get_messages_for_thread(thread_id, page_param)
    messages = messages_response['messages']
    while messages_response['moreMessagesExist']:
        page_param['page'] += 1
        messages_response = client.get_messages_for_thread(thread_id, page_param)
        messages += messages_response['messages']
    messages_with_attachments = list(filter(lambda x: x['hasAttachments'], messages))
    return messages_with_attachments

def get_image_data(album: AlbumToDownload, output_directory, file_data):
    album_directory_name = album.creation_date.strftime('%Y%m%d') + ' ' + album.name
    album_directory_path = os.path.join(output_directory, album_directory_name)
    image_creation_time = datetime.strptime(file_data['created'], '%Y-%m-%dT%H:%M:%S%z')
    image_response = requests.get(file_data['url'], timeout=30)

    if image_creation_time.date() == album.creation_date:
        image_directory_path = album_directory_path
    else:
        folder_name = image_creation_time.strftime('%Y%m%d')
        image_directory_path = os.path.join(album_directory_path, folder_name)

    return {
        "image_directory_path": image_directory_path,
        "image_content": image_response.content,
        "image_creation_time": image_creation_time
    }

def main():
    args = Arguments()
    args.print_arguments()

    try:
        profiles = client.get_profiles()
    except PermissionError as error:
        console.print(error, style="red")
        console.print("Could not get profiles, exiting.", style="red")
        sys.exit()

    institution_ids = list(map(lambda p: p['id'], profiles[0]['institutionProfiles']))
    children_ids = list(map(lambda p: p['id'], profiles[0]['children']))

    albums_to_download = []
    albums_to_download += get_albums_from_gallery(institution_ids, args.cutoff_date)
    albums_to_download += get_albums_from_posts(institution_ids, children_ids, args.cutoff_date)
    albums_to_download += get_albums_from_messages(args.cutoff_date)

    print('Download Pictures...')
    for album in track(albums_to_download, "Albums to download..."):
        if album.creation_date < args.cutoff_date:
            continue
        print('>', album, end=' ', flush=True)
        for picture in album.pictures:
            tags_are_found_or_ignored = (not args.tags_to_find
                                         or picture_has_tags(picture, args.tags_to_find))
            if tags_are_found_or_ignored:
                file_data = picture['file']
                image_data = get_image_data(album, args.output_directory, file_data)

                os.makedirs(image_data["image_directory_path"], exist_ok=True)
                image_path = os.path.join(image_data["image_directory_path"], file_data['name'])
                with open(image_path, "wb") as image_file:
                    image_file.write(image_data["image_content"])
                add_exif_creation_time(image_path, image_data["image_creation_time"])

if __name__ == '__main__':
    console = Console()
    client = AulaClient()
    main()


import random as R

#LEER UN ENTERO CON CONTROL DE ERROR DE TIPO DE DATO declarar fichas!!
def leerInt(cartel,desde=-9999999999,hasta=9999999999):
    salir = False
    numero = 0
    while not salir:
        try:
            numero = int(input(cartel))
            if numero < desde or  numero > hasta:
                print("ERROR ==> numero fuera de rango\n")
            else:
                salir = True
        except:
            print("ERROR ==> Ingrese un numero entero\n")
    return numero

class Ficha:
    def __init__(self,caracter):
        self.caracter = caracter

    def __str__(self):
        return '['+self.caracter+']'

class Tablero:

    def __init__(self,filas=3,columnas=3):
        self.cf = filas
        self.cc = columnas
        self.mat = []
        for f in range(self.cf):
            col = []
            for c in range(self.cc):
                col.append(Ficha(' '))
            self.mat.append(col)

    def __str__(self):
        cadena = ""
        for f in range(self.cf):
            for c in range(self.cc):
                cadena += str(self.mat[f][c])
            cadena += "\n"
        return cadena

    def poner(self,f,c,ficha):
        self.mat[f][c] = ficha

    def ver(self,f,c):
        return self.mat[f][c]

    # def tableroVacio(self):
    #     salir = False
    #     cont = 0
    #     while cont < 9 and salir:
    #         for f in range(self.cf):
    #             for c in range(self.cc):
    #                 if str(self.mat[f][c]) == str(Ficha(" ")):
    #                     cont += 1
    #                     if cont > 9:
    #                         salir = True
    #     return True

    def existe(self,ficha):
        for f in range(self.cf):
            for c in range(self.cc):

                if str(ficha) == str(self.mat[f][c]):
                    return True
        return False

    def filaIgual(self,fila,ficha):
        for c in range(self.cc):
            if str(ficha) != str(self.mat[fila][c]):
                return False
        return True

    def columnaIgual(self,columna,ficha):
        for f in range(self.cf):
            if str(ficha) != str(self.mat[f][columna]):
                return False
        return True

    def digonalIgual(self,ficha):
        for x in range(self.cf):
            if str(self.mat[x][x]) != str(ficha):
                return False
        return True

    def digonalSecIgual(self,ficha):
        f = 0
        c = self.cc-1
        while f < self.cf:
            if str(self.mat[f][c]) != str(ficha):
                return False
            f += 1
            c -= 1
        return True

class Jugador(object):

    def __init__(self,nombre,ficha):
        self.nombre = nombre
        self.ficha = ficha

    def __str__(self):
        return self.nombre + " ==> "+str(self.ficha)

    def jugar(self,tablero):
        pass

class Humano(Jugador):

    def __init__(self,nombre,ficha):
        Jugador.__init__(self,nombre,ficha)

    def jugar(self,tablero):
        salir = False
        while not salir:
            fila = leerInt("Fila: ",0,tablero.cf-1)
            columna = leerInt("Columna: ",0,tablero.cc-1)
            if str(tablero.ver(fila,columna)) == str(Ficha(' ')):
                salir = True
        return Coordenada(fila,columna)

class Computadora(Jugador):

    def __init__(self,nombre,ficha):
        Jugador.__init__(self,nombre,ficha)

    def jugar(self,tablero):
        salir = False
        while not salir:
            fila = R.randint(0,tablero.cf-1)
            columna = R.randint(0,tablero.cc-1)
            if str(tablero.ver(fila,columna)) == str(Ficha(' ')):
                salir = True
        return Coordenada(fila,columna)

class IA(Jugador):

    def __init__(self,nombre,ficha):
        Jugador.__init__(self,nombre,ficha)

    def esTateti(self,ficha,tablero):
            for fila in  range(tablero.cf):
                if tablero.filaIgual(fila,ficha):
                    return True
            for columna in range(tablero.cc):
                if tablero.columnaIgual(columna,ficha):
                    return True
            return tablero.digonalIgual(ficha) or tablero.digonalSecIgual(ficha)

    def jugar(self,tablero):
        salir = False
        miFicha = self.ficha
        if str(self.ficha) == str(Ficha("X")):
            suFucha = Ficha('O')
        else:
            suFicha = Ficha("X")
        while not salir:
            for f in range(tablero.cf):
                for c in range(tablero.cc):
                    if str(tablero.ver(f,c)) == str(Ficha(" ")):
                        tablero.poner(f,c,miFicha)
                        if self.esTateti(miFicha,tablero):
                            tablero.poner(f,c,Ficha(" "))
                            return Coordenada(f,c)
                        else:
                            tablero.poner(f,c,Ficha(" "))

            for f in range(tablero.cf):
                for c in range(tablero.cc):
                    if str(tablero.ver(f,c)) == str(Ficha(" ")):
                        tablero.poner(f,c,suFicha)
                        if self.esTateti(suFicha,tablero):
                            tablero.poner(f,c,Ficha(" "))
                            return Coordenada(f,c)
                        else:
                            tablero.poner(f,c,Ficha(" "))

            fila = R.randint(0,tablero.cf-1)
            columna = R.randint(0,tablero.cc-1)
            if str(tablero.ver(fila,columna)) == str(Ficha(' ')):
                salir = True
        return Coordenada(fila,columna)

class SUPERIA(Jugador):

    def __init__(self,nombre,ficha):
        Jugador.__init__(self,nombre,ficha)

    def esTateti(self,ficha,tablero):
            for fila in  range(tablero.cf):
                if tablero.filaIgual(fila,ficha):
                    return True
            for columna in range(tablero.cc):
                if tablero.columnaIgual(columna,ficha):
                    return True
            return tablero.digonalIgual(ficha) or tablero.digonalSecIgual(ficha)

    def tableroVacio(self,tablero):
        salir = False
        cont = 0
        while cont < 9 and salir:
            for f in range(tablero.cf):
                for c in range(tablero.cc):
                    if str(tablero.mat[f][c]) == str(Ficha(" ")):
                        cont += 1
                        if cont > 9:
                            salir = True
        return True

    def dondepone(self,tablero):
        cont = 0
        for f in range(tablero.cf):
                for c in range(tablero.cc):
                    if str(tablero.ver(f,c)) != str(Ficha(" ")):
                        cont += 1
                        return tablero.ver(f,c)

    def jugar(self,tablero):
        salir = False
        miFicha = self.ficha
        dPone = self.dondepone(tablero)
        if str(self.ficha) == str(Ficha("X")):
            suFucha = Ficha('O')
        else:
            suFicha = Ficha("X")
        for f in range(tablero.cf):
            for c in range(tablero.cc):
                if self.tableroVacio(tablero):
                    jugada = R.randint(0,1)
                    if jugada == 0:
                        ub = R.randint(1,4)
                        if ub == 1:
                            f=0
                            c=0
                        else:
                            if ub == 2:
                                f=0
                                c=2
                            else:
                                if ub == 3:
                                    f=2
                                    c=0
                                else:
                                    if ub == 4:
                                        f=2
                                        c=2
                                        return Coordenada(f,c)
                    else:
                        if jugada == 1:
                            ub = R.randint(1,4)
                            if ub == 1:
                                f=1
                                c=0
                            else:
                                if ub == 2:
                                    f=0
                                    c=1
                                else:
                                    if ub == 3:
                                        f=2
                                        c=1
                                    else:
                                        if ub == 4:
                                            f=1
                                            c=2
                            return Coordenada(f,c)
                        else:
                            if dPone == tablero.ver(0,0):
                                return Coordenada(1,1)
                            else:
                                if dPone == tablero.ver(2,0):
                                    return Coordenada(1,1)

                #REMATE
        for f in range(tablero.cf):
            for c in range(tablero.cc):
                if str(tablero.ver(f,c)) == str(Ficha(" ")):
                    tablero.poner(f,c,miFicha)
                    if self.esTateti(miFicha,tablero):
                        tablero.poner(f,c,Ficha(" "))
                        return Coordenada(f,c)
                    else:
                        tablero.poner(f,c,Ficha(" "))
                #DEFENSA
        for f in range(tablero.cf):
            for c in range(tablero.cc):
                if str(tablero.ver(f,c)) == str(Ficha(" ")):
                    tablero.poner(f,c,suFicha)
                    if self.esTateti(suFicha,tablero):
                        tablero.poner(f,c,Ficha(" "))
                        return Coordenada(f,c)
                    else:
                        tablero.poner(f,c,Ficha(" "))
                #RANDOM
        fila = R.randint(0,tablero.cf-1)
        columna = R.randint(0,tablero.cc-1)
        if str(tablero.ver(fila,columna)) == str(Ficha(' ')):
            salir = True
        return Coordenada(fila,columna)

class Coordenada:
    def __init__(self,fila=0,columna=0):
        self.fila = fila
        self.columna = columna

class Tateti:

    def __init__(self,jug1,jug2):
        self.jug1 = jug1
        self.jug2 = jug2
        self.tablero = Tablero()

    def jugarTateti(self):

        if R.randint(0,1) == 0:
            jugAux = self.jug1
        else:
            jugAux = self.jug2

        ganar = False
        print(str(self.tablero))

        while not ganar and self.tablero.existe(Ficha(' ')):
            print("JUEGA: " + str(jugAux))
            coor = jugAux.jugar(self.tablero)
            self.tablero.poner(coor.fila,coor.columna,jugAux.ficha)
            print(str(self.tablero))
            if self.esTateti(jugAux.ficha):
                ganar = True
            else:
                jugAux = self.elOtro(jugAux)
        if ganar:
            print("Ganador: " + str(jugAux))
        else:
            print("Empate!!!!!!!")

    def elOtro(self,humano):
        if humano == self.jug2:
            return self.jug1
        return self.jug2

    def esTateti(self,ficha):
        for fila in  range(self.tablero.cf):
            if self.tablero.filaIgual(fila,ficha):
                return True
        for columna in range(self.tablero.cc):
            if self.tablero.columnaIgual(columna,ficha):
                return True
        return self.tablero.digonalIgual(ficha) or self.tablero.digonalSecIgual(ficha)

def main():

    """
    h = Humano("Juan",Ficha('O'))
    c = Computadora("CompuJuan",Ficha('X'))

    print(str(h))
    print(str(c))
    t = Tablero()
    t.poner(0,0,Ficha('X'))
    t.poner(1,1,Ficha('X'))
    t.poner(2,2,Ficha('X'))
    print(str(t))
    """
    print("---------------")
    print(f"Comienza el Juego de TA-TE-TI\nPara poder jugar primero debe indicarnos su nombre. \nPara poner una ficha debe indicar la fila y luego la columna (tenga en cuanta que para ambos casos se comienza a contar del 0 al 2) ")
    print("===============")
    name_p1 = input("Escribe tu nombre:")
    juego = Tateti(Humano(name_p1,Ficha('X')),SUPERIA("Computer",Ficha('O')))
    juego.jugarTateti()

main()


import pandas as pd
import numpy as np

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import pathlib

from typing import Union, Tuple, List, Iterable

'''defity the fuction to import, split, clean and normalize data'''
class dataTool():
    def __init__(self, trainDF_Path: str, testDF_Path: str):
        '''importing training and test sets'''
        self.train = pd.read_csv(trainDF_Path)
        self.test = pd.read_csv(testDF_Path)
    #cleaning part
    def cleaning(self):
        '''to be defined'''
        pass
    #splitting part
    def split_data(self, data: pd.DataFrame, targetVar: str, split: bool = False, testSize: float = 0.25) -> Iterable[Union[pd.DataFrame, pd.DataFrame]]:
        '''split data based on users defne paramater'''
        df = data
        x_df = df.drop(targetVar, axis=1)
        y_df = df[targetVar]

        if split:

            x_train, x_test, y_train, y_test = train_test_split(x_df, y_df, test_size=testSize)
            self.brr

            return x_train, x_test, y_train, y_test

        self.brr

        return x_df, y_df
    # normalizing part
    def normalize(self, trainData, data: List[pd.DataFrame]) -> np.array:
        '''normalize data with minmaxscaler, using train data to train model'''
        outputList = []
        scalar = MinMaxScaler()
        scalar.fit(trainData)

        for item in data:
            normalData = scalar.transform(item)
            outputList.append(normalData)

        return outputList

    def __create_directory(self, path):
        pathlib.Path(path).mkdir(parents=True, exist_ok=True)

    def write_models(self, path):
        '''
        Kaan write your code here :dogeBuff:
        and also a really quick but clear documentation for the method :dogeBuff:
        '''
        self.__create_directory(path) # the path should end with a '/' for example 'models/'
        # Here use the pickle library to "pickle" the models, the return from that is a .pkl file
        # which can then be imported and used for prediction on any platform, even webpages back code, cool huh?
        # dogeBuff
        return f'Models written, located in {path}'

    @property
    def retrieveData(self) -> Union[pd.DataFrame, pd.DataFrame]:
        self.brr

        return self.train, self.test

    @property
    def brr(self):
        print(f'Data go {"brr"}')


def ficha_jogador(nome='', gols=''):
    if nome == '':
        nome = '< desconhecido >'
    if gols == '':
        gols = 0
    return print(f'O jogador {nome} fez {gols} gols(s) no campeonato.')

jogador = str(input('Nome do jogador: '))
gol = (input('Número de Gols: '))
if gol.isnumeric() == False:
    gol = ''
ficha_jogador(jogador, gol)


import os
from config import TOKEN, URL, url_davis, mbar_mmHg, mph_ms, in_mm
import flask
from flask import Flask, request
import telebot
import json
import urllib.request
import datetime
import pytz

#import requests

bot = telebot.TeleBot(TOKEN)
server = Flask(__name__)

def json_getweather():
    tzkiev = pytz.timezone('Europe/Kiev')
    date_now = datetime.datetime.now(tzkiev)
    data = urllib.request.urlopen(url_davis).read().decode()
    obj =  json.loads(data)
    observation_time = obj['observation_time_rfc822']
    lastupdated_time = datetime.datetime.strptime(observation_time, '%a, %d %b %Y %H:%M:%S %z')
    delta_time = date_now - lastupdated_time
    if delta_time.seconds < 3800:
        try:
            pressure = round(float(obj['pressure_mb']) * mbar_mmHg)
            temperature = float(obj['temp_c'])
            wind_speed = round(float(obj['wind_mph']) * mph_ms,1)
            wind_direction = obj['wind_dir']
            humidity = obj['relative_humidity']
            rain_ratehr = round(float(obj['davis_current_observation']['rain_rate_in_per_hr']) * in_mm,2)
            rain_dayin = round(float(obj['davis_current_observation']['rain_day_in']) * in_mm,2)
            if wind_direction == "North":
                wind_dir_uk = "ÐŸÑ–Ð²Ð½Ñ–Ñ‡Ð½Ð¸Ð¹"
            elif wind_direction == "South":
                wind_dir_uk = "ÐŸÑ–Ð²Ð´ÐµÐ½Ð½Ð¸Ð¹"
            elif wind_direction == "West":
                wind_dir_uk = "Ð—Ð°Ñ…Ñ–Ð´Ð½Ð¸Ð¹"
            elif wind_direction == "East":
                wind_dir_uk = "Ð¡Ñ…Ñ–Ð´Ð½Ð¸Ð¹"
            elif wind_direction == "Northeast" or wind_direction == "North-northeast" or wind_direction == "East-northeast":
                wind_dir_uk = "ÐŸÑ–Ð²Ð½Ñ–Ñ‡Ð½Ð¾-Ð¡Ñ…Ñ–Ð´Ð½Ð¸Ð¹"
            elif wind_direction == "Northwest" or wind_direction == "North-northwest" or wind_direction == "West-northwest":
                wind_dir_uk = "ÐŸÑ–Ð²Ð½Ñ–Ñ‡Ð½Ð¾-Ð—Ð°Ñ…Ñ–Ð´Ð½Ð¸Ð¹"
            elif wind_direction == "Southeast" or wind_direction == "South-southeast" or wind_direction == "East-southeast":
                wind_dir_uk = "ÐŸÑ–Ð²Ð´ÐµÐ½Ð½Ð¾-Ð¡Ñ…Ñ–Ð´Ð½Ð¸Ð¹"
            elif wind_direction == "Southwest" or wind_direction == "South-southwest" or wind_direction == "West-southwest":
                wind_dir_uk = "ÐŸÑ–Ð²Ð´ÐµÐ½Ð½Ð¾-Ð—Ð°Ñ…Ñ–Ð´Ð½Ð¸Ð¹"
            collecting_data ='ÐŸÐ¾Ð³Ð¾Ð´Ð° Ñ�Ñ‚Ð°Ð½Ð¾Ð¼ Ð½Ð° '+lastupdated_time.strftime("%H:%M\n")+'======================\n''Ð¢ÐµÐ¼Ð¿ÐµÑ€Ð°Ñ‚ÑƒÑ€Ð°: '+str(temperature)+' â„ƒ\n''Ð¢Ð¸Ñ�Ðº: '+str(pressure)+' Ð¼Ð¼ Ñ€Ñ‚. Ñ�Ñ‚.\n''Ð’Ð¾Ð»Ð¾Ð³Ñ–Ñ�Ñ‚ÑŒ: '+str(humidity)+'%\n''Ð¨Ð²Ð¸Ð´ÐºÑ–Ñ�Ñ‚ÑŒ Ð²Ñ–Ñ‚Ñ€Ñƒ: '+str(wind_speed)+' Ð¼/Ñ�\n''Ð�Ð°Ð¿Ñ€Ñ�Ð¼Ð¾Ðº Ð²Ñ–Ñ‚Ñ€Ñƒ: '+str(wind_dir_uk)+'\n''ÐžÐ¿Ð°Ð´Ð¸: '+str(rain_dayin)+' Ð¼Ð¼/Ð´ÐµÐ½ÑŒ, '+str(rain_ratehr)+' Ð¼Ð¼/Ð³Ð¾Ð´.'
        except KeyError:
                collecting_data = "â�—ï¸�ÐœÐµÑ‚ÐµÐ¾Ñ�Ñ‚Ð°Ð½Ñ†Ñ–Ñ� OfflineðŸ’¤\n"+"Ð· " +lastupdated_time.strftime("%d/%m/%Y %H:%M")
    else:collecting_data = "â�—ï¸�ÐœÐµÑ‚ÐµÐ¾Ñ�Ñ‚Ð°Ð½Ñ†Ñ–Ñ� OfflineðŸ’¤\n"+"Ð· " +lastupdated_time.strftime("%d/%m/%Y %H:%M")
    return collecting_data

keyboard = telebot.types.ReplyKeyboardMarkup(resize_keyboard=True)
keyboard.row('ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ Ð¿Ð¾Ð³Ð¾Ð´Ñƒ \u26F7ðŸ�‚ \u2603')

#markup = telebot.types.InlineKeyboardMarkup()
#26F7
#stringList = {"Name": "John", "Language": "Python", "API": "pyTelegramBotAPI"}
#crossIcon = u"\u26C5"
#for key, value in stringList.items():
#    markup.add(telebot.types.InlineKeyboardButton(text=value, callback_data="['value', '" + value + "', '" + key + "']"),
#               telebot.types.InlineKeyboardButton(text=crossIcon, callback_data="['key', '" + key + "']"))

@bot.message_handler(commands=['start','help'])
def start(message):
    #bot.reply_to(message, 'ÐŸÑ€Ð¸Ð²Ñ–Ñ‚, ' + message.from_user.first_name)
    bot.send_message(message.chat.id, ' \u2744 Ð’Ð°Ñ� Ð²Ñ–Ñ‚Ð°Ñ” Ð¿Ð¾Ð³Ð¾Ð´Ð½Ñ–Ð¹ Ð±Ð¾Ñ‚ Ð“Ð›Ðš Ð—Ð°Ñ…Ð°Ñ€ Ð‘ÐµÑ€ÐºÑƒÑ‚\n\n''Ð©Ð¾Ð± Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ñ–Ñ†Ñ–ÑŽ Ñ‚Ð¸Ñ�Ð½Ñ–Ñ‚ÑŒ ÐºÐ½Ð¾Ð¿ÐºÑƒ "ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ Ð¿Ð¾Ð³Ð¾Ð´Ñƒ", Ñ�ÐºÐ° Ð·Ð½Ð°Ñ…Ð¾Ð´Ð¸Ñ‚ÑŒÑ�Ñ� Ð²Ð½Ð¸Ð·ÑƒðŸ‘‡\n', reply_markup=keyboard)

@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
    collecting_data = json_getweather()
    #bot.reply_to(message, message.text)
    bot.send_message(message.chat.id, 'Ð’Ñ–Ñ‚Ð°ÑŽ ' + message.from_user.first_name + '\n'+collecting_data, reply_markup=keyboard)

@server.route("/" + TOKEN, methods=['POST'])
def getMessage():
    bot.process_new_updates([telebot.types.Update.de_json(request.stream.read().decode("utf-8"))])
    return "!", 200

@server.route("/")
def webhook():
    bot.remove_webhook()
    bot.set_webhook(url=URL + TOKEN)
    return "!", 200
if __name__ == "__main__":
    server.run(host="0.0.0.0", port=int(os.environ.get('PORT', 5000)))
    #server.run(threaded=True)


#docs.python.org/zh-cn/3/library/functions.html
#最小值、最大值的内置函数
b = min(1,2,3,6)
print(b)

b = max(1,2,3,6)
print(b)

#学过的内置函数
#print:输出
#input:输入
#type:查看数据类型
#id:生成数据
#len:获取数据的长度（元素总数）
#int\float\bool\str\list\tuple\dict\set:代表对应的数据类型

#最小值、最大值、求和的内置函数
#min\max\sum
#列表、元组
# a = [1,2,3,4]
# b = (1,2,3,4)
# print(sum(a))
# print(sum(a))

#python中高级内置函数
#enumerate:利用它可以同时获得序列类型数据的下标和值

#eval:
#1、取出字符串中的内容，
#2、将字符串str当成有效的表达式来求值并返回计算结果
# print("4+8")
# b = eval("4+8")
# print(b)
#
# a = "{'name':'suifeng'}"
# print(type(a))
# print(type(eval(a)))
# print(eval(a)["name"])

#filter(参数1，参数2)
#参数1：过滤规则的函数
#参数2：要过滤的数据

#zip
title = ["case_id","title","url"]
data = ["登录","http://www.baidu.com"]

totle = zip(title,data)
#print(dict(totle))
print(list(totle))


import re

from yaql.language import specs
from yaql.language import yaqltypes

REGEX_TYPE = type(re.compile('.'))

@specs.parameter('pattern', yaqltypes.String())
def regex(pattern, ignore_case=False, multi_line=False, dot_all=False):
    """:yaql:regex

    Returns regular expression object with provided flags. Can be used for
    matching using matches method.

    :signature: regex(pattern,ignoreCase => false, multiLine => false,
        dotAll => false)
    :arg pattern: regular expression pattern to be compiled to regex object
    :argType pattern: string
    :arg ignoreCase: true makes performing case-insensitive matching.
    :argType ignoreCase: boolean
    :arg multiLine: true makes character '^' to match at the beginning of the
        string and at the beginning of each line, the character '$' to match
        at the end of the string and at the end of each line. false means
        '^' to match only at the beginning of the string, '$' only at the end
        of the string.
    :argType multiLine: boolean
    :arg dotAll: true makes the '.' special character to match any character
        (including a newline). false makes '.' to match anything except
        a newline.
    :argType dotAll: boolean
    :returnType: regex object

    .. code::

        yaql> regex("a.c").matches("abc")
        true
        yaql> regex("A.c").matches("abc")
        false
        yaql> regex("A.c", ignoreCase => true).matches("abc")
        true
    """
    flags = re.UNICODE
    if ignore_case:
        flags |= re.IGNORECASE
    if multi_line:
        flags |= re.MULTILINE
    if dot_all:
        flags |= re.DOTALL
    return re.compile(pattern, flags)

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.method
def matches(regexp, string):
    """:yaql:matches

    Returns true if string matches regexp.

    :signature: regexp.matches(string)
    :receiverArg regexp: regex pattern
    :argType regexp: regex object
    :arg string: string to find match in
    :argType string: string
    :returnType: boolean

    .. code::

        yaql> regex("a.c").matches("abc")
        true
    """
    return regexp.search(string) is not None

@specs.parameter('string', yaqltypes.String())
@specs.parameter('regexp', yaqltypes.String())
@specs.method
def matches_(string, regexp):
    """:yaql:matches

    Returns true if string matches regexp, false otherwise.

    :signature: string.matches(regexp)
    :receiverArg string: string to find match in
    :argType string: string
    :arg regexp: regex pattern
    :argType regexp: regex object
    :returnType: boolean

    .. code::

        yaql> "abc".matches("a.c")
        true
    """
    return re.search(regexp, string) is not None

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.name('#operator_=~')
def matches_operator_regex(string, regexp):
    """:yaql:operator =~

    Returns true if left matches right, false otherwise.

    :signature: left =~ right
    :arg left: string to find match in
    :argType left: string
    :arg right: regex pattern
    :argType right: regex
    :returnType: boolean

    .. code::

        yaql> "abc" =~ regex("a.c")
        true
    """
    return regexp.search(string) is not None

@specs.parameter('pattern', yaqltypes.String())
@specs.parameter('string', yaqltypes.String())
@specs.name('#operator_=~')
def matches_operator_string(string, pattern):
    """:yaql:operator =~

    Returns true if left matches right, false otherwise.

    :signature: left =~ right
    :arg left: string to find match in
    :argType left: string
    :arg right: regex pattern
    :argType right: string
    :returnType: boolean

    .. code::

        yaql> "abc" =~ "a.c"
        true
    """
    return re.search(pattern, string) is not None

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.name('#operator_!~')
def not_matches_operator_regex(string, regexp):
    """:yaql:operator !~

    Returns true if left doesn't match right, false otherwise.

    :signature: left !~ right
    :arg left: string to find match in
    :argType left: string
    :arg right: regex pattern
    :argType right: regex
    :returnType: boolean

    .. code::

        yaql> "acb" !~ regex("a.c")
        true
        yaql> "abc" !~ regex("a.c")
        false
    """
    return regexp.search(string) is None

@specs.parameter('pattern', yaqltypes.String())
@specs.parameter('string', yaqltypes.String())
@specs.name('#operator_!~')
def not_matches_operator_string(string, pattern):
    """:yaql:operator !~

    Returns true if left doesn't match right, false otherwise.

    :signature: left !~ right
    :arg left: string to find match in
    :argType left: string
    :arg right: regex pattern
    :argType right: regex object
    :returnType: boolean

    .. code::

        yaql> "acb" !~ regex("a.c")
        true
        yaql> "abc" !~ regex("a.c")
        false
    """
    return re.search(pattern, string) is None

def _publish_match(context, match):
    rec = {
        'value': match.group(),
        'start': match.start(0),
        'end': match.end(0)
    }
    context['$1'] = rec
    for i, t in enumerate(match.groups(), 1):
        rec = {
            'value': t,
            'start': match.start(i),
            'end': match.end(i)
        }
        context['$' + str(i + 1)] = rec

    for key, value, in match.groupdict().values():
        rec = {
            'value': value,
            'start': match.start(value),
            'end': match.end(value)
        }
        context['$' + key] = rec

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.parameter('selector', yaqltypes.Lambda(with_context=True))
@specs.method
def search(context, regexp, string, selector=None):
    """:yaql:search

    Search substring which matches regexp. Returns selector applied to
    dictionary {"start" => ..., "end" => ..., "value" => ...} where appropriate
    values describe start of substring, its end and itself. By default, if no
    selector is specified, returns only substring.
    null is a return value if there is no substring which matches regexp.

    :signature: regexp.search(string, selector => null)
    :receiverArg regexp: regex pattern
    :argType regexp: regex object
    :arg string: string to find match in
    :argType string: string
    :arg selector: lambda function to be applied to resulted dictionary with
        keys 'start', 'end', 'value'. null by default, which means to return
        only substring.
    :argType selector: lambda
    :returnType: string or selector return type

    .. code::

        yaql> regex("a.c").search("abcabc")
        "abc"
        yaql> regex("a.c").search("cabc", $)
        {
            "start": 1,
            "end": 4,
            "value": "abc"
        }
        yaql> regex("a.c").search("cabc", $.start)
        1
    """
    res = regexp.search(string)
    new_context = context.create_child_context()
    if res is None:
        return None
    if selector is None:
        return res.group()
    _publish_match(new_context, res)
    return selector(new_context)

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.parameter('selector', yaqltypes.Lambda(with_context=True))
@specs.method
def search_all(context, regexp, string, selector=None):
    """:yaql:searchAll

    Search all substrings which matches regexp. Returns list of applied to
    dictionary {"start" => ..., "end" => ..., "value" => ...} selector, where
    appropriate values describe start of every substring, its end and itself.
    By default, if no selector is specified, returns only list of substrings.

    :signature: regexp.searchAll(string, selector => null)
    :receiverArg regexp: regex pattern
    :argType regexp: regex object
    :arg string: string to find match in
    :argType string: string
    :arg selector: lambda function to be applied to resulted dictionary of
        every substring with keys 'start', 'end', 'value'. null by default,
        which means to return only list of substrings.
    :argType selector: lambda
    :returnType: list

    .. code::

        yaql> regex("a.c").searchAll("abcadc")
        ["abc", "adc"]
        yaql> regex("a.c").searchAll("abcadc", $)
        [
            {
                "start": 0,
                "end": 3,
                "value": "abc"
            },
            {
                "start": 3,
                "end": 6,
                "value": "adc"
            }
        ]

    :name: searchAll
    """
    for res in regexp.finditer(string):
        new_context = context.create_child_context()
        if selector is None:
            yield res.group()
        else:
            _publish_match(new_context, res)
            yield selector(new_context)

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.parameter('max_split', int)
@specs.method
def split(regexp, string, max_split=0):
    """:yaql:split

    Splits string by regexp matches and returns list of strings.

    :signature: regexp.split(string, maxSplit => 0)
    :receiverArg regexp: regex pattern
    :argType regexp: regex object
    :arg string: string to be splitted
    :argType string: string
    :arg maxSplit: how many first splits to do. 0 by default, which means
        to split by all matches
    :argType maxSplit: integer
    :returnType: list

    .. code::

        yaql> regex("a.").split("abcadc")
        ["", "c", "c"]
        yaql> regex("a.").split("abcadc", maxSplit => 1)
        ["", "cadc"]
    """
    return regexp.split(string, max_split)

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.parameter('max_split', int)
@specs.method
@specs.name('split')
def split_string(string, regexp, max_split=0):
    """:yaql:split

    Splits string by regexp matches and returns list of strings.

    :signature: string.split(regexp, maxSplit => 0)
    :receiverArg string: string to be splitted
    :argType string: string
    :arg regexp: regex pattern
    :argType regexp: regex object
    :arg maxSplit: how many first splits to do. 0 by default, which means
        to split by all matches
    :argType maxSplit: integer
    :returnType: list

    .. code::

        yaql> "abcadc".split(regex("a."))
        ["", "c", "c"]
        yaql> "abcadc".split(regex("a."), maxSplit => 1)
        ["", "cadc"]
    """
    return regexp.split(string, max_split)

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.parameter('repl', yaqltypes.String())
@specs.parameter('count', int)
@specs.method
def replace(regexp, string, repl, count=0):
    """:yaql:replace

    Returns the string obtained by replacing the leftmost non-overlapping
    matches of regexp in string by the replacement repl, where the latter is
    only string-type.

    :signature: regexp.replace(string, repl, count => 0)
    :receiverArg regexp: regex pattern
    :argType regexp: regex object
    :arg string: string to make replace in
    :argType string: string
    :arg repl: string to replace matches of regexp
    :argType repl: string
    :arg count: how many first replaces to do. 0 by default, which means
        to do all replacements
    :argType count: integer
    :returnType: string

    .. code::

        yaql> regex("a.").replace("abcadc", "xx")
        "xxcxxc"
        yaql> regex("a.").replace("abcadc", "xx", count => 1)
        "xxcadc"
    """
    return regexp.sub(repl, string, count)

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.parameter('repl', yaqltypes.String())
@specs.parameter('count', int)
@specs.method
@specs.name('replace')
def replace_string(string, regexp, repl, count=0):
    """:yaql:replace

    Returns the string obtained by replacing the leftmost non-overlapping
    matches of regexp in string by the replacement repl, where the latter is
    only string-type.

    :signature: string.replace(regexp, repl, count => 0)
    :receiverArg string: string to make replace in
    :argType string: string
    :arg regexp: regex pattern
    :argType regexp: regex object
    :arg repl: string to replace matches of regexp
    :argType repl: string
    :arg count: how many first replaces to do. 0 by default, which means
        to do all replacements
    :argType count: integer
    :returnType: string

    .. code::

        yaql> "abcadc".replace(regex("a."), "xx")
        "xxcxxc"
    """
    return replace(regexp, string, repl, count)

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.parameter('repl', yaqltypes.Lambda(with_context=True))
@specs.parameter('count', int)
@specs.method
def replace_by(context, regexp, string, repl, count=0):
    """:yaql:replaceBy

    Returns the string obtained by replacing the leftmost non-overlapping
    matches of regexp in string by repl, where the latter is an expression to
    get replacements by obtained matches.

    :signature: regexp.replaceBy(string, repl, count => 0)
    :receiverArg regexp: regex pattern
    :argType regexp: regex object
    :arg string: string to make replace in
    :argType string: string
    :arg repl: lambda function which returns string to make replacements
        according to input matches
    :argType repl: lambda
    :arg count: how many first replaces to do. 0 by default, which means
        to do all replacements
    :argType count: integer
    :returnType: string

    .. code::

        yaql> regex("a.c").replaceBy("abcadc", switch($.value = "abc" => xx,
                                                      $.value = "adc" => yy))
        "xxyy"
    """
    def repl_func(match):
        new_context = context.create_child_context()
        _publish_match(context, match)
        return repl(new_context)
    return regexp.sub(repl_func, string, count)

@specs.parameter('regexp', REGEX_TYPE)
@specs.parameter('string', yaqltypes.String())
@specs.parameter('repl', yaqltypes.Lambda(with_context=True))
@specs.parameter('count', int)
@specs.method
@specs.name('replaceBy')
def replace_by_string(context, string, regexp, repl, count=0):
    """:yaql:replaceBy

    Replaces matches of regexp in string with values provided by the
    supplied function.

    :signature: string.replaceBy(regexp, repl, count => 0)
    :receiverArg string: string to make replace in
    :argType string: string
    :arg regexp: regex pattern
    :argType regexp: regex object
    :arg repl: lambda function which returns string to make replacements
        according to input matches
    :argType repl: lambda
    :arg count: how many first replaces to do. 0 by default, which means
        to do all replacements
    :argType count: integer
    :returnType: string

    .. code::

        yaql> "abcadc".replaceBy(regex("a.c"), switch($.value = "abc" => xx,
                                                      $.value = "adc" => yy))
        "xxyy"
    """
    return replace_by(context, regexp, string, repl, count)

@specs.parameter('string', yaqltypes.String())
def escape_regex(string):
    """:yaql:escapeRegex

    Returns string with all the characters except ASCII letters, numbers,
    and '_' escaped.

    :signature: escapeRegex(string)
    :arg string: string to backslash all non-alphanumerics
    :argType string: string
    :returnType: string

    .. code::

        yaql> escapeRegex('a.')
        "a\\."
    """
    return re.escape(string)

def is_regex(value):
    """:yaql:isRegex

    Returns true if value is a regex object.

    :signature: isRegex(value)
    :arg value: string to backslash all non-alphanumerics
    :argType value: any
    :returnType: boolean

    .. code::

        yaql> isRegex(regex("a.c"))
        true
        yaql> isRegex(regex("a.c").matches("abc"))
        false
    """
    return isinstance(value, REGEX_TYPE)

def register(context):
    context.register_function(regex)
    context.register_function(matches)
    context.register_function(matches_)
    context.register_function(matches_operator_string)
    context.register_function(matches_operator_regex)
    context.register_function(not_matches_operator_string)
    context.register_function(not_matches_operator_regex)
    context.register_function(search)
    context.register_function(search_all)
    context.register_function(split)
    context.register_function(split_string)
    context.register_function(replace)
    context.register_function(replace_by)
    context.register_function(replace_string)
    context.register_function(replace_by_string)
    context.register_function(escape_regex)
    context.register_function(is_regex)


from googletrans import Translator
import json

def run(file_name):
    translator = Translator()
    with open(file_name, "r+") as file:
        data = file.read()
        data = json.loads(data)['data']
        for d in data:
            paragraphs = d['paragraphs']
            for page in paragraphs:
                context = page['context']

                context_trans = translator.translate(context, src='en', dest='vi')
                print(context_trans.text)

if __name__ == '__main__':
    run("dataset/train-v2.0.json")