from django.core.management.base import BaseCommand
from usaspending_api.references.models import Cfda
from datetime import datetime
import os
import csv
import logging
import django
import ftplib

logger = logging.getLogger('console')
cfda_relative_path = '/usaspending_api/references/management/commands/programs-full-usaspending.csv'
cfda_abs_path = os.path.join(django.conf.settings.BASE_DIR + cfda_relative_path)

class Command(BaseCommand):

    help = 'Loads program information obtained from csv file on ftp.cfda.gov'

    def add_arguments(self, parser):
        parser.add_argument(
            '--update-file',
            action='store_true',
            dest='update-file',
            default=False,
            help='Pull the updated CSV from ftp.cfda.gov before running.'
        )

    def handle(self, *args, **options):

        if options['update-file']:

            ftp_conn = ftplib.FTP()
            ftp_conn.connect("ftp.cfda.gov")
            ftp_conn.login()
            ftp_conn.cwd('usaspending')
            most_recent = sorted(ftp_conn.nlst(), reverse=True)[0]

            logger.info('Updating {} with new file {}...'.format(cfda_abs_path, most_recent))
            ftp_conn.retrbinary("RETR " + most_recent, open(cfda_abs_path, 'wb').write)

        load_cfda(cfda_abs_path)

def load_cfda(abs_path):
    """
    Using file at abs_path, update/create CFDA objects.
    """
    try:

        with open(abs_path, errors='backslashreplace') as csvfile:

            reader = csv.DictReader(csvfile, delimiter=',', quotechar='"', skipinitialspace='true')

            rows = list(reader)
            total_rows = len(rows)

            for index, row in enumerate(rows, 1):

                if not (index % 100):
                    logger.info('CFDA loading/updating row {} of {}'.format(index, total_rows))

                cfda_program, created = Cfda.objects.get_or_create(
                                program_number=row['Program Number'])

                cfda_program.data_source = "USA"
                cfda_program.program_title = row['Program Title']
                cfda_program.popular_name = row['Popular Name (020)']
                cfda_program.federal_agency = row['Federal Agency (030)']
                cfda_program.authorization = row['Authorization (040)']
                cfda_program.objectives = row['Objectives (050)']
                cfda_program.types_of_assistance = row['Types of Assistance (060)']
                cfda_program.uses_and_use_restrictions = row['Uses and Use Restrictions (070)']
                cfda_program.applicant_eligibility = row['Applicant Eligibility (081)']
                cfda_program.beneficiary_eligibility = row['Beneficiary Eligibility (082)']
                cfda_program.credentials_documentation = row['Credentials/Documentation (083)']
                cfda_program.pre_application_coordination = row['Preapplication Coordination (091)']
                cfda_program.application_procedures = row['Application Procedures (092)']
                cfda_program.award_procedure = row['Award Procedure (093)']
                cfda_program.deadlines = row['Deadlines (094)']
                cfda_program.range_of_approval_disapproval_time = row['Range of Approval/Disapproval Time (095)']
                cfda_program.appeals = row['Appeals (096)']
                cfda_program.renewals = row['Renewals (097)']
                cfda_program.formula_and_matching_requirements = row['Formula and Matching Requirements (101)']
                cfda_program.length_and_time_phasing_of_assistance = row['Length and Time Phasing of Assistance (102)']
                cfda_program.reports = row['Reports (111)']
                cfda_program.audits = row['Audits (112)']
                cfda_program.records = row['Records (113)']
                cfda_program.account_identification = row['Account Identification (121)']
                cfda_program.obligations = row['Obligations (122)']
                cfda_program.range_and_average_of_financial_assistance = row['Range and Average of '
                                                                             'Financial Assistance (123)']
                cfda_program.program_accomplishments = row['Program Accomplishments (130)']
                cfda_program.regulations_guidelines_and_literature = row['Regulations, Guidelines, '
                                                                         'and Literature (140)']
                cfda_program.regional_or_local_office = row['Regional or Local Office (151) ']
                cfda_program.headquarters_office = row['Headquarters Office (152)']
                cfda_program.website_address = row['Website Address (153)']
                cfda_program.related_programs = row['Related Programs (160)']
                cfda_program.examples_of_funded_projects = row['Examples of Funded Projects (170)']
                cfda_program.criteria_for_selecting_proposals = row['Criteria for Selecting Proposals (180)']
                cfda_program.url = row['URL']
                cfda_program.recovery = row['Recovery']
                cfda_program.omb_agency_code = row['OMB Agency Code']
                cfda_program.omb_bureau_code = row['OMB Bureau Code']
                if row['Published Date']:
                    cfda_program.published_date = datetime.strptime(row['Published Date'], '%b, %d %Y')
                if row['Archived Date']:
                    cfda_program.archived_date = datetime.strptime(row['Archived Date'], '%b, %d %Y')

                # TODO: add way to check/print out any cfda codes that got updated (not just created)
                if created:
                    logger.info('Created a new cfda code for {} ({})'.format(row['Program Number'],
                                                                             row['Program Title']))

                cfda_program.save()

    except IOError:
        logger.info('Could not open file to load: {}'.format(abs_path))


from time import sleep

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.options import Options
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.firefox.service import Service

def get_full_page(driver: webdriver, url: str, out_path_png: str) -> None:
    driver.get(url)

    for _ in range(1000):
        driver.execute_script("window.scrollBy(0,10);")
        sleep(0.0001)

    for _ in range(1000):
        driver.execute_script("window.scrollBy(0,-20);")
        sleep(0.0001)

    driver.find_element(By.TAG_NAME, "body").screenshot(out_path_png)

def get_short_page(driver: webdriver, url: str, out_path_png: str) -> None:
    driver.get(url)
    driver.execute_script("window.scrollBy(0,0);")
    sleep(1)
    driver.get_screenshot_as_file(out_path_png)

def get_driver_firefox():
    options = Options()
    options.headless = True
    options.binary = "/usr/bin/firefox"
    return webdriver.Firefox(
        service=Service(GeckoDriverManager().install()),
        options=options,
    )

def get_driver_chrome():
    options = Options()
    options.headless = True

    linux_chrome_path = {
        "binary_location": "/opt/chrome-linux/chrome",
        "executable_path": "/opt/chrome-linux/chromedriver",
    }

    options.binary = linux_chrome_path["binary_location"]
    return webdriver.Chrome(
        executable_path=linux_chrome_path["executable_path"],
        options=options,
    )

if __name__ == "__main__":
    domain = "https://example.com"

    driver = get_driver_firefox()
    driver.get(domain)
    get_full_page(driver, domain + "/", "/home/user/results/example-full.png")
    get_short_page(driver, domain + "/", "/home/user/results/example-short.png")

    driver.close()


'''
Leetcode: 871. Minimum Number of Refueling Stops
Educative: https://www.educative.io/courses/grokking-coding-interview-patterns-python/qVRq9mQnqV7

A car travels from a starting position to a destination which is target miles east of the starting position.

There are gas stations along the way. The gas stations are represented as an array stations where stations[i] = [positioni, fueli] indicates that the ith gas station is positioni miles east of the starting position and has fueli liters of gas.

The car starts with an infinite tank of gas, which initially has startFuel liters of fuel in it. It uses one liter of gas per one mile that it drives. When the car reaches a gas station, it may stop and refuel, transferring all the gas from the station into the car.

Return the minimum number of refueling stops the car must make in order to reach its destination. If it cannot reach the destination, return -1.

Note that if the car reaches a gas station with 0 fuel left, the car can still refuel there. If the car reaches the destination with 0 fuel left, it is still considered to have arrived.

Example 1:
Input: target = 1, startFuel = 1, stations = []
Output: 0
Explanation: We can reach the target without refueling.

Example 2:
Input: target = 100, startFuel = 1, stations = [[10,100]]
Output: -1
Explanation: We can not reach the target (or even the first gas station).

Example 3:
Input: target = 100, startFuel = 10, stations = [[10,60],[20,30],[30,30],[60,40]]
Output: 2
Explanation: We start with 10 liters of fuel.
We drive to position 10, expending 10 liters of fuel.  We refuel from 0 liters to 60 liters of gas.
Then, we drive from position 10 to position 60 (expending 50 liters of fuel),
and refuel from 10 liters to 50 liters of gas.  We then drive to and reach the target.
We made 2 refueling stops along the way, so we return 2.

'''
from heapq import heappush, heappop
from typing import List

def minRefuelStops(target: int, startFuel: int, stations: List[List[int]]) -> int:
    # target = 100 miles .. startFuel = 10
    # stations = [[10,60], [20,30], [30,30], [60,40]] ,, [[position, fuel]]
    # start(10)-------(10+60)-----------------------(70+40)--->Target=100
    #                    +1                           +2

    if startFuel >= target:
        return 0

    max_heap = []
    max_distance = startFuel #Max miles that we can reach, starting with startFuel
    min_refuel = 0

    i = 0
    while max_distance < target: #Loop until car reach the target or it's out of fuel
        if i < len(stations) and max_distance >= stations[i][0]: #There are still stations
            '''
            Sice, I am already ahead of or at this station (i.e.
            max_distance >= stations[i][0]) we don't use this station and try to move ahead but I store this station in maxheap to use in future
            '''
            heappush(max_heap, -stations[i][1]) #So, add its fuel capacity to the heap
            i += 1

        elif not max_heap: #If there are no more stations and we can't reach the target
            return -1

        else: #Otherwise, fill up at the station with the highest fuel capacity
            max_distance += -heappop(max_heap)
            min_refuel += 1 #And increment stops

    return min_refuel

def main():
    input = [
        (1, 1, []),
        (100, 1, [[10, 100]]),
        (59, 14, [[9, 12], [11, 7], [13, 16], [21, 18], [47, 6]]),
        (15, 3, [[2, 5], [3, 1], [6, 3], [12, 6]]),
        (570, 140, [[140, 200], [160, 130], [310, 200], [330, 250]]),
        (1360, 380, [[310, 160], [380, 620], [700, 89], [850, 190],[990, 360]])
    ]
    num = 1
    for i in input:
        print(num, '.\tStations =', i[2])
        print('\tTarget =', i[0])
        print('\tStarting fuel =', i[1])
        print('\n\tMinimum number of refueling stops is:', minRefuelStops(i[0], i[1], i[2]))
        num += 1
        print('-' * 85, '\n')

if __name__ == '__main__':
    main()

'''
TC -> O(nlogn), where n is the number of stations. The while loop runs until the car reaches the target or runs out of fuel, which takes O(target/startFuel) iterations in the worst case. The inner while loop runs until all the stations that can be reached from the current fuel level are added to the heap, which takes O(n) iterations in the worst case. The heappush and heappop operations take O(logn) time each, and they are performed for each station, so the total time complexity of the heap operations is O(nlogn). Therefore, the overall time complexity of the function is O(nlogn)
SC -> O(n), since there will be maximum n fuel capacities in the heap.
'''


from datetime import datetime, timezone
from functools import partial
import struct
from enum import Enum

from demo_analyzer.constants import FormatStrings

class Field:
    _creation_counter = 0

    def __init__(self, flag=None):
        self._creation_counter = Field._creation_counter
        Field._creation_counter += 1

        self.flag = flag

        self.field_name = None

    def bind(self, field_name):
        self.field_name = field_name

        if self.flag is None:
            self.flag = field_name

    def get_attribute(self, data):
        return data.get(self.field_name, None)

    def encode(self, value):
        raise NotImplementedError

    def get_value(self, raw_value):
        return raw_value

    def decode(self, buffer):
        raise NotImplementedError

FMT_BYTE_ORDERS = ('@', '=', '<', '>', '!')

class StructField(Field):
    fmt = None
    size = None

    def __init__(self, fmt=None, **kwargs):
        super().__init__(**kwargs)

        if fmt:
            self.fmt = fmt

        if isinstance(self.fmt, Enum):
            self.fmt = self.fmt.value

        if self.fmt[0] not in FMT_BYTE_ORDERS:
            self.fmt = '<' + self.fmt

        self.size = struct.calcsize(self.fmt)

    def encode(self, value):
        return struct.pack(
            self.fmt,
            value
        )

    def decode(self, buffer):
        return struct.unpack(
            self.fmt,
            buffer.read(self.size)
        )[0]

class ByteField(StructField):
    fmt = FormatStrings.BYTE

class Int8Field(StructField):
    fmt = FormatStrings.INT8

class UInt8Field(StructField):
    fmt = FormatStrings.UINT8

class Int16Field(StructField):
    fmt = FormatStrings.INT16

class UInt16Field(StructField):
    fmt = FormatStrings.UINT16

class Int32Field(StructField):
    fmt = FormatStrings.INT32

class UInt32Field(StructField):
    fmt = FormatStrings.UINT32

class Int64Field(StructField):
    fmt = FormatStrings.INT64

class UInt64Field(StructField):
    fmt = FormatStrings.UINT64

class FloatField(StructField):
    fmt = FormatStrings.FLOAT

class BoolField(StructField):
    fmt = FormatStrings.BOOL

class TimestampField(StructField):
    def get_attribute(self, data):
        return super().get_attribute(data).timestamp()

    def get_value(self, raw_value):
        return datetime.fromtimestamp(raw_value, timezone.utc)

class StringField(Field):
    @staticmethod
    def encode(value):
        return value + '\x00'

    @staticmethod
    def decode(buffer):
        slist = []

        while True:
            try:
                val = buffer.read(1)[0]
            except ValueError:
                break
            if val == 0:
                break
            slist.append(chr(val))

        return ''.join(slist)

class FlagsField(StructField):
    def __init__(self, flags, **kwargs):
        super().__init__(**kwargs)

        self.flags = flags

    def get_attribute(self, data):
        flags = super().get_attribute(data)
        if flags is None:
            flags = self.generate_flags(data)
        return flags

    def encode(self, flags):
        flags_int = sum(
            (getattr(self.flags, name) for name, value in flags if value is True)
        )
        return super().encode(flags_int)

    def get_value(self, raw_value):
        return {
            name: self.bitwise_check(raw_value, member)
            for name, member in self.flags.__members__.items()
        }

    def generate_flags(self, data):
        return {
            name: True if data.get(name, None) is not None else False
            for name in self.flags.__members__
        }

    @staticmethod
    def bitwise_check(bits, bit_to_check):
        return True if (bits & bit_to_check) == bit_to_check else False


from django.urls import path
from courses.views import CourseListCreateView, CourseRetrieveUpdateDestroyAPIViewView, ModuleListByCourseView, EnrollmentListByCourseView

urlpatterns = [
    path('', CourseListCreateView.as_view(), name='course-list-create'),
    path('<int:pk>/', CourseRetrieveUpdateDestroyAPIViewView.as_view(),
         name='course-detail'),

    path('<int:pk>/modules/', ModuleListByCourseView.as_view(),
         name='module-list-by-course'),
    path('<int:pk>/enrollments/', EnrollmentListByCourseView.as_view(),
         name='enrollment-list-by-course'),
]


import math, functools as ft

def Ejercicio1():
    num = int(input("Escribi un numero: "))
    if (num > 0) :
        print("\nEs positivo")
    elif (num < 0):
        print("\nEs negativo")
    else:
        print("\nEs 0!")

def Ejercicio2():
    radio = int(input("Ingresa el radio: "))
    print(f"EL perimetro del radio {radio} es {radio * math.pi * 2}")
    print(f"EL area del radio {radio} es {(radio*radio) * math.pi}")

def Ejercicio3():
    parimpar = int(input("Ingresa un numero: "))
    if parimpar % 2 == 0:
        print("Es par!")
    else:
        print("Es impar!")

def Ejercicio4(socio1, socio2, socio3, socio4):
    total = socio1 + socio2 + socio3 + socio4
    print(f"El socio 1 tiene {socio1 * 100 / total}%")
    print(f"El socio 2 tiene {socio2 * 100 / total}%")
    print(f"El socio 3 tiene {socio3 * 100 / total}%")
    print(f"El socio 4 tiene {socio4 * 100 / total}%")

def Ejercicio5y6(rango):
    pares = 0
    impares = 0
    for i in range(rango):
        numerico = int(input("Escribi un numero: "))
        if esPar(numerico):
            print("Es par")
            pares += 1
        else:
            print("Es impar")
            impares += 1

    print(f"Hay {pares} pares y {impares} impares")

def esPar(numero):
    return numero % 2 == 0

def Ejercicio7():
    mayor = 0
    menor = 0
    for i in range(10):
        num = int(input("Escriba un numero: "))
        if i == 0:
            mayor = num
        else:
            if num > mayor:
                mayor = num
            elif num < menor:
                menor = num

    print(f"El mayor numero fue {mayor}\nEl menor numero fue {menor}")

def Ejercicio8(cant_nums):
    lista_numeritos = [int(input("Escriba un numero: ")) for i in range(0, cant_nums)]
    print(f"Resultado de la multiplicacion de dichos numeros: {ft.reduce(lambda suma, num: suma * num, lista_numeritos)}")

def Ejercicio9():
    USUARIO = "TINI"
    CONTRASENIA = "GUOLIS123"

    usu_guess = input("Nombre: ")
    pass_guess = input("Password: ")

    if (USUARIO == usu_guess and CONTRASENIA == pass_guess):
        print("Bienvenidx!")
    else:
        print("Intente de nuevo!")
        if (USUARIO != usu_guess):
            print("Verificar usuario")
        if (CONTRASENIA != pass_guess):
            print("Verificar contrasenia")

def Ejercicio10():
    suma = 0
    num = -1
    while num != 0:
        num = int(input("Ingrese un numero (0 para salir): "))
        if (num != 0):
            suma += num

    print(f"La suma final es de {suma}")

def Ejercicio11():
    MESES = ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"]
    ganancia_mensual = dict()
    facturacion_total = 0
    coste_total = 0
    gasto_mes = 0
    ingreso_mes = 0

    for mes in MESES:
        print(f"{mes}.")
        ingreso_mes = int(input("Ingreso: "))
        gasto_mes = int(input("Gasto: "))

        facturacion_total += ingreso_mes
        coste_total += gasto_mes
        ganancia_mensual.update({mes: ingreso_mes - gasto_mes})

    print("Facturacion anual: ", facturacion_total)
    print("Ganancia promedio = ", facturacion_total / 12)
    print("Ganancia mensual: ", ganancia_mensual)

def Ejercicio12():
    n1 = int(input("Ingrese un valor: "))
    n2 = int(input("Ingrese otro valor: "))
    op = input("Ingrese operacion a realizar (+, -, /, *): ")

    if (op == '+'):
        print(n1 + n2)
    elif (op == '-'):
        print(n1 - n2)
    elif (op == '*'):
        print(n1 * n2)
    elif (op == '/'):
        print(n1 / n2)
    else:
        print("Elija un operador valido!")

if __name__ == "__main__":
    # ir hardcoding q ejercicio se hace :)
    Ejercicio1()


#%%
#!/usr/bin/env python
import os, sys, json, argparse, math
import cv2
import numpy as np
from flask import Flask, render_template, Response
from camera_opencv import Camera
import tensorflow as tf
from datetime import datetime
sys.path.insert(0, os.path.abspath(''))
from segment.display import DrawFeatures

parser = argparse.ArgumentParser()

parser.add_argument('-debug', action='store_true',help='Wait for debugge attach')

#parser.add_argument('-model_dir', type=str, default='./trainings/unetcoco',help='Directory to store training model')
parser.add_argument('-model_dir', type=str, default=None,help='Directory to store training model')
parser.add_argument('-loadsavedmodel', type=str, default='./saved_model/2020-09-07-16-16-50-dl3', help='Saved model to load if no checkpoint')

parser.add_argument('-record_dir', type=str, default='./record', help='Path training set tfrecord')
parser.add_argument('-devices', type=json.loads, default=["/gpu:0"],  help='GPUs to include for training.  e.g. None for all, [/cpu:0], ["/gpu:0", "/gpu:1"]')
parser.add_argument('-image_size', type=json.loads, default='[480, 640]', help='Training crop size [height, width]/  [90, 160],[120, 160],[120, 160], [144, 176],[288, 352], [240, 432],[480, 640],[576,1024],[720, 960], [720,1280],[1080, 1920]')
parser.add_argument('-image_depth', type=int, default=3, help='Number of input colors.  1 for grayscale, 3 for RGB')

FLAGS, unparsed = parser.parse_known_args()

config = {
      'input_shape': [FLAGS.image_size[0], FLAGS.image_size[1], FLAGS.image_depth],
      'area_filter_min': 250,
      'size_divisible': 32,
      }

app = Flask(__name__)

model = None
infer = None
lut = None

@app.route('/')
def index():
    """Video streaming home page."""
    return render_template('index.html')

def PadValid(image, divisible=config['size_divisible']):
    [height, width, depth] = image.shape
    newwidth = int(divisible*math.ceil(float(width)/divisible))
    newheight = int(divisible*math.ceil(float(height)/divisible))
    pad = [[0,newheight-height],[0,newwidth-width], [0,0]]
    if np.max(pad) > 0:
        image = np.pad(image, pad)
    return image
    #return tf.image.pad_to_bounding_box(image, 0, 0, height, width)

def CropOrigonal(image, height, width):
    return image[:height,:width,:]
    #return tf.image.crop_to_bounding_box(image, 0, 0, height, width

def gen(camera):
    """Video streaming generator function."""

    #loaded = tf.saved_model.load_v2(FLAGS.model)
    #loaded = tf.saved_model.load(FLAGS.savedmodel)
    #print(list(loaded.signatures.keys()))
    #infer = loaded.signatures["serving_default"]
    #print(infer.structured_outputs)
    #print (infer.inputs[0])

    while True:
        img = camera.get_frame()
        [height, width, depth] = img.shape
        #print('img.shape={}'.format(img.shape))
        #img = cv2.flip(img, +1)
        tbefore = datetime.now()
        img = PadValid(img)

        if model is not None:
            seg = model.predict(np.expand_dims(img, axis=0))
            seg = tf.squeeze(seg).astype(np.uint8) # Drop batch dimension
        elif infer is not None:
            outputs = infer(tf.constant(np.expand_dims(img.astype(np.float32), axis=0)))
            seg = tf.math.argmax(outputs['logits'], axis=-1, output_type=tf.int32)
            seg = tf.squeeze(seg).numpy().astype(np.uint8)

        tPredict = datetime.now()
        #imseg = img
        #imseg = DrawFeatures(img, seg, config)

        seg = [cv2.LUT(seg, lut[:, i]) for i in range(3)]
        seg = np.dstack(seg)
        imseg = (img*seg).astype(np.uint8)
        #imseg = (img).astype(np.uint8)

        imseg = CropOrigonal(imseg, height, width)

        tAfter = datetime.now()
        dInfer = tPredict-tbefore
        dImAn = tAfter-tPredict

        #outputs['pred_age'].numpy()

        font = cv2.FONT_HERSHEY_COMPLEX_SMALL
        resultsDisplay = 'infer:{:.3f}s display:{:.3f}s'.format(dInfer.total_seconds(), dImAn.total_seconds())
        cv2.putText(imseg, resultsDisplay, (10,25), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA)
        # encode as a jpeg image and return it
        frame = cv2.imencode('.jpg', imseg)[1].tobytes()

        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

@app.route('/video_feed')
def video_feed():
    """Video streaming route. Put this in the src attribute of an img tag."""
    return Response(gen(Camera(config)), mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    FLAGS, unparsed = parser.parse_known_args()

    if FLAGS.debug:
        # https://code.visualstudio.com/docs/python/debugging#_remote-debugging
        # Launch applicaiton on remote computer:
        # > python3 -m ptvsd --host 0.0.0.0 --port 3000 --wait predict_imdb.py
        import ptvsd
        # Allow other computers to attach to ptvsd at this IP address and port.
        ptvsd.enable_attach(address=('0.0.0.0', 3000), redirect_output=True)
        # Pause the program until a remote debugger is attached
        print("Wait for debugger attach")
        ptvsd.wait_for_attach()
        print("Debugger Attached")

    print(tf.version)

    trainingsetDescriptionFile = '{}/description.json'.format(FLAGS.loadsavedmodel)
    trainingsetDescription = json.load(open(trainingsetDescriptionFile))['config']['trainingset']

    config['ignore_label'] = trainingsetDescription['classes']['ignore']
    config['classes'] = trainingsetDescription['classes']['classes']
    config['background'] = trainingsetDescription['classes']['background']
    config['trainingset'] = trainingsetDescription

    if FLAGS.model_dir is not None:
        try:
            model = tf.keras.models.load_model(FLAGS.model_dir) # Load from checkpoint
        except:
            print('Unable to load weghts from {}'.format(FLAGS.model_dir))

    if not model and FLAGS.loadsavedmodel:
        try:
            # model = tf.keras.models.load_model(FLAGS.loadsavedmodel) # Load from checkpoint

            loaded = tf.saved_model.load(FLAGS.loadsavedmodel)
            print(list(loaded.signatures.keys()))
            infer = loaded.signatures["serving_default"]
            print(infer.structured_outputs)
            print (infer.inputs[0])

            lut = np.zeros([256,3], dtype=np.uint8)
            for obj in config['trainingset']['classes']['objects']: # Load RGB colors as BGR
                lut[obj['trainId']][0] = obj['color'][2]
                lut[obj['trainId']][1] = obj['color'][1]
                lut[obj['trainId']][2] = obj['color'][0]
            lut = lut.astype(np.float) * 1/255. # scale colors 0-1
            lut[config['background']] = [1.0,1.0,1.0] # Pass Through

        except:
            print('Unable to load weghts from {}'.format(FLAGS.loadsavedmodel))

    app.run(host='0.0.0.0', threaded=True)


import sys
import joblib
import pandas as pd
from functools import partial
from functools import reduce
from sklearn.preprocessing import StandardScaler
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (
    QApplication,
    QGridLayout,
    QLineEdit,
    QMainWindow,
    QPushButton,
    QVBoxLayout,
    QHBoxLayout,
    QComboBox,
    QWidget,
    QLabel,
    QScrollArea,
    QGroupBox,
)
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure

WINDOW_WIDTH = 1000
WINDOW_HEIGHT = 700
DISPLAY_HEIGHT = 35
BUTTON_HEIGHT = 30
BUTTON_WIDTH = 120

class AppWindow(QMainWindow):
    ###Main window GUI/View###
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Predicting Match Outcomes")
        self.setFixedSize(WINDOW_WIDTH, WINDOW_HEIGHT)
        self.generalLayout = QVBoxLayout()
        centralWidget = QWidget(self)
        centralWidget.setLayout(self.generalLayout)
        self.setCentralWidget(centralWidget)
        self._createMainTitle()
        self._createTeamSelection()
        self._createOutputButton()
        self._createOutput()
        self._createHistoryButton()

    def _createMainTitle(self):
        self.mainTitle = QLabel("
Predicting Match Outcomes
")
        self.mainTitle.setFixedHeight(DISPLAY_HEIGHT)
        self.mainTitle.setAlignment(Qt.AlignmentFlag.AlignHCenter)
        self.generalLayout.addWidget(self.mainTitle)

    def _createTeamSelection(self):
        teamsLayout = QHBoxLayout()
        currentyeardata = pd.read_csv('project\data\currentyeardata.csv')
        teams = currentyeardata.loc[:, 'Squad']

        self.teamSelection1 = QComboBox(self)
        for col, val in enumerate(teams):
            self.teamSelection1.addItem(val)
        teamsLayout.addWidget(self.teamSelection1)

        self.teamSelection2 = QComboBox(self)
        for col, val in enumerate(teams):
            self.teamSelection2.addItem(val)
        teamsLayout.addWidget(self.teamSelection2)

        self.generalLayout.addLayout(teamsLayout)

    def _createOutputButton(self):
        self.outputButton = QPushButton("Predict Outcome")
        self.outputButton.setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT)
        self.generalLayout.addWidget(self.outputButton)

    def _createOutput(self):
        outputLayout = QVBoxLayout()

        self.outputDisplay = QLineEdit()
        self.outputDisplay.setFixedHeight(DISPLAY_HEIGHT)
        self.outputDisplay.setAlignment(Qt.AlignmentFlag.AlignLeft)
        self.outputDisplay.setReadOnly(True)
        outputLayout.addWidget(self.outputDisplay)

        fig = Figure(figsize=(4,4))
        self.axes = fig.add_subplot()
        self.canvas = FigureCanvas(fig)
        outputLayout.addWidget(self.canvas)

        self.generalLayout.addLayout(outputLayout)

    def _createHistoryButton(self):
        self.historyButton = QPushButton("History")
        self.historyButton.setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT)
        self.generalLayout.addWidget(self.historyButton)

    def _createSeasonsButton(self):
        self.seasonButton = QPushButton("Season")
        self.seasonButton.setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT)
        self.generalLayout.addWidget(self.seasonButton)

    def setOutputDisplay(self, result):
        if (result == '[0]') :
            text = "Home Win"
        elif (result == '[1]'):
            text = "Draw"
        elif (result == '[2]'):
            text = "Away Win"
        else :
            text = result;

        self.outputDisplay.setText(text)
        self.outputDisplay.setFocus()

    def updateOutputGraph(self, probas):
        labels = ["Home Win", "Draw", "Away Win"]
        self.axes.cla()
        self.axes.pie(probas, labels=labels, autopct='%1.1f%%')
        self.canvas.draw()

class HistoryWindow(QWidget):
    def __init__(self, history):
        super().__init__()
        self.setWindowTitle("Prediction History")
        self.setFixedSize(WINDOW_WIDTH-350, WINDOW_HEIGHT)
        self.generalLayout = QVBoxLayout(self)
        self._createHistoryLabel(history)
        scroll = QScrollArea()
        scroll.setWidget(self.groupBox)
        scroll.setWidgetResizable(False)
        self.generalLayout.addWidget(scroll)

    def _createMainTitle(self):
        self.mainTitle = QLabel("
Prediction History
")
        self.mainTitle.setFixedHeight(DISPLAY_HEIGHT)
        self.mainTitle.setAlignment(Qt.AlignmentFlag.AlignHCenter)
        self.generalLayout.addWidget(self.mainTitle)

    def _createHistoryLabel(self, history):
        self.groupBox = QGroupBox("Prediction History")
        if not history:
            self.historyLabel = QLabel("No prediction history.")
            tempLayout = QHBoxLayout()
            tempLayout.addWidget(self.historyLabel)
            self.groupBox.setLayout(tempLayout)
        else:
            self.historyStack = {}
            self.graphStack = {}
            historyLayout = QGridLayout()
            for i in range(len(history)):
                # Label
                key = history[i]['HomeTeam'] + history[i]['AwayTeam']
                if (history[i]['Pred'][0] == 0):
                    result = "Home Win"
                elif (history[i]['Pred'][0] == 1):
                    result = "Draw"
                elif (history[i]['Pred'][0] == 2):
                    result = "Away Win"
                self.historyStack[key] = QLabel(f"Home Team: {history[i]['HomeTeam']}, Away Team: {history[i]['AwayTeam']}, Result: {result}")
                historyLayout.addWidget(self.historyStack[key], i, 0)

                # Graph
                fig = Figure(figsize=(2,1))
                self.axes = fig.add_subplot()
                self.graphStack[key] = FigureCanvas(fig)
                probas = history[i]["Proba"][0]
                labels = ["Home Win", "Draw", "Away Win"]
                self.axes.pie(probas, labels=labels, autopct='%1.1f%%')
                self.graphStack[key].draw()
                historyLayout.addWidget(self.graphStack[key], i, 1)

            self.groupBox.setLayout(historyLayout)

class PredModel:
    ###Model###
    def __init__(self):
        rawdata = self.retrieveData()
        matchesData = self.storeData(rawdata)
        self.currentYearData = self.scaleData(matchesData)
        print("Data Loaded")

        self.predictingModel = joblib.load('project\models\\randomtree.sav')
        # self.predictingModel = joblib.load('project\models\\logisticreg.sav')
        print("Model loaded")

        self.history = [] #stack of history

    def retrieveData(self) :
        # Get from data source
        yearURL = 'https://fbref.com/en/comps/9/2022-2023/2022-2023-Premier-League-Stats'
        year = pd.read_html(yearURL)

        # Calculate the average number of games played in the season so far
        temp = pd.DataFrame(year[0])
        averageGamesPlayed = temp.loc[:, 'MP'].mean()

        # Clean standard stats
        standard = year[2].drop(columns=['Unnamed: 1_level_0','Unnamed: 2_level_0','Unnamed: 3_level_0','Playing Time','Expected', 'Per 90 Minutes'], axis=1, level=0)
        standard.columns = standard.columns.droplevel()
        standard = standard.drop(columns=['G+A','G-PK','PK','PKatt'])
        standard[['Gls','Ast','CrdY','CrdR','PrgC','PrgP']] = standard[['Gls','Ast','CrdY','CrdR','PrgC','PrgP']].div(averageGamesPlayed)

        # Clean goalkeeping stats
        goalkeeping = year[4]
        goalkeeping.columns = goalkeeping.columns.droplevel()
        goalkeeping = goalkeeping[['Squad','Saves']]
        goalkeeping[['Saves']] = goalkeeping[['Saves']].div(averageGamesPlayed)

        # Clean shooting stats
        shooting = year[8].drop(columns=['Unnamed: 1_level_0','Unnamed: 2_level_0','Expected'], axis=1, level=0)
        shooting.columns = shooting.columns.droplevel()
        shooting = shooting[['Squad','Sh','SoT']]
        shooting[['Sh','SoT']] = shooting[['Sh','SoT']].div(averageGamesPlayed)

        # Clean pass types stats
        passtypes = year[12].drop(columns=['Unnamed: 1_level_0','Unnamed: 2_level_0','Unnamed: 3_level_0','Corner Kicks','Outcomes'], axis=1, level=0)
        passtypes.columns = passtypes.columns.droplevel()
        passtypes = passtypes[['Squad','FK','TB','Sw','Crs','CK']]
        passtypes[['FK','TB','Sw','Crs','CK']] = passtypes[['FK','TB','Sw','Crs','CK']].div(averageGamesPlayed)

        # Clean creativity stats
        creativity = year[14].drop(columns=['Unnamed: 1_level_0','Unnamed: 2_level_0','SCA Types','GCA Types'], axis=1, level=0)
        creativity.columns = creativity.columns.droplevel()
        creativity = creativity[['Squad','SCA','GCA']]
        creativity[['SCA','GCA']] = creativity[['SCA','GCA']].div(averageGamesPlayed)

        # Clean defensive stats
        defensive = year[16].drop(columns=['Unnamed: 1_level_0','Unnamed: 2_level_0','Challenges','Unnamed: 16_level_0'],axis=1,level=0)
        defensive.columns = defensive.columns.droplevel()
        defensive = defensive[['Squad','TklW','Blocks','Int','Clr','Err']]
        defensive[['TklW','Blocks','Int','Clr','Err']] = defensive[['TklW','Blocks','Int','Clr','Err']].div(averageGamesPlayed)

        # Clean possesion stats
        possession = year[18].drop(
            columns=['Unnamed: 1_level_0','Unnamed: 3_level_0','Touches','Take-Ons','Carries','Receiving'],axis=1,level=0)
        possession.columns = possession.columns.droplevel()

        # Clean misc stats
        misc = year[22].drop(columns=['Unnamed: 1_level_0','Unnamed: 2_level_0','Aerial Duels'],axis=1,level=0)
        misc.columns = misc.columns.droplevel()
        misc = misc[['Squad','Fls','Fld','Off','PKwon','PKcon','Recov']]
        misc[['Fls','Fld','Off','PKwon','PKcon','Recov']] = misc[['Fls','Fld','Off','PKwon','PKcon','Recov']].div(averageGamesPlayed)

        currentYear = {'standard' : standard, 'goalkeeping' : goalkeeping, 'shooting' : shooting, 'passtypes' : passtypes,
            'creativity' : creativity, 'defensive' : defensive, 'possession' : possession, 'misc' : misc}

        dataframe = [currentYear['standard'],currentYear['goalkeeping'],currentYear['shooting'],
                    currentYear['passtypes'],currentYear['defensive'],currentYear['possession'],currentYear['misc']]

        df_merged = reduce(lambda  left,right: pd.merge(left,right,on=['Squad'],how='outer'), dataframe)
        return df_merged

    def storeData(self, rawdata):
        matchesData = pd.DataFrame()
        teams = rawdata.loc[:, 'Squad']
        for i in range(len(teams)):
            temp = list(teams)
            temp.remove(teams[i])
            for j in range(len(temp)):
                data = self.cleanAndProcessData(teams[i], temp[j], rawdata)
                matchesData = pd.concat([matchesData, data], ignore_index=True, axis=0)

        return matchesData

    def scaleData(self, matchesData):
        matchups = matchesData[['HomeTeam','AwayTeam']].copy()
        matchstats = matchesData.drop(columns=['HomeTeam', 'AwayTeam'])

        scaler = StandardScaler()
        scaler.fit(matchstats)
        scaledMatchstats = pd.DataFrame(scaler.transform(matchstats))

        scaledData = pd.merge(matchups, scaledMatchstats, left_index=True, right_index=True)

        return scaledData

    def cleanAndProcessData(self, homeTeam, awayTeam, rawdata):
        # Retrieve corresponding team stats from data and rename variables `home_'
        homeTeamStats = rawdata.loc[rawdata['Squad'] == homeTeam]
        homeTeamStats = homeTeamStats.drop(columns=['CrdY','CrdR'])
        homeTeamStats = homeTeamStats.rename(columns={c: 'home_'+ c for c in homeTeamStats.columns if c not in ['Squad']})
        homeTeamStats = homeTeamStats.rename(columns={'Squad':'HomeTeam'})

        # Retrieve corresponding team stats from data and rename variables `away_'
        awayTeamStats = rawdata.loc[rawdata['Squad'] == awayTeam]
        awayTeamStats = awayTeamStats.drop(columns=['CrdY','CrdR'])
        awayTeamStats = awayTeamStats.rename(columns={c: 'away_'+ c for c in awayTeamStats.columns if c not in ['Squad']})
        awayTeamStats = awayTeamStats.rename(columns={'Squad':'AwayTeam'})

        # temporary merge key
        homeTeamStats['key'] = 1
        awayTeamStats['key'] = 1

        # merge records together for one match-up record
        teamStats = pd.merge(homeTeamStats, awayTeamStats, on=['key'])
        temp = teamStats['AwayTeam']
        teamStats = teamStats.drop(columns=['AwayTeam'])
        teamStats.insert(loc=1, column='AwayTeam', value=temp)
        teamStats = teamStats.drop(columns=['key'])

        return teamStats

    def predict(self, homeTeam, awayTeam):
        if (homeTeam == awayTeam):
            return ["ERROR", "NULL"]
        else:
            teamstats = self.currentYearData.loc[(self.currentYearData['HomeTeam'] == homeTeam) &
                                     (self.currentYearData['AwayTeam'] == awayTeam)]
            pureData = teamstats.drop(columns=['HomeTeam', 'AwayTeam'])
            # Predict outcome and probas
            pred = self.predictingModel.predict(pureData)
            proba = self.predictingModel.predict_proba(pureData)

            # Add predictions to new dictionary
            predResult = {'HomeTeam' : homeTeam,
                          'AwayTeam' : awayTeam,
                          'Pred' : pred,
                          'Proba' : proba}

            self.history.append(predResult)

            return [pred, proba]

class Controller:
    ###Controller Class###
    def __init__(self, model, view):
        self._predModel = model
        self._view = view
        self.historyWindow = None
        self._connectSignalsAndSlots()

    def _predictResult(self):
        result = self._predModel.predict(
            homeTeam=str(self._view.teamSelection1.currentText()),
            awayTeam=str(self._view.teamSelection2.currentText())
            )

        self._view.setOutputDisplay(str(result[0]))
        if (str(result[1])!="NULL"):
            self._view.updateOutputGraph(result[1][0])

    def _showHistoryWindow(self):
        # if self.historyWindow is None:
        self.historyWindow = HistoryWindow(self._predModel.history)
        self.historyWindow.show()

    def _connectSignalsAndSlots(self):
        self._view.outputButton.clicked.connect(partial(self._predictResult))
        self._view.historyButton.clicked.connect(partial(self._showHistoryWindow))

def main():
    ###Main function for app###
    predModel = PredModel()
    app = QApplication([])
    appWindow = AppWindow()
    appWindow.show()
    Controller(model=predModel, view=appWindow)
    sys.exit(app.exec())

### Entry point ###
if __name__ == "__main__":
    main()


from typing import Optional, Dict, Set

def solve_single(letters: str, result: Dict[str, int],
                 base: int, summed: int, no_zero: Set[str]) -> Optional[bool]:

    if len(letters) == 0 and summed == 0:
        return True

    elif len(letters) == 0:
        return None

    letter = letters[0]

    if letter == '=':
        r = result.get(letters[1])

        if r is not None:
            if r == summed % base and not (r == 0 and letters[1] in no_zero):
                return solve_single(letters[2:], result, base,
                                    0 + summed // base, no_zero)
            elif r != summed % base:
                return None

        else:
            if summed % base in result.values() or \
                   (summed % base == 0 and letters[1] in no_zero):
                return None
            else:
                result[letters[1]] = summed % base
                if solve_single(letters[2:], result, base,
                                0 + summed // base, no_zero):
                    return True

                result.pop(letters[1])
                return None

    if result.get(letter) is not None:
        summed += result[letter]
        letter = letters[0]

        if solve_single(letters[1:], result, base, summed, no_zero):
            return True
    else:

        for num in range(base):
            if num == 0 and letter in no_zero:
                continue

            if num in result.values():
                continue

            result[letter] = num

            if solve_single(letters[1:], result, base, summed + num, no_zero):
                return True

            result.pop(letter)

    return None

def solve(equation: str, base: int) -> Optional[Dict[str, int]]:

    result: Dict[str, int] = {}

    left_side = equation.split(" = ")[0].split(" + ")
    right_side = equation.split(" = ")[1]

    no_zero = set([word[0] for word in left_side]) | set([right_side[0]])
    equation = ""

    for i in range(len(right_side)):
        for word in left_side:

            if i < len(word):
                equation += (word[(-i - 1) % len(word)])

        equation += "=" + right_side[-i - 1]

    solve_single(equation, result, base, 0, no_zero)
    return result if result else None

def main() -> None:

    assert solve("SEND + MORE = MONEY", 10) \
        == {'S': 9, 'E': 5, 'N': 6, 'D': 7, 'M': 1, 'O': 0, 'R': 8, 'Y': 2}

    for base in range(2, 27):
        result = solve("XY + XY = YX", base)

        if base == 2 or base % 3 != 2:
            assert result is None
        else:
            x = base // 3
            y = 2 * x + 1
            assert result == {'X': x, 'Y': y}

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
"""Tool to load program from YAML and print out progression for lifting."""
from __future__ import absolute_import, division, print_function

from dataclasses import dataclass
from typing import Any, Iterable, List, Optional, Mapping, Union, Sequence, Text, TextIO

# third party
import yaml

from contracts import check, contract, new_contract  # type: ignore

# TYPES ##########

Numeric = Union[float, int]
ProgramData = Sequence[Mapping[str, Any]]

# CONTRACTS ##########

new_contract('program_data', 'seq(map(str: *))')

# DATA CLASSES ##########

@dataclass(frozen=True)
class WorkingSet:
    percent: float
    reps: int

    # optional
    amrap: bool = False

    def calculate_weight(self, tm: Optional[Numeric] = None, rounding: Optional[Numeric] = None) -> Numeric:
        """Calculate weight based on optional training max.

        >>> WorkingSet(percent=0.5, reps=10).calculate_weight()
        0.5

        >>> WorkingSet(percent=0.5, reps=10).calculate_weight(205, 10.0)
        100.0
        """
        return mround(float(tm) * self.percent, rounding) if tm else self.percent

    def stringify(self, tm: Optional[Numeric] = None, rounding: Optional[Numeric] = None) -> Text:
        """Pretty-print string representation for working set with optional training max.

        >>> WorkingSet(percent=0.5, reps=10).stringify()
        '0.5 x 10'

        >>> WorkingSet(amrap=True, percent=0.5, reps=10).stringify(215, 10.0)
        '100.0 x 10+'
        """
        weight = self.calculate_weight(tm, rounding=rounding)
        reps = f'{self.reps}+' if self.amrap else self.reps
        return f'{weight:.1f} x {reps}'

@dataclass(frozen=True)
class Session:
    __slots__ = ('name', 'sets')
    name: str
    sets: List[WorkingSet]

@dataclass(frozen=True)
class MicroCycle:
    __slots__ = ('name', 'sessions')
    name: str
    sessions: List[Session]

@dataclass(frozen=True)
class MesoCycle:
    name: str
    micros: List[MicroCycle]

    # optional
    tm_inc: Numeric = 0

    def effective_tm(self, tm: Optional[Numeric] = None) -> Optional[Numeric]:
        """Get effective training max for this mesocycle.

        >>> MesoCycle('m1', []).effective_tm(100)
        100.0

        >>> MesoCycle('m1', [], tm_inc=5).effective_tm(100)
        105.0
        """
        return float(tm) + float(self.tm_inc) if tm else None

@dataclass(frozen=True)
class Program:
    __slots__ = ('mesos', 'name')
    name: str
    mesos: List[MesoCycle]

    def present(self, rounding: Optional[Numeric] = None, tm: Optional[int] = None) -> None:
        """Pretty print program."""
        header = '=' * max(20, len(self.name))
        print(header, self.name, header)
        flattened = ((s, u, m) for m in self.mesos for u in m.micros for s in u.sessions)
        for session, micro, meso in flattened:
            flattened_name = '.'.join([meso.name, micro.name, session.name]).upper()
            banner = '-' * min(10, len(flattened_name))

            etm = meso.effective_tm(tm)
            if tm:
                print(banner, flattened_name, f'[TM: {etm}]', banner)
            else:
                print(banner, flattened_name, banner)

            for ws in session.sets:
                print(ws.stringify(meso.effective_tm(tm), rounding))

    def present_table(self, rounding: Optional[Numeric] = None, tm: Optional[int] = None) -> None:
        """Pretty print program as tabular data."""
        try:
            from tabulate import tabulate
        except ImportError:
            raise ImportError('Need to pip install tabulate!')

        header = '=' * max(20, len(self.name))
        print(header, self.name, header)

        for meso in self.mesos:
            headers: List[str] = []
            table: List[List[str]] = []
            for micro_number, micro in enumerate(meso.micros):
                headers.append('.'.join([meso.name, micro.name]))
                for session_number, session in enumerate(micro.sessions):
                    value = '\n'.join(ws.stringify(meso.effective_tm(tm), rounding) for ws in session.sets)
                    if len(table) <= session_number:
                        table.append([])
                    if len(table[session_number]) <= micro_number:
                        table[session_number].append(value)
                    else:
                        table[session_number][micro_number] = value
            print(tabulate(table, headers=headers, tablefmt='grid'))

# PUBLIC FUNCTIONS ##########

@contract(mesos='program_data')
def generate_mesos(mesos: ProgramData) -> Iterable[MesoCycle]:
    """Generate mesocycles from data."""
    for meso in mesos:
        micros = [micro for micro in generate_micros(meso['micros'])]
        options = {k: v for k, v in meso.items() if k in ('tm_inc',)}
        yield MesoCycle(meso['name'], micros, **options)

@contract(micros='program_data')
def generate_micros(micros: ProgramData) -> Iterable[MicroCycle]:
    """Generate microcycles from data."""
    for micro in micros:
        sessions = [session for session in generate_sessions(micro['sessions'])]
        yield MicroCycle(micro['name'], sessions)

@contract(sessions='program_data')
def generate_sessions(sessions: ProgramData) -> Iterable[Session]:
    """Generate sessions from data."""
    for session in sessions:
        workingsets = [ws for ws in generate_workingsets(session['sets'])]
        yield Session(session['name'], workingsets)

@contract(workingsets='program_data')
def generate_workingsets(workingsets: ProgramData) -> Iterable[WorkingSet]:
    """Generate workingsets from data for session."""
    for ws in workingsets:
        workingset = WorkingSet(amrap=ws.get('amrap', False), percent=ws['percent'], reps=ws['reps'])
        for _ in range(ws.get('sets', 1)):
            yield workingset

def load_program(handle: TextIO) -> Program:
    """Load program from YAML file handle."""
    program: Mapping[str, Any] = yaml.safe_load(handle)
    check('map(str: str|program_data)', program)
    mesos = [meso for meso in generate_mesos(program['mesos'])]
    return Program(program['name'], mesos)

def mround(value: Numeric, rounding: Optional[Numeric] = None) -> Numeric:
    """Round to nearest rounding value.

    >>> mround(103, 2.5)
    102.5
    """
    if not rounding:
        rounding = 5.0
    return (float(value) // rounding) * rounding


import argparse
import os
import json

import numpy as np
from scipy.spatial.transform import Rotation as R

def parse_args():
    parser = argparse.ArgumentParser(description="Create camera path from transforms.json")

    parser.add_argument("--scene", "--training_data", default="", help="The scene to load. Can be the scene's name or a full path to the training data.")

    args = parser.parse_args()
    return args

if __name__ == "__main__":
    args = parse_args()
    path = os.getcwd().replace("\\","/")
    path = os.path.join(path, args.scene)
    path = path.replace("\\","/")
    # path = path.replace("/","\\")

    def nerf_to_ngp(xf):
        mat = np.copy(xf)
        mat = mat[:-1,:]
        mat[:,1] *= -1 # flip axis
        mat[:,2] *= -1
        mat[:,3] *= 0.33 #scale
        mat[:,3] += [0.5, 0.5, 0.5] #offset

        mat = mat[[1,2,0], :] # swap axis

        rm = R.from_matrix(mat[:,:3])

        # quaternion (x, y, z, w) and translation
        #  + 0.025
        return rm.as_quat(), mat[:,3]

    def smooth_camera_path(path_to_transforms, ):
        out = {"path":[], "time":1.0}
        with open(path_to_transforms + '/transforms.json') as f:
            data = json.load(f)

        n_frames = len(data['frames'])
        # fov = 85.0
        fov = data["camera_angle_y"] * 180 / np.pi
        print(fov)
        xforms = {}
        for i in range(n_frames):
            # file = int(data['frames'][i]['file_path'].split('/')[-1][:-4])
            file = int(data['frames'][i]['file_path'].split('/')[-1][-7:-4])
            xform = data['frames'][i]['transform_matrix']
            xforms[file] = xform

        xforms = dict(sorted(xforms.items()))
        indexes = list(xforms.keys())

        # linearly take n (4) transformation from transforms.json
        for ind in np.linspace(0, n_frames - 1, 4, endpoint=True, dtype=int):

            q, t = nerf_to_ngp(np.array(xforms[indexes[ind]]))

            out['path'].append({
                "R": list(q),
                "T": list(t),
                "aperture_size":0.0,
                "fov":fov,
                "glow_mode":0,
                "glow_y_cutoff":0.0,
                "scale":1.25,
                "slice":0.0
            })

        with open(path_to_transforms+'/base_cam_script.json', "w") as outfile:
            json.dump(out, outfile, indent=2)

    smooth_camera_path(path)


#!/usr/bin/env python
# coding: utf-8

# In[3]:

from functools import reduce
def function_one():
    print("I am function one")

def function_two():
    return function_one

def function_three(x):
    return x, x**2, x**3

def function_four(x):
    return abs(x)

def function_five(a,b,c):
    return a+b+c

def function_six(x):
    if x%2 ==0:
        return False
    return True

def function_seven(a,b):
    return a+b

def main():
    """
    another_name = fuction_one
    another_name()
    my_list = [1,"string",function_one]
    my_list[2]()
    print(function_one)
    # function composition
    (function_two())()
    my_list_2 = ["ram", "rohit", "ansari", "aman", "surabhi"]
    print(sort(my_list_2))
    print(sorted(my_list_2, key=len))
    """
    #lamda
    lambda_ex = (lambda x: x**2)
    print(lambda_ex(5))
    print((lambda x: x + 10)(90))
    my_list_2 = ["ran", "rohit", "ansari", "aman", "surabhi"]
    print(sorted(my_list_2, key=lambda x: -len(x)))

    #multiple values
    print(function_three(3))

    lambda_multiple = (lambda x: [x, x * 2, x * 3])
    print(lambda_multiple(4))
    lambda_multiple = (lambda x: (x, x*2,x*3))
    print(lambda_multiple(4))

    #map:(map(function/operation, list/iterable))
    my_list_3 = [1,-4,7,-10,101,-123]
    map_lambda_obj = map(function_four, my_list_3)
    print("Lambda method abs: ",list(map_lambda_obj))
    for item in map_lambda_obj:
        print(item)
    map_output =list(map(function_four, my_list_3))
    print(map_output)

    #map multiple iterables
    list1 = [1,2,3,4,5]
    list2 = [6,7,8,9,10]
    list3 = [11,12,13,14,15]
    print(map(function_five, list1,list2,list3))
    print(list(map(lambda x1,x2,x3: x1 + x2 + x3, list1, list2, list3)))

    #filter
    list4 = []
    for i in range(1,101,1):
        list4.append(i)
    #print(list4)
    print(list(filter(function_six, list4)))
    print(list(filter(lambda x: x%2 == 1, list4)))

    #reduce
    list5 = []
    for i in range(1,11,1):
        list5.append(i)
    print(list5)
    print(reduce(function_seven, list5))
    print(reduce(function_seven, list5, 10))
    print("List5 is: ", list5)
    print(sum(list5))

    #List comprehension
    list6 = []
    for i in range(1, 51, 1):
        list6.append(i)
    print(list6)
    list7 = [itr for itr in range(1,51,1)]
    print(list7)
    list8 = [i + j for i in range(1,10) for j in range(1,10) if i == j]
    print(list8)

    #dictionary comprehension
    my_dict ={i: i ** 3 for i in range(1,10) if i%2 ==0}
    print(my_dict)

    #set comprehension
    duplicates_list = [1,2,3,4,4,5,5,5]
    my_set = {i for i in duplicates_list if i%2 ==1}
    print(my_set)
    my_tuple = (i for i in range(1,10))
    for i in my_tuple:
        print(i)
    #print(my_tuple)

if __name__=="main__":
    main()

# # Practise

# In[17]:

#1.Define any class of your choice and use these keywords to introspect your object:
#dir, id, type, hasattr(), getattr(), __repr__, __doc__, __name__
class Car:
    def __init__(self,company_name,model,year_of_release,price):
        self.company_name=company_name
        self.model=model
        self.year_of_release=year_of_release
        self.price=price

    def print_car_details(self):
        print("Company name: ",self.company_name,"\tModel: ",self.model,"\tYear of market release: ",self.year_of_release,"\tPrice: ",self.price)

    def __repr__(self):
        return "Car attributes: ",self.company_name,self.model,self.year_of_release,self.price

def main():
    c1=Car("Tata","Punch",2020,600000)
    c1.print_car_details()
    print(dir(c1))
    print(id(c1))
    print(type(c1))
    print(hasattr(c1,"print_car_details"))
    print(getattr(c1,"model"))
    #print(repr(c1))
    #print(c1)
    print(Car.__doc__)
    print(Car.__name__)

if __name__=="__main__":
    main()

# In[22]:

#2.Define 1 parent class and 3 child classes of your choice. The parent class should be an abstract class and you must
#create 3 abstractmethods in it which should be overridden in the child classes
from abc import ABC, abstractmethod
class Laptop(ABC):
    @abstractmethod
    def __init__(self):
        pass

    @abstractmethod
    def print_laptop_details(self):
        pass

class Dell(Laptop):
    def __init__(self,model,ram,storage,price):
        self.model=model
        self.ram=ram
        self.storage=storage
        self.price=price

    def print_laptop_details(self):
        print("Dell Laptop have, Model no: ",self.model,"\tRAM: ",self.ram,"\tStorage: ",self.storage,"\tPrice: ",self.price)

class HP(Laptop):
    def __init__(self,model,ram,storage,price):
        self.model=model
        self.ram=ram
        self.storage=storage
        self.price=price

    def print_laptop_details(self):
        print("HP Laptop have, Model no: ",self.model,"\tRAM: ",self.ram,"\tStorage: ",self.storage,"\tPrice: ",self.price)

class Lenovo(Laptop):
    def __init__(self,model,ram,storage,price):
        self.model=model
        self.ram=ram
        self.storage=storage
        self.price=price

    def print_laptop_details(self):
        print("Lenovo Laptop have, Model no: ",self.model,"\tRAM: ",self.ram,"\tStorage: ",self.storage,"\tPrice: ",self.price)

def main():
    d1=Dell("Dell1","4GB","250GB HDD",35000)
    d1.print_laptop_details()
    h1=HP("HP4","8GB","512GB HDD",55000)
    h1.print_laptop_details()
    l1=Lenovo("GamerX","16GB","2TB SSD",87000)
    l1.print_laptop_details()

if __name__=="__main__":
    main()

# In[30]:

#3.Create 3 classes in which 2 are parent child and 1 is completely different and utilise the isinstance and issubclass
#keywords to show  their usage.
class Language:
    def __init__(self,name,level):
        self.name=name
        self.level=level

    def print_details(self):
        print("Programming language name: ",self.name,"\tLevel: ",self.level)

class Programming(Language):
    def __init__(self,name,level,applications):
        super().__init__(name,level)
        self.applications=applications

    def print_details(self):
        print("Programming language name: ",self.name,"\tLevel: ",self.level,"\tApplications: ",self.applications)

class Speaking:
    def __init__(self,name,applications):
        self.name=name
        self.applications=applications

    def print_details(self):
        print("Speaking language name: ",self.name,"\tApplications: ",self.applications)

def main():
    l1=Language("Java","High Level")
    l1.print_details()
    p1=Programming("Python","High Level","AI")
    p1.print_details()
    s1=Speaking("English","Communication")
    s1.print_details()
    print(issubclass(Programming,Language))
    print(issubclass(Speaking,Language))
    print(issubclass(Speaking,Programming))
    print(issubclass(Language,Programming))
    print(issubclass(Language,Speaking))

if __name__=="__main__":
    main()

# In[ ]:

# In[ ]:

# In[ ]:


import unittest
import tempfile
import os
import json
from mock import patch
from ..utilities import DataStoreUtilities, JsonParser, FileNotFound, NonParsableFile, DeviceUtilities

class TestUtilities(unittest.TestCase):
    def setUp(self):
        pass

    def test_tail_file(self):
        temp_file = tempfile.NamedTemporaryFile("w", delete=False)
        temp_file.write("""aligator;;
bat;;
cat;;
dog;;
elephant;;
flamingo;;
gorilla;;""")
        temp_file.close()
        result = DataStoreUtilities.tail_file(temp_file.name, 100)
        self.assertEqual(7, len(result))

        result = DataStoreUtilities.tail_file(temp_file.name, 5)
        self.assertEqual(5, len(result))

        result = DataStoreUtilities.tail_file(temp_file.name, 0)
        self.assertEqual(0, len(result))

        def only_dogs(line):
            print(line)
            return str(line) == "dog" or str(line) == "Dog"

        result = DataStoreUtilities.tail_file(temp_file.name, 100, None, only_dogs)
        self.assertEqual(1, len(result))

        def change_to_capitalized(line):
            return line.capitalize()

        result = DataStoreUtilities.tail_file(temp_file.name, 100, change_to_capitalized, only_dogs)
        self.assertEqual(1, len(result))

        os.remove(temp_file.name)

    def test_json_read_file(self):
        temp_file = tempfile.NamedTemporaryFile("w", delete=False)
        temp_file.write("""{}""")
        temp_file.close()
        result = JsonParser.read_file(temp_file.name)
        self.assertEqual(result, {})
        os.remove(temp_file.name)

        with self.assertRaises(FileNotFound):
            temp_file = tempfile.NamedTemporaryFile("w", delete=True)
            temp_file.close()
            JsonParser.read_file(temp_file.name)

        temp_file = tempfile.NamedTemporaryFile("w", delete=False)
        temp_file.write("""foo""")
        temp_file.close()
        with self.assertRaises(NonParsableFile):
            JsonParser.read_file(temp_file.name)
        os.remove(temp_file.name)

    def test_json_not_parsable(self):
        temp_file = tempfile.NamedTemporaryFile("w", delete=False)
        temp_file.write("")
        temp_file.close()
        try:
            result = JsonParser.read_file(temp_file.name)
            self.fail()
        except NonParsableFile as npf:
            self.assertEqual(str(npf), "'File {} cannot be parsed.'".format(temp_file.name))

        os.remove(temp_file.name)

    @patch.object(json, "dumps", side_effect=ValueError())
    def test_json_not_parseable2(self, mock_json):
        temp_file = tempfile.NamedTemporaryFile("w", delete=False)
        temp_file.write("")
        temp_file.close()
        try:
            JsonParser.write_file(temp_file.name, "")
            self.fail()
        except NonParsableFile:
            pass

        os.remove(temp_file.name)

    def test_json_write(self):
        temp_file = tempfile.NamedTemporaryFile("w", delete=False)
        temp_file.close()
        JsonParser.write_file(temp_file.name, "{}")
        os.remove(temp_file.name)

        temp_file = tempfile.NamedTemporaryFile("w", delete=False)
        temp_file.close()
        # with self.assertRaises(NonParsableFile):
        #     JsonParser.write_file(temp_file.name, "{[")
        os.remove(temp_file.name)

        with self.assertRaises(FileNotFound):
            JsonParser.write_file('/root/not-allowed', "")

        try:
            JsonParser.write_file('/root/not-allowed', "")
        except FileNotFound as fnf:
            self.assertEqual(str(fnf), "'File /root/not-allowed not found.'")

    def test_json_get_string(self):
        result = JsonParser.get_file_content_string({"one": 1, "two": "two"})
        self.assertEqual('{\n  "one": 1,\n  "two": "two"\n}', result)


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

import argparse
import itertools
import os
import json
import codecs
import operator
import cPickle
import numpy as np

def parse_args():
    parser = argparse.ArgumentParser(
        description="Translate using existing NMT models",
        usage="translator.py [<args>] [-h | --help]"
    )

    # input files
    # parser.add_argument("--input", type=str, required=True,
    #                     help="Path of input file")

    # input files
    parser.add_argument("--source", type=str, default= None, required=False,
                        help="Path of source corpus length")
    parser.add_argument("--target", type=str, default= None, required=False,
                        help="Path of target corpus length")
    parser.add_argument("--rev_align", type=str, default=None, required=False,
                        help="Path of reverse alignment")
    return parser.parse_args()

def main(args):
    # 读取src tgt的句长
    src_lens = None
    with open(args.source + '.len', "r") as len_file:
        src_lens = [int(line) for line in len_file]

    tgt_lens = None
    with open(args.target + '.len', "r") as len_file:
        tgt_lens = [int(line) for line in len_file]

    align_pos = []
    with open(args.rev_align, "r") as align_file:
        # i = 1
        for i, line in enumerate(align_file):
            # print(i)
            tgt_align_list = line.split()
            sen_align_src = []
            sen_align_tgt = []
            tgt_pos_set = set()
            for word_align in tgt_align_list:
                src_pos, tgt_pos = word_align.split('-')
                sen_align_src.append(src_pos)
                sen_align_tgt.append(tgt_pos)
                tgt_pos_set.add(int(tgt_pos))
            # aligning missed tgt word to eos
            for xpos in range(tgt_lens[i] + 1):  # +3 to add eos--eos
                if xpos not in tgt_pos_set:
                    sen_align_src.append(str(src_lens[i]))  # eos positon
                    sen_align_tgt.append(str(xpos))
            align_pos_mask = ['1'] * len(sen_align_tgt)  # 产生mask以便GPU处理
            align_pos.append([' '.join(sen_align_tgt), ' '.join(sen_align_src), ' '.join(align_pos_mask)])

    mask_file = open(args.target+'.align_mask', "w")
    src_align_pos_file = open(args.source + '.align_pos', "w")
    tgt_align_pos_file = open(args.target + '.align_pos', "w")
    for tgt_align_line, src_align_line, align_mask_line in align_pos:
        tgt_align_pos_file.write(tgt_align_line)
        tgt_align_pos_file.write('\n')
        src_align_pos_file.write(src_align_line)
        src_align_pos_file.write('\n')
        mask_file.write(align_mask_line)
        mask_file.write('\n')
    mask_file.close()
    src_align_pos_file.close()
    tgt_align_pos_file.close()

if __name__ == "__main__":
    main(parse_args())


import os
import json
import sys
import datetime
import time
from NucleiDataset import NucleiDataset
from seglib import SEG_ALGS
import segml
import segutils
import numpy as np
import pandas as pd

if __name__ == "__main__":

    timestamp = datetime.datetime.fromtimestamp(time.time()).strftime("%Y-%m-%d-%H-%M-%S")

    config_filename = sys.argv[1]
    with open(config_filename) as json_config_file:
        config = json.load(json_config_file)

    paths_config = config.get("paths")
    data_path = paths_config.get("input_path")
    output_path = paths_config.get("output_path")

    actions_config = config.get("actions")
    explore = actions_config.get("explore")
    preprocess = actions_config.get("preprocess")
    evaluate = actions_config.get("evaluate")
    test = actions_config.get("test")
    visualize = actions_config.get("visualize")

    action = "collecting images details"
    start_time = segutils.start_action(action)
    imgs_details = segutils.collect_imgs_details(data_path)
    segutils.complete_action(action, start_time)

    action = "creating train dataset"
    start_time = segutils.start_action(action)
    train_labels_file = os.path.join(data_path, 'train_labels.csv')
    train_dataset = NucleiDataset('train', imgs_df=imgs_details,
                                  labels_file=train_labels_file)
    print("set size: {}".format(len(train_dataset)))
    segutils.complete_action(action, start_time)

    if explore:
        for i in xrange(5):
            sample = train_dataset[i]
            for cls in xrange(len(SEG_ALGS)):
                segutils.plot_sample_segmentation(sample, cls, SEG_ALGS)
        sys.exit(0)

    labels = {"ImageId":[], "Class":[], "Name":[], "IoU":[]}
    if preprocess:
        action = "assigning best segmentation class"
        start_time = segutils.start_action(action)
        best_segs = segml.assign_best_seg(train_dataset, SEG_ALGS)
        segutils.complete_action(action, start_time)

        n_imgs_to_plot = 5
        i = 0
        n_seg_candidates = len(SEG_ALGS)
        sum_seg_ious = np.zeros(n_seg_candidates)
        n_seg_chosen = np.zeros(n_seg_candidates)
        for img_id, best_seg in best_segs.items():
            cls = best_seg.get('cls')
            iou = best_seg.get('iou')
            sum_seg_ious[cls] = sum_seg_ious[cls] + iou
            n_seg_chosen[cls] = n_seg_chosen[cls] + 1
            labels.get('ImageId').append(img_id)
            labels.get('Class').append(cls)
            labels.get('Name').append(str(SEG_ALGS.get(cls)))
            labels.get('IoU').append(iou)
            if visualize and i < n_imgs_to_plot:
                sample = train_dataset[i]
                segutils.plot_sample_segmentation(sample, cls, SEG_ALGS, iou)
            i = i+1

        print("IOUs for segmentation algorithms (by class): {}".format(sum_seg_ious/n_seg_chosen))
        print("mean IoU for train set: {}".format(sum_seg_ious.sum()/(i-1)))
        labels = pd.DataFrame.from_dict(labels)
        labels.to_csv(output_path+"train_seg_assignment_"+timestamp+".csv", index=False)
    else:
        seg_cls_labels_file = paths_config.get("seg_cls_labels_file")
        labels = pd.DataFrame.from_csv(seg_cls_labels_file)

    action = "training classifier"
    start_time = segutils.start_action(action)
    model = segml.train_seg_classifier(train_dataset, best_segs)
    segutils.complete_action(action, start_time)

    if evaluate:
        action = "creating validation  dataset"
        start_time = segutils.start_action(action)
        validation_labels_file = os.path.join(data_path, 'validation_labels.csv')
        validation_dataset = NucleiDataset('validation', imgs_df=imgs_details,
                                           labels_file=validation_labels_file)
        print("set size: {}".format(len(validation_dataset)))
        segutils.complete_action(action, start_time)

        action = "making predictions for the validation set"
        start_time = segutils.start_action(action)
        predictions, examples = segml.test(model, validation_dataset, SEG_ALGS)
        segutils.complete_action(action, start_time)

        action = "evaluating predictions"
        start_time = segutils.start_action(action)
        mean_avg_precision_iou = segml.evaluate(predictions, validation_dataset, examples=examples)
        print("IoU for validation dataset: {}".format(mean_avg_precision_iou))
        segutils.complete_action(action, start_time)
        if visualize:
            # visually evaluate a few images by comparing images and masks
            segutils.plot_predicted_masks(examples, (22, 27))

    if test:

        test_dataset = NucleiDataset('test', imgs_df=imgs_details)

        action = "making predictions for the test set"
        start_time = segutils.start_action(action)
        predictions, examples = segml.test(model, test_dataset, SEG_ALGS)
        segutils.complete_action(action, start_time)
        # visually evaluate a few images by comparing images and masks
        if visualize:
            segutils.plot_predicted_masks(examples, (7, 12), plot_true_mask=False)

        action = "writing the predictions to submission format"
        start_time = segutils.start_action(action)
        submission_df = segutils.to_submission_df(predictions)
        submission_filename = output_path + "model_predictions_" + timestamp + ".csv"
        submission_df.to_csv(submission_filename, columns=('ImageId','EncodedPixels'), index=False)
        print("predictions on tess set written to: {}".format(submission_filename))
        segutils.complete_action(action, start_time)


import streamlit as st
import altair as alt
import folium
from streamlit_folium import st_folium
import pandas as pd
from pathlib import Path

alojamiento_csv = Path(__file__).parents[1] / "data/alojamiento.csv"
ocupacion_csv = Path(__file__).parents[1] / "data/ocupacion.csv"
ibera_coord_csv = Path(__file__).parents[1] / "data/ibera coordenadas.csv"
APN_csv = Path(__file__).parents[1] / "data/parques_visitantes.csv"

st.set_page_config(page_title="Datathon 2023", layout="wide", page_icon=":bar_chart:")

@st.cache_data
def read_alojamientos():
    df = pd.read_csv(alojamiento_csv)
    return df

@st.cache_data
def read_ocupacion():
    df = pd.read_csv(ocupacion_csv)
    return df

@st.cache_data
def read_ibera_coord():
    df = pd.read_csv(ibera_coord_csv)
    return df

@st.cache_data
def read_ibera():
    df = pd.read_csv(APN_csv)
    ibera = df[df["name"] == "Iberá"]
    return ibera

alojamiento = read_alojamientos()
ocupacion = read_ocupacion()
ibera_coord = read_ibera_coord()
ibera = read_ibera()

def create_esteros_map(ibera_coord):
    # Coordinates of 5 provinces in Esteros del Ibera, Corrientes
    lat = list(ibera_coord["lat"])
    lon = list(ibera_coord["lon"])
    names = list(ibera_coord["Nombre"])

    # Create a folium map centered around Esteros del Ibera
    esteros_center = (
        -28.32641799784776,
        -57.34674731559198,
    )  # Esteros del Ibera coordinates
    # Create a Streamlit app
    st.markdown("### Esteros del Iberá")

    # Create a map
    m = folium.Map(location=esteros_center, zoom_start=8, tiles="openstreetmap")

    # Add markers for each province
    for i, row in ibera_coord.iterrows():
        folium.Marker(
            location=[float(row["lat"]), float(row["lon"])],
            popup=row["Nombre"],
            icon=folium.Icon(color="blue"),
        ).add_to(m)
    return m

## PAGE FORMAT ##

st.markdown("# Datos Abiertos de Corrientes")
st.write(
    """A continuación, presentaremos un breve análisis sobre alojamientos disponibles, ocupación
      hotelera y turismo en base a datos abiertos proporcionados por el Municpio de Corrientes y la Administración de Parques Nacionales.
        """
)
st.markdown("----")
st.markdown(
    "##### Cantidad de Habitaciones de Alojamientos (Hoteles y para-Hoteles) en la Ciudad de Corrientes"
)

st.line_chart(
    data=alojamiento, x="Fecha", y="Habitaciones Total", use_container_width=True
)

st.write(
    """A simple vista, es evidente que la cantidad de habitaciones en hoteles y establecimientos similares se
    mantuvo relativamente constante hasta el año 2020, momento en el cual se produjo una marcada disminución en
    la cantidad de alojamientos disponibles. Presumimos que este descenso se debe a la crisis desencadenada por la
    pandemia de COVID-19 y su impacto significativo en la industria turística."""
)
st.write(
    """También se observa que, a partir de la mitad del año 2020, la cantidad de habitaciones disponibles ha ido en aumento,
      **aunque aún no ha logrado recuperar el nivel previo a la crisis del COVID-19**. Esto podría representar una
     oportunidad del sector."""
)

###
st.markdown("----")

st.markdown("##### Cantidad de Habitaciones Disponibles por Tipo de Alojamiento")
st.line_chart(
    data=alojamiento,
    x="Fecha",
    y=["Habitaciones Hoteles", "Habitaciones Para-Hoteles"],
    use_container_width=True,
)
st.write(
    """
Aunque la crisis derivada de la pandemia de COVID-19 ha tenido un impacto significativo en el sector del hospedaje,
al analizarlo detenidamente, resulta evidente que la industria hotelera ha sido la más perjudicada. Esto lo atribuimos,
en gran medida, a que los costos asociados con la operación de alojamientos alternativos, como pequeños establecimientos
 o alquileres de corta duración, son considerablemente menores en comparación con los gastos de mantener un hotel en funcionamiento.
 Esto permite a los establecimientos alternativos resistir las épocas de crisis con mayor resiliencia que los grandes hoteles."""
)

###
st.markdown("----")

percentage_hoteles = sum(
    alojamiento["Habitaciones Hoteles"] / alojamiento["Habitaciones Total"]
) / len(alojamiento)
percentage_para_hoteles = sum(
    alojamiento["Habitaciones Para-Hoteles"] / alojamiento["Habitaciones Total"]
) / len(alojamiento)

alojamiento_pie = pd.DataFrame(
    {
        "Tipo de Alojamiento": ["Hoteles", "Otros"],
        "Porcentaje": [percentage_hoteles, percentage_para_hoteles],
    }
)
tipo_alojamiento = (
    alt.Chart(alojamiento_pie)
    .mark_arc()
    .encode(theta="Porcentaje", color="Tipo de Alojamiento")
)
st.markdown(
    "##### Porcentaje de Habitaciones de Cada Tipo de Alojamiento Sobre Total de Habitaciones Disponibles"
)
col1, col2 = st.columns(2)
with col1:
    st.altair_chart(tipo_alojamiento, use_container_width=True)
with col2:
    st.write(
        """Teniendo en cuenta las fechas correspondientes a los datos analizados, las habitaciones disponibles
        en alojamientos alternativos constituyen, en promedio, el 10% del total de habitaciones disponibles en Corrientes.
        Este dato pone de manifiesto la notable dependencia del turismo en Corrientes respecto a la industria hotelera,
        y la reciente disminución en estas cifras podría presentar una oportunidad para que los alojamientos alternativos
        ganen presencia en el mercado
        """
    )
    st.write(
        """Sin embargo, el lento crecimiento de los alojamientos alternativos durante los años también nos brinda una señal sobre
        la demanda del mercado turístico de corrientes: quizás exista alguna razón por la cuál no han tenido un mayor éxito.
        """
    )

###
st.markdown("----")

st.markdown(
    "##### Porcentaje de Ocupacion de Hoteles en la Ciudad de Corrientes Durante el Año"
)

ciclo_ocupacion = (
    alt.Chart(ocupacion)
    .mark_line()
    .encode(x="Mes", y="Porcentaje Ocupacion", color="Año:N")
)
st.altair_chart(ciclo_ocupacion, use_container_width=True)
st.write(
    """Basándonos en el gráfico de ciclos, como era previsible, se evidencia una estacionalidad
    en la ocupación hotelera en la ciudad de Corrientes. Esta tiende a aumentar durante el verano
    (enero y febrero), disminuir al punto más bajo en los meses subsiguientes (de marzo a junio),
    experimentar un notorio incremento durante el período de vacaciones de invierno (junio y julio),
    para luego mantenerse en un nivel constante, generalmente por debajo del 50% de ocupación.
        """
)

###
st.markdown("----")
st.markdown(
    "##### Estacia Promedio Mensual en Hoteles de la Ciudad de Corrientes (2016-2022)"
)
st.bar_chart(data=ocupacion, x="Fecha", y="Estadia Promedio", use_container_width=True)
st.write(
    """También se puede notar que la duración media de la estancia en hoteles de la Ciudad de Corrientes
     se mantiene en torno a los dos días. Con un promedio total de 1.84 días de estancia, consideramos que
    este factor influye considerablemente en la preferencia de los turistas por los hoteles en Corrientes
    frente a otros tipos de alojamiento. Los alojamientos alternativos suelen ser más atractivos para viajeros
    con estancias prolongadas, pero dado que Corrientes es principalmente un destino de tránsito, los servicios
    ofrecidos por los hoteles parecen ser la elección ideal.
    """
)

###
st.markdown("----")

st.write(
    """No obstante, en la provincia de Corrientes contamos con un atractivo turístico internacional
    de gran envergadura: el Parque Nacional Iberá. A continuación, se destacan las principales ciudades
    cercanas al parque que consideramos representan una oportunidad dada su proximidad a algunos de los portales de acceso y su desarrollo urbano,
    y presentamos un breve análisis acerca de los visitantes al parque.
    """
)

ibera_map = create_esteros_map(ibera_coord)
st_map = st_folium(ibera_map, width=700, height=450)

###
st.markdown("----")

st.markdown("##### Visitantes del Parque por Tipo de Residencia desde 2017-2020")

residentes = ibera[ibera["categoria"] == "Residentes"]["visitantes"].sum()
extranjeros = ibera[ibera["categoria"] == "Extranjeros"]["visitantes"].sum()
visitante_pie = pd.DataFrame(
    {
        "Visitante": ["Residente", "Extranjero"],
        "Cantidad": [residentes, extranjeros],
    }
)
tipo_visitante = (
    alt.Chart(visitante_pie).mark_arc().encode(theta="Cantidad:Q", color="Visitante")
)

st.altair_chart(tipo_visitante, use_container_width=True)
st.write(
    """Podemos observar que el total de visitantes al Parque Nacional Iberá desde el año 2017 hasta el año 2020 fue de 31854,
    y el 12% (3884) de estos visitantes provienen del extranjero.
    """
)

###
st.markdown("----")

st.markdown("##### Total de Visitantes del Parque por Año  (2017-2020)")

residentes_por_ano = ibera.groupby("ano")["visitantes"].sum()
st.bar_chart(data=residentes_por_ano, use_container_width=True)

st.write(
    """La cantidad de visitantes iba en aumento hasta el 2020, cuándo la crisis del COVID golpeó más duramente. Sería interesante poder
    analizar los datos de los años posteriores para ver si el crecimiento sigue vigente.
    """
)

st.markdown("##### Total de Visitantes del Parque Agrupados por Mes Durante 2017-2020")

residentes_por_mes = ibera.groupby("mes")["visitantes"].sum()
st.bar_chart(data=residentes_por_mes, use_container_width=True)

st.write(
    """Se observa que la cantidad de visitantes al Parque Nacional tiene un idéntico patrón de estacionalidad que el porcentaje de ocupación
    hotelera de la ciudad de Corrientes.
    """
)


from django.forms import ModelForm
from bank.system.models import Category

class AdminAddCategoryForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(AdminAddCategoryForm, self).__init__(*args, **kwargs)

        self.fields['name'].widget.attrs.update(
            {'class': 'form-control', 'maxlength': 50}
        )

    class Meta:
        model = Category
        fields = ('name',)


import os
import sys
import time
import subprocess
from argparse import ArgumentParser
from pipeline_modules import import_assemblies, check_dir, write_job_script

def parse_arguments():
    parser = ArgumentParser(description = "Submit Prokka jobs to the HPC for annotating bacterial genomes")

    # Annotation parameters
    parser.add_argument('--assemblies', '-a', dest = 'assemblies', type = str, required = True, help = "A tab-delimited, header-free file of two columns ID\\tFile_path")
    parser.add_argument('--conda', '-c', dest = 'conda', type = str, required = True, help = "Name of the conda environment for Prokka")
    parser.add_argument('--genus', '-g', dest = 'genus', type = str, required = True, help = "Genus name")
    parser.add_argument('--species', '-sp', dest = 'species', type = str, required = True, help = "Species name")
    parser.add_argument('--strain', '-st', dest = 'strain', type = str, required = False, default = '', help = "Strain name (default: none)")
    parser.add_argument('--proteins', '-p', dest = 'proteins', type = str, required = True, help = "A FASTA or GenBank file to use for first-priority annotation searches")
    parser.add_argument('--mincontiglen', '-l', dest = 'mincontiglen', type = str, required = False, default = '200', help = "Minimum length of contigs to keep (default: 200 bp)")
    parser.add_argument('--rna', '-r', dest = 'rna', action = 'store_true', help = "Enable annotation of tRNA and rRNA")

    # Job parameters
    parser.add_argument('--outdir', '-o', dest = 'outdir', type = str, required = False, default = 'output', help = "Absolute path to the parental output directory")
    parser.add_argument('--ncpus', '-n', dest = 'ncpus', type = str, required = False, default = '8', help = "Number of computational cores to be requested (default: 8)")
    parser.add_argument('--mem', '-m', dest = 'mem', type = str, required = False, default = '16', help = "Memory size (GB) to be requested (default: 16)")
    parser.add_argument('--queue', '-q', dest = 'queue', type = int, required = False, default = 20, help = "Size of each serial job queue (default: 20)")
    parser.add_argument('--scheduler', '-s', dest = 'scheduler', type = str, required = False, default = 'SGE', help = "Job scheduler (SGE/PBS/bash) (default: SGE)")
    parser.add_argument('--debug', '-d', dest = 'debug', action = 'store_true', help = "Only generate job script but do not submit it")
    return parser.parse_args()

def main():
    args = parse_arguments()
    assemblies = import_assemblies(args.assemblies)  # Dictionary {i : path}
    submit = (not args.debug) and (args.scheduler in ['SGE', 'PBS'])
    check_dir(args.outdir)
    queue = list()
    scripts = list()
    k = 0  # Counter of genomes of a queue
    n = 0  # Number of scripts to be written
    for i in assemblies.keys():  # Create and submit scripts of serial jobs based on args.queue
        k += 1
        queue.append(i)
        if k == args.queue:
            n += 1
            scripts.append(write_job_script(create_job_script({genome : assemblies[genome] for genome in queue}, args.conda, args.genus, args.species, args.strain,\
                                                              args.proteins, args.mincontiglen, args.rna, args.ncpus, args.mem, args.outdir, args.scheduler),\
                                            k, n, args.outdir, args.scheduler))  # Append the path of the new script to list 'scripts'
            queue = list()
            k = 0
    if k > 0:  # When there are remaining tasks in the last queue.
        n += 1
        scripts.append(write_job_script(create_job_script({genome : assemblies[genome] for genome in queue}, args.conda, args.genus, args.species, args.strain,\
                                                          args.proteins, args.mincontiglen, args.rna, args.ncpus, args.mem, args.outdir, args.scheduler),\
                                        k, n, args.outdir, args.scheduler))
    if submit:
        for s in scripts:
            print("Submit job script " + s, file = sys.stdout)
            p = subprocess.Popen(['qsub', s])  # Do not use parameters 'shell = True, stdin = None, stdout = None, stderr = None, close_fds = True', or the job will not be submitted successfully.
            time.sleep(1)
    else:
        print("Debugging/bash mode: no job is submitted.", file = sys.stdout)
    return

def create_job_script(assemblies, conda_env, genus, species, strain, proteins, mincontiglen, rna, ncpus, mem, outdir, scheduler):
    outdir = os.path.abspath(outdir)
    rna_conf = '--quiet' if rna else '--norrna --notrna --quiet'
    strain_conf = f'--strain {strain} --force' if strain != '' else '--force'
    if scheduler == 'SGE':
        script = f"""#!/bin/bash
# SGE configurations
#$ -N Prokka
#$ -S /bin/bash
#$ -pe multithread {ncpus}
#$ -l h_vmem={mem}G

# Environmental settings
source $HOME/.bash_profile
source /etc/profile.d/modules.sh
module purge
module load anaconda/5.3.1_python3
conda activate {conda_env}
cd {outdir}

# Prokka jobs"""
    elif scheduler == 'PBS':  # PBS job script
        script = f"""#!/bin/bash
# PBS configurations
#PBS -N Prokka
#PBS -l select=1:ncpus={ncpus}:mem={mem}gb:ompthreads={ncpus}
#PBS -l walltime=24:00:00

# Environmental settings
module load anaconda3/personal
source activate {conda_env}
cd {outdir}

# Prokka jobs"""
    else:
        script = f"""#!/bin/bash\nsource activate {conda_env}"""

    for g in assemblies.keys():
        fasta = assemblies[g]
        subdir = os.path.join(outdir, g)  # Do not need to run check_dir(subdir) as SPAdes creates an output directory if it does not exist.
        script += f"""\nprokka --outdir {subdir} --prefix {g} --locustag {g} --increment 1 --kingdom Bacteria --genus {genus} --species {species} {strain_conf} --gcode 11 --addgenes --proteins {proteins} --cpus {ncpus} --mincontiglen {mincontiglen} {rna_conf} {fasta}"""
    return script

if __name__ == '__main__':
    main()


from tests.util import simple_wrapper, retry, forgiving_wrapper
from tests.test_base import TestBase
from nose.tools import assert_equals, assert_true, nottest
from nose.plugins.attrib import attr
from nose.plugins.skip import SkipTest
import nose
import inspect
import logging
from tests.twiddle import Twiddle

logger = logging.getLogger(__name__)

def setup_module():
    logger.debug("Module setup_module: pull the lever ##########################")

def teardown_module():
    logger.debug("Module teardown_module: push the lever ##########################")

class TestTwiddling(TestBase):
    @classmethod
    def setup_class(cls):
        logger.debug("Class setup_class: tie the knot ==========================")

    @classmethod
    def teardown_class(cls):
        logger.debug("Class teardown_class: untie the knot ==========================")

    def setup(self):
        logger.debug("Method setup: lift the lid --------------------------")

    def teardown(self):
        logger.debug("Method teardown: drop the lid --------------------------")

    @attr("twiddletest")
    @attr("weekly")
    @attr(versions="all")
    @attr(status="wip")
    def test_twiddling_all(self):
        """
        NOTE: This is the _test_generator_ of multiple tests
        Test twiddling every version, one at a time
        ("version" is a placeholder for whatever parameters are needed)
        """
        logger.info(">>Test Start: %s" % inspect.stack()[0][3])

        versions = [
            "Able",
            "Baker",
            "Charlie",
            "Dog",
            "Easy",
            "Fox",
        ]
        platforms = ["Macintosh", "Linux"]

        for version in versions:
            for platform in platforms:
                test_desc = "Testing twiddling of version = '{}' platform = '{}'".format(
                    version, platform
                )
                # Nose uses this value in the results output, otherwise it just uses the vanilla docstring over and over
                self.verify_twiddle.__func__.description = test_desc
                logger.info(test_desc)
                yield self.verify_twiddle, version, platform

        logger.info("<<Test Complete: %s" % inspect.stack()[0][3])

    # @retry(retries=3, wait=2, patience=2)
    def verify_twiddle(self, version, platform):
        """
        NOTE: This is the _test_ which exercises the function itself
        The retry is handled by the @retry decorator
        :param version:
        :return:
        """
        # TODO: The generator might be able to call straight to the FUT without this intermediate
        #   or this could include other specialized functionality -- perhaps more logging or
        #   something in a try/catch if the retries are exhausted vs. other exceptions?
        self.verify_twiddle.__func__.description = ""
        t = Twiddle(version, platform)
        t.twiddle()

class TestBar(TestBase):
    @attr(status="good")
    def test_base_fixtures(self):
        logger.debug(
            "++++ In the TestBar class, this is to see if the base class fixtures run"
        )

    @attr(status="good")
    @forgiving_wrapper
    def test_forgiving_wrapper(self):
        logger.debug("++++ Do some cool crap here")
        assert False, "Did a bad thing, but we're in a forgiving wrapper"

    @attr("daily")
    @attr(versions="latest")
    @attr(status="bad")
    def test_reality(self):
        logger.info("++++ Reality Test: nothing unreal exists")
        try:
            assert_equals("real", "rael")
        except AssertionError as ae:
            logger.info(
                "Ha! The test_reality assertion failure gets swallowed by an except clause."
            )


import pandas as pd
import numpy as np
from io import StringIO

f = open("day4.txt", "r")
numbers = list(map(int, ''.join(f.readline()).strip().split(",")))
print("Sample:", numbers[:5])

boards = []
while True:
    board = ''.join(f.readline() for _ in range(6)).strip().replace("  ", " ").replace("\n ", "\n")
    if not board:
        break
    boards.append(pd.read_csv(StringIO(board), sep=" ", header=None))

print("Sample:\n", boards[3])

stop = False
for x in numbers:
    if stop:
        break
    for df in boards:
        df.replace(x, -1, inplace=True)
        if any((df == -1).sum(axis=0) == 5) or any((df == -1).sum(axis=1) == 5):
            print("Winning board:\n", df)
            print("x=", x)
            unmarked = df.sum().sum() + (df == -1).sum().sum()
            print("Sum of unmarked numbers:", unmarked)
            print("Product is:", x * unmarked)
            stop = True

stop_df = None
stop_x = None
for x in numbers:
    for i, df in enumerate(boards):
        if df is not None:
            df.replace(x, -1, inplace=True)
            if any((df == -1).sum(axis=0) == 5) or any((df == -1).sum(axis=1) == 5):
                stop_df = df
                stop_x = x
                boards[i] = None
print("Last winning board:\n", stop_df)
print("x=", stop_x)
unmarked = stop_df.sum().sum() + (stop_df == -1).sum().sum()
print("Sum of unmarked numbers:", unmarked)
print("Product is:", stop_x * unmarked)