#%matplotlib notebook
#from matplotlib import style
#style.use('fivethirtyeight')
import matplotlib.pyplot as plt

import numpy as np
import pandas as pd

import datetime as dt

# Reflect Tables into SQLAlchemy ORM

# Python SQL toolkit and Object Relational Mapper
import sqlalchemy
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import Session
from sqlalchemy import create_engine, func

engine = create_engine("sqlite:///Resources/hawaii.sqlite")

# reflect an existing database into a new model
Base = automap_base()
# reflect the tables
Base.prepare(engine, reflect=True)

# We can view all of the classes that automap found
Base.classes.keys()

# Save references to each table
Measurement = Base.classes.measurement
Station = Base.classes.station

# Saving this here
# Measurement.__table__.columns.keys()

# Create our session (link) from Python to the DB
session = Session(engine)

# Exploratory Climate Analysis

# Design a query to retrieve the last 12 months from 08-23-2017 of precipitation data and plot the results
# Calculate the date 1 year ago from today
today_not_today = dt.date(2017, 8, 23)
one_year_before_tnt = today_not_today - dt.timedelta(days=365)

########
# NOTE # Adding the station to the filter redueced the data points from 2021 to 343
########
# Perform a query to retrieve the data and precipitation scores
query_results = session.query(Measurement.date, Measurement.prcp).\
    filter(Measurement.date >= one_year_before_tnt).\
    filter(Measurement.date <= today_not_today).filter(Measurement.station == 'USC00513117').all()

# Save the query results as a Pandas DataFrame and set the index to the date column
year_of_rain_df = pd.DataFrame(query_results)
year_of_rain_df.set_index('date', inplace=True)

# Sort the dataframe by date
year_of_rain_df.sort_index(ascending=True, inplace=True)

# Use Pandas Plotting with Matplotlib to plot the data
year_of_rain_df.plot.bar(rot=90)

plt.xlabel("Date", fontsize = 20)
plt.ylabel("Precipitation", fontsize = 20)
plt.title('Year of Rain', fontsize = 20)

plt.rcParams['figure.figsize'] = (20,12)
plt.rc('xtick',labelsize=10)
plt.rc('ytick',labelsize=20)

# Rotate the xticks for the dates
# See the rot=90 added to plot command above

# Show plot
plt.show()

# Use Pandas to calcualte the summary statistics for the precipitation data
year_of_rain_df.describe()

# How many stations are available in this dataset?
rows = session.query(Station).count()
print(f'Total stations = {rows}')

# What are the most active stations?
# List the stations and the counts in descending order.

# Get station IDs
stations = engine.execute('SELECT station FROM station').fetchall()

station_freq = []
for station in stations:
    station_count = session.query(Measurement.station).filter(Measurement.station == station[0]).count()
    station_freq.append((station[0], station_count))

station_freq.sort(key=lambda x: x[1], reverse=True)
# So they are listed in a column
for station in station_freq:
    print(f'{station}')

# Using the station id from the previous query, calculate the lowest temperature recorded,
# highest temperature recorded, and average temperature most active station?
temps_from_station = session.query(Measurement.tobs).filter(Measurement.station == station_freq[0][0]).all()

# Sort the returned temps and get high/low values
temps_from_station.sort()
lowest_temp = temps_from_station[0]
highest_temp = temps_from_station[len(temps_from_station) - 1]

# Get average temp for the station with the most measurements
temp_total = 0
for temps in temps_from_station:
    temp_total = temp_total + temps[0]
average_temp = temp_total/(len(temps_from_station))
temp_results = [lowest_temp, highest_temp, average_temp]
print(temp_results)

# Choose the station with the highest number of temperature observations.
# Query the last 12 months of temperature observation data for this station and plot the results as a histogram
temps_from_station_12m = session.query(Measurement.tobs).filter((Measurement.date >= one_year_before_tnt) & \
                                                            (Measurement.date <= today_not_today) & \
                                                            (Measurement.station == station_freq[0][0])).all()

temps_from_station_12m.sort()
lowest_temp_12m = temps_from_station_12m[0]
highest_temp_12m = temps_from_station_12m[len(temps_from_station_12m) - 1]

temps_array = np.asarray(temps_from_station_12m, dtype = float)

plt.hist(temps_array, bins=12)

plt.xlabel("Temperature", fontsize=20)
plt.ylabel("Frequency", fontsize=20)
plt.yticks(np.arange(0, 80, step=10))
plt.title('Year of Temps', fontsize=20)
plt.show()

# Write a function called `calc_temps` that will accept start date and end date in the format '%Y-%m-%d'
# and return the minimum, average, and maximum temperatures for that range of dates
def calc_temps(start_date, end_date):
    """TMIN, TAVG, and TMAX for a list of dates.

    Args:
        start_date (string): A date string in the format %Y-%m-%d
        end_date (string): A date string in the format %Y-%m-%d

    Returns:
        TMIN, TAVE, and TMAX
    """

    return session.query(func.min(Measurement.tobs), func.avg(Measurement.tobs), func.max(Measurement.tobs)).\
        filter(Measurement.date >= start_date).filter(Measurement.date <= end_date).all()
print(calc_temps('2012-02-28', '2012-03-05'))

# Use your previous function `calc_temps` to calculate the tmin, tavg, and tmax
# for your trip using the previous year's data for those same dates.
# calc_temps(one_year_before_tnt, today_not_today)

# Plot the results from your previous query as a bar chart.
# Use "Trip Avg Temp" as your Title
# Use the average temperature for the y value
# Use the peak-to-peak (tmax-tmin) value as the y error bar (yerr)
# calc_temp_results = calc_temps(one_year_before_tnt, today_not_today)
# ltemp = calc_temp_results[0][0]
# atemp = calc_temp_results[0][1]
# htemp = calc_temp_results[0][2]

# y_axis = [atemp, 1.0, 1.0]
# x_axis = [" ", " ", " "]
# myerr = (htemp - ltemp)
# print(myerr)
# temp_handle = plt.bar(x_axis, y_axis, width=1.0, yerr=myerr)

# plt.rcParams['figure.figsize'] = (5, 12)

## Optional Challenge Assignment

# Calculate the rainfall per weather station for your trip dates using the previous year's matching dates.
# Sort this in descending order by precipitation amount and list the station, name, latitude, longitude, and elevation

# Create a query that will calculate the daily normals
# (i.e. the averages for tmin, tmax, and tavg for all historic data matching a specific month and day)

def daily_normals(date):
    """Daily Normals.

    Args:
        date (str): A date string in the format '%m-%d'

    Returns:
        A list of tuples containing the daily normals, tmin, tavg, and tmax

    """

    sel = [func.min(Measurement.tobs), func.avg(Measurement.tobs), func.max(Measurement.tobs)]
    return session.query(*sel).filter(func.strftime("%m-%d", Measurement.date) == date).all()

daily_normals("01-01")

# calculate the daily normals for your trip
# push each tuple of calculations into a list called `normals`

# Set the start and end date of the trip

# Use the start and end date to create a range of dates

# Stip off the year and save a list of %m-%d strings

# Loop through the list of %m-%d strings and calculate the normals for each date

# Load the previous query results into a Pandas DataFrame and add the `trip_dates` range as the `date` index

# Plot the daily normals as an area plot with `stacked=False`


from django.contrib import admin
from django.utils.translation import gettext, gettext_lazy as _
from django.contrib.auth.admin import UserAdmin

from .models import User, PersistentId
from .admin_inlines import PersistentIdInline

@admin.register(User)
class CustomUserAdmin(UserAdmin):
    readonly_fields = ('date_joined', 'last_login',)
    list_display = ('username', 'email', 'is_active',
                    'is_staff', 'is_superuser', )
    list_editable = ('is_active', 'is_staff', 'is_superuser',)
    inlines = [PersistentIdInline,]
    fieldsets = (
        (None, {'fields': (('username', 'is_active', 'is_staff', 'is_superuser', ),
                           ('password'),
                           ('origin'),
                           )
                }),
        (_('Anagrafica'), {'fields': (('first_name', 'last_name'),
                                          'email',
                                         ('taxpayer_id',)
                                        )
                          }),

        (_('Permissions'), {'fields': ('groups', 'user_permissions'),
                            'classes':('collapse',)
                            }),

        (_('Date accessi sistema'), {'fields': (('date_joined',
                                                 'last_login', ))
                                    }),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2'),
        }),
    )

admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)

@admin.register(PersistentId)
class PersistentIdAdmin(admin.ModelAdmin):
    list_display = ('user', 'persistent_id', 'recipient_id', 'created')
    list_filter = ('created',)


from threading import Thread
from download import objects, dl_utils
import hashlib
import zlib
import time
import logging
import os
from copy import copy

class DLWorker():
    def __init__(self, data, path, api_handler, gameId, submit_downloaded_size, endpoint):
        self.data = data
        self.path = path
        self.api_handler = api_handler
        self.submit_downloaded_size = submit_downloaded_size
        self.gameId = gameId
        self.completed = False
        self.endpoint = endpoint
        self.logger = logging.getLogger("DOWNLOAD_WORKER")
        self.downloaded_size = 0

    def do_stuff(self, is_dependency=False):
        item_path = os.path.join(self.path, self.data.path)
        if self.verify_file(item_path):
            size = 0
            for chunk in self.data.chunks:
                size += chunk['compressedSize']
            self.submit_downloaded_size(size)
            self.completed = True
            return
        if os.path.exists(item_path):
            os.remove(item_path)

        for index in range(len(self.data.chunks)):
            chunk = self.data.chunks[index]
            compressed_md5 = chunk['compressedMd5']
            md5 = chunk['md5']
            self.downloaded_size = chunk['compressedSize']
            download_path = os.path.join(
                self.path, self.data.path+f'.tmp{index}')
            dl_utils.prepare_location(
                dl_utils.parent_dir(download_path), self.logger)
            if is_dependency:
                url = dl_utils.get_dependency_link(self.api_handler, dl_utils.galaxy_path(compressed_md5))
            else:
                parameters = copy(self.endpoint['parameters'])
                parameters['path'] += "/" + dl_utils.galaxy_path(compressed_md5)
                url = dl_utils.merge_url_with_params(self.endpoint['url_format'], parameters)
            self.get_file(url, download_path, compressed_md5, md5, index)
            if not is_dependency:
                self.submit_downloaded_size(self.downloaded_size)
        path = os.path.join(self.path, self.data.path)
        with open(path, 'ab') as output_file:
            for index in range(len(self.data.chunks)):
                self.decompress_file(path+f'.tmp{index}', output_file)
        self.completed = True

    def decompress_file(self, compressed, output_file):
        if os.path.exists(compressed):
            file = open(compressed, 'rb')
            dc = zlib.decompress(file.read(), 15)
            output_file.write(dc)
            file.close()
            os.remove(compressed)

    def get_file(self, url, path, compressed_sum='', decompressed_sum='', index=0):
        isExisting = os.path.exists(path)
        if isExisting and (dl_utils.calculate_sum(path, hashlib.md5) == compressed_sum):
            return
        elif isExisting:
            os.remove(path)
        with open(path, 'ab') as f:
            response = self.api_handler.session.get(
                url, stream=True, allow_redirects=True)
            total = response.headers.get('Content-Length')
            if total is None:
                f.write(response.content)
            else:
                total = int(total)
                for data in response.iter_content(chunk_size=max(int(total/1000), 1024*1024)):
                    f.write(data)
            f.close()
            isExisting = os.path.exists(path)
            if isExisting and (dl_utils.calculate_sum(path, hashlib.md5) != compressed_sum):
                self.logger.warning(
                    f'Checksums dismatch for compressed chunk of {path}')
                if isExisting:
                    os.remove(path)
                self.get_file(url, path, compressed_sum,
                              decompressed_sum, index)
            elif not isExisting:
                self.get_file(url, path, compressed_sum,
                              decompressed_sum, index)
    def verify_file(self, item_path):
        if os.path.exists(item_path):
            calculated = None
            should_be = None
            if len(self.data.chunks) > 1:
                if self.data.md5:
                    should_be = self.data.md5
                    calculated = dl_utils.calculate_sum(item_path, hashlib.md5)
                elif self.data.sha256:
                    should_be = self.data.sha256
                    calculated = dl_utils.calculate_sum(item_path, hashlib.sha256)
            else:
                # In case if there are sha256 sums in chunks
                if 'sha256' in self.data.chunks[0]:
                    calculated = dl_utils.calculate_sum(item_path, hashlib.sha256)
                    should_be = self.data.chunks[0]['sha256']
                elif 'md5' in self.data.chunks[0]:
                    calculated = dl_utils.calculate_sum(item_path, hashlib.md5)
                    should_be = self.data.chunks[0]['md5']
            return calculated == should_be
        else:
            return False

class DLWorkerV1():
    def __init__(self, data, path, download_link, api_handler, gameId, submit_downloaded_size):
        self.data = data
        self.path = path
        self.api_handler = api_handler
        self.submit_downloaded_size = submit_downloaded_size
        self.gameId = gameId
        self.completed = False
        self.logger = logging.getLogger("DOWNLOAD_WORKER_V1")
        self.download_link = download_link
        self.downloaded_size = 0

    def do_stuff(self, is_dependency=False):
        if self.data['path'].startswith('/'):
            self.data['path'] = self.data['path'][1:]
        item_path = os.path.join(self.path, self.data['path'])
        if self.verify_file(item_path):
            self.completed = True
            if not is_dependency:
                self.submit_downloaded_size(int(self.data['size']))
            return
        else:
            if os.path.exists(item_path):
                os.remove(item_path)
        dl_utils.prepare_location(
                dl_utils.parent_dir(item_path), self.logger)
        self.get_file(item_path)
        if not is_dependency:
            self.submit_downloaded_size(int(self.data['size']))

    def get_file(self, item_path):
        headers = {
            "Range": dl_utils.get_range_header(self.data['offset'], self.data['size'])
        }
        with open(item_path, 'ab') as f:
            response = self.api_handler.session.get(self.download_link, headers=headers, stream=True, allow_redirects=True)
            total = response.headers.get('Content-Length')
            if total is None:
                f.write(response.content)
            else:
                total = int(total)
                for data in response.iter_content(chunk_size=max(int(total/1000), 1024*1024)):
                    f.write(data)
            f.close()
            if os.path.exists(item_path):
                if not self.verify_file(item_path):
                    self.logger.warning(f'Checksums dismatch for compressed chunk of {item_path}')
                    os.remove(item_path)
                    self.get_file(item_path)

    def verify_file(self, item_path):
        if os.path.exists(item_path):
            calculated = dl_utils.calculate_sum(item_path, hashlib.md5)
            should_be = self.data['hash']
            return calculated == should_be
        return False


'''
Created on Nov 7, 2013

@author: ezulkosk
'''
from common.Common import METRICS_MAXIMIZE, METRICS_MINIMIZE
from visitors import VisitorTemplate, Visitor
import sys
import visitors

def run(cfr_inst, parameters=None, non_modelstats=[]):
    stats = []
    if parameters:
        for (parameter,_,_) in parameters:
            if parameter in non_modelstats:
                continue
            stats.append(getParameter(parameter, cfr_inst))
        return stats
    else:
        numClafers = getNumClafers(cfr_inst)
        numBracketedConstraints = getNumBracketedConstraints(cfr_inst)
        numBracketedConstraintOperatorsList = getNumBracketedConstraintsOperators(cfr_inst)
        numTopLevelClafers = getNumTopLevelClafers(cfr_inst)
        (isObjectives, numObjectives) = getObjectiveStats(cfr_inst)
        (maxCard, maxBoundedGroupCard) = getMaxCards(cfr_inst)
        maxDepth = getMaxDepth(cfr_inst)
        numXors = getNumXorGCard(cfr_inst)
        numOptionalGCard = getNumOptionalGCard(cfr_inst)
        numOptionalCard = getNumOptionalCard(cfr_inst)
        numMandatoryCard = getNumMandatoryCard(cfr_inst)

        print("Num Clafers: " + str(numClafers))
        print("Num Bracketed Constraints: " + str(numBracketedConstraints))
        print("Num Bracketed Constraint Operators: " + str(numBracketedConstraintOperatorsList))
        print("Num Top Level Clafers: " + str(numTopLevelClafers))
        print("Objectives?: " + str(isObjectives))
        print("Num Objectives: " + str(numObjectives))
        print("Max Card: " + str(maxCard))
        print("Max Bounded Group Card: " + str(maxBoundedGroupCard))
        print("Max Depth: " + str(maxDepth))
        print("Num Xors GCard: " + str(numXors))
        print("Num Optional GCard: " + str(numOptionalGCard))
        print("Num Optional Card: " + str(numOptionalCard))
        print("Num Mandatory Card: " + str(numMandatoryCard))

''' ---------------------------------------------------------------'''

def getNumTopLevelClafers(cfr_inst):
    tops = 0
    for i in cfr_inst.cfr_sorts.values():
        if i.isTopLevel:
            tops = tops + 1
    return tops

''' ---------------------------------------------------------------'''

def getMaxDepth(cfr_inst):
    maxDepth = 0
    for i in cfr_inst.cfr_sorts.values():
        if len(i.parentStack) > maxDepth:
            maxDepth = len(i.parentStack)
    return maxDepth

''' ---------------------------------------------------------------'''

def getNumXorGCard(cfr_inst):
    numXors = 0
    for i in cfr_inst.cfr_sorts.values():
        if i.lowerGCard == 1 and i.upperGCard == 1:
            numXors = numXors + 1
    return numXors

def getNumOptionalGCard(cfr_inst):
    numOpts = 0
    for i in cfr_inst.cfr_sorts.values():
        if i.lowerGCard == 1 and i.upperGCard == -1:
            numOpts = numOpts + 1
    return numOpts

def getNumAnyGCard(cfr_inst):
    numAnys = 0
    for i in cfr_inst.cfr_sorts.values():
        if i.lowerGCard == 0 and i.upperGCard == -1:
            numAnys = numAnys + 1
    return numAnys

''' ---------------------------------------------------------------'''

def getNumMandatoryCard(cfr_inst):
    numMandatory = 0
    for i in cfr_inst.cfr_sorts.values():
        if i.lowerCardConstraint == 1 and i.upperCardConstraint == 1:
            numMandatory = numMandatory + 1
    return numMandatory

def getNumOptionalCard(cfr_inst):
    numOptional = 0
    for i in cfr_inst.cfr_sorts.values():
        if i.lowerCardConstraint == 0 and i.upperCardConstraint == 1:
            numOptional = numOptional + 1
    return numOptional

''' ---------------------------------------------------------------'''

def getObjectiveStats(cfr_inst):
    isObjectives = True if cfr_inst.objectives else False
    numObjectives = len(cfr_inst.objectives)
    return (isObjectives, numObjectives)

def getNumObjectives(cfr_inst):
    return len(cfr_inst.objectives)

def getNumMaximizeObjectives(cfr_inst):
    numObjectives = 0
    for i in cfr_inst.objectives:
        (polarity,_) = i
        if polarity == METRICS_MAXIMIZE:
            numObjectives = numObjectives + 1
    return numObjectives

def getNumMinimizeObjectives(cfr_inst):
    numObjectives = 0
    for i in cfr_inst.objectives:
        (polarity,_) = i
        if polarity == METRICS_MINIMIZE:
            numObjectives = numObjectives + 1
    return numObjectives

''' ---------------------------------------------------------------'''

def getMaxCards(cfr_inst):
    maxCard = -1
    maxBoundedGroupCard = -1
    for i in cfr_inst.cfr_sorts.values():
        if i.upperCardConstraint > maxCard:
            maxCard = i.upperCardConstraint
        if i.upperGCard > maxBoundedGroupCard:
            maxBoundedGroupCard = i.upperGCard
    return (maxCard, maxBoundedGroupCard)

''' ---------------------------------------------------------------'''

def getNumClafers(cfr_inst):
    return len(cfr_inst.cfr_sorts)

''' ---------------------------------------------------------------'''

def getNumBracketedConstraints(cfr_inst):
    return len(cfr_inst.smt_bracketed_constraints)

''' ---------------------------------------------------------------'''

def getNumBracketedConstraintsOperators(cfr_inst):
    module = cfr_inst.module
    constraintsStatsVisitor = GetBracketedConstraintsStats()
    Visitor.visit(constraintsStatsVisitor, module)
    counts = sorted(constraintsStatsVisitor.counts)
    return counts

class GetBracketedConstraintsStats(VisitorTemplate.VisitorTemplate):

    def __init__(self):
        self.counts = []
        self.currCount = 0

    def constraintVisit(self, element):
        self.inConstraint = True
        visitors.Visitor.visit(self, element.exp)
        self.inConstraint = False
        self.counts.append(self.currCount)
        self.currCount = 0

    def funexpVisit(self, element):
        for i in element.elements:
            visitors.Visitor.visit(self, i)
        if(self.inConstraint):
            self.currCount = self.currCount + 1

''' ---------------------------------------------------------------'''

def getParameter(parameter, cfr_inst):
    if parameter in parameter_functions.keys():
        function = parameter_functions[parameter]
        return function(cfr_inst)
    else:
        sys.exit("Unimplimented parameter: " + parameter)

parameter_functions = {
                       "numClafers"                : getNumClafers,
                       "numBracketedConstraints"   : getNumBracketedConstraints,
                       "numMandatoryCards"         : getNumMandatoryCard,
                       "numOptionalCards"          : getNumOptionalCard,
                       "numXorGCards"              : getNumXorGCard,
                       "numOptionalGCards"         : getNumOptionalGCard,
                       "numAnyGCards"              : getNumAnyGCard,
                       "numObjectives"             : getNumObjectives,
                       "numMaximizeObjectives"     : getNumMaximizeObjectives,
                       "numMinimizeObjectives"     : getNumMinimizeObjectives,
                       "maxDepth"                  : getMaxDepth

                       }


import ctypes
import os
import re
import socket
import subprocess
import time
import platform
import requests
import bisect
from xml.dom.minidom import parse
import xml.dom.minidom

# 根据IP地址获取位置
from requests import RequestException

from config import RMT_MEDIAEXT

def get_location(ip):
    url = 'https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?co=&resource_id=6006&t=1529895387942&ie=utf8' \
          '&oe=gbk&cb=op_aladdin_callback&format=json&tn=baidu&' \
          'cb=jQuery110203920624944751099_1529894588086&_=1529894588088&query=%s' % ip
    try:
        r = requests.get(url)
        r.encoding = 'gbk'
        html = r.text
        c1 = html.split('location":"')[1]
        c2 = c1.split('","')[0]
        return c2
    except requests.exceptions:
        return ''

# 计算文件大小
def str_filesize(size):
    d = [(1024 - 1, 'K'), (1024 ** 2 - 1, 'M'), (1024 ** 3 - 1, 'G'), (1024 ** 4 - 1, 'T')]
    s = [x[0] for x in d]
    index = bisect.bisect_left(s, size) - 1
    if index == -1:
        return str(size)
    else:
        b, u = d[index]
    return str(round(size / (b + 1), 2)) + u

# 判断是否为中文
def is_chinese(word):
    for ch in word:
        if '\u4e00' <= ch <= '\u9fff':
            return True
    return False

# 执地本地命令，返回信息
def system_exec_command(cmd, timeout=60):
    try:
        p = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, shell=True)
        t_beginning = time.time()
        while True:
            if p.poll() is not None:
                break
            seconds_passed = time.time() - t_beginning
            if timeout and seconds_passed > timeout:
                p.terminate()
                raise TimeoutError(cmd, timeout)
            time.sleep(0.1)
        result_out = p.stdout.read().decode(encoding='utf8')
        return '', str(result_out)
    except TimeoutError as err1:
        return "timeout", str(err1)
    except Exception as err2:
        return str(err2), str(err2)

# 获得目录下的媒体文件列表List，按后缀过滤
def get_dir_files_by_ext(in_path, exts=""):
    ret_list = []
    if not os.path.exists(in_path):
        return []
    if os.path.isdir(in_path):
        for root, dirs, files in os.walk(in_path):
            for file in files:
                ext = os.path.splitext(file)[-1]
                if ext in exts:
                    cur_path = os.path.join(root, file)
                    if cur_path not in ret_list:
                        ret_list.append(cur_path)
    else:
        ext = os.path.splitext(in_path)[-1]
        if ext in exts:
            if in_path not in ret_list:
                ret_list.append(in_path)
    return ret_list

# 获得目录下的媒体文件列表List，按文件名过滤
def get_dir_files_by_name(in_path, namestr=""):
    ret_list = []
    if not os.path.exists(in_path):
        return []
    if os.path.isdir(in_path):
        for root, dirs, files in os.walk(in_path):
            for file in files:
                file_name = os.path.basename(file)
                if namestr in file_name:
                    cur_path = os.path.join(root, file)
                    if cur_path not in ret_list:
                        ret_list.append(cur_path)
    else:
        file_name = os.path.basename(in_path)
        if namestr in file_name:
            if in_path not in ret_list:
                ret_list.append(in_path)
    return ret_list

# cookie字符串解析成字典
def cookieParse(cookies_str):
    cookie_dict = {}
    cookies = cookies_str.split(';')

    for cookie in cookies:
        cstr = cookie.split('=')
        cookie_dict[cstr[0]] = cstr[1]

    return cookie_dict

# 生成HTTP请求头
def generateHeader(url):
    header = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0',
        'Accept-Language': 'zh-CN',
        'Referer': url
    }
    return header

# 计算目录剩余空间大小
def get_free_space_gb(folder):
    if platform.system() == 'Windows':
        free_bytes = ctypes.c_ulonglong(0)
        ctypes.windll.kernel32.GetDiskFreeSpaceExW(ctypes.c_wchar_p(folder), None, None, ctypes.pointer(free_bytes))
        return free_bytes.value / 1024 / 1024 / 1024
    else:
        st = os.statvfs(folder)
        return st.f_bavail * st.f_frsize / 1024 / 1024 / 1024

# 获取主机名
def get_host_name():
    return socket.gethostname()

# 获取当前IP地址
def get_host_ip():
    s = None
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('223.5.5.5', 80))
        ip = s.getsockname()[0]
    finally:
        if s:
            s.close()
    if ip:
        return ip
    else:
        return ''

# 解析RSS的XML，返回标题及URL
def parse_rssxml(url):
    ret_array = []
    if not url:
        return []
    try:
        ret = requests.get(url)
    except Exception as e2:
        print(str(e2))
        return []
    if ret:
        ret_xml = ret.text
        try:
            # 解析XML
            dom_tree = xml.dom.minidom.parseString(ret_xml)
            rootNode = dom_tree.documentElement
            items = rootNode.getElementsByTagName("item")
            for item in items:
                try:
                    # 获取XML值
                    firstChild = item.getElementsByTagName("title")[0].firstChild
                    if not firstChild:
                        continue
                    else:
                        title = firstChild.data
                    tagName = item.getElementsByTagName("enclosure")[0]
                    if not tagName:
                        continue
                    else:
                        enclosure = tagName.getAttribute("url")
                    tmp_dict = {'title': title, 'enclosure': enclosure}
                    ret_array.append(tmp_dict)
                except Exception as e1:
                    print(str(e1))
                    continue
        except Exception as e2:
            print(str(e2))
            return ret_array
    return ret_array

# 解析Jackett的XML，返回标题及URL等
def parse_jackettxml(url):
    ret_array = []
    if not url:
        return ret_array
    try:
        ret = requests.get(url)
    except Exception as e2:
        print(str(e2))
        return []
    if ret:
        ret_xml = ret.text
        try:
            # 解析XML
            dom_tree = xml.dom.minidom.parseString(ret_xml)
            rootNode = dom_tree.documentElement
            items = rootNode.getElementsByTagName("item")
            for item in items:
                try:
                    # 获取XML值
                    firstChild = item.getElementsByTagName("title")[0].firstChild
                    if firstChild:
                        title = firstChild.data
                    else:
                        continue
                    firstChild = item.getElementsByTagName("description")[0].firstChild
                    if firstChild:
                        description = firstChild.data
                    else:
                        description = ""
                    firstChild = item.getElementsByTagName("size")[0].firstChild
                    if firstChild:
                        size = firstChild.data
                    else:
                        size = 0
                    tagName = item.getElementsByTagName("enclosure")[0]
                    if tagName:
                        enclosure = tagName.getAttribute("url")
                    else:
                        continue

                    seeders = 0
                    peers = 0
                    torznab_attrs = item.getElementsByTagName("torznab:attr")
                    for torznab_attr in torznab_attrs:
                        name = torznab_attr.getAttribute('name')
                        value = torznab_attr.getAttribute('value')
                        if name == "seeders":
                            seeders = value
                        if name == "peers":
                            peers = value

                    tmp_dict = {'title': title, 'enclosure': enclosure, 'description': description, 'size': size,
                                'seeders': seeders, 'peers': peers}
                    ret_array.append(tmp_dict)
                except Exception as e:
                    print(str(e))
                    continue
        except Exception as e2:
            print(str(e2))
            return ret_array
    return ret_array

def is_media_files_tv(file_list):
    flag = False
    # 不是list的转为list，避免发生字符级的拆分
    if not isinstance(file_list, list):
        file_list = [file_list]
    for tmp_file in file_list:
        tmp_name = os.path.basename(tmp_file)
        re_res = re.search(r"[\s.]*[SE]P?\d{1,3}", tmp_name, re.IGNORECASE)
        if re_res:
            flag = True
            break
    return flag

def get_keyword_from_string(content):
    # 稍微切一下剧集吧
    season_num = None
    episode_num = None
    year = None
    season_re = re.search(r"第\s*(\d+)\s*季", content, re.IGNORECASE)
    episode_re = re.search(r"第\s*(\d+)\s*集", content, re.IGNORECASE)
    year_re = re.search(r"[\s(]+(\d{4})[\s)]*", content)
    if season_re:
        season_num = int(season_re.group(1))
    if episode_re:
        episode_num = int(episode_re.group(1))
    if year_re:
        year = year_re.group(1)
    key_word = re.sub(r'第\s*\d+\s*季|第\s*\d+\s*集|[\s(]+(\d{4})[\s)]*', '', content, re.IGNORECASE).strip()
    return key_word, season_num, episode_num, year


import sys
import threading
import time

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from numpy import matlib as m

from src.neuralNetwork import NeuralNetwork

class View(QDialog):

    selectedFields = []
    neuralNetwork = None
    inputLayout = None
    modelResult = None
    plotCanvas = None
    threadFinishedSignal = pyqtSignal(tuple)
    errorDialogSignal = pyqtSignal(str)
    teaching = False
    taught = False

    def __init__(self):
        super().__init__()
        self.title = 'NAI PRO2'
        self.width = 720
        self.height = 580
        self.horizontalGroupBox = QGroupBox("Grid")

        # initialize 3 main sections
        self.inputGroupBox = QGroupBox("Teach settings")
        self.inputGroupBox.setFixedWidth(self.width//2)
        self.panel = QGroupBox("Classification")
        self.plot = QGroupBox("Error plot")

        self.initUI()

        self.threadFinishedSignal.connect(self.on_teaching_finish)
        self.errorDialogSignal.connect(self.error_dialog)

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(600, 300, self.width, self.height)

        # Create main layout
        windowLayout = QGridLayout()
        windowLayout.addWidget(self.inputGroupBox, 0, 0)
        windowLayout.addWidget(self.panel, 0, 1)
        windowLayout.addWidget(self.plot, 1, 0, 1, 2)

        # Add plot to main layout
        self.plotCanvas = PlotCanvas(self)
        layout = QBoxLayout(QBoxLayout.LeftToRight)
        layout.addWidget(self.plotCanvas)
        self.plot.setLayout(layout)

        # Initialize main layouts
        self.create_settings()
        self.create_panel()

        self.setLayout(windowLayout)
        self.show()

    def create_settings(self):
        # Create settings section and add widgets to layout
        self.inputLayout = QFormLayout()
        self.inputLayout.addRow(QLabel("Epochs amount"), QLineEdit("700"))
        self.inputLayout.addRow(QLabel("Error threshold"), QLineEdit("0.5"))
        self.inputLayout.addRow(QLabel("Learning factor"), QLineEdit("0.5"))
        self.inputLayout.addRow(QLabel("Number of hidden layers"), QLineEdit("17"))
        self.inputLayout.addRow(QLabel("Steepness factor"), QLineEdit("1"))

        statusLabel = QLabel("untaught")
        statusLabel.setStyleSheet("color: red; font-weight: bold;")
        self.inputLayout.addRow(QLabel("Model status"), statusLabel)

        teachButton = QPushButton("Teach")
        teachButton.setFixedHeight(40)
        teachButton.clicked.connect(self.teach_click)

        self.inputLayout.addRow(None, teachButton)
        self.inputGroupBox.setLayout(self.inputLayout)

    def create_panel(self):
        # Create settings section and add widgets to layout

        mainGrid = QGridLayout()

        # Generate clickable grid
        clickableGrid = QGridLayout()
        clickableGrid.setSpacing(0)

        for col in range(4):
            for row in range(6):
                id = row * 4 + col
                btn = MyQPushButton("")
                btn.setFixedWidth(25)
                btn.setFixedHeight(25)
                btn.setAccessibleName(str(id))
                btn.setStyleSheet("background-color: white;")
                clickableGrid.addWidget(btn, row, col)
                btn.clicked.connect(self.grid_button_click)
                self.selectedFields.append(0)

        mainGrid.addLayout(clickableGrid, 0, 0)
        mainGrid.setSpacing(10)

        label = QLabel("Draw a digit")
        label.setAlignment(Qt.AlignCenter)
        mainGrid.addWidget(label, 1, 0)

        label = QLabel("Model result")
        label.setAlignment(Qt.AlignCenter)
        mainGrid.addWidget(label, 1, 1)

        label = QLabel("?")
        label.setAlignment(Qt.AlignCenter)
        label.setStyleSheet("font-size:60px")
        mainGrid.addWidget(label, 0, 1)
        self.modelResult = label

        classifyButton = QPushButton("Classify")
        classifyButton.setFixedHeight(40)
        classifyButton.clicked.connect(self.classify_click)
        mainGrid.addWidget(classifyButton, 2, 0, 1, 2)

        self.panel.setLayout(mainGrid)

    def teach_click(self):
        if not self.teaching:
            threading.Thread(target=self.execute_teach).start()
        else:
            self.error_dialog('Teaching is in progress!')

    def on_teaching_finish(self, learn_data):
        self.teaching = False
        self.taught = True
        info = "Elapsed time: {:.2f}s \nAchieved error: {:.4f}\nEpochs: {:d}".format(learn_data[2], learn_data[0][len(learn_data[0]) - 1], learn_data[1])

        msgBox = QMessageBox()
        msgBox.setText('Neural network has been taught and is ready to classify!')
        msgBox.setWindowTitle("Teaching successful")
        msgBox.setIcon(QMessageBox.Information)
        msgBox.setDetailedText(info)
        msgBox.setStandardButtons(QMessageBox.Ok)
        msgBox.exec_()

    def execute_teach(self):
        # Teaching thread
        try:
            # Fetch data from textboxes
            maxEpoch = int(self.inputLayout.itemAt(0, QFormLayout.FieldRole).widget().text())
            maxError = float(self.inputLayout.itemAt(1, QFormLayout.FieldRole).widget().text())
            alpha = float(self.inputLayout.itemAt(2, QFormLayout.FieldRole).widget().text())
            lambd = float(self.inputLayout.itemAt(4, QFormLayout.FieldRole).widget().text())
            hiddenLayers = int(self.inputLayout.itemAt(3, QFormLayout.FieldRole).widget().text())

            # Set model status
            modelStatusText = self.inputLayout.itemAt(5, QFormLayout.FieldRole).widget()
            modelStatusText.setText("Teaching in progress...")
            modelStatusText.setStyleSheet("color: red; font-weight: bold;")
            self.teaching = True

            # Start teaching
            startTime = time.time()
            self.neuralNetwork = NeuralNetwork(hiddenLayers, alpha, maxError, maxEpoch, lambd)
            errors, epochs = self.neuralNetwork.teach()
            elapsedTime = time.time() - startTime

            # Draw plot
            self.plotCanvas.plot(errors)

            # Change model status
            modelStatusText.setText("Taught")
            modelStatusText.setStyleSheet("color: green; font-weight: bold;")

            self.threadFinishedSignal.emit((errors, epochs, elapsedTime))

        except ValueError:
            self.errorDialogSignal.emit('Please enter valid values')
        except:
            self.errorDialogSignal.emit('An error has occurred while teaching')

    def error_dialog(self, msg):
        msgBox = QMessageBox()
        msgBox.setText(msg)
        msgBox.setWindowTitle("Error")
        msgBox.setIcon(QMessageBox.Critical)
        msgBox.setStandardButtons(QMessageBox.Ok)
        msgBox.exec_()

    def classify_click(self):
        if not self.taught:
            if self.teaching:
                self.error_dialog('Please wait until teaching process finishes')
            else:
                self.error_dialog('Please teach neural network before starting classification')
            return

        result = self.neuralNetwork.classify_input(m.mat(self.selectedFields))
        if result == -1:
            self.modelResult.setText("?")
        else:
            self.modelResult.setText(str(result))

    def grid_button_click(self):
        sending_button = self.sender()
        sending_button.setInserted(not sending_button.isInserted())
        self.selectedFields[int(sending_button.accessibleName())] = 1 if sending_button.isInserted() else 0

        sending_button.setStyleSheet("background-color: red;") \
            if sending_button.isInserted() else sending_button.setStyleSheet("background-color: white;")

class MyQPushButton(QPushButton):

    __inserted = False

    def isInserted(self):
        return self.__inserted

    def setInserted(self, inserted):
        self.__inserted = inserted

class PlotCanvas(FigureCanvas):

    def __init__(self, parent=None):
        FigureCanvas.__init__(self, Figure())
        FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        self.setParent(parent)
        self.plot([1])
        self.draw()

    def plot(self, data):
        ax = self.figure.add_subplot(111)
        ax.plot(data, 'r-')
        self.draw()

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


from data.image_folder_dataset import ImageFolderDataset
from processing.XDoG import PARAM_DEFAULT
import pytorch_lightning as pl
from torch.utils.data import DataLoader
import torch

class ImageDataModule(pl.LightningDataModule):
  def __init__(self,
              data_dir = "portraits/",
              batch_size = 32,
              split_ratios = [.8, .1, .1],
              image_size=128,
              training_sizes=None,
              hatch_pattern_path="./processing/textures/",
              sketch_params=PARAM_DEFAULT,
              *args,
              **kwargs):

    super().__init__()
    self.data_dir = data_dir
    self.batch_size = batch_size
    self.split_ratios = split_ratios
    self.image_size = image_size
    self.training_sizes = training_sizes
    self.hatch_pattern_path = hatch_pattern_path

  def prepare_data(self):
    self.train_set, self.val_set, self.test_set = \
      ImageFolderDataset(
        path=self.data_dir,
        mode='train',
        ratios=self.split_ratios,
        image_size=self.image_size,
        training_sizes=self.training_sizes,
        hatch_pattern_path=self.hatch_pattern_path), \
      ImageFolderDataset(
        path=self.data_dir,
        mode='val',
        ratios=self.split_ratios,
        image_size=self.image_size,
        hatch_pattern_path=self.hatch_pattern_path), \
      ImageFolderDataset(
        path=self.data_dir,
        mode='test',
        ratios=self.split_ratios,
        image_size=self.image_size,
        hatch_pattern_path=self.hatch_pattern_path)

  def setup(self, stage = None):
    self.prepare_data()

  def train_dataloader(self):
    return DataLoader(
      self.train_set,
      batch_size=self.batch_size,
      shuffle=True,
      num_workers=2,)

  def val_dataloader(self):
    return DataLoader(
      self.val_set,
      batch_size=self.batch_size,
      shuffle=False,
      num_workers=2,)

  def test_dataloader(self):
    return DataLoader(
      self.test_set,
      batch_size=self.batch_size,
      shuffle=False,
      num_workers=2,)

  def teardown(self, stage = None):
    pass


from collections import defaultdict
from nltk.tokenize import word_tokenize
from random import sample

ENG_ALPHA = 'abcdefghijklmnopqrstuvwxyzé'

def get_lines(filename):
    '''returns a list of items from each line in the lexicon or the corpus.'''
    items = []
    with open(filename, encoding='unicode-escape') as f: #I could not find an encoding to decode 'É'
        for line in f:
            line = line.strip()
            if '\x83' in line: #to decode 'É'
                line = line.replace('\x83', 'é')
            items.append(line)
    return items

class AutoCorrect:

    def __init__(self, word_list=get_lines('usenglish.txt'), alpha=ENG_ALPHA):
        self.word_list = word_list
        self.alpha = alpha

    def insertion(self, word):
        #return a list of suggestions to alternative spellings for words with edit distance 1
        alternatives = []
        for i in range(len(word)+1):
            for letter in self.alpha:
                possible_word = word[:i] + letter + word[i:]
                if possible_word in self.word_list:
                    alternatives.append(possible_word)
        return alternatives

    def deletion(self, word):
        alternatives = []
        for i in range(len(word)):
            possible_word = word[:i] + word[i+1:]
            if possible_word in self.word_list:
                alternatives.append(possible_word)
        return alternatives

    def substitution(self, word):
        alternatives = []
        for i in range(len(word)):
            for letter in self.alpha:
                possible_word = word[:i] + letter + word[i+1:]
                if possible_word in self.word_list:
                    alternatives.append(possible_word)
        return alternatives

    def swapping(self, word):
        alternatives = []
        letters = list(word)
        for i in range(len(letters)-1):
            letters[i], letters[i+1] = letters[i+1], letters[i]
            possible_word = ''.join(letters)
            if possible_word in self.word_list:
                alternatives.append(possible_word)
        return alternatives

    def call_operation(self, word):
        #call the operation methods, put the elements of the lists in a set, and return that set.
        all_alternatives = set()
        all_alternatives.update(self.insertion(word))
        print(all_alternatives)
        all_alternatives.update(self.deletion(word))
        print(all_alternatives)
        all_alternatives.update(self.substitution(word))
        print(all_alternatives)
        all_alternatives.update(self.swapping(word))
        print(all_alternatives)
        return all_alternatives

def tokenize(sents):
    return [word_tokenize(sent) for sent in sents]

def populate_dict(tokenized_sents):
    bigram_frequency = defaultdict(int)
    for sent in tokenized_sents:
        for i in range(len(sent)-1): #last punctuation
            bigram_frequency[(sent[i].lower(), sent[i+1].lower())] += 1
    return bigram_frequency

def fetch_next(bigrams, input_word):
    suggestions = {}
    for (word, next_word), count in bigrams.items():
        if word == input_word:
            if len(suggestions) < 3:
                suggestions[count] = next_word
            elif count > min(suggestions): #only with a non-empty dictionry
                suggestions.pop(min(suggestions)) #remove the less frequent option
                suggestions[count] = next_word
    return list(suggestions.values())

def main():
    a = AutoCorrect()
    #tie everything together, run until interrupted
    tokenized_sents = tokenize(get_lines('UNv1.0.testset.en'))
    bigrams = populate_dict(tokenized_sents)
    while True:
        word = input('Type a word: ')
        if word not in get_lines('usenglish.txt'):
            suggestions = a.call_operation(word)
            if len(suggestions) > 3:
                print(sample(suggestions, 3))
            else:
                print(suggestions)
        else:
            print(fetch_next(bigrams, word))

if __name__ == "__main__":
    main()


from requests import get
from yt_dlp import YoutubeDL
import discord
from discord.ext import commands
import logging
import asyncio

# bot setup
print(discord.__version__)
description = 'I have no enemies, merely topologies of ignorance!'
intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix='$', description=description, intents=intents, help_command=None)

# Error logging class, unused right now.
class ErrorLogging(object):
    def debug(self, msg):
        pass
    def warning(self, msg):
        pass
    def error(self, msg):
        print(msg)

# Queries youtube with passed search term or link and downloads an audio file in opus format.
def download_video(search):
    ydl_opts = {
        'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'opus',
        }],
        'outtmpl': 'output.%(ext)s',
        'verbose': False,
        'logger': ErrorLogging(),
    }
    with YoutubeDL(ydl_opts) as ydl:
        try:
            get(search)
        except:
            video = ydl.extract_info(f"ytsearch:{search}", download=False)['entries'][0]['webpage_url']
        else:
            video = search
        ydl.download([video])

# commands
@bot.event
async def on_ready():
    print("Behold! The great and powerful Elminster!")
    print(bot.user.name + '@%s' % bot.user.id)

@bot.command()
async def help(ctx):
    await ctx.send('Begin a request with \'$\' and I will dazzle you with my abilities!')

@bot.command()
async def play(ctx, *, search):
    download_video(search)
    source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio("output.opus"), volume=0.1)
    if ctx.voice_client is None:
        channel = ctx.message.author.voice.channel
        await channel.connect()
    ctx.voice_client.play(source)
    while ctx.voice_client.is_playing():
        await asyncio.sleep(.1)
    await ctx.voice_client.disconnect()

@bot.command()
async def developers(ctx):
    await ctx.send("DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS")
    source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio("developers.opus"), volume=0.1)
    if ctx.voice_client is None:
        channel = ctx.message.author.voice.channel
        await channel.connect()
    ctx.voice_client.play(source)

@bot.command()
async def dc(ctx):
    if ctx.voice_client is not None:
        if ctx.voice_client:
            await ctx.guild.voice_client.disconnect()
            await ctx.send('Elminster shall take his leave!')
        else:
            await ctx.send('Silence knave, I\'m not in a voice channel.')

# discord.py logs
logger = logging.getLogger('discord')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
logger.addHandler(handler)

# open
with open('./secret', 'r') as f:
    token = f.readline()
bot.run(token)


import cv2
import numpy as np
import os
import PySimpleGUI as sg

def main(cascade, names, timeout):
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    # Read the trained .yml file that was generated previously
    recognizer.read('trainer/trainer.yml')
    # Give the type of cascade we are using at this time
    faceCascade = cv2.CascadeClassifier(cascade)
    font = cv2.FONT_HERSHEY_SIMPLEX
    #indicate id counter
    id = 0
    # Initialize and start realtime video capture
    cam = cv2.VideoCapture(0)
    cam.set(3, 480) # set video widht
    cam.set(4, 350) # set video height
    # Define min window size to be recognized as a face
    minW = 0.01*cam.get(3)
    minH = 0.01*cam.get(4)
    # Loop until we kill the program
    count = 0
    recognized = 0
    num_of_times = []
    while count <= int(timeout):
        ret, img =cam.read()
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

        faces = faceCascade.detectMultiScale(
            gray,
            scaleFactor = 1.2,
            minNeighbors = 5,
            minSize = (int(minW), int(minH)),
        )
        for(x,y,w,h) in faces:
            cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
            id, confidence = recognizer.predict(gray[y:y+h,x:x+w])

            # If confidence is less then 70 ==> "0" : perfect match
            # The smaller the number confidence needs to be less than, the harder it is to get a match
            if (confidence < 100):
                id = names[id - 1]
                id = id.replace('\n', '')
                num_of_times.append(id)
                recognized = recognized + 1
            else:
                id = "unknown"

            cv2.putText(
                        img,
                        str(id),
                        (x+5,y-5),
                        font,
                        1,
                        (255,255,255),
                        2
                    )

        cv2.imshow('camera',img)
        k = cv2.waitKey(10) & 0xff # Press 'ESC' for exiting video
        if k == 27:
            break
        if recognized == 20:
            highest_count = 0
            loop_count = 0
            for i in names:
                current = num_of_times.count(i)
                if(current > highest_count):
                    highest_count = current
                    id = str(names[loop_count])
                loop_count = loop_count + 1
            break
        count = count + 1
    # Do a bit of cleanup
    if count > int(timeout):
        id = "unknown"
    print("\n [INFO] Exiting Program and cleanup stuff")
    cam.release()
    cv2.destroyAllWindows()
    return(str(id))


import argparse
import os
import git
from enum import Enum

script_location = os.path.dirname(__file__)
repo_path = os.path.abspath(os.sep.join([script_location, '..', '..']))
print('Using git repository location {}'.format(repo_path))
repo = git.Repo(repo_path)
repo_submodules = repo.submodules

patches_folder = os.sep.join([repo_path, 'PolyEngine', 'ThirdParty', 'patches'])

for submodule in repo_submodules:
    sub_name = os.path.basename(os.path.normpath(submodule.path))
    print('Initializing submodule [{}] in path: {}'.format(sub_name, submodule.path))
    submodule.update(init=True, force=True)

    patch_name = os.sep.join([patches_folder, '{}.patch'.format(sub_name)])

    # Apply patch if needed
    if os.path.isfile(patch_name):
        print('Applying patch to submodule {} found in {}'.format(sub_name,patch_name))
        sub_repo = submodule.module()
        sub_repo.git.reset(['--hard']) # Reset first
        sub_repo.git.apply([patch_name]) # Apply patch


import re

from sqlalchemy import String, event, schema
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.types import VARCHAR

engine_regex = re.compile("engine=innodb", re.IGNORECASE)
trans_regex = re.compile("savepoint|rollback|release savepoint", re.IGNORECASE)

def enable_ndb_support(engine):
    """Enable NDB Support.

    Function to flag the MySQL engine dialect to support features specific
    to MySQL Cluster (NDB).
    """
    engine.dialect._oslodb_enable_ndb_support = True

def ndb_status(engine_or_compiler):
    """Test if NDB Support is enabled.

    Function to test if NDB support is enabled or not.
    """
    return getattr(engine_or_compiler.dialect,
                   '_oslodb_enable_ndb_support',
                   False)

def init_ndb_events(engine):
    """Initialize NDB Events.

    Function starts NDB specific events.
    """
    @event.listens_for(engine, "before_cursor_execute", retval=True)
    def before_cursor_execute(conn, cursor, statement, parameters, context,
                              executemany):
        """Listen for specific SQL strings and replace automatically.

        Function will intercept any raw execute calls and automatically
        convert InnoDB to NDBCLUSTER, drop SAVEPOINT requests, drop
        ROLLBACK requests, and drop RELEASE SAVEPOINT requests.
        """
        if ndb_status(engine):
            statement = engine_regex.sub("ENGINE=NDBCLUSTER", statement)
            if re.match(trans_regex, statement):
                statement = "SET @oslo_db_ndb_savepoint_rollback_disabled = 0;"

        return statement, parameters

@compiles(schema.CreateTable, "mysql")
def prefix_inserts(create_table, compiler, **kw):
    """Replace InnoDB with NDBCLUSTER automatically.

    Function will intercept CreateTable() calls and automatically
    convert InnoDB to NDBCLUSTER. Targets compiler events.
    """
    existing = compiler.visit_create_table(create_table, **kw)
    if ndb_status(compiler):
        existing = engine_regex.sub("ENGINE=NDBCLUSTER", existing)

    return existing

class AutoStringTinyText(String):
    """Class definition for AutoStringTinyText.

    Class is used by compiler function _auto-string_tiny_text().
    """

    pass

@compiles(AutoStringTinyText, 'mysql')
def _auto_string_tiny_text(element, compiler, **kw):
    if ndb_status(compiler):
        return "TINYTEXT"
    else:
        return compiler.visit_string(element, **kw)

class AutoStringText(String):
    """Class definition for AutoStringText.

    Class is used by compiler function _auto_string_text().
    """

    pass

@compiles(AutoStringText, 'mysql')
def _auto_string_text(element, compiler, **kw):
    if ndb_status(compiler):
        return "TEXT"
    else:
        return compiler.visit_string(element, **kw)

class AutoStringSize(String):
    """Class definition for AutoStringSize.

    Class is used by the compiler function _auto_string_size().
    """

    def __init__(self, length, ndb_size, **kw):
        """Initialize and extend the String arguments.

        Function adds the innodb_size and ndb_size arguments to the
        function String().
        """
        super(AutoStringSize, self).__init__(length=length, **kw)
        self.ndb_size = ndb_size
        self.length = length

@compiles(AutoStringSize, 'mysql')
def _auto_string_size(element, compiler, **kw):
    if ndb_status(compiler):
        return compiler.process(VARCHAR(element.ndb_size), **kw)
    else:
        return compiler.visit_string(element, **kw)


import tkinter.ttk as ttk
from turtle import title
from datetime import datetime
from datetime import date
import time
import threading
from threading import Event
import threading
from plyer import notification

class Reminder:
    def __init__(self, parent, uniqueID, expired, hours, minutes, ampm, date, title, description, count):
        self.parent = parent
        self.hours = hours
        self.min = minutes
        if(int(hours) > 12):
            self.ampm = "PM"
        else:
            self.ampm = ampm
        self.date = date
        self.title = title
        self.desc = description
        self.row = count
        self.alarm_time = ""
        self.expired = expired
        self.stop_event = Event()
        self.displayhours = self.hours
        self.uniqueID = uniqueID

        self.check_expire()
        self.daemon = threading.Thread(target=self.alarm, args=(self.stop_event,), daemon=True, name="Alarm")

        if(self.expired == False):
            self.daemon.start()
        else:
            pass

    def check_expire(self):
        if(0 <= int(self.hours) < 10 and self.ampm == "AM" and self.hours[0] != "0"):
            self.displayhours = self.hours
            self.hours = "0" + self.hours
        elif(1 <= int(self.hours) < 12 and self.ampm == "PM"):
            self.displayhours = self.hours
            self.hours = int(self.hours) + 12
        elif(int(self.hours) == 12 and self.ampm == "AM"):
            self.displayhours = self.hours
            self.hours = "00"

        current_date = date.today()
        current_date.strftime("%m/%d/%Y")
        reminder_date = datetime.strptime(self.date, "%m/%d/%Y").date()
        current_time = datetime.now().strftime("%H:%M")
        reminder_time = str(self.hours) + ":" + self.min
        if(current_date > reminder_date):
            self.expired = True
        elif((current_date == reminder_date) and (current_time >= reminder_time)):
            self.expired = True
        else:
            self.expired = False

    def alarm(self, event):
        self.alarm_time = str(self.hours) + ":" + self.min + ":00"

        if(self.expired == False):
            while not event.is_set():
                time.sleep(1)
                current_time = datetime.now()
                print(current_time)
                now = current_time.strftime("%H:%M:%S") # Set to 24 hour to accept both 12 hour as well
                date = current_time.strftime("%m/%d/%Y")
                if(now == self.alarm_time and date == self.date):
                    print(self.alarm_time)
                    notification.notify(title=self.title, message=self.desc, timeout=1)
                    self.expired = True
                    self.parent.remind_button_list[self.row].configure(bg="tomato")
                    break
        else:
            self.stop_event.clear()

    def update(self):
        if(self.daemon.is_alive()):
            self.stop_event.set()
            self.daemon.join()
            self.stop_event.clear()
            self.daemon = threading.Thread(target=self.alarm, args=(self.stop_event,), daemon=True, name="Alarm")
            self.daemon.start()
        else:
            self.daemon = threading.Thread(target=self.alarm, args=(self.stop_event,), daemon=True, name="Alarm")
            self.daemon.start()

    def open(self, calendar, hentry, mentry, drop, tentry, dentry):
        hentry.configure(bg="white")
        mentry.configure(bg="white")
        tentry.configure(bg="white")
        dentry.configure(bg="white")

        hentry.delete(0, "end")
        mentry.delete(0, "end")
        tentry.delete(0, "end")
        dentry.delete(1.0, "end")

        calendar.selection_set(self.date)
        if(self.hours == "00" and self.ampm == "AM"):
            hentry.insert(0, "12")
        elif(self.ampm == "PM" and int(self.hours) > 12):     # Might need
            hentry.insert(0, (str(int(self.hours) - 12)))
        else:
            hentry.insert(0, self.hours)
        mentry.insert(0, self.min)
        drop.set(self.ampm)
        tentry.insert(0, self.title)
        dentry.insert(1.0, self.desc)

    def saveToFile(self):
        remind_file_name = "C:\See Anchor\\Reminders\\" + self.title + "_" + str(self.uniqueID) + ".txt"
        f = open(remind_file_name, 'w')
        f.write(str(self.uniqueID) + "\n")
        f.write(str(self.expired) + "\n")
        f.write(str(self.hours) + "\n")
        f.write(str(self.min) + "\n")
        f.write(self.ampm + "\n")
        f.write(self.date + "\n")
        f.write(self.title + "\n")
        f.write(self.desc + "\n")
        f.close()


import boto3

dynamodb = boto3.client("dynamodb", endpoint_url="http://localhost:8000", region_name="us-west-2",
                           aws_access_key_id="foo", aws_secret_access_key="foo")
try:
    response = dynamodb.delete_table(
        TableName="Books"
    )
except Exception as e:
    print("Error when deleting db")
    print(e)


from datetime import datetime, date, timedelta
from django import forms
from django.contrib.auth import get_user_model
from django_registration.forms import RegistrationFormUniqueEmail

from reservations.models import Reservation
from rooms.models import Room

CustomUser = get_user_model()

class MyCustomUserForm(RegistrationFormUniqueEmail):

    first_name = forms.CharField(
        max_length=64,
        required=True,
        help_text="Requerido, por favor poné tu nombre",
        label="Nombre",
    )
    last_name = forms.CharField(
        max_length=64,
        required=True,
        help_text="Requerido, por favor poné tu apellido",
        label="Apellido",
    )

    class Meta(RegistrationFormUniqueEmail.Meta):
        model = CustomUser
        fields = ("email", "first_name", "last_name", "password1", "password2")
        help_texts = {
            "email": "Requerida. Luego será usada para entrar al sitio.",
            "password1": "No te preocupes: si te la olvidas podrás recuperarla.",
            "password2": "La misma que pusiste antes (para asegurarnos que la escribiste bien)",
        }
        labels = {
            "first_name": "Nombre",
            "last_name": "Apellido",
            "email": "Dirección de email",
            "password1": "Contraseña",
            "password2": "Repetir contraseña",
        }

class ReservationValidationFormMixin(forms.ModelForm):
    """Mixin to validate a reservation: dates and room"""

    def clean(self):
        cleaned_data = super().clean()
        if len(self.errors):
            return
        # cc_myself = cleaned_data.get("cc_myself")
        # subject = cleaned_data.get("subject")
        rooms = cleaned_data.get("rooms")
        from_date = cleaned_data.get("from_date")
        to_date = cleaned_data.get("to_date")

        if from_date >= to_date:
            self.add_error(
                "from_date", "La fecha Desde tiene que ser anterior a la de Hasta"
            )

        if self.instance:
            reservations = Reservation.objects.exclude(id=self.instance.id)
        else:
            reservations = Reservation.objects.all()

        potential_conflicts = reservations.filter(
            to_date__gt=from_date, from_date__lt=to_date
        )

        reserved_rooms_ids = set(
            potential_conflicts.values_list("rooms__id", flat=True)
        )
        conflicting_rooms = reserved_rooms_ids.intersection(
            set(rooms.values_list("id", flat=True))
        )

        if conflicting_rooms:
            rooms = ", ".join(
                str(r) for r in Room.objects.filter(id__in=reserved_rooms_ids)
            )
            msg = "En ese período hay conflictos con reservas de: {}".format(rooms)
            self.add_error("rooms", msg)

class MyReservationAdminForm(ReservationValidationFormMixin):
    pass

class ReservationCreationForm(ReservationValidationFormMixin):
    from_date = forms.DateField(
        label="Desde",
        widget=forms.DateInput(attrs={"type": "date"}),
        help_text="Fecha de la primer noche",
        required=True,
    )
    to_date = forms.DateField(
        label="Hasta",
        widget=forms.DateInput(attrs={"type": "date"}),
        help_text="Fecha de salida (esa noche no se usa habitación)",
        required=True,
    )

    class Meta:
        model = Reservation
        # fields = ["from_date", "to_date", "rooms", "notes"]
        exclude = ("user",)
        help_texts = {
            "from_date": "Fecha de la primer noche",
            "to_date": "Fecha de salida (esa noche no se usa habitación)",
            "rooms": "Seleccione múltiples habitaciones dejando apretado Ctrl",
            "notes": "Opcional. Cualquier mensaje que consideres oportuno.",
        }

TARGET_YEAR = datetime.now().year + 1
TURNS_START = date(TARGET_YEAR, 1, 1)

class TurnsPreparationForm(forms.Form):
    """Form for the definition of holiday turns."""

    year = forms.IntegerField(
        label="Año para el que calcular los turnos",
        required=True,
        min_value=2000,
        max_value=2100,
        initial=TARGET_YEAR,
    )
    date_start = forms.DateField(
        label="Día concreto en que empieza el primer turno",
        required=True,
        widget=forms.DateInput(attrs={"type": "date"}),
        initial=TURNS_START,
    )
    turn_length = forms.IntegerField(
        label="Largo (en días) deseado para cada turno",
        required=True,
        min_value=1,
        max_value=365,
        initial=8,
    )

class TurnsCreationForm(forms.Form):
    """Form for the creation of holiday turns"""

    year = forms.IntegerField(
        label="Año para el que calcular los turnos",
        required=True,
        widget=forms.widgets.Input(attrs={"readonly": True}),
    )
    date_start = forms.DateField(
        label="Día concreto en que empieza el primer turno",
        required=True,
        widget=forms.widgets.Input(attrs={"readonly": True}),
    )
    turn_length = forms.IntegerField(
        label="Largo (en días) deseado para cada turno",
        required=True,
        widget=forms.widgets.Input(attrs={"readonly": True}),
    )


from __future__ import print_function
import sys
import requests
import json
import yaml
import os
import base64

def update(session, headers, endpoint, HOST, projectname, configfile):
    with open(os.path.join(sys.path[0], configfile), 'r') as ymlfile:
            config = yaml.load(ymlfile)
    r = requests.get(HOST + endpoint.format('projects'), headers=headers, cookies=session)
    if r.status_code != 200:
        print("ERROR: Failed to fetch the project....")
        sys.exit(1)
    try:
        # Get Project ID
        projects = json.loads(r.text)["items"]
        project_exist = False
        for project in projects:
            if project["name"] == projectname:
               project_id = project["id"]
               project_exist = True
        if project_exist == False:
            print("ERROR: Project Name does not exist....")
            sys.exit(2)

        # Update encryption key and replication server
        rep = requests.get(HOST + endpoint.format('projects/{}/replicationConfigurations').format(project_id), headers=headers, cookies=session)
        for replication in json.loads(rep.text)["items"]:
            url = endpoint.format('projects/{}/replicationConfigurations/').format(project_id) + replication['id']
            replication["volumeEncryptionKey"] = config["replication"]["encryptionkey"]
            replication["volumeEncryptionAllowed"] = True
            replication["subnetId"] = config["replication"]["subnetID"]
            replication["replicatorSecurityGroupIDs"] = config["replication"]["securitygroupIDs"]
            eresult = requests.patch(HOST + url, data=json.dumps(replication), headers=headers, cookies=session)
            if eresult.status_code == 200:
               print("Encryption Key and replication server updated for project: " + projectname + "....")
            else:
               print("ERROR: Updating Encryption key or replication server failed....")

    except:
        print("ERROR: Updating project failed....")
        print(sys.exc_info())
        sys.exit(3)


import pytest

from src.domain.entities import Feature
from src.infra.repositories.implementations import FeatureRepository
from src.services.DTOs.feature import UpdateFeatureRequestServiceDto
from src.services.implementations.feature.update_feature_service import \
    UpdateFeatureService
from tests.unit.services.teste_service_base import DbHandlerFake, TestServiceBase

class TestUpdateFunction(TestServiceBase):
    def test_update_execute_ok(self, mocker):
        # Arrange
        db = self.db_handler
        repo = FeatureRepository(db)
        feature_id = 1234
        paper_id = 5678
        function_id = 4321

        update_feature_dto = UpdateFeatureRequestServiceDto(create=True, read=True, update=True, delete=True)

        feature_not_updated = Feature(feature_id=feature_id, paper_id=paper_id, function_id=function_id)
        feature_updated = Feature(feature_id=feature_id, paper_id=paper_id, function_id=function_id, create=True, read=True, update=True, delete=True)

        mocker.patch.object(Feature, 'validate')
        mocker.patch.object(FeatureRepository, 'get', return_value=feature_not_updated)
        mocker.patch.object(FeatureRepository, 'update')
        mocker.patch.object(DbHandlerFake, 'commit')

        # Act
        UpdateFeatureService.execute(db=db, repo=repo, feature_id=feature_id, data=update_feature_dto)

        # Assert
        Feature.validate.assert_called_once_with()
        FeatureRepository.get.assert_called_once_with(id=feature_id)
        FeatureRepository.update.assert_called_once_with(feature_updated)
        db.commit.assert_called_once()

    def test_update_feature_not_found_error(self, mocker):
        # Arrange
        db = self.db_handler
        repo = FeatureRepository(db)
        feature_id = 1234

        update_feature_dto = UpdateFeatureRequestServiceDto(create=True, read=True, update=True, delete=True)

        mocker.patch.object(FeatureRepository, 'get', return_value=None)

        # Act
        with pytest.raises(Exception) as error:
            UpdateFeatureService.execute(db=db, repo=repo, feature_id=feature_id, data=update_feature_dto)

        # Assert
        assert str(error.value) == f"Feature not found. [feature_id={feature_id}]"


import os
import requests

from altruz import ALTRUZ, CMD_HELP
from altruz.helpers.pyrogram_help import get_arg
from altruz.core.main_cmd import altruz_on_cmd, e_or_r
from config import Config

# Help
CMD_HELP.update(
    {
        "paste": f"""
**Paste,**
  `paste` - To Paste Text to Hastebin
**Example:**
  `paste`,
   ⤷ Send text with command = `{Config.CMD_PREFIX}paste Paste this text`
   ⤷ Reply to a text file = `{Config.CMD_PREFIX}paste` (Reply to a text file)
   ⤷ Reply to a text message = `{Config.CMD_PREFIX}paste (Reply to a text message)
"""
    }
)

mod_file = os.path.basename(__file__)

@altruz_on_cmd(command="paste", modlue=mod_file)
async def paste(client, message):
    paste_msg = await e_or_r(altruz_message=message, msg_text="`Executing Command..`")
    replied_msg = message.reply_to_message
    tex_t = get_arg(message)
    message_s = tex_t
    if not tex_t:
        if not replied_msg:
            await paste_msg.edit("`Reply To File or Send This Command With Text!`")
            return
        if not replied_msg.text:
            file = await replied_msg.download()
            m_list = open(file, "r").read()
            message_s = m_list
            print(message_s)
            os.remove(file)
        elif replied_msg.text:
            message_s = replied_msg.text
    haste_url = "https://hastebin.com/documents"
    haste_paste = requests.post(haste_url, data=message_s.encode('utf-8'), timeout=3)
    hp_data = haste_paste.json()
    url_key = hp_data['key']
    pasted_url = f"https://hastebin.com/{url_key}"
    pasted_url_raw = f"https://hastebin.com/raw/{url_key}"
    await paste_msg.edit(f"**Pasted to Hastebin** \n\n**Hastebin Url:** [Click here]({pasted_url}) \n**Raw Url:** [Click here]({pasted_url_raw})", disable_web_page_preview=True)


from functools import partial
from twisted.internet.defer import inlineCallbacks, returnValue
from device import OutputRelay, InputRelay, DeviceException
from device.devices.e1212.factory import ModBusClientFactory, E1212ServerFactory
import voluptuous as vol
from configuration import val

class E1212(OutputRelay, InputRelay):

    CONFIG_SCHEMA = OutputRelay.CONFIG_SCHEMA.extend({
        vol.Required('host'): vol.Any(val.hostname, val.ipv4_host),
        vol.Required('port', default=502): val.ipv4_port,
        vol.Required('listen_port', default=9020): val.ipv4_port,
    })

    def __init__(self, device_id, config, checkpoint):
        super(E1212, self).__init__(device_id, config, checkpoint)
        self.unit = None
        self.client = None
        self.server = None

    def starting(self):
        client_factory = ModBusClientFactory(self.config['max_reconnection_delay'])
        self.client = self.tcp_client(self.config['host'], self.config['port'], client_factory)
        self.server = self.tcp_server(self.config['listen_port'], E1212ServerFactory())
        self.server.factory.on_port_changed = partial(self.on_port_changed, self.unit)

    def is_ready(self):
        if not self.client:
            raise DeviceException('device not started')

        return self.client.factory.is_ready()

    @inlineCallbacks
    def set_port(self, unit, port, value):
        if not self.client:
            raise DeviceException('device not started')

        assert unit == self.unit, 'unit is not supported'
        yield self.client.factory.set_port(port, value)

    @inlineCallbacks
    def get_port(self, unit, port):
        if not self.client:
            raise DeviceException('device not started')

        assert unit == self.unit, 'unit is not supported'
        value = yield self.client.factory.get_port(port)
        returnValue(value)


# -*- coding: utf-8 -*-
"""

Description :
    Implementation of server on ports 8000, 80001
    The server on port 8000 based on the uuid of the clients is generating encrypted codes
    and send them to clients
    Then in the port 8001 there is the validation of uuid and the decrypted code that the client is sending
    if the validation is successful the message is been written to the log file

@author: Panagiotis Nikolaou

"""
import socket, select
import sys
from cryptography.fernet import Fernet
import re
import logging

logging.basicConfig(filename='server_comm.log', encoding='utf-8', level=logging.DEBUG)

def validation_server() -> None:
    # ports definition
    client_port_8000 = 8000
    client_port_8001 = 8001

    socket_list = []
    # host address
    host = '127.0.0.1'
    # amount of user connection on wait
    backlog = 50
    # buffer size
    buffer_size = 1024
    # fernet key generation for encryption/decryption
    f_key = Fernet(Fernet.generate_key())

    # loop through ports
    try:
        for item in client_port_8000, client_port_8001:
            # establish the connection
            try:
                socket_list.append(socket.socket(socket.AF_INET, socket.SOCK_STREAM))
            except socket.error:
                print('Failed to create socket')
                sys.exit()
            print(f'Socket Created on port : {item}')
            # allows sockets in use binding
            socket_list[-1].setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            # bind to host / port
            socket_list[-1].bind((host, item))
            # listen for clients
            socket_list[-1].listen(backlog)
    except socket.error as message:
        if socket_list[-1]:
            socket_list[-1].close()
            socket_list = socket_list[:-1]
        print('Could not open socket: ' + message)
        sys.exit(1)

    while True:
        read, write, error = select.select(socket_list, [], [])

        for r_port in read:
            for item in socket_list:
                if r_port == item:
                    accepted_socket, address = item.accept()
                    print('New connection : ', address)
                    # detect the port
                    forward_port = accepted_socket.getsockname()[1]
                    if forward_port == 8000:
                        data = accepted_socket.recv(buffer_size)
                        print("UUID received from client")
                        # encrypt the uuid and send it to client as code
                        token = f_key.encrypt(data)
                        try:
                            accepted_socket.send(token)
                        except socket.error:
                            # Send failed
                            print('Client code send failed')
                            sys.exit()
                        print('Client code send successfully')
                    if forward_port == 8001:
                        # receive data as list
                        data = accepted_socket.recv(buffer_size).decode()
                        print("Data received from client")
                        # split the list items
                        data = list(data.split(','))
                        # decode with regular expression
                        quoted = re.compile("(?<=b')(.*?)(?=\')")
                        commands = quoted.findall(str(data))
                        uuid = commands[0]
                        encrypted_uuid = commands[1]
                        decrypted_uuid = f_key.decrypt(encrypted_uuid.encode())
                        message = commands[2]
                        # if the uuid of the client is equal to the fernet decrypted code then log the message
                        if decrypted_uuid.decode() == uuid:
                            print("Client validation succeeded. Logging message")
                            logging.info(message)
                    # close the connection
                    print("Closing socket")
                    accepted_socket.close()

if __name__ == "__main__":
    validation_server()


import torch
import torch.nn as nn
import numpy as np
import itertools
import logging
from crowd_sim.envs.policy.policy import Policy
from crowd_sim.envs.utils.action import ActionRot, ActionXY
from crowd_sim.envs.utils.state import ObservableState, FullState

def mlp(input_dim, mlp_dims, last_relu=False):
    layers = []
    mlp_dims = [input_dim] + mlp_dims
    for i in range(len(mlp_dims) - 1):
        layers.append(nn.Linear(mlp_dims[i], mlp_dims[i + 1]))
        if i != len(mlp_dims) - 2 or last_relu:
            layers.append(nn.ReLU())
    net = nn.Sequential(*layers)
    return net

class ValueNetwork(nn.Module):
    def __init__(self, input_dim, mlp_dims):
        super().__init__()
        self.value_network = mlp(input_dim, mlp_dims)

    def forward(self, state_input):
        # input size: (batch_size, # of humans, state_length)
        if isinstance(state_input, tuple):
            state = state_input[0]
        else:
            state = state_input

        value = self.value_network(state.squeeze(dim=1))
        return value

class CADRL(Policy):
    def __init__(self):
        super().__init__()
        self.name = 'CADRL'
        self.trainable = True
        self.multiagent_training = None
        self.kinematics = None
        self.epsilon = None
        self.gamma = None
        self.sampling = None
        self.speed_samples = None
        self.rotation_samples = None
        self.query_env = None
        self.action_space = None
        self.rotation_constraint = None
        self.speeds = None
        self.rotations = None
        self.action_values = None
        self.with_om = None
        self.cell_num = None
        self.cell_size = None
        self.om_channel_size = None
        self.self_state_dim = 6
        self.human_state_dim = 7
        self.joint_state_dim = self.self_state_dim + self.human_state_dim

    def configure(self, config):
        self.set_common_parameters(config)
        self.model = ValueNetwork(self.joint_state_dim, config.cadrl.mlp_dims)
        self.multiagent_training = config.cadrl.multiagent_training
        logging.info('Policy: CADRL without occupancy map')

    def set_common_parameters(self, config):
        self.gamma = config.rl.gamma
        self.kinematics = config.action_space.kinematics
        self.sampling = config.action_space.sampling
        self.speed_samples = config.action_space.speed_samples
        self.rotation_samples = config.action_space.rotation_samples
        self.query_env = config.action_space.query_env
        self.rotation_constraint = config.action_space.rotation_constraint
        self.cell_num = config.om.cell_num
        self.cell_size = config.om.cell_size
        self.om_channel_size = config.om.om_channel_size

        logging.info('Query environment: {}'.format(self.query_env))

    def set_device(self, device):
        self.device = device
        self.model.to(device)

    def set_epsilon(self, epsilon):
        self.epsilon = epsilon

    def build_action_space(self, v_pref):
        """
        Action space consists of 25 uniformly sampled actions in permitted range and 25 randomly sampled actions.
        """
        holonomic = True if self.kinematics == 'holonomic' else False
        speeds = [(np.exp((i + 1) / self.speed_samples) - 1) / (np.e - 1) * v_pref for i in range(self.speed_samples)]
        if holonomic:
            rotations = np.linspace(0, 2 * np.pi, self.rotation_samples, endpoint=False)
        else:
            rotations = np.linspace(-self.rotation_constraint, self.rotation_constraint, self.rotation_samples)

        action_space = [ActionXY(0, 0) if holonomic else ActionRot(0, 0)]
        for rotation, speed in itertools.product(rotations, speeds):
            if holonomic:
                action_space.append(ActionXY(speed * np.cos(rotation), speed * np.sin(rotation)))
            else:
                action_space.append(ActionRot(speed, rotation))

        self.speeds = speeds
        self.rotations = rotations
        self.action_space = action_space

    def propagate(self, state, action):
        if isinstance(state, ObservableState):
            # propagate state of humans
            next_px = state.px + action.vx * self.time_step
            next_py = state.py + action.vy * self.time_step
            next_state = ObservableState(next_px, next_py, action.vx, action.vy, state.radius)
        elif isinstance(state, FullState):
            # propagate state of current agent
            # perform action without rotation
            if self.kinematics == 'holonomic':
                next_px = state.px + action.vx * self.time_step
                next_py = state.py + action.vy * self.time_step
                next_state = FullState(next_px, next_py, action.vx, action.vy, state.radius,
                                       state.gx, state.gy, state.v_pref, state.theta)
            else:
                next_theta = state.theta + action.r
                next_vx = action.v * np.cos(next_theta)
                next_vy = action.v * np.sin(next_theta)
                next_px = state.px + next_vx * self.time_step
                next_py = state.py + next_vy * self.time_step
                next_state = FullState(next_px, next_py, next_vx, next_vy, state.radius, state.gx, state.gy,
                                       state.v_pref, next_theta)
        else:
            raise ValueError('Type error')

        return next_state

    def predict(self, state):
        """
        Input state is the joint state of robot concatenated by the observable state of other agents

        To predict the best action, agent samples actions and propagates one step to see how good the next state is
        thus the reward function is needed

        """
        if self.phase is None or self.device is None:
            raise AttributeError('Phase, device attributes have to be set!')
        if self.phase == 'train' and self.epsilon is None:
            raise AttributeError('Epsilon attribute has to be set in training phase')

        if self.reach_destination(state):
            return ActionXY(0, 0) if self.kinematics == 'holonomic' else ActionRot(0, 0)
        if self.action_space is None:
            self.build_action_space(state.self_state.v_pref)
        if not state.human_states:
            assert self.phase != 'train'
            return self.select_greedy_action(state.self_state)

        probability = np.random.random()
        if self.phase == 'train' and probability < self.epsilon:
            max_action = self.action_space[np.random.choice(len(self.action_space))]
        else:
            self.action_values = list()
            max_min_value = float('-inf')
            max_action = None
            for action in self.action_space:
                next_self_state = self.propagate(state.self_state, action)
                if self.query_env:
                    next_human_states, reward, done, info = self.env.onestep_lookahead(action)
                else:
                    next_human_states = [self.propagate(human_state, ActionXY(human_state.vx, human_state.vy))
                                         for human_state in state.human_states]
                    reward = self.compute_reward(next_self_state, next_human_states)
                batch_next_states = torch.cat([torch.Tensor([next_self_state + next_human_state]).to(self.device)
                                              for next_human_state in next_human_states], dim=0)

                # VALUE UPDATE
                outputs = self.model(self.rotate(batch_next_states))
                min_output, min_index = torch.min(outputs, 0)
                min_value = reward + pow(self.gamma, self.time_step * state.self_state.v_pref) * min_output.data.item()
                self.action_values.append(min_value)
                if min_value > max_min_value:
                    max_min_value = min_value
                    max_action = action

        if self.phase == 'train':
            self.last_state = self.transform(state)

        return max_action

    def select_greedy_action(self, self_state):
        # find the greedy action given kinematic constraints and return the closest action in the action space
        direction = np.arctan2(self_state.gy - self_state.py, self_state.gx - self_state.px)
        distance = np.linalg.norm((self_state.gy - self_state.py, self_state.gx - self_state.px))
        if self.kinematics == 'holonomic':
            speed = min(distance / self.time_step, self_state.v_pref)
            vx = np.cos(direction) * speed
            vy = np.sin(direction) * speed

            min_diff = float('inf')
            closest_action = None
            for action in self.action_space:
                diff = np.linalg.norm(np.array(action) - np.array((vx, vy)))
                if diff < min_diff:
                    min_diff = diff
                    closest_action = action
        else:
            rotation = direction - self_state.theta
            # if goal is not in the field of view, always rotate first
            if rotation < self.rotations[0]:
                closest_action = ActionRot(self.speeds[0], self.rotations[0])
            elif rotation > self.rotations[-1]:
                closest_action = ActionRot(self.speeds[0], self.rotations[-1])
            else:
                speed = min(distance / self.time_step, self_state.v_pref)

                min_diff = float('inf')
                closest_action = None
                for action in self.action_space:
                    diff = np.linalg.norm(np.array((np.cos(action.r) * action.v, np.sin(action.r) * action.v)) -
                                          np.array((np.cos(rotation) * speed), np.sin(rotation) * action.v))
                    if diff < min_diff:
                        min_diff = diff
                        closest_action = action

        return closest_action

    def transform(self, state):
        """
        Take the state passed from agent and transform it to tensor for batch training

        :param state:
        :return: tensor of shape (len(state), )
        """
        state = torch.Tensor([state.self_state + state.human_states[0]]).to(self.device)
        state = self.rotate(state)
        return state

    def rotate(self, state):
        """
        Transform the coordinate to agent-centric.
        Input state tensor is of size (batch_size, state_length)

        """
        # 'px', 'py', 'vx', 'vy', 'radius', 'gx', 'gy', 'v_pref', 'theta', 'px1', 'py1', 'vx1', 'vy1', 'radius1'
        #  0     1      2     3      4        5     6      7         8       9     10      11     12       13
        batch = state.shape[0]
        dx = (state[:, 5] - state[:, 0]).reshape((batch, -1))
        dy = (state[:, 6] - state[:, 1]).reshape((batch, -1))
        rot = torch.atan2(state[:, 6] - state[:, 1], state[:, 5] - state[:, 0])

        dg = torch.norm(torch.cat([dx, dy], dim=1), 2, dim=1, keepdim=True)
        v_pref = state[:, 7].reshape((batch, -1))
        vx = (state[:, 2] * torch.cos(rot) + state[:, 3] * torch.sin(rot)).reshape((batch, -1))
        vy = (state[:, 3] * torch.cos(rot) - state[:, 2] * torch.sin(rot)).reshape((batch, -1))

        radius = state[:, 4].reshape((batch, -1))
        if self.kinematics == 'unicycle':
            theta = (state[:, 8] - rot).reshape((batch, -1))
        else:
            theta = torch.zeros_like(v_pref)

        vx1 = (state[:, 11] * torch.cos(rot) + state[:, 12] * torch.sin(rot)).reshape((batch, -1))
        vy1 = (state[:, 12] * torch.cos(rot) - state[:, 11] * torch.sin(rot)).reshape((batch, -1))
        px1 = (state[:, 9] - state[:, 0]) * torch.cos(rot) + (state[:, 10] - state[:, 1]) * torch.sin(rot)
        px1 = px1.reshape((batch, -1))
        py1 = (state[:, 10] - state[:, 1]) * torch.cos(rot) - (state[:, 9] - state[:, 0]) * torch.sin(rot)
        py1 = py1.reshape((batch, -1))
        radius1 = state[:, 13].reshape((batch, -1))
        radius_sum = radius + radius1
        da = torch.norm(torch.cat([(state[:, 0] - state[:, 9]).reshape((batch, -1)), (state[:, 1] - state[:, 10]).
                                  reshape((batch, -1))], dim=1), 2, dim=1, keepdim=True)
        new_state = torch.cat([dg, v_pref, theta, radius, vx, vy, px1, py1, vx1, vy1, radius1, da, radius_sum], dim=1)
        return new_state


import requests
import json
import boto3
import os

API_KEY = os.getenv('API_KEY')
AWS_ACCESS_KEY = os.getenv('AWS_ACCESS_KEY')
AWS_SECRET_KEY = os.getenv('AWS_SECRET_KEY')

HEADERS = {
    "accept": "application/json",
    "content-type": "application/json",
    "authorization": f"Bearer {API_KEY}"
}

s3 = boto3.resource('s3',
    aws_access_key_id=AWS_ACCESS_KEY,
    aws_secret_access_key=AWS_SECRET_KEY)
bucket = s3.Bucket('authetication-images')

keys = []

for obj in bucket.objects.all():
    keys.append(obj.key)

IMAGES = []
s3 = boto3.client('s3',
    aws_access_key_id=AWS_ACCESS_KEY,
    aws_secret_access_key=AWS_SECRET_KEY)

# Defina o nome do seu bucket e do arquivo
bucket_name = 'authetication-images'
file_names = keys
for file_name in file_names:
  # Gere a URL pública com uma validade de 1 hora (3600 segundos)
  url = s3.generate_presigned_url('get_object', Params={'Bucket': bucket_name, 'Key': file_name}, ExpiresIn=3600)
  IMAGES.append(url)
  # Use a URL pública diretamente em seu código

def create_model(title):
    url = "https://api.tryleap.ai/api/v1/images/models"

    payload = {
        "title": title,
        "subjectKeyword": "@me"
    }

    response = requests.post(url, json=payload, headers=HEADERS)

    model_id = json.loads(response.text)["id"]
    return model_id

def upload_image_samples(model_id):
    url = f"https://api.tryleap.ai/api/v1/images/models/{model_id}/samples/url"

    payload = {"images": IMAGES}
    response = requests.post(url, json=payload, headers=HEADERS)
    return response.status_code

def queue_training_job(model_id):
    url = f"https://api.tryleap.ai/api/v1/images/models/{model_id}/queue"
    response = requests.post(url, headers=HEADERS)
    print(response.text)
    data = json.loads(response.text)

    version_id = data["id"]
    status = data["status"]

    print(f"Version ID: {version_id}. Status: {status}")

    return version_id, status

def get_model_version(model_id, version_id):
    url = f"https://api.tryleap.ai/api/v1/images/models/{model_id}/versions/{version_id}"
    response = requests.get(url, headers=HEADERS)
    data = json.loads(response.text)

    version_id = data["id"]
    status = data["status"]

    print(f"Version ID: {version_id}. Status: {status}")

    return version_id, status

def generate_image(model_id, prompt):
    url = f"https://api.tryleap.ai/api/v1/images/models/{model_id}/inferences"

    payload = {
        "prompt": prompt,
        "steps": 50,
        "width": 512,
        "height": 512,
        "numberOfImages": 1,
        "seed": 4523184
    }

    response = requests.post(url, json=payload, headers=HEADERS)
    print(response.status_code)
    data = json.loads(response.text)

    inference_id = data["id"]
    status = data["status"]

    print(f"Inference ID: {inference_id}. Status: {status}")

    return inference_id, status

def get_inference_job(model_id, inference_id):
    url = f"https://api.tryleap.ai/api/v1/images/models/{model_id}/inferences/{inference_id}"

    response = requests.get(url, headers=HEADERS)
    data = json.loads(response.text)

    inference_id = data["id"]
    state = data["state"]
    image = None

    if len(data["images"]):
        image = data["images"][0]["uri"]

    print(f"Inference ID: {inference_id}. State: {state}")

    return inference_id, state, image