import csv
import os
from os import path
from typing import Optional, Tuple

import numpy as np
import torch
from torch import nn
from torch.optim import Adam
from torch.optim.lr_scheduler import ReduceLROnPlateau
from torch.utils.data import DataLoader, random_split

from dataset import load_dataset
from model import create_inn
import mmd

# factors for the loss terms
FORWARD_FIT_FACTOR = 1
FORWARD_MMD_FACTOR = 50
BACKWARD_MMD_FACTOR = 500
RECONSTRUCTION_FACTOR = 1

def run_epoch(
    inn: nn.Module,
    data_loader: DataLoader,
    optimizer: Optional[Adam],
    batch_size: int,
    position_dim: int,
    z_dim: int,
) -> Tuple[float, Tuple[float, float, float, float]]:
    """
    `optimizer` should be `None` during validation.
    :return: 1. The average loss in this epoch
             2. The individual, weighted loss terms (forward L2 fit, forward MMD, backward MMD, reconstruction L2 fit)
    """
    loss_history = []

    for priors, positions in data_loader:
        noise_batch = torch.randn(batch_size, z_dim)
        positions = torch.cat((noise_batch, positions), dim=1)

        # TODO use jac=False for inn(...)?

        # forward loss
        positions_pred, _ = inn(priors)
        # remove gradients wrt positions
        output_block_grad = torch.cat((positions_pred[:, :z_dim], positions_pred[:, -position_dim:].data), dim=1)
        loss_forward_fit = FORWARD_FIT_FACTOR * mmd.l2_fit(positions_pred[:, z_dim:], positions[:, z_dim:])
        loss_forward_mmd = FORWARD_MMD_FACTOR * torch.mean(mmd.forward_mmd(output_block_grad, positions))

        # backward loss
        priors_pred, _ = inn(positions, rev=True)
        loss_backward_mmd = BACKWARD_MMD_FACTOR * torch.mean(mmd.backward_mmd(priors, priors_pred))

        # reconstruction loss
        x_reconstructed, _ = inn(positions_pred.data, rev=True)
        loss_reconstruction = RECONSTRUCTION_FACTOR * mmd.l2_fit(x_reconstructed, priors)

        batch_losses = [loss_forward_fit, loss_forward_mmd, loss_backward_mmd, loss_reconstruction]
        loss_history.append([batch_loss.item() for batch_loss in batch_losses])

        total_batch_loss = sum(batch_losses)

        if optimizer:
            total_batch_loss.backward()
            optimizer.step()

    loss_mean = np.mean(loss_history, axis=0)
    return sum(loss_mean), tuple(loss_mean)

def train(
    batch_size: int = 128,
    lr: float = 1e-6,
    epochs: int = 10000000,
    lr_scheduler_patience: int = 10,
    val_set_portion: float = 0.1,
    log_path: str = "log",
    checkpoint_path: Optional[str] = None,
):
    """
    val_set_portion: Portion of the dataset that will be used for validation
    log_path: Directory where losses and checkpoints will be written
    checkpoint_path: Path to a checkpoint to load
    """
    # prepare dataset
    dataset, priors_dim, position_dim = load_dataset()
    z_dim = priors_dim - position_dim
    val_set_size = int(len(dataset) * val_set_portion)
    train_dataset, val_dataset = random_split(dataset, [len(dataset) - val_set_size, val_set_size])
    train_loader = DataLoader(train_dataset, batch_size, shuffle=True, num_workers=2, drop_last=True)
    val_loader = DataLoader(val_dataset, batch_size, shuffle=True, num_workers=2, drop_last=True)

    inn = create_inn(priors_dim)
    optimizer = Adam(inn.parameters(), lr=lr)
    lr_scheduler = ReduceLROnPlateau(optimizer, patience=lr_scheduler_patience, verbose=True)

    # load checkpoint
    if checkpoint_path:
        checkpoint = torch.load(checkpoint_path)
        starting_epoch = checkpoint["epoch"] + 1
        inn.load_state_dict(checkpoint["model"])
        optimizer.load_state_dict(checkpoint["optimizer"])
        lr_scheduler.load_state_dict(checkpoint["lr_scheduler"])
        print(f"Resuming at checkpoint '{checkpoint_path}', epoch {starting_epoch}")
    else:
        starting_epoch = 0

    for epoch in range(starting_epoch, epochs):

        # Training
        ###########

        inn.train()

        train_loss, train_loss_terms = run_epoch(inn, train_loader, optimizer, batch_size, position_dim, z_dim)

        lr_scheduler.step(train_loss)
        print(f"[Epoch {epoch}] Train loss: {train_loss}, {train_loss_terms}")

        # Validation
        #############

        inn.eval()

        with torch.no_grad():
            val_loss, val_loss_terms = run_epoch(inn, val_loader, None, batch_size, position_dim, z_dim)

        print(f"[Epoch {epoch}] Val loss:   {val_loss}, {val_loss_terms}")

        # Log
        ######

        # log losses
        os.makedirs(log_path, exist_ok=True)
        with open(path.join(log_path, "losses.csv"), 'a+', newline='') as file:
            csv.writer(file).writerow([train_loss, *train_loss_terms, val_loss, *val_loss_terms])

        # save model and other data required to resume training
        checkpoint = {
            "epoch": epoch,
            "model": inn.state_dict(),
            "optimizer": optimizer.state_dict(),
            "lr_scheduler": lr_scheduler.state_dict(),
        }
        torch.save(checkpoint, path.join(log_path, f"{epoch}_checkpoint.pt"))

if __name__ == "__main__":
    train()


from typing import (
    Any,
    AsyncGenerator,
    Coroutine,
    Dict,
    Generator,
    Mapping,
    Optional,
    Union,
)

__all__ = ["BaseCallBuilder"]

class BaseCallBuilder:
    """Creates a new :class:`BaseCallBuilder` pointed to server defined by horizon_url.

    :param horizon_url: Horizon server URL.
    """

    def __init__(self, horizon_url: str) -> None:
        self.horizon_url: str = horizon_url
        self.params: Dict[str, str] = {}
        self.endpoint: str = ""
        self.prev_href: Optional[str] = None
        self.next_href: Optional[str] = None

    def call(self) -> Union[Dict[str, Any], Coroutine[Any, Any, Dict[str, Any]]]:
        """Triggers a HTTP request using this builder's current configuration.

        :return: If it is called synchronous, the response will be returned. If
            it is called asynchronously, it will return Coroutine.
        :raises:
            | :exc:`ConnectionError <stellar_sdk.exceptions.ConnectionError>`: if you have not successfully
                connected to the server.
            | :exc:`NotFoundError <stellar_sdk.exceptions.NotFoundError>`: if status_code == 404
            | :exc:`BadRequestError <stellar_sdk.exceptions.BadRequestError>`: if 400 <= status_code < 500
                and status_code != 404
            | :exc:`BadResponseError <stellar_sdk.exceptions.BadResponseError>`: if 500 <= status_code < 600
            | :exc:`UnknownRequestError <stellar_sdk.exceptions.UnknownRequestError>`: if an unknown error occurs,
                please submit an issue
        """
        raise NotImplementedError

    def stream(
        self,
    ) -> Union[
        AsyncGenerator[Dict[str, Any], None], Generator[Dict[str, Any], None, None]
    ]:
        """Creates an EventSource that listens for incoming messages from the server.

        See `Horizon Response Format <https://developers.stellar.org/api/introduction/response-format/>`__

        See `MDN EventSource <https://developer.mozilla.org/en-US/docs/Web/API/EventSource>`__

        :return: If it is called synchronous, it will return ``Generator``, If
            it is called asynchronously, it will return ``AsyncGenerator``.

        :raise: :exc:`StreamClientError <stellar_sdk.exceptions.StreamClientError>` - Failed to fetch stream resource.
        """
        raise NotImplementedError

    def next(self):
        raise NotImplementedError

    def prev(self):
        raise NotImplementedError

    def cursor(self, cursor: Union[int, str]):
        """Sets ``cursor`` parameter for the current call. Returns the CallBuilder object on which this method has been called.

        See `Pagination <https://developers.stellar.org/api/introduction/pagination/>`__

        :param cursor: A cursor is a value that points to a specific location in a collection of resources.
        :return: current CallBuilder instance
        """
        self._add_query_param("cursor", cursor)
        return self

    def limit(self, limit: int):
        """Sets ``limit`` parameter for the current call. Returns the CallBuilder object on which this method has been called.

        See `Pagination <https://developers.stellar.org/api/introduction/pagination/>`__

        :param limit: Number of records the server should return.
        :return:
        """
        self._add_query_param("limit", limit)
        return self

    def order(self, desc: bool = True):
        """Sets `order` parameter for the current call. Returns the CallBuilder object on which this method has been called.

        :param desc: Sort direction, ``True`` to get desc sort direction, the default setting is ``True``.
        :return: current CallBuilder instance
        """
        order = "asc"
        if desc:
            order = "desc"
        self._add_query_param("order", order)
        return self

    def _add_query_param(self, key: str, value: Union[str, float, int, bool, None]):
        if value is None:
            pass  # pragma: no cover
        elif value is True:
            self.params[key] = "true"
        elif value is False:
            self.params[key] = "false"
        else:
            self.params[key] = str(value)

    def _check_pageable(self, response: dict) -> None:
        links = response.get("_links")
        if not links:
            return
        prev_page = links.get("prev")
        next_page = links.get("next")
        if prev_page:
            self.prev_href = prev_page.get("href")
        if next_page:
            self.next_href = next_page.get("href")

    def _add_query_params(
        self, params: Mapping[str, Union[str, float, int, bool, None]]
    ) -> None:
        for k, v in params.items():
            self._add_query_param(k, v)


from __future__ import division

import logging as log
from enum import Enum

from nicelib import NiceLib, NiceObjectDef, load_lib

__all__ = ['K10CR1']

# Message Enums
#
class MessageType(Enum):
    GenericDevice = 0
    GenericPiezo = 1
    GenericMotor = 2
    GenericDCMotor = 3
    GenericSimpleMotor = 4
    RackDevice = 5
    Laser = 6
    TECCtlr = 7
    Quad = 8
    NanoTrak = 9
    Specialized = 10
    Solenoid = 11

class GenericDevice(Enum):
    SettingsInitialized = 0
    SettingsUpdated = 1
    Error = 2
    Close = 3

class GenericMotor(Enum):
    Homed = 0
    Moved = 1
    Stopped = 2
    LimitUpdated = 3

class GenericDCMotor(Enum):
    Error = 0
    Status = 1

MessageIDs = {
    MessageType.GenericDevice: GenericDevice,
    MessageType.GenericMotor: GenericMotor,
    MessageType.GenericDCMotor: GenericDCMotor
}

def _instrument(params):
    if 'kinesis_serial' not in params:
        raise InstrumentTypeError("K10CR1 requires 'kinesis_serial'")
    serial = params['kinesis_serial']
    kwds = {key: params[key] for key in ('gear_box_ratio', 'steps_per_rev', 'micro_steps_per_step',
                                         'offset') if key in params}
    return K10CR1(serial, **kwds)

def list_instruments():
    NiceKinesisISC.BuildDeviceList()
    serial_nums = NiceKinesisISC.GetDeviceListExt().strip(',').split(',')
    instruments = []
    for serial_num in serial_nums:
        params = _ParamDict("<K10CR1 '{}'>".format(serial_num))
        params['module'] = 'positioners.K10CR1'
        params['kinesis_serial'] = serial_num
        instruments.append(params)
    return instruments

class KinesisError(Exception):
    messages = {
        0: 'Success',
        1: 'The FTDI functions have not been initialized',
        2: 'The device could not be found. Make sure to call TLI_BuildDeviceList().',
        3: 'The device must be opened before it can be accessed',
        4: 'An I/O Error has occured in the FTDI chip',
        5: 'There are insufficient resources to run this application',
        6: 'An invalid parameter has been supplied to the device',
        7: 'The device is no longer present',
        8: 'The device detected does not match that expected',
        32: 'The device is already open',
        33: 'The device has stopped responding',
        34: 'This function has not been implemented',
        35: 'The device has reported a fault',
        36: 'The function could not be completed because the device is disconnected',
        41: 'The firmware has thrown an error',
        42: 'The device has failed to initialize',
        43: 'An invalid channel address was supplied',
        37: 'The device cannot perform this function until it has been Homed',
        38: 'The function cannot be performed as it would result in an illegal position',
        39: 'An invalid velocity parameter was supplied. The velocity must be greater than zero',
        44: 'This device does not support Homing. Check the Limit switch parameters are correct',
        45: 'An invalid jog mode was supplied for the jog function',
    }

    def __init__(self, code=None, msg=''):
        if code is not None and not msg:
            msg = '(0x{:X}) {}'.format(code, self.messages[code])
        super(KinesisError, self).__init__(msg)
        self.code = code

class NiceKinesisISC(NiceLib):
    """ This class provides a convenient low-level wrapper for the library
    Thorlabs.MotionControl.FilterFlipper.dll"""
    _info = load_lib('kinesis', __package__)

    #
    # Error wrapping functions
    #
    def _ret(ret):
        if ret != 0:
            raise KinesisError(ret)

    def _ret_success(ret, funcname):
        if not ret:
            raise KinesisError(msg="Call to function '{}' failed".format(funcname))

    #
    # Function signatures
    #
    _prefix = 'TLI_'

    BuildDeviceList = ()
    GetDeviceListSize = ({'ret': 'return'},)
    GetDeviceListExt = ('buf', 'len')
    GetDeviceListByTypeExt = ('buf', 'len', 'in')
    GetDeviceListByTypesExt = ('buf', 'len', 'in', 'in')
    GetDeviceInfo = ('in', 'out')

    # GetDeviceList = ('out')
    # GetDeviceListByType = ('out', 'in', dict(first_arg=False))
    # GetDeviceListByTypes = ('out', 'in', 'in', dict(first_arg=False))

    Device = NiceObjectDef(prefix='ISC_', attrs=dict(
        Open = ('in'),
        Close = ('in', {'ret': 'return'}),
        Identify = ('in', {'ret': 'ignore'}),
        GetHardwareInfo = ('in', 'buf', 'len', 'out', 'out', 'buf', 'len', 'out', 'out', 'out'),
        GetFirmwareVersion = ('in', {'ret': 'return'}),
        GetSoftwareVersion = ('in', {'ret': 'return'}),
        LoadSettings = ('in', {'ret': 'success'}),
        PersistSettings = ('in', {'ret': 'success'}),
        GetNumberPositions = ('in', {'ret': 'return'}),
        Home = ('in'),
        NeedsHoming = ('in', {'ret': 'return'}),
        MoveToPosition = ('in', 'in'),
        GetPosition = ('in', {'ret': 'return'}),
        RequestStatus = ('in'),
        RequestStatusBits = ('in'),
        GetStatusBits = ('in', {'ret': 'return'}),
        StartPolling = ('in', 'in', {'ret': 'success'},),
        PollingDuration = ('in', {'ret': 'return'}),
        StopPolling = ('in', {'ret': 'ignore'}),
        RequestSettings = ('in'),
        ClearMessageQueue = ('in', {'ret': 'ignore'}),
        RegisterMessageCallback = ('in', 'in', {'ret': 'ignore'}),
        MessageQueueSize = ('in', {'ret': 'return'}),
        GetNextMessage = ('in', 'out', 'out', 'out', {'ret': 'success'}),
        WaitForMessage = ('in', 'out', 'out', 'out', {'ret': 'success'}),
        GetMotorParamsExt = ('in', 'out', 'out', 'out'),
        SetJogStepSize = ('in', 'in'),
        GetJogVelParams = ('in', 'out', 'out'),
        GetBacklash = ('in', {'ret': 'return'}),
        SetBacklash = ('in', 'in'),
    ))

STATUS_MOVING_CW = 0x10
STATUS_MOVING_CCW = 0x20
STATUS_JOGGING_CW = 0x40
STATUS_JOGGING_CCW = 0x80

class K10CR1(Motion):
    """ Class for controlling Thorlabs K10CR1 integrated stepper rotation stages
    Takes the serial number of the device as a string as well as the gear box ratio,
    steps per revolution and microsteps per step as integers. It also takes the polling
    period as a pint quantity.
    The polling period, which is how often the device updates its status, is
    passed as a pint pint quantity with units of time and is optional argument,
    with a default of 200ms
    """
    _lib = NiceKinesisISC

    # Enums
    MessageType = MessageType
    GenericDevice = GenericDevice
    GenericMotor = GenericMotor
    GenericDCMotor = GenericDCMotor

    @check_units(polling_period='ms')
    def __init__(self, serial, gear_box_ratio=120, steps_per_rev=200, micro_steps_per_step=2048,
                 polling_period='200 ms', offset='0 deg'):
        """
        Parameters
        ----------
        serial: str
        polling_period: pint quantity with units of time
        """
        self.serial = serial
        self.offset = offset
        self._unit_scaling = (gear_box_ratio * micro_steps_per_step *
                              steps_per_rev / (360.0 * u.deg))
        self._open()
        self._start_polling(polling_period)
        self._wait_for_message(0, 0)  # Make sure status has been loaded before we return

    @property
    def _param_dict(self):
        param_dict = _ParamDict(self.__class__.__name__)
        param_dict['module'] = 'motion.kinesis'
        param_dict['kinesis_serial'] = self.serial
        param_dict['offset'] = str(self.offset)
        return param_dict

    def _open(self):
        NiceKinesisISC.BuildDeviceList()  # Necessary?
        self.dev = NiceKinesisISC.Device(self.serial)
        self.dev.Open()

    def close(self):
        self.dev.StopPolling()
        self.dev.Close()

    @check_units(polling_period='ms')
    def _start_polling(self, polling_period='200ms'):
        """Starts polling the device to update its status with the given period provided, rounded
        to the nearest millisecond
        Parameters
        ----------
        polling_period: pint quantity with units of time
        """
        self.polling_period = polling_period
        self.dev.StartPolling(self.polling_period.m_as('ms'))

    @check_units(angle='deg')
    def move_to(self, angle, wait=False):
        """Rotate the stage to the given angle
        Parameters
        ----------
        angle : Quantity
            Angle that the stage will rotate to. Takes the stage offset into account.
        """
        log.debug("Moving stage to {}".format(angle))
        log.debug("Current position is {}".format(self.position))
        self.dev.ClearMessageQueue()
        self.dev.MoveToPosition(self._to_dev_units(angle + self.offset))
        if wait:
            self.wait_for_move()

    def _wait_for_message(self, match_type, match_id):
        msg_type, msg_id, msg_data = self.dev.WaitForMessage()
        log.debug("Received kinesis message ({},{},{})".format(msg_type, msg_id, msg_data))
        while msg_type != match_type or msg_id != match_id:
            msg_type, msg_id, msg_data = self.dev.WaitForMessage()
            log.debug("Received kinesis message ({},{},{})".format(msg_type, msg_id, msg_data))

    def _check_for_message(self, match_type, match_id):
        """Check if a message of the given type and id is in the queue"""
        while True:
            try:
                msg_type, msg_id, msg_data = self.dev.GetNextMessage()
            except KinesisError:
                return False

            log.debug("Received kinesis message ({},{},{})".format(msg_type, msg_id, msg_data))
            if msg_type == match_type and msg_id == match_id:
                return True

    def wait_for_move(self):
        """Wait for the most recent move to complete"""
        self._wait_for_message(2, 1)

    def move_finished(self):
        """Check if the most recent move has finished"""
        return self._check_for_message(2, 1)

    def _to_real_units(self, dev_units):
        return (dev_units / self._unit_scaling).to('deg')

    @check_units(real_units='deg')
    def _to_dev_units(self, real_units):
        return int(round(float(real_units * self._unit_scaling)))

    def home(self, wait=False):
        """Home the stage
        Parameters
        ----------
        wait : bool, optional
            Wait until the stage has finished homing to return
        """
        self.dev.ClearMessageQueue()
        self.dev.Home()

        if wait:
            self.wait_for_home()

    def wait_for_home(self):
        """Wait for the most recent homing operation to complete"""
        self._wait_for_message(2, 0)

    def homing_finished(self):
        """Check if the most recent homing operation has finished"""
        return self._check_for_message(2, 0)

    @property
    def needs_homing(self):
        """True if the device needs to be homed before a move can be performed"""
        return bool(self.dev.NeedsHoming())

    @property
    def offset(self):
        return self._offset

    @offset.setter
    @check_units(offset='deg')
    def offset(self, offset):
        self._offset = offset

    @property
    def position(self):
        return self._to_real_units(self.dev.GetPosition()) - self.offset

    @property
    def is_homing(self):
        return bool(self.dev.GetStatusBits() & 0x00000200)

    @property
    def is_moving(self):
        return bool(self.dev.GetStatusBits() & 0x00000030)

    def get_next_message(self):
        msg_type, msg_id, msg_data = self.dev.GetNextMessage()
        type = MessageType(msg_type)
        id = MessageIDs[type](msg_id)
        return (type, id, msg_data)

    def get_messages(self):
        messages = []
        while True:
            try:
                messages.append(self.get_next_message())
            except Exception:
                break
        return messages


import cv2
import os
import numpy as np

def loadImages(folder_name):
    files = os.listdir(folder_name)
    print("Loading images from ", folder_name)
    images = []
    for f in files:
        # print(f)
        image_path = folder_name + "/" + f
        image = cv2.imread(image_path)
        if image is not None:
            images.append(image)
        else:
            print("Error in loading image ", image)

    return images

def extractParamFromA(init_A, init_kc):
    alpha = init_A[0,0]
    gamma = init_A[0,1]
    beta = init_A[1,1]
    u0 = init_A[0,2]
    v0 = init_A[1,2]
    k1 = init_kc[0]
    k2 = init_kc[1]

    x0 = np.array([alpha, gamma, beta, u0, v0, k1, k2])
    return x0

def retrieveA(x0):
    alpha, gamma, beta, u0, v0, k1, k2 = x0
    A = np.array([[alpha, gamma, u0], [0, beta, v0], [0, 0, 1]]).reshape(3,3)
    kc = np.array([k1, k2]).reshape(2,1)
    return A, kc


class Alumno:
    def __init__(self, rut, nombre, apellido, fecha_nacimiento, carrera):
        self.rut = rut
        self.nombre = nombre
        self.apellido = apellido
        self.fecha_nacimiento = fecha_nacimiento
        self.carrera = carrera
        self.asignaturas = []

    def agregar_asignatura(self, nombre_asignatura, promedio):
        asignatura = {'nombre': nombre_asignatura, 'promedio': promedio}
        self.asignaturas.append(asignatura)

    def obtener_promedio_total(self):
        total = 0
        for asignatura in self.asignaturas:
            total += asignatura['promedio']
        return total / len(self.asignaturas)

def grabar_alumno():
    rut = input("Ingrese el Rut del alumno: ")
    nombre = input("Ingrese el nombre del alumno: ")
    apellido = input("Ingrese el apellido del alumno: ")
    fecha_nacimiento = input("Ingrese la fecha de nacimiento del alumno: ")
    carrera = input("Ingrese la carrera del alumno: ")

    alumno = Alumno(rut, nombre, apellido, fecha_nacimiento, carrera)

    agregar_asignaturas = True
    while agregar_asignaturas:
        nombre_asignatura = input("Ingrese el nombre de la asignatura: ")
        promedio = float(input("Ingrese el promedio de la asignatura: "))
        alumno.agregar_asignatura(nombre_asignatura, promedio)

        respuesta = input("¿Desea agregar más asignaturas? (S/N): ")
        if respuesta.upper() != "S":
            agregar_asignaturas = False

    # Guardar el alumno en una lista o base de datos
    # Por simplicidad, en este ejemplo lo guardaremos en una lista
    alumnos.append(alumno)

    print("Alumno registrado correctamente.\n")

def buscar_alumno():
    rut_buscar = input("Ingrese el Rut del alumno a buscar: ")

    for alumno in alumnos:
        if alumno.rut == rut_buscar:
            print("Información del alumno:")
            print("Rut:", alumno.rut)
            print("Nombre:", alumno.nombre)
            print("Apellido:", alumno.apellido)
            print("Fecha de Nacimiento:", alumno.fecha_nacimiento)
            print("Carrera:", alumno.carrera)

            if alumno.asignaturas:
                print("Asignaturas:")
                for asignatura in alumno.asignaturas:
                    print("- Nombre:", asignatura['nombre'])
                    print("- Promedio:", asignatura['promedio'])

            print()
            return

    print("No se encontró ningún alumno con ese Rut.\n")

def imprimir_certificados():
    rut_certificado = input("Ingrese el Rut del alumno para imprimir el certificado: ")

    for alumno in alumnos:
        if alumno.rut == rut_certificado:
            print("Tipos de certificados:")
            print("1. Certificado de Alumno Regular de Notas")
            print("2. Certificado de Matrícula")
            opcion_certificado = input("Seleccione el tipo de certificado a imprimir (1/2): ")

            if opcion_certificado == "1":
                print("Certificado de Alumno Regular de Notas")
                print("Nombre:", alumno.nombre)
                print("Rut:", alumno.rut)
                print("Carrera:", alumno.carrera)

                if alumno.asignaturas:
                    print("Asignaturas y Promedios:")
                    for asignatura in alumno.asignaturas:
                        print("- Asignatura:", asignatura['nombre'])
                        print("- Promedio:", asignatura['promedio'])

            elif opcion_certificado == "2":
                certificado = str(randint(1000, 5000))
                print("Certificado de Matrícula")
                print("Nombre:", alumno.nombre)
                print("Rut:", alumno.rut)
                print("Carrera:", alumno.carrera)
                print("Número de Certificado:", certificado)

            else:
                print("Opción inválida. Por favor, seleccione una opción válida.\n")
                return

            print()
            return

    print("No se encontró ningún alumno con ese Rut.\n")

# Lista para almacenar los alumnos registrados
alumnos = []

# Función principal
def main():
    while True:
        print("Menú:")
        print("1. Grabar")
        print("2. Buscar")
        print("3. Imprimir certificados")
        print("4. Salir")

        opcion = input("Ingrese una opción: ")

        if opcion == "1":
            grabar_alumno()
        elif opcion == "2":
            buscar_alumno()
        elif opcion == "3":
            imprimir_certificados()
        elif opcion == "4":
            break
        else:
            print("Opción inválida. Por favor, ingrese una opción válida.\n")

# Iniciar el programa
if __name__ == "__main__":
    main()


import xml.etree.ElementTree as ET
from lxml.etree import parse
import os
from PIL import Image, ImageDraw,ImageFont

def read_xml(xml_path):
    '''
    读取xml模板
    args:
        xml_path: xml文件路径
    '''
    try:
        tree = parse(xml_path)
        root = tree.getroot()
        return tree,root
    except:
        return None

def make_dirs(path):
    '''
    目录不存在就创建
    args:
        path: 要创建的目录
    '''
    if not os.path.exists(path):
        os.makedirs(path)

def get_color_map_list(num_classes):
    """
    Args:
        num_classes (int): number of class
    Returns:
        color_map (list): RGB color list
    """

    color_map = [(0,230,0),(255,255,0),(0,255,255),(255,0,255),(255,0,0)]
    return color_map

def get_color_map_list_(num_classes):
    """
    Args:
        num_classes (int): number of class
    Returns:
        color_map (list): RGB color list
    """
    color_map = num_classes * [0, 0, 0]
    for i in range(0, num_classes):
        j = 0
        lab = i
        while lab:
            color_map[i * 3] |= (((lab >> 0) & 1) << (7 - j))
            color_map[i * 3 + 1] |= (((lab >> 1) & 1) << (7 - j))
            color_map[i * 3 + 2] |= (((lab >> 2) & 1) << (7 - j))
            j += 1
            lab >>= 3
    color_map = [color_map[i:i + 3] for i in range(0, len(color_map), 3)]
    return color_map

def draw_box(im, np_boxes, labels, threshold=0.5):
    """
    Args:
        im (PIL.Image.Image): PIL image
        np_boxes (np.ndarray): shape:[N,6], N: number of box,
                               matix element:[class, score, x_min, y_min, x_max, y_max]
        labels (list): labels:['class1', ..., 'classn']
        threshold (float): threshold of box
    Returns:
        im (PIL.Image.Image): visualized image
    """
    draw_thickness = min(im.size) // 300
    draw = ImageDraw.Draw(im)
    clsid2color = {}
    color_list = get_color_map_list(len(labels))
    expect_boxes = (np_boxes[:, 1] > threshold) & (np_boxes[:, 0] > -1)
    np_boxes = np_boxes[expect_boxes, :]

    font_path = "F:/Datasets/matting/Image_Text/font/微软雅黑.ttf"
    font_size = 15
    font = ImageFont.truetype(font_path, font_size)

    for dt in np_boxes:
        clsid, bbox, score = int(dt[0]), dt[2:], dt[1]
        if clsid not in clsid2color:
            clsid2color[clsid] = color_list[clsid]
        color = tuple(clsid2color[clsid])

        if len(bbox) == 4:
            xmin, ymin, xmax, ymax = bbox
            # print('class_id:{:d}, confidence:{:.4f}, left_top:[{:.2f},{:.2f}],'
            #       'right_bottom:[{:.2f},{:.2f}]'.format(
            #           int(clsid), score, xmin, ymin, xmax, ymax))
            # draw bbox
            draw.line(
                [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin),
                 (xmin, ymin)],
                width=draw_thickness,
                fill=color)
        elif len(bbox) == 8:
            x1, y1, x2, y2, x3, y3, x4, y4 = bbox
            draw.line(
                [(x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1)],
                width=2,
                fill=color)
            xmin = min(x1, x2, x3, x4)
            ymin = min(y1, y2, y3, y4)

        # draw label
        # text = "{} {:.4f}".format(labels[clsid], score)
        text = "{}".format(labels[clsid])
        tw, th = draw.textsize(text)
        tw = len(text)*int(font_size*2/3)
        th = font_size
        draw.rectangle(
            [(xmin + 1, ymin - th), (xmin + tw + 1, ymin)], fill=color)
        # draw.text((xmin + 1, ymin - th), text, fill=(255, 255, 255))
        draw.text((xmin + 1, ymin - th), text, fill=(0, 0, 0),font=font)
    return im

def cal_iou(boxa, boxb):
    x1, y1, w1, h1 = boxa
    x2, y2, w2, h2 = boxb
    if (x1 > x2 + w2):
        return 0
    if (y1 > y2 + h2):
        return 0
    if (x1 + w1 < x2):
        return 0
    if (y1 + h1 < y2):
        return 0
    colInt = abs(min(x1 + w1, x2 + w2) - max(x1, x2))
    rowInt = abs(min(y1 + h1, y2 + h2) - max(y1, y2))
    overlap_area = colInt * rowInt
    area1 = w1 * h1
    area2 = w2 * h2
    return overlap_area / (area1 + area2 - overlap_area)

def cal_overlap(boxa, boxb):
    x1, y1, w1, h1 = boxa
    x2, y2, w2, h2 = boxb
    if (x1 > x2 + w2):
        return 0
    if (y1 > y2 + h2):
        return 0
    if (x1 + w1 < x2):
        return 0
    if (y1 + h1 < y2):
        return 0
    colInt = abs(min(x1 + w1, x2 + w2) - max(x1, x2))
    rowInt = abs(min(y1 + h1, y2 + h2) - max(y1, y2))
    overlap_area = colInt * rowInt
    area1 = w1 * h1
    area2 = w2 * h2
    return overlap_area / (area1)


from rasa_core.policies.keras_policy import KerasPolicy
import logging
logger = logging.getLogger(__name__)
class MomPolicy(KerasPolicy):
    def _build_model(self, num_features, num_actions, max_history_len):
        """Build a keras model and return a compiled model.
        :param max_history_len: The maximum number of historical turns used to
                                decide on next action"""
        from keras.layers import LSTM, Activation, Masking, Dense
        from keras.models import Sequential

        n_hidden = 32  # size of hidden layer in LSTM
        # Build Model
        batch_shape = (None, max_history_len, num_features)

        model = Sequential()
        model.add(Masking(-1, batch_input_shape=batch_shape))
        model.add(LSTM(n_hidden, batch_input_shape=batch_shape))
        model.add(Dense(input_dim=n_hidden, output_dim=num_actions))
        model.add(Activation('softmax'))

        model.compile(loss='categorical_crossentropy',
                      optimizer='adam',
                      metrics=['accuracy'])

        logger.debug(model.summary())
        return model


"""
skoop.py

Muutujate ja funktsioonide nähtavuse reeglid
"""

#
# Globaalse muutuja kasutamine funktsioonis ja välaspool seda
#

a = 0

def func():
    print("Sisemine:", a)

func()
print("Välimine:", a)

#
# Samanimelise muutuja kasutamine funktsioonis ja välaspool seda
#

a = 0

def func2():
    a = 11
    print("Sisemine:", a)

func2()
print("Välimine:", a)

#
# Funktsiooni sees globaalse muutuja kasutamine ja selle muutmine
#

a = 0

def func3():
    global a
    a = 11
    print("Sisemine:", a)

func3()
print("Välimine:", a)

#
# Mitmetasemelised näited
#

# Kohalikud muutujad
x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 0

# Mitte-lokaalsed muutujad
x = 0
def outer2():
    x = 1
    def inner2():
        nonlocal x
        x = 2
        print("inner:", x)

    inner2()
    print("outer:", x)

outer2()
print("global:", x)

# inner: 2
# outer: 2
# global: 0

# Globaalsed muutujad
x = 0
def outer3():
    x = 1
    def inner3():
        global x
        x = 2
        print("inner:", x)

    inner3()
    print("outer:", x)

outer3()
print("global:", x)

# inner: 2
# outer: 1
# global: 2


from scipy.stats import boxcox
import os
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import MinMaxScaler
import statsmodels.api as sm
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.stattools import adfuller, kpss
from statsmodels.tsa.seasonal import seasonal_decompose
import math
from sklearn.metrics import mean_squared_error, mean_absolute_error
from statsmodels.tsa.holtwinters import ExponentialSmoothing
from statsmodels.tsa.arima_model import ARMA

# https://docs.oracle.com/cd/E16582_01/doc.91/e15111/und_forecast_levels_methods.htm#EOAFM00004

def error_check(orig, prev, nome_col='', nome_indice=''):
    vies = np.mean(orig - prev)
    mse = mean_squared_error(orig, prev)
    rmse = math.sqrt(mean_squared_error(orig, prev))
    mae = mean_absolute_error(orig, prev)
    mape = np.mean(np.abs((orig-prev)/orig))*100
    grupo_erro = [vies, mse, rmse, mae, mape]
    serie = pd.DataFrame(grupo_erro, index=[
        'VIÉS', 'MSE', 'RMSE', 'MAE', 'MAPE'], columns=[nome_col])
    serie.index.name = nome_indice
    return serie

def errorPLot(dados, figsize=(18, 8)):
    dados['Erro'] = dados.iloc[:, 0] - dados.iloc[:, 1]
    plt.figure(figsize=figsize)
    ax1 = plt.subplot2grid((2, 2), (0, 0))
    ax2 = plt.subplot2grid((2, 2), (0, 1))
    ax3 = plt.subplot2grid((2, 2), (1, 0))
    ax4 = plt.subplot2grid((2, 2), (1, 1))

    # Graph real x prev
    ax1.plot(dados.iloc[:, 0:2])
    ax1.legend(['Real', 'Prev'])
    ax1.set_title('Valores Reais vs Previstos')

    # Error x Prev
    ax2.scatter(dados.iloc[:, 1], dados.iloc[:, 2])
    ax2.set_xlabel('Valores Previstos')
    ax2.set_ylabel('Resíduo')
    ax2.set_title('Resíduo vs Valores Previstos')

    # QQ Plot
    sm.graphics.qqplot(dados.iloc[:, 2], line='r', ax=ax3)

    # Graph correlation
    plot_acf(dados.iloc[:, 2], lags=60, zero=False, ax=ax4)
    plt.tight_layout()
    plt.show()

os.chdir('C:\\Users\\arthu\\OneDrive\\Ambiente de Trabalho\\Projects\\Python\\DataSeries\\Etanol- Esalq\\Etanol_priceAnalysis')
df = pd.read_excel("cepea-consulta-20210110095152.xls")
# Transform string to date format in Pandas
df['Data'] = pd.to_datetime(df['Data'], dayfirst=True)
df['À vista R$'] = df['À vista R$'].str.replace(",", ".")
df['À vista US$'] = df['À vista US$'].str.replace(",", ".")
df['À vista R$'] = df['À vista R$'].astype(float)
df['À vista US$'] = df['À vista US$'].astype(float)
print(df.head())
df.sort_values('Data')
df.set_index('Data', inplace=True)
df.columns = ['Preço R$', 'Preço US$']
df['Preço R$'] = df['Preço R$'] * 1000
print(df.head())
print(df.shape[0])
print(df.dtypes)
base_testSize = int(round(df.shape[0]*0.2, 0))
treino = df.iloc[:-base_testSize, 0:1].copy()
teste = df.iloc[-base_testSize:, 0:1].copy()

# Inflation Price adjust !Important for prices
infl = pd.read_excel('IPCA.xls', sheet_name='IPCA')
infl['Data'] = pd.to_datetime(infl['Data'])
infl.set_index('Data', inplace=True)
print(infl.head(-10))
infl['Acumulado'] = pd.to_numeric(infl['Acumulado'])
inf_actual = infl.loc[infl.index.max()]
inf_actual = inf_actual['Acumulado']
# Creating New columns in training DB for the Month and Year
treino['Ano'] = treino.index.year
treino['Mês'] = treino.index.month
index = treino.index

# Merge Inflation DataFrame Into Training DB
treino = treino.merge(
    infl.loc[:, ['Ano', 'Mês', 'Acumulado']], how='left', on=['Ano', 'Mês'])
treino['Preço Ajustado'] = (
    treino['Preço R$']/treino['Acumulado']) * inf_actual
treino.set_index(index, inplace=True)
treino.dropna(inplace=True)

# Model using previous period value
# Just Used to generate error and validations values as base to other methods of prediction
# Cannot be used to do forecasting
# Training DB
simples_treino = treino[['Preço Ajustado']]
simples_treino.columns = ['Real']
simples_treino['Previsão'] = simples_treino['Real'].shift()
simples_treino.dropna(inplace=True)
simples_treino.plot()
plt.show()
erro_treino = error_check(
    simples_treino['Real'], simples_treino['Previsão'], nome_col='Simples', nome_indice='Base Treino')
errorPLot(simples_treino)
# Testing DB
simples_teste = teste[['Preço R$']]
simples_teste.columns = ['Real']
hist = [simples_treino.iloc[i, 0] for i in range(len(simples_treino))]
prev = []
for t in range(len(simples_teste)):
    yhat = hist[-1]
    obs = simples_teste.iloc[t, 0]
    prev.append(yhat)
    hist.append(obs)

simples_teste['Previsão'] = prev
erro_teste = error_check(
    simples_teste['Real'], simples_teste['Previsão'], nome_col='Simples', nome_indice='Base Teste')

# Simple Mean Model
# Training DB
ms_treino = treino[['Preço Ajustado']]
ms_treino.columns = ['Real']
ms_treino['Previsão'] = ms_treino['Real'].expanding().mean()
erro_treino['Média Simples'] = error_check(
    ms_treino['Real'], ms_treino['Previsão'])
errorPLot(ms_treino)
# Testing DB
ms_teste = teste[['Preço R$']]
ms_teste.columns = ['Real']
hist = [ms_treino.iloc[i, 0] for i in range(len(ms_treino))]
prev = []
for t in range(len(ms_teste)):
    # Mean of array Hist, all values
    yhat = np.mean(hist)
    obs = ms_teste.iloc[t, 0]
    prev.append(yhat)
    hist.append(obs)

ms_teste['Previsão'] = prev
erro_teste['Média Simples'] = error_check(
    ms_teste['Real'], ms_teste['Previsão'], nome_col='Mean Model')

# Simple Moving Mean
# Training DB
mm_treino = treino[['Preço Ajustado']]
mm_treino.columns = ['Real']
mm_treino['Previsão'] = mm_treino.rolling(5).mean()
mm_treino.dropna(inplace=True)
erro_treino['Média Movel'] = error_check(
    mm_treino['Real'], mm_treino['Previsão'])
# Testing DB
mm_teste = teste[['Preço R$']]
mm_teste.columns = ['Real']
hist = [mm_treino.iloc[i, 0] for i in range(len(mm_treino))]
prev = []
for t in range(len(mm_teste)):
    yhat = np.mean(hist[-5:])
    obs = mm_teste.iloc[t, 0]
    prev.append(yhat)
    hist.append(obs)

mm_teste['Previsão'] = prev
errorPLot(mm_teste)
erro_teste['Média Móvel'] = error_check(mm_teste['Real'], mm_teste['Previsão'])

# Exp Moving Mean
# Testing for Alpha
mme = treino[['Preço Ajustado']]
alpha_ = [0, 0.2, 1]
for i, valor in enumerate(alpha_):
    model = ExponentialSmoothing(
        mme['Preço Ajustado']).fit(smoothing_level=valor)
    mme['Alpha {}'.format(valor)] = model.predict(start=0, end=len(mme)-1)

mme.plot(figsize=(18, 5), title='Vários valores de Alpha contra a série de treino')
plt.show()
# Model with 0.5 alpha Training DB
mme_treino = treino[['Preço Ajustado']]
mme_treino.columns = ['Real']
alpha = 0.5
modelo = ExponentialSmoothing(mme_treino['Real']).fit(smoothing_level=alpha)
mme_treino['Previsão'] = modelo.predict(start=0, end=len(mme_treino)-1)
erro_treino['Média Móvel Exp'] = error_check(
    mme_treino['Real'], mme_treino['Previsão'])
# Model with Testing DB
mme_teste = teste[['Preço R$']]
mme_teste.columns = ['Real']
print(mme_treino.head(10))
hist = [mme_treino.iloc[i, 0] for i in range(len(mme_treino))]
hist_prev = [mme_treino.iloc[i, 1] for i in range(len(mme_treino))]
prev = []
for t in range(len(mme_teste)):
    yhat = hist_prev[-1] + alpha * (hist[-1] - hist_prev[-1])
    obs = mme_teste.iloc[t, 0]
    prev.append(yhat)
    hist.append(obs)
    hist_prev.append(yhat)

mme_teste['Previsão'] = prev

erro_teste['Média Móvel Exp'] = error_check(
    mme_teste['Real'], mme_teste['Previsão'])
errorPLot(mme_teste)

# Regressive model
plot_acf(treino['Preço Ajustado'], lags=60, zero=False)
plot_pacf(treino['Preço Ajustado'], lags=60, zero=False)
# Model in Training DB
ar_treino = treino[['Preço Ajustado']]
ar_treino.columns = ['Real']
modelo = ARMA(ar_treino['Real'], order=[2, 0]).fit()
ar_treino['Previsão'] = modelo.predict(start=0, end=len(ar_treino)-1)
erro_treino['ARMA'] = error_check(ar_treino['Real'], ar_treino['Previsão'])
# Model in Testing DB
ar_teste = teste[['Preço R$']]
ar_teste.columns = ['Real']
print(modelo.arparams)
coef_1, coef_2 = modelo.arparams
hist = [ar_treino.iloc[i, 0] for i in range(len(ar_treino))]
prev = []
for t in range(len(ar_teste)):
    yhat = (hist[-1]*coef_1)+(hist[-2]*coef_2)
    obs = ar_teste.iloc[t, 0]
    prev.append(yhat)
    hist.append(obs)

ar_teste['Previsão'] = prev
errorPLot(ar_teste)
erro_teste['ARMA'] = error_check(ar_teste['Real'], ar_teste['Previsão'])


def reversersiffer(n):
    nn = int(str(abs(n))[::-1])

    if n < 0:
        nn *= -1

    return nn

def opp7(n):
    while str(n)[-1] != '7':
        n += 1

    return n

def gangemsd(n):
    return n * int(str(abs(n))[0])

def delemsd(n):
    return n // int(str(abs(n))[0])

def pluss1tilpar(n):
    ns = str(abs(n))
    nn = ''

    for i in range(len(ns)):
        if int(ns[i]) % 2 == 0:
            nn += str(int(ns[i]) + 1)
        else:
            nn += ns[i]

    return int(nn) * (-1 if n < 0 else 1)

def trekk1fraodde(n):
    ns = str(abs(n))
    nn = ''

    for i in range(len(ns)):
        if int(ns[i]) % 2 == 1:
            nn += str(int(ns[i]) - 1)
        else:
            nn += ns[i]

    return int(nn) * (-1 if n < 0 else 1)

def wheelspinner(n):
    operations = [[op.strip() for op in line.strip()[8:].split(',')] for line in open('input/08').readlines()]
    pos = [0]*10

    while True:
        idx = n % 10
        op_code = operations[idx][pos[idx]]

        # print(n, idx, op_code)
        func = None

        if op_code.lower() in globals():
            func = globals()[op_code.lower()]

        if func:
            n = func(n)
        elif op_code == 'STOPP':
            return n
        elif op_code == 'PLUSS4':
            n += 4
        elif op_code == 'PLUSS101':
            n += 101
        elif op_code == 'MINUS9':
            n -= 9
        elif op_code == 'MINUS1':
            n -= 1
        elif op_code == 'ROTERPAR':
            for i in range(0, len(pos), 2):
                pos[i] = (pos[i] + 1) % len(operations[i])
        elif op_code == 'ROTERODDE':
            for i in range(1, len(pos), 2):
                pos[i] = (pos[i] + 1) % len(operations[i])
        elif op_code == 'ROTERALLE':
            for i in range(0, len(pos)):
                pos[i] = (pos[i] + 1) % len(operations[i])
        else:
            print("UNKNOWN OPCODE: " + op_code)
            return

        pos[idx] = (pos[idx] + 1) % len(operations[idx])

def test_reversersiffer():
    assert 321 == reversersiffer(123)
    assert -321 == reversersiffer(-123)
    assert 21 == reversersiffer(12)

def test_opp7():
    assert 27 == opp7(21)
    assert -7 == opp7(-13)
    assert 17 == opp7(17)

def test_gangemsd():
    assert 46 == gangemsd(23)
    assert -93 == gangemsd(-31)

def test_delemsd():
    assert 11 == delemsd(23)
    assert -11 == delemsd(-31)

def test_pluss1tilpar():
    assert 131 == pluss1tilpar(120)
    assert -1335 == pluss1tilpar(-1234)

def test_trekk1fraodde():
    assert 224 == trekk1fraodde(1234)
    assert -224 == trekk1fraodde(-1234)

if __name__ == '__main__':
    best = 0

    for coins in range(1, 10):
        result = wheelspinner(coins)

        if result > best:
            best = result
            print('new best: ' + str(result) + ' - ' + str(coins) + ' coins')


import os
import time
from cognitojwt import decode
from chalicelib.config import (COGNITO_CLIENT_ID, USER_POOL_ID, USER_POOL_REGION,
                                LIVE_ARN_RESOURCES, LOCAL_ARN_RESOURCES)

class CognitoAuthSingleton:
    _instance = None

    @staticmethod
    def get_instance():
        """
        Get the singleton instance of CognitoAuthSingleton class.

        Returns:
            CognitoAuthSingleton: The singleton instance.
        """
        if not CognitoAuthSingleton._instance:
            CognitoAuthSingleton._instance = CognitoAuthSingleton()
        return CognitoAuthSingleton._instance

    def __init__(self):
        """
        Initialize the CognitoAuthSingleton class.
        """
        if CognitoAuthSingleton._instance:
            raise Exception("This class is a singleton!")
        CognitoAuthSingleton._instance = self

    def authenticate_request(self, auth_request):
        """
        Authenticate the request using the provided authentication request.

        Args:
            auth_request (AuthRequest): The authentication request.

        Returns:
            dict: The policy document.

        Raises:
            Exception: If the token is expired or the issuer is invalid.
        """
        token = auth_request.token.replace('Bearer ', '')
        try:
            decoded_token = self._decode_token(token)
            self._validate_token(decoded_token)

            principal_id = decoded_token['sub']
            policy_document = self._generate_policy_document(principal_id, decoded_token)
            return policy_document

        except Exception as e:
            return {"message": str(e)}

    def _decode_token(self, token):
        """
        Decode the provided token.

        Args:
            token (str): The token to decode.

        Returns:
            dict: The decoded token.
        """
        return decode(
            token=token,
            region=USER_POOL_REGION,
            userpool_id=USER_POOL_ID,
            app_client_id=COGNITO_CLIENT_ID
        )

    def _validate_token(self, decoded_token):
        """
        Validate the decoded token.

        Args:
            decoded_token (dict): The decoded token.

        Raises:
            Exception: If the token is expired or the issuer is invalid.
        """
        if decoded_token['exp'] < time.time():
            raise Exception('Token has expired')

        expected_issuer = f'https://cognito-idp.{USER_POOL_REGION}.amazonaws.com/{USER_POOL_ID}'
        if decoded_token['iss'] != expected_issuer:
            raise Exception('Token issuer is invalid')

    def _generate_policy_document(self, principal_id, decoded_token):
        """
        Generate the policy document.

        Args:
            principal_id (str): The principal ID.
            decoded_token (dict): The decoded token.

        Returns:
            dict: The policy document.
        """
        resource_list = LIVE_ARN_RESOURCES + LOCAL_ARN_RESOURCES
        policy_document = {
            'principalId': principal_id,
            'context': decoded_token,
            'policyDocument': {
                'Version': '2012-10-17',
                'Statement': [
                    {
                        'Action': 'execute-api:Invoke',
                        'Effect': 'Allow',
                        'Resource': resource_list
                    }
                ]
            }
        }
        return policy_document


import re
import rfc822
from datetime import datetime
try:
    from hashlib import md5
except ImportError:
    from md5 import new as md5
try:
    set = set
    frozenset = frozenset
except NameError:
    from sets import Set as set, ImmutableSet as frozenset

_accept_re = re.compile(r'([^\s;,]+)(?:[^,]*?;\s*q=(\d*(?:\.\d+)?))?')
_token_chars = frozenset("!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                         '^_`abcdefghijklmnopqrstuvwxyz|~')
_token = '[%s]' % ''.join(_token_chars).replace('-', '\\-')
_cachecontrol_re = re.compile(r'(%s+)(?:=(?:(%s+|".*?")))?' %
                              (_token, _token))
_etag_re = re.compile(r'([Ww]/)?(?:"(.*?)"|(.*?))(?:\s*,\s*|$)')

HTTP_STATUS_CODES = {
    100:    'Continue',
    101:    'Switching Protocols',
    102:    'Processing',
    200:    'OK',
    201:    'Created',
    202:    'Accepted',
    203:    'Non Authoritative Information',
    204:    'No Content',
    205:    'Reset Content',
    206:    'Partial Content',
    207:    'Multi Status',
    226:    'IM Used',              # see RFC 3229
    300:    'Multiple Choices',
    301:    'Moved Permanently',
    302:    'Found',
    303:    'See Other',
    304:    'Not Modified',
    305:    'Use Proxy',
    307:    'Temporary Redirect',
    400:    'Bad Request',
    401:    'Unauthorized',
    402:    'Payment Required',     # unused
    403:    'Forbidden',
    404:    'Not Found',
    405:    'Method Not Allowed',
    406:    'Not Acceptable',
    407:    'Proxy Authentication Required',
    408:    'Request Timeout',
    409:    'Conflict',
    410:    'Gone',
    411:    'Length Required',
    412:    'Precondition Failed',
    413:    'Request Entity Too Large',
    414:    'Request URI Too Long',
    415:    'Unsupported Media Type',
    416:    'Requested Range Not Satisfiable',
    417:    'Expectation Failed',
    422:    'Unprocessable Entity',
    423:    'Locked',
    424:    'Failed Dependency',
    426:    'Upgrade Required',
    449:    'Retry With',           # propritary MS extension
    500:    'Internal Server Error',
    501:    'Not Implemented',
    502:    'Bad Gateway',
    503:    'Service Unavailable',
    504:    'Gateway Timeout',
    505:    'HTTP Version Not Supported',
    507:    'Insufficient Storage',
    510:    'Not Extended'
}

class Accept(list):
    """
    An `Accept` object is just a list subclass for lists of
    ``(value, quality)`` tuples.  It is automatically sorted by quality.
    """

    def __init__(self, values=()):
        if values is None:
            list.__init__(self)
            self.provided = False
        else:
            self.provided = True
            values = [(a, b) for b, a in values]
            values.sort()
            values.reverse()
            list.__init__(self, [(a, b) for b, a in values])

    def __getitem__(self, key):
        """
        Beside index lookup (getting item n) you can also pass it a string to
        get the quality for the item.  If the item is not in the list, the
        returned quality is ``0``.
        """
        if isinstance(key, basestring):
            for value in self:
                if value[0] == key:
                    return value[1]
            return 0
        return list.__getitem__(self, key)

    def __contains__(self, key):
        return self.find(key) > -1

    def __repr__(self):
        return '%s(%s)' % (
            self.__class__.__name__,
            list.__repr__(self)
        )

    def index(self, key):
        """Get the position of en entry or raise `IndexError`."""
        rv = self.find(key)
        if rv < 0:
            raise IndexError(key)
        return key

    def find(self, key):
        """Get the position of an entry or return -1"""
        if isinstance(key, basestring):
            for idx, value in enumerate(self):
                if value[0] == key:
                    return idx
            return -1
        return list.find(self, key)

    def values(self):
        """Return a list of the values, not the qualities."""
        return [x[1] for x in self]

    def itervalues(self):
        """Iterate over all values."""
        for item in self:
            yield item[0]

    def best(self):
        """The best match as value."""
        return self and self[0][0] or None
    best = property(best)

class HeaderSet(object):
    """
    Similar to the `ETags` class this implements a set like structure.
    Unlike `ETags` this is case insensitive and used for vary, allow, and
    content-language headers.

    If not constructed using the `parse_set_header` function the instanciation
    works like this:

    >>> hs = HeaderSet(['foo', 'bar', 'baz'])
    >>> hs
    HeaderSet(['foo', 'bar', 'baz'])
    """

    def __init__(self, headers=None, on_update=None):
        self._headers = list(headers or ())
        self._set = set([x.lower() for x in self._headers])
        self.on_update = on_update

    def add(self, header):
        """Add a new header to the set."""
        self.update((header,))

    def remove(self, header):
        """
        Remove a layer from the set.  This raises an `IndexError` if the
        header is not in the set.
        """
        key = header.lower()
        if key not in self._set:
            raise IndexError(header)
        self._set.remove(key)
        for idx, key in enumerate(self._headers):
            if key.lower() == header:
                del self._headers[idx]
                break
        if self.on_update is not None:
            self.on_update(self)

    def update(self, iterable):
        """Add all the headers from the iterable to the set."""
        inserted_any = False
        for header in iterable:
            key = header.lower()
            if key not in self._set:
                self._headers.append(header)
                self._set.add(key)
                inserted_any = True
        if inserted_any and self.on_update is not None:
            self.on_update(self)

    def discard(self, header):
        """Like remove but ignores errors."""
        try:
            return self.remove(header)
        except IndexError:
            pass

    def find(self, header):
        """Return the index of the header in the set or return -1 if not found."""
        header = header.lower()
        for idx, item in enumerate(self._headers):
            if item.lower() == header:
                return idx
        return -1

    def index(self, header):
        """Return the index of the headerin the set or raise an `IndexError`."""
        rv = self.find(header)
        if rv < 0:
            raise IndexError(header)
        return rv

    def clear(self):
        """Clear the set."""
        self._set.clear()
        del self._headers[:]
        if self.on_update is not None:
            self.on_update(self)

    def as_set(self, preserve_casing=False):
        """
        Return the set as real python set structure.  When calling this all
        the items are converted to lowercase and the ordering is lost.

        If `preserve_casing` is `True` the items in the set returned will
        have the original case like in the `HeaderSet`, otherwise they will
        be lowercase.
        """
        if preserve_casing:
            return set(self._headers)
        return set(self._set)

    def to_header(self):
        """Convert the header set into an HTTP header string."""
        return ', '.join(self._headers)

    def __getitem__(self, idx):
        return self._headers[idx]

    def __delitem__(self, idx):
        rv = self._headers.pop(idx)
        self._set.remove(rv.lower())
        if self.on_update is not None:
            self.on_update(self)

    def __setitem__(self, idx, value):
        old = self._headers[idx]
        self._set.remove(old.lower())
        self._headers[idx] = value
        self._set.add(value.lower())
        if self.on_update is not None:
            self.on_update(self)

    def __contains__(self, header):
        return header.lower() in self._set

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

    def __iter__(self):
        return iter(self._headers)

    def __nonzero__(self):
        return bool(self._set)

    def __str__(self):
        return self.to_header()

    def __repr__(self):
        return '%s(%r)' % (
            self.__class__.__name__,
            self._headers
        )

class CacheControl(dict):
    """
    Subclass of a dict that stores values for a Cache-Control header.  It has
    accesors for all the cache-control directives specified in RFC 2616.  The
    class does not differentiate between request and response directives.

    Because the cache-control directives in the HTTP header use dashes the
    python descriptors use underscores for that.

    To get a header of the `CacheControl` object again you can convert the
    object into a string or call the `to_header()` function.  If you plan
    to subclass it and add your own items have a look at the sourcecode for
    that class.

    The following attributes are exposed:

    `no_cache`, `no_store`, `max_age`, `max_stale`, `min_fresh`,
    `no_transform`, `only_if_cached`, `public`, `private`, `must_revalidate`,
    `proxy_revalidate`, and `s_maxage`
    """

    def cache_property(key, default, type):
        """
        Return a new property object for a cache header.  Useful if you
        want to add support for a cache extension in a subclass.
        """
        return property(lambda x: x._get_cache_value(key, default, type),
                        lambda x, v: x._set_cache_value(key, v, type),
                        'accessor for %r' % key)

    no_cache = cache_property('no-cache', '*', bool)
    no_store = cache_property('no-store', None, bool)
    max_age = cache_property('max-age', -1, int)
    max_stale = cache_property('max-stale', '*', int)
    min_fresh = cache_property('min-fresh', '*', int)
    no_transform = cache_property('no-transform', None, None)
    only_if_cached = cache_property('only-if-cached', None, bool)
    public = cache_property('public', None, bool)
    private = cache_property('private', '*', None)
    must_revalidate = cache_property('must-revalidate', None, bool)
    proxy_revalidate = cache_property('proxy-revalidate', None, bool)
    s_maxage = cache_property('s-maxage', None, None)

    def __init__(self, values=(), on_update=None):
        self.on_update = on_update
        if values is None:
            dict.__init__(self)
            self.provided = False
        else:
            dict.__init__(self, values)
            self.provided = True

    def calls_update(f):
        def oncall(self, *args, **kw):
            rv = f(self, *args, **kw)
            if self.on_update is not None:
                self.on_update(self)
            return rv
        try:
            oncall.__name__ = f.__name__
            oncall.__module__ = f.__module__
            oncall.__doc__ = f.__doc__
        except:
            pass
        return oncall

    __setitem__ = calls_update(dict.__setitem__)
    __delitem__ = calls_update(dict.__delitem__)
    clear = calls_update(dict.clear)
    pop = calls_update(dict.pop)
    popitem = calls_update(dict.popitem)
    setdefault = calls_update(dict.setdefault)
    update = calls_update(dict.update)

    def _get_cache_value(self, key, default, type):
        """Used internally be the accessor properties."""
        if type is bool:
            return key in self
        if key in self:
            value = self[key]
            if value is None:
                return default
            elif type is not None:
                try:
                    value = type(value)
                except ValueError:
                    pass
            return value

    def _set_cache_value(self, key, value, type):
        """Used internally be the accessor properties."""
        if type is bool:
            if value:
                self[key] = None
            else:
                self.pop(key, None)
        else:
            if value is not None:
                self[key] = value
            else:
                self.pop(key, None)
    _set_cache_value = calls_update(_set_cache_value)

    def to_header(self):
        """Convert the stored values into a cache control header."""
        items = []
        for key, value in self.iteritems():
            if value is None:
                items.append(key)
            else:
                value = str(value)
                if not set(value).issubset(_token_chars):
                    value = '"%s"' % value.replace('"', "'")
                items.append('%s=%s' % (key, value))
        return ', '.join(items)

    def __str__(self):
        return self.to_header()

    def __repr__(self):
        return '%s(%s)' % (
            self.__class__.__name__,
            dict.__repr__(self)
        )

    # make cache_property a staticmethod so that subclasses of
    # `CacheControl` can use it for new properties.
    cache_property = staticmethod(cache_property)
    del calls_update

class ETags(object):
    """
    A set that can be used to check if one etag is present in a collection
    of etags.
    """

    def __init__(self, strong_etags=None, weak_etags=None, star_tag=False):
        self._strong = frozenset(not star_tag and strong_etags or ())
        self._weak = frozenset(weak_etags or ())
        self.star_tag = star_tag

    def as_set(self, include_weak=False):
        """
        Convert the `ETags` object into a python set.  Per default all the
        weak etags are not part of this set.
        """
        rv = set(self._strong)
        if include_weak:
            rv.update(self._weak)
        return rv

    def is_weak(self, etag):
        """Check if an etag is weak."""
        return etag in self._weak

    def contains_weak(self, etag):
        """Check if an etag is part of the set including weak and strong tags."""
        return self.is_weak(etag) or self.contains(etag)

    def contains(self, etag):
        """Check if an etag is part of the set ignoring weak tags."""
        if self.star_tag:
            return True
        return etag in self._strong

    def contains_raw(self, etag):
        """
        When passed a quoted tag it will check if this tag is part of the set.
        If the tag is weak it is checked against weak and strong tags, otherwise
        weak only.
        """
        etag, weak = unquote_etag(etag)
        if weak:
            return self.contains_weak(etag)
        return self.contains(etag)

    def to_header(self):
        """Convert the etags set into a HTTP header string."""
        if self.star_tag:
            return '*'
        return ', '.join(['"%s"' % item for item in self.as_set(True)])

    def __call__(self, etag=None, data=None, include_weak=False):
        if [etag, data].count(None) != 1:
            raise TypeError('either tag or data required, but at least one')
        if etag is None:
            etag = generate_etag(data)
        if include_weak:
            if etag in self._weak:
                return True
        return etag in self._strong

    def __nonzero__(self):
        return bool(self.star_tag or self._strong)

    def __str__(self):
        return self.to_header()

    def __iter__(self):
        return iter(self._strong)

    def __contains__(self, etag):
        return self.contains(etag)

    def __repr__(self):
        return '<%s %r>' % (self.__class__.__name__, str(self))

def parse_accept_header(value):
    """
    Parses an HTTP Accept-* header.  This does not implement a complete valid
    algorithm but one that supports at least value and quality extraction.

    Returns a new `Accept` object (basicly a list of ``(value, quality)``
    tuples sorted by the quality with some additional accessor methods)
    """
    if not value:
        return Accept(None)
    result = []
    for match in _accept_re.finditer(value):
        quality = match.group(2)
        if not quality:
            quality = 1
        else:
            quality = max(min(float(quality), 1), 0)
        result.append((match.group(1), quality))
    return Accept(result)

def parse_cache_control_header(value, on_update=None):
    """
    Parse a cache control header.  The RFC differs between response and
    request cache control, this method does not.  It's your responsibility
    to not use the wrong control statements.
    """
    if not value:
        return CacheControl(None, on_update)
    result = {}
    for match in _cachecontrol_re.finditer(value):
        name, value = match.group(1, 2)
        if value and value[0] == value[-1] == '"':
            value = value[1:-1]
        result[name] = value
    return CacheControl(result, on_update)

def parse_set_header(value, on_update=None):
    """
    Parse a set like header and return a `HeaderSet` object.  The return
    value is an object that treats the items case insensitive and keeps the
    order of the items.
    """
    if not value:
        return HeaderSet(None, on_update)
    return HeaderSet([x.strip() for x in value.split(',')], on_update)

def quote_etag(etag, weak=False):
    """Quote an etag."""
    if '"' in etag:
        raise ValueError('invalid etag')
    etag = '"%s"' % etag
    if weak:
        etag = 'w/' + etag
    return etag

def unquote_etag(etag):
    """Unquote a single etag.  Return a ``(etag, weak)`` tuple."""
    if not etag:
        return None, None
    etag = etag.strip()
    weak = False
    if etag[:2] in ('w/', 'W/'):
        weak = True
        etag = etag[2:]
    if etag[:1] == etag[-1:] == '"':
        etag = etag[1:-1]
    return etag, weak

def parse_etags(value):
    """Parse and etag header.  Returns an `ETags` object."""
    if not value:
        return ETags()
    strong = []
    weak = []
    end = len(value)
    pos = 0
    while pos < end:
        match = _etag_re.match(value, pos)
        if match is None:
            break
        is_weak, quoted, raw = match.groups()
        if raw == '*':
            return ETags(star_tag=True)
        elif quoted:
            raw = quoted
        if is_weak:
            weak.append(raw)
        else:
            strong.append(raw)
        pos = match.end()
    return ETags(strong, weak)

def generate_etag(data):
    """Generate an etag for some data."""
    return md5(data).hexdigest()

def parse_date(value):
    """
    Parse one of the following date formats into a datetime object:

    .. sourcecode:: text

        Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
        Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
        Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format

    If parsing fails the return value is `None`.
    """
    if value:
        t = rfc822.parsedate_tz(value)
        if t is not None:
            return datetime.utcfromtimestamp(rfc822.mktime_tz(t))

def is_resource_modified(environ, etag=None, data=None, last_modified=None):
    """Convenience method for conditional requests."""
    if etag is None and data is not None:
        etag = generate_etag(data)
    elif data is not None:
        raise TypeError('both data and etag given')
    if environ['REQUEST_METHOD'] not in ('GET', 'HEAD'):
        return False

    unmodified = False
    if isinstance(last_modified, basestring):
        last_modified = parse_date(last_modified)
    modified_since = parse_date(environ.get('HTTP_IF_MODIFIED_SINCE'))

    if modified_since and last_modified and last_modified <= modified_since:
        unmodified = True
    if etag:
        if_none_match = parse_etags(environ.get('HTTP_IF_NONE_MATCH'))
        if if_none_match:
            unmodified = if_none_match.contains_raw(etag)

    return not unmodified


from typing import Coroutine, Optional

from core.models import Subject
from core.schemas.subject import CreateSubjectSchema
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

async def get_subject_by_title(db: AsyncSession, title: str) -> Optional[Subject]:
    query = select(Subject).where(Subject.title == title)
    result = await db.execute(query)
    return result.scalar()

async def create_subject(db: AsyncSession, subject: CreateSubjectSchema) -> Subject:
    result = Subject(
        title=subject.title
    )
    db.add(result)
    await db.commit()
    await db.refresh(result)
    return result


# -*- coding: utf-8 -*-
import requests

url = "http://www.dzzsb.com.cn:7777/cjxs.asp"

# form-data参数要写成如下格式，注意有None
data = {
    "zkzh": (None, 201381100362),
    "bmxh": (None, 13812020013251),
    "jym": (None, '孔丽玄'),
    "button2": (None, '查询2')
}

response = requests.session().post(url, data=data)
response.encoding='utf-8'
print(response.text)


import sys
input = sys.stdin.readline

k = int(input().rstrip())

for i in range(k):
    array = list(map(int, input().rstrip().split()))
    people = array[0]
    grade = array[1:]
    grade.sort(reverse=True)
    gap = []
    for j in range(people - 1):
        gap.append(grade[j] - grade[j + 1])

    print(f"Class {i+1}")
    print(f"Max {max(grade)}, Min {min(grade)}, Largest gap {max(gap)}")


# -*- coding: utf-8 -*-
'''
    rauth.utils
    -----------

    General utilities.
'''

from rauth.compat import quote, parse_qsl, is_basestring

from requests.structures import CaseInsensitiveDict as cidict
from requests.auth import AuthBase

FORM_URLENCODED = 'application/x-www-form-urlencoded'
ENTITY_METHODS = ('POST', 'PUT', 'PATCH')
OPTIONAL_OAUTH_PARAMS = ('oauth_callback', 'oauth_verifier', 'oauth_version')

def absolute_url(url):
    return url.startswith(('http://', 'https://'))

def parse_utf8_qsl(s):
    d = dict(parse_qsl(s))

    for k, v in d.items():  # pragma: no cover
        if not isinstance(k, bytes) and not isinstance(v, bytes):
            # skip this iteration if we have no keys or values to update
            continue
        d.pop(k)
        if isinstance(k, bytes):
            k = k.decode('utf-8')
        if isinstance(v, bytes):
            v = v.decode('utf-8')
        d[k] = v
    return d

def get_sorted_params(params):
    def sorting_gen():
        for k in sorted(params.keys()):
            yield '='.join((k, params[k]))
    return '&'.join(sorting_gen())

class CaseInsensitiveDict(cidict):
    def __init__(self, d=None):
        lowered_d = {}

        if d is not None:
            if isinstance(d, dict):
                lowered_d = self._get_lowered_d(d)
            elif isinstance(d, list):
                return self.__init__(dict(d))

        return super(CaseInsensitiveDict, self).__init__(lowered_d)

    def _get_lowered_d(self, d):
        lowered_d = {}
        for key in d:
            if is_basestring(key):
                lowered_d[key.lower()] = d[key]
            else:  # pragma: no cover
                lowered_d[key] = d[key]
        return lowered_d

    def setdefault(self, key, default):
        if is_basestring(key):
            key = key.lower()

        super(CaseInsensitiveDict, self).setdefault(key, default)

    def update(self, d):
        super(CaseInsensitiveDict, self).update(self._get_lowered_d(d))

class OAuth2Auth(AuthBase):
    ''' Attaches OAuth 2 Authentication to a given Request object. '''
    def __init__(self, access_token):
        self.access_token = access_token

    def __call__(self, r):
        r.headers['Authorization'] = 'Bearer ' + self.access_token
        return r

class OAuth1Auth(AuthBase):
    ''' Attaches OAuth 1 Authentication to a given Request object. '''
    def __init__(self, oauth_params, realm=None):
        self.oauth_params = oauth_params
        self.realm = realm or ''

    def _get_auth_header(self):
        ''' Constructs and returns an authentication header. '''
        realm = 'realm="{realm}"'.format(realm=self.realm)
        params = ['{k}="{v}"'.format(k=k, v=quote(str(v), safe=''))
                  for k, v in self.oauth_params.items()]
        return 'OAuth ' + ','.join([realm] + params)

    def __call__(self, r):
        r.headers['Authorization'] = self._get_auth_header()
        return r


"""
Determine bad pixels from a calibration file.
Usage:
  bad_pixels.py [options]

Options:
  --help                        Show this
  --calib_file=PATH             Calibration YAML file used to determine the
                                bad pixels together with --nsigma_gain and
                                --nsigma_elecnoise
                                [Default: none]
  --nsigma_gain=INT             Number of sigmas around the mean value
                                acceptable for the gain. If the gain value of a
                                pixel is outside of the acceptable range, this
                                pixel is considered bad.
                                [Default: 5]
  --nsigma_elecnoise=INT        Number of sigmas around the mean value
                                acceptable for the electronic noise. If the
                                electronic noise value of a pixel is outside
                                of the acceptable range, this pixel is
                                considered bad.
                                [Default: 5]
  --dark_histo=FILE             Histogram of the adc samples during dark run
                                used to determine the bad pixels together with
                                --nsigma_dark
                                [Default: none]
  --nsigma_dark=INT             Number of sigmas around the mean value
                                acceptable for raw adc values in dark. If the
                                value of a pixel is outside of the acceptable
                                range, this pixel is considered bad.
                                [Default: 8]
  --plot=FILE                   path to the output plot. Will show the
                                histograms of the values used to determine bad
                                pixels and highlight those.
                                If set to "show", the plot is displayed and not
                                saved. If set to "none", no plot is done.
                                [Default: show]
  --output=FILE                 Same calibration YAML file as the one used as
                                input plus the list of bad pixels. If "none"
                                no file is created. It is safe to use the same
                                file as the input.
                                [Default: none]

"""
import matplotlib.pyplot as plt
import numpy as np
from docopt import docopt
import yaml
from astropy.stats import SigmaClip
from histogram.histogram import Histogram1D

from digicampipe.utils.docopt import convert_int, convert_text

def get_bad_pixels(
        calib_file=None, nsigma_gain=5, nsigma_elecnoise=5,
        dark_histo=None, nsigma_dark=8,
        plot="none", output=None
):
    bad_pix = np.array([], dtype=int)
    if calib_file is not None:
        with open(calib_file) as file:
            calibration_parameters = yaml.load(file)
        gain = np.array(calibration_parameters['gain'])
        elecnoise = np.array(calibration_parameters['sigma_e'])
        nan_mask = np.logical_or(~np.isfinite(gain), ~np.isfinite(elecnoise))
        sigclip_gain = SigmaClip(sigma=nsigma_gain, iters=10,
                                 cenfunc=np.nanmean, stdfunc=np.nanstd)
        sigclip_elecnoise = SigmaClip(sigma=nsigma_elecnoise, iters=10,
                                      cenfunc=np.nanmean, stdfunc=np.nanstd)
        gain_mask = sigclip_gain(gain).mask
        elecnoise_mask = sigclip_elecnoise(elecnoise).mask
        bad_mask = np.logical_or(nan_mask,
                                 np.logical_or(gain_mask, elecnoise_mask))
        bad_pix = np.where(bad_mask)[0]
        if output is not None:
            calibration_parameters['bad_pixels'] = bad_pix
            with open(output, 'w') as file:
                yaml.dump(calibration_parameters, file)
        if plot is not None:
            fig, (ax_gain, ax_elecnoise) = plt.subplots(2, 1)
            gain_bins = np.linspace(np.nanmin(gain), np.nanmax(gain), 100)
            ax_gain.hist(gain[~bad_mask], gain_bins, color='b')
            ax_gain.hist(gain[bad_mask], gain_bins, color='r')
            ax_gain.set_xlabel('integral gain [LSB p.e.$^{-1}$]')
            elecnoise_bins = np.linspace(np.nanmin(elecnoise),
                                         np.nanmax(elecnoise), 100)
            ax_elecnoise.hist(elecnoise[~bad_mask], elecnoise_bins, color='b')
            ax_elecnoise.hist(elecnoise[bad_mask], elecnoise_bins, color='r')
            ax_elecnoise.set_xlabel('electronic noise [LSB]')
            plt.tight_layout()
            if plot != "show":
                plt.savefig(plot)
            else:
                plt.show()
            plt.close(fig)
    if dark_histo is not None:
        dark_histo = Histogram1D.load(dark_histo)
        baseline = dark_histo.mean(method='mid')
        sigclip_dark = SigmaClip(sigma=nsigma_dark, iters=10,
                                 cenfunc=np.nanmean, stdfunc=np.nanstd)
        dark_mask = sigclip_dark(baseline).mask
        bad_dark = np.where(dark_mask)[0]
        bad_pix = np.unique(np.concatenate((bad_pix, bad_dark)))
    return bad_pix

def entry():
    args = docopt(__doc__)
    calib_file = convert_text(args['--calib_file'])
    nsigma_gain = convert_int(args['--nsigma_gain'])
    nsigma_elecnoise = convert_int(args['--nsigma_elecnoise'])
    dark_file = convert_text(args['dark_histo'])
    nsigma_dark = convert_int(args['--nsigma_dark'])
    plot = convert_text(args['--plot'])
    output = convert_text(args['--output'])
    bad_pix = get_bad_pixels(calib_file, nsigma_gain, nsigma_elecnoise,
                             dark_file, nsigma_dark, plot, output)
    print('bad pixels found:', bad_pix)

if __name__ == '__main__':
    entry()


# Condicionales [Python]
# Ejercicios de profundización

# Autor: Inove Coding School
# Version: 2.0

# NOTA:
# Estos ejercicios son de mayor dificultad que los de clase y práctica.
# Están pensados para aquellos con conocimientos previo o que dispongan
# de mucho más tiempo para abordar estos temas por su cuenta.
# Requiere mayor tiempo de dedicación e investigación autodidacta.

# IMPORTANTE: NO borrar los comentarios en VERDE o NARANJA

# Ejercicios de práctica con texto
'''
Enunciado:
Realice un programa que solicite por consola 3 palabras cualesquiera
Luego el programa debe consultar al usuario como quiere ordenar las palabras
1 - Ordenar por orden alfabético (usando el operador ">")
2 - Ordenar por cantidad de letras (longitud de la palabra (len) y operador ">")

Si se ingresa "1" por consola se deben ordenar las 3 palabras por orden alfabético
e imprimir en pantalla de la mayor a la menor

Si se ingresa "2" por consola se deben ordenar las 3 palabras por cantidad de letras
e imprimir en pantalla de la mayor a la menor

IMPORTANTE: Para ordenar las palabras deben realizar condicionales compuestos o anidados,
no se busca utilizar bucles o algoritmos de ordenamiento ya que aún no hemos llegado a ese
contenido.
'''

print('Ejercicios de práctica con cadenas')
# Empezar aquí la resolución del ejercicio

# Palabras

palabra_1 = str(input('Ingrese la primera palabra:\n'))

palabra_2 = str(input('Ingrese la segunda palabra:\n'))

palabra_3 = str(input('Ingrese la tercera palabra:\n'))

# Tipo de orden alfabetico

orden = int(input('Ingrese 1 si quiere ordenar las palabras alfabeticamente o 2 si quiere que se orden por cantidad de letras:\n'))

if orden == 1:
    if palabra_1 > palabra_2 and palabra_1 > palabra_3:
        if palabra_2 > palabra_3:
            print(palabra_1, palabra_2, palabra_3)
        else:
            print(palabra_1, palabra_3, palabra_2)

    elif palabra_2 > palabra_1 and palabra_2 > palabra_3:
        if palabra_1 > palabra_3:
            print(palabra_2, palabra_1, palabra_3)
        else:
            print(palabra_2, palabra_3, palabra_1)

    elif palabra_3 > palabra_1 and palabra_3 > palabra_2:
        if palabra_1 > palabra_2:
            print(palabra_3, palabra_1, palabra_2)
        else:
            print(palabra_3, palabra_2, palabra_1)

# Tipo de orden por cantidad

if orden == 2:
    if len(palabra_1) > len(palabra_2) and len(palabra_1) > len(palabra_3):
        if len(palabra_2) > len(palabra_3):
            print(palabra_1, palabra_2, palabra_3)
        else:
            print(palabra_1, palabra_3, palabra_2)

    elif len(palabra_2) > len(palabra_1) and len(palabra_2) > len(palabra_3):
        if len(palabra_1) > len(palabra_3):
            print(palabra_2, palabra_1, palabra_3)
        else:
            print(palabra_2, palabra_3, palabra_1)

    elif len(palabra_3) > len(palabra_1) and len(palabra_3) > len(palabra_2):
        if len(palabra_1) > len(palabra_2):
            print(palabra_3, palabra_1, palabra_2)
        else:
            print(palabra_3, palabra_2, palabra_1)


"""Abrir uma imagem colorida, transformar em tom de cinza,
visualizar imagem de entrada.
Apliquem uma limiarização (thresholding),
visualizem os resultados e salvem.
Obs: busquem compreender os resultados da técnica."""

import cv2

imagem = cv2.imread('flor.jpg')

imagem_cinza = cv2.cvtColor(imagem, cv2.COLOR_BGR2GRAY)

# Applicando o threshold
ret, threshold_imagem = cv2.threshold(imagem_cinza, 70, 255, cv2.THRESH_BINARY)

# Show the input image
cv2.imshow('Input grayscale image', imagem_cinza)

# Show the result of the threshold
cv2.imshow('Canny filter result', threshold_imagem)

cv2.waitKey(0)

# Save the results
cv2.imwrite('canny_filter_result.jpg', threshold_imagem)


pessoas = {
    'nome': [],
    'ano': [],
    'sexo': []
}
i = 0
while True:
    nome = input('Digite seu nome: ')
    ano = int(input('Digite seu ano de nascimento: '))
    sexo = input('Digite seu sexo[Masculino/Feminino]: ')
    sexo = sexo.lower()
    pessoas['nome'].append(nome)
    pessoas['ano'].append(ano)
    pessoas['sexo'].append(sexo)
    i += 1
    sair = input('Deseja parar de cadastrar?[S/N]:\n>>>')
    sair = sair.upper()
    if (sair == 'S'):
        print('Parando de cadastrar...')
        break

print('Total de pessoas cadastradas: {}'.format(i))
indice = 0
soma_idade = 0
print('Mulheres com menos de 30 anos:')
for n in pessoas['ano']:
    idade = 2023 - pessoas['ano'][indice]
    if (idade < 30 and pessoas['sexo'][indice] == 'feminino'):
        print(' - Nome: {}'.format(pessoas['nome'][indice]))
    soma_idade += idade
    indice += 1
media = soma_idade / i
indice = 0
print('A média de idade das pessoas é: {}'.format(media))
print('Homens com idade acima da média:')
for n in pessoas['ano']:
    idade = 2023 - pessoas['ano'][indice]
    if (idade > media and pessoas['sexo'][indice] == 'masculino'):
        print(' - Nome: {}'.format(pessoas['nome'][indice]))
    indice += 1


import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"]='2'

def linear_regression():
    # 实现线性回归
    # 1.创建数据，x特征值[1,100], y目标值[100]
    x = tf.random_normal(shape=(100,1),mean=1.75,stddev=0.5,name='x_data')
    y_true = tf.matmul(x,[[0.7]])+ 0.8
    # 2 建立线性模型 --y=kx+b
    # x [100,1] * [1,1] , y[100]
    # y = wx +b,w[1,1],b[1,1]
    # 训练模型参数必须使用tf.Variable
    # 随机初始化W1和b1,然后计算损失，在当前y_true下进行优化
    weight = tf.Variable(initial_value=tf.random_normal([1,1]),name='w') # 标准正太分布初始化权重
    bias = tf.Variable(initial_value=tf.random_normal([1,1]),name='b')
    y_predict = tf.matmul(x,weight)+bias
    # 3 确定损失函数（预测值与真实值之间的误差）-均方误差
    loss = tf.reduce_mean(tf.square(y_true-y_predict))
    # 4.梯度下降优化损失
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1,).minimize(loss)
    # 初始化变量
    init = tf.global_variables_initializer()
    # 实例化保存模型加载模型对象
    saver = tf.train.Saver()
    # 收集需要观察的变量
    tf.summary.scalar('losses',loss)  # scalar收集标量信息
    tf.summary.histogram('weight',weight)
    tf.summary.histogram('bias',bias) # 收集直方图信息
    # 合并tensor
    merge = tf.summary.merge_all()
    # 通过会话运行程序
    with tf.Session() as sess:
        sess.run(init)
        # 打印初始化的变量值
        print('初始化权重为%lf,偏置为%lf' % (weight.eval(),bias.eval()))
        print('训练前损失为',loss)
        # 将整张图写入文件
        file_writer = tf.summary.FileWriter('./temp/summary/linearmodel_2',graph=sess.graph)
        # 保存模型
        checkpoint = tf.train.latest_checkpoint('./temp/ckpt/test_2/mymodel.ckpt')
        if checkpoint is not None:
            saver.restore(sess,checkpoint)
        # if os.path.exists('./temp/ckpt/test_2/mymodel.ckpt'):
        #     saver.restore(sess, './temp/ckpt/test_2/mymodel.ckpt')
        # 训练模型
        for i in range(1,101):
            sess.run(optimizer)
            print("第%d步的误差为%f，权重为%f， 偏置为%f" % (i, loss.eval(), weight.eval(), bias.eval()))
            # 运行观察tensor结果
            summary = sess.run(merge)
            file_writer.add_summary(summary,i) # 观察第i步结果
            saver.save(sess,'./temp/ckpt/test_2/mymodel.ckpt')
if __name__ =='__main__':
    linear_regression()


# Este programa mostra uma imagem de um astronauta na matriz LED do SenseHat

# importar a biblioteca do SenseHat
from sense_hat import SenseHat

# Inicializar o SenseHat e a rotação dos sensores
sense = SenseHat()
sense.set_rotation(270)

# definir cores
w = (255, 255, 255)
b = (0, 0, 0)
g = (50,50,50)
s = (200,255,200)
r = (255,0,0)

# imagem a desenhar (8x8)
imagem = [
    g, b, b, b, b, b, b, g,
    b, g, g, g, g, g, g, b,
    b, g, b, b, g, w, g, g,
    b, g, b, b, g, g, g, g,
    b, g, g, g, s, s, g, g,
    b, g, r, g, g, g, g, g,
    b, g, g, g, g, g, g, b,
    g, b, b, b, b, b, b, g
    ]

# desenhar a imagem
sense.set_pixels(imagem)

correr = True

while correr:
    # deteta movimento no joystick
    for event in sense.stick.get_events():
        # limpa a matrix do senseHat e sai do loop
        sense.clear()
        correr = False


# Finality

import math

def to_decimal(snafu):
    if len(snafu) == 1:
        return {
            '=': -2,
            '-': -1,
            '0': 0,
            '1': 1,
            '2': 2
        }[snafu]

    decimal = 0
    for i, l in enumerate(reversed(snafu)):
        decimal += pow(5, i)*to_decimal(l)
    return decimal

def to_snafu(decimal):
    max_len = math.ceil(math.log(decimal, 5))
    snafu = list('2'*max_len)
    for i, l in enumerate(snafu):
        for snaf in ['1','0','-','=']:
            new_snafu = snafu.copy()
            new_snafu[i] = snaf
            if to_decimal(new_snafu) >= decimal:
                snafu = new_snafu
    if(to_decimal(''.join(snafu)) != decimal):
        print("Error, snafu is ", ''.join(snafu), '(', to_decimal(''.join(snafu)), ')', " decimal is ", decimal)
        exit(-1)
    return ''.join(snafu)

def start(line, lines):
    sum = 0
    for l in lines:
        sum += to_decimal(l)
    print(to_snafu(sum))


import pandas as pd
import numpy as np

#Inizializzo i dataframe per il totale non definitivo
df_young_rank_pergusa_final = pd.DataFrame(columns=['Full Name', 'Category', 'Club', 'Pts Pergusa'])
df_young_rank_marinadimodica_final = pd.DataFrame(columns=['Full Name', 'Category', 'Club', 'Pts Marina di Modica'])
df_young_rank_cefalu_final = pd.DataFrame(columns=['Full Name', 'Category', 'Club', 'Pts Cefalù'])
df_young_rank_augusta_final = pd.DataFrame(columns=['Full Name', 'Category', 'Club', 'Pts Augusta'])
df_young_rank_catania_final = pd.DataFrame(columns=['Full Name', 'Category', 'Club', 'Pts Catania'])

#importo il file dei punti
df_points = pd.read_excel('pointsyoung.xlsx')

#Importo i file delle singole gare per uomini donne e bambini
df_young_results_pergusa = pd.read_excel('resultsyoungPergusa.xlsx')

#Pulisco i dataframe lasciando solo i dati utili alla classifica
df_young_results_pergusa_3field = df_young_results_pergusa[['CatPos', 'Category', 'Club', 'Surname', 'FirstName']].copy()

#Genero la classifica di ogni singola gara per uomini donne bambini
# inner join
df_young_rank_pergusa = pd.merge(df_young_results_pergusa_3field,df_points,on='CatPos',how='left')

df_young_rank_pergusa = df_young_rank_pergusa[['CatPos', 'Category', 'Club', 'Surname', 'FirstName', 'Full']]

#Genero la classifica totale per uomini donne e bambini
df_young_rank_pergusa.insert(0,'Full Name', df_young_rank_pergusa['Surname'] + ' ' + df_young_rank_pergusa['FirstName'])

df_young_rank_pergusa_final = df_young_rank_pergusa.drop(['Surname', 'FirstName'], 1)

#Cambio il nome delle colonne
df_young_rank_pergusa_final.columns = ['Full Name', 'CatPos', 'Category', 'Club', 'Pts Pergusa']

#Genero dataframe con nome e punteggio totale ordinato per punteggio

df_young_rank_total = df_young_rank_pergusa_final.merge(df_young_rank_marinadimodica_final, on=['Full Name', 'Category', 'Club'], how='outer').merge(df_young_rank_cefalu_final, on=['Full Name', 'Category', 'Club'], how='outer').merge(df_young_rank_augusta_final, on=['Full Name', 'Category', 'Club'], how='outer').merge(df_young_rank_catania_final, on=['Full Name', 'Category', 'Club'], how='outer').fillna(0)

df_young_rank_total.insert(9, 'Total', df_young_rank_total['Pts Pergusa'] + df_young_rank_total['Pts Marina di Modica'] + df_young_rank_total['Pts Cefalù'] + df_young_rank_total['Pts Augusta'] + df_young_rank_total['Pts Catania'])

#Ordino per punteggio finale
df_young_rank_total = df_young_rank_total.sort_values(['Category', 'Total'], ascending=[False, False])

#Salvo in file
#print(df_young_rank_pergusa_final)
#print(df_woman_rank_pergusa_final)
print(df_young_rank_total)

df_young_rank_total.to_excel('TotalRankYoung.xlsx', index=True)


from urllib.parse import urlparse

import requests
from bs4 import BeautifulSoup

def extract_name(url):
    parsing_result = urlparse(url)
    return f'{parsing_result[0]}://{parsing_result[1]}'.lower()

def parse_site(url):
    page_data = {}
    try:
        r = requests.get(url.name)
    except requests.exceptions.RequestException:
        return page_data
    else:
        soup = BeautifulSoup(r.text, 'html.parser')
        page_data['status_code'] = r.status_code
        page_data['title'] = soup.select_one('title')
        page_data['h1'] = soup.select_one('h1')
        page_data['description'] = soup.select_one('meta[name="description"]')
    return page_data


import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
import pickle

data = pd.read_csv("spam.csv", encoding="latin-1")#reading dataset

#Dataframe includes 3 unwanted columns Unnamed:2, Unnamed:3, Unnamed:4
data.drop(['Unnamed: 2', 'Unnamed: 3', 'Unnamed: 4'], axis=1, inplace=True)

#Since in the df, spam and ham are non numerical values, need to map spam and ham to 1 and 0 respectively
data['class']=data['class'].map({'ham':0, 'spam':1})#mapping func

#The messages must be represented as a numerical structure, use a count vectorizer to convert from text to numbers
cvectorizer = CountVectorizer()

X = data['message']
Y=data['class']

X = cvectorizer.fit_transform(X)
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.2)

#use a naive bayes classifier
NBmodel = MultinomialNB()
NBmodel.fit(x_train, y_train)

print(NBmodel.score(x_test, y_test)) #accuracy is approx. 98%

#save current model into pickle format
pickle.dump(NBmodel, open("spam.pkl", "wb"))
pickle.dump(cvectorizer, open("vectorizer.pkl", "wb"))

#test model using string
message = input("Enter your mail here: ")

def is_spam(message):
    data = [message]
    vector = cvectorizer.transform(data).toarray()#saved into vector format
    result = NBmodel.predict(vector)
    if(result==1):
        result="The mail is spam"
    else:
        result = "The mail is not spam"
    print(result)

is_spam(message)


# --------------------------------------------------------
# SSD @ Dragon
# Copyright(c) 2017 SeetaTech
# Written by Ting Pan
# --------------------------------------------------------

from config import cfg
from .cpu_nms import cpu_nms

def nms(dets, thresh, force_cpu=False):
    if dets.shape[0] == 0:
        return []
    if cfg.USE_GPU_NMS and not force_cpu:
        raise NotImplementedError('gpu_nms is not implemented.')
    else: return cpu_nms(dets, thresh)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ABOUT THIS SCRIPT:

Export Scribus Colors to CSV

color2csv.py allows a user to export  the colors of a given scribus document in a csv file. The file will be a text file with comma separated values in the following format:
"colorname", c,m,y,k

If there is a document opened in scribus, color2csv uses this document as color source.
If there is no document opened in scribus, color2csv displays a file open dialog to allow the user to chose a scribus file to get the colors from.

Use csv2color to import the colors into a scribus document from a csv file.

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

LICENSE:

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Author: Sebastian Stetter

please report bugs to: scribusscript@sebastianstetter.de
"""
from __future__ import division
import sys

__version__=1.0

try:
    # Please do not use 'from scribus import *' . If you must use a 'from import',
    # Do so _after_ the 'import scribus' and only import the names you need, such
    # as commonly used constants.
    import scribus
except ImportError as err:
    print ("This Python script is written for the Scribus scripting interface.")
    print ("It can only be run from within Scribus.")
    sys.exit(1)

#########################
# YOUR IMPORTS GO HERE  #
#########################
import csv
import os
#define some variables

def getColorsFromDoc():
    """returns a list ("name", c,y,m,k)
    get all the colors of that doc. """
    #get a list of al the colornames
    scribus.statusMessage("Reading Colors...")

    try:
        colorlist = scribus.getColorNames()
        scribus.progressTotal(len(colorlist))
        i=0
        colordata=[]
        for color in colorlist:
            colorvalues=scribus.getColor(color)
            c=int(colorvalues[0]/2.55) #convert values from 0-255 to 0-100
            m=int(colorvalues[1]/2.55)
            y=int(colorvalues[2]/2.55)
            k=int(colorvalues[3]/2.55)
            name=color.strip() #eliminate leading and tailing whitespace
            cd = [name,c ,m,y,k]
            colordata.append(cd)
            i=i+1
            scribus.progressSet(i)

        return colordata
    except:
        scribus.messageBox("color2csv", "Can not retrieve colors - There is no Document", icon=scribus.ICON_WARNING)
        sys.exit()

def writeColorCsvFile(filename, colorlist):
    """writes all the colors to a csv file"""
    scribus.statusMessage("Writing colors to csv file...")
    scribus.progressTotal(len(colorlist))
    i=0
    try:
        csvwriter=csv.writer(open(filename, "w"), quoting=csv.QUOTE_NONNUMERIC)
        for line in colorlist:
            csvwriter.writerow(line)
            i=i+1
            scribus.progressSet(i)
    except:
        scribus.messageBox("color2csv", "Could not write file!", icon=scribus.ICON_WARNING)
        sys.exit()

def main(argv):
    """Main method - here we check if we have a doc - else we open one. we get all the colors and write them to a csv file."""
    if scribus.haveDoc() > 0:  #DOC OPEN
    #get colors, get filename, write stuff
        cols = getColorsFromDoc()
        filename = scribus.fileDialog("color2csv: Save csv color file", defaultname="colors.csv",  issave=True ,  haspreview=False)

        #@TODO: optimize path checking
        if filename !="":
            if os.path.exists(filename): #make sure we don't accidentally overwrite existing files
                answer= scribus.messageBox("color2csv", "File already exists! \n do you want to overwrite it?",  icon=scribus.ICON_WARNING,  button1=scribus.BUTTON_YES,  button2=scribus.BUTTON_ABORT)
                if answer == scribus.BUTTON_YES:
                    writeColorCsvFile(filename,  cols)
                else:
                    sys.exit()
            else:
                writeColorCsvFile(filename,  cols)
        else:
            sys.exit()
    else: # NO DOC OPEN - open one!
        scribusfile = scribus.fileDialog("color2csv: Open scribus file",  "Scribus files(*.sla *.SLA *.sla.gz *.SLA.GZ)")
        if scribusfile !="":
            try:
                scribus.openDoc(scribusfile)
            except:
                scribus.messageBox("color2csv", "Could not open file!")
                sys.exit()
            #get colors, get filename, write stuff
            cols = getColorsFromDoc()
            filename = scribus.fileDialog("color2csv: Save csv color file", defaultname="colors.csv",  issave=True )
            writeColorCsvFile(filename,  cols)
        else:
            sys.exit()

def main_wrapper(argv):
    """The main_wrapper() function disables redrawing, sets a sensible generic
    status bar message, and optionally sets up the progress bar. It then runs
    the main() function. Once everything finishes it cleans up after the main()
    function, making sure everything is sane before the script terminates."""
    try:
        #scribus.statusMessage("Running script...")
        #scribus.progressReset()
        main(argv)
    finally:
        # Exit neatly even if the script terminated with an exception,
        # so we leave the progress bar and status bar blank and make sure
        # drawing is enabled.
        if scribus.haveDoc():
            scribus.setRedraw(True)
        scribus.statusMessage("")
        scribus.progressReset()

# This code detects if the script is being run as a script, or imported as a module.
# It only runs main() if being run as a script. This permits you to import your script
# and control it manually for debugging.
if __name__ == '__main__':
    main_wrapper(sys.argv)