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

import os
import math
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import scipy.interpolate as interpolate
from skimage import restoration
from PIL import Image
from pylab import *
from sklearn.mixture import BayesianGaussianMixture
import time
import matplotlib as mpl
from scipy import linalg
import itertools

dir = 'Testoversize'                # data directory
multithreshold = 0.25
PSFsize = 200
deconiter = 200

def COGcut(inputdata, cutratio):
    COGdata = inputdata.copy()
    COGx = 0
    COGy = 0
    tot = 0
    COGdata /= np.nanmax(COGdata)
    ver, hor = COGdata.shape
    for j in range(ver):
        for k in range(hor):
            if np.isnan(COGdata[j,k]) == False and COGdata[j,k] > cutratio:
                COGx += COGdata[j,k] * k
                COGy += COGdata[j,k] * j
                tot += COGdata[j,k]
    COGx /= tot
    COGy /= tot
    return COGx, COGy

def plot_results(X, Y_, means, covariances, index, title):
    #splot = plt.subplot(2, 1, 1 + index)
    for i, (mean, covar, color) in enumerate(zip(
            means, covariances, color_iter)):
        #v, w = linalg.eigh(covar)
        #print(v, w)
        v = [covar, covar]
        w = [[1,0],[0,1]]
        v = 2. * np.sqrt(2.) * np.sqrt(v)
        u = w[0] / linalg.norm(w[0])
        # as the DP will not use every component it has access to
        # unless it needs it, we shouldn't plot the redundant
        # components.
        if not np.any(Y_ == i):
            continue
        plt.scatter(X[Y_ == i, 0], X[Y_ == i, 1], .8, color=color,alpha=0.1)

    #plt.xlim(-9., 5.)
    #plt.ylim(-3., 6.)
    #plt.xticks(())
    #plt.yticks(())
    plt.title(title)

# PandaX parameters & initialization
dataInProcess = []
dataoversize = []
datafailed = []
dataasymmetric = []

grid_x, grid_y = np.mgrid[-600:600:1, -600:600:1]
grid_x_mirror, grid_y_mirror = np.mgrid[200:1000:1, -400:400:1]

color_iter = itertools.cycle(['navy', 'c', 'cornflowerblue', 'gold',
                              'darkorange'])

# input data
for file in os.listdir(path = dir):
    dataInProcess.append(file)
for i in range(len(dataInProcess)):
#for i in range(1,2):
    processstarttime = time.time()
    print(dataInProcess[i])
    euler = np.array([[1,0],[0,1]])
    eventtype = ''

    data = pd.read_table(dir + '/' + dataInProcess[i], header = None, names = ['PMTID','x','y','Intensity'])
    zdata = data.iloc[-2,0]
    xCOG = eval(data.iloc[-8,0].split(" = ")[1])
    yCOG = eval(data.iloc[-7,0].split(" = ")[1])
    xTMs = eval(data.iloc[-6,0].split(" = ")[1])
    yTMs = eval(data.iloc[-5,0].split(" = ")[1])
    xPAF = eval(data.iloc[-4,0].split(" = ")[1])
    yPAF = eval(data.iloc[-3,0].split(" = ")[1])
    data = data.dropna()            # Last 8 rows are not raw data, and contain NaNs

    x = data['x'].values.tolist()
    y = data['y'].values.tolist()
    coord = data.loc[:,['x','y']].values.tolist()
    intens = data['Intensity'].values.tolist()

# interpolation
    interp = interpolate.griddata(coord, intens, (grid_x, grid_y), method='cubic')
    interp = interp.T

# preprocess
    preprocess = interp.copy()
    preprocess = np.where(np.isnan(preprocess), 1e-9, preprocess)
    preprocess = np.where(preprocess <= 0, 1e-9, preprocess)        # clear out nan/0/negatives

# estimate approximate position: COG/max
    intensmaxloc = np.nanargmax(preprocess)
    height, width = preprocess.shape
    maxlocy = int(intensmaxloc / height) - 600
    maxlocx = intensmaxloc % height - 600
    #print("max:", maxlocx, maxlocy)
    if maxlocx ** 2 + maxlocy ** 2 < 550 ** 2:
        COGdataslice = preprocess[max(0, maxlocy + 600 - 300) : min(1200, maxlocy + 600 + 300 + 1), max(0, maxlocx + 600 - 300) : min(1200, maxlocx + 600 + 300 + 1)]
        appx, appy = COGcut(COGdataslice, 0.1)

        appx = int(appx)
        appy = int(appy)
        appy += max(0, maxlocy + 600 - 300)
        appy -= 600
        appx += max(0, maxlocx + 600 - 300)
        appx -= 600
        print("approximate:", appx, appy)
        if appx ** 2 + appy ** 2 < 450 ** 2:
            eventtype = 'central'
        else:
            eventtype = 'margin'
    else:
        appx = maxlocx
        appy = maxlocy
        eventtype = 'oversized'
        dataoversize.append(dataInProcess[i])
        '''
        print("Event in " + dataInProcess[i] + " seemed to occur somewhere between the center of the farthest PMT and the wall. No algorithm found valid for this type of event yet. You can refer to x = " + str(appx) +", y = " + str(appy) + ", however, for a single oversized event, by 3 cm radial error\n")

        #visualization skipped
        processendtime = time.time()
        print(str(i + 1) + " finished! elapsed time: " + str(processendtime - processstarttime))
        continue
    '''
    print(eventtype)

    if eventtype != 'central':
        angle = math.degrees(math.atan2(appy, appx))

        rotated = interp.copy()
        #mirror
        im = Image.fromarray(rotated)
        im = im.rotate(angle)
        im = im.crop((800,200,1200,1000))
        im_flipped = im.transpose(Image.FLIP_LEFT_RIGHT)
        im = array(im)
        im_flipped = array(im_flipped)

        rotated = np.append(im, im_flipped, axis = 1)
        coord_mirror = []
        intens_mirror = []
        for j in range(-400,400):
            for k in range(200,1000):
                if np.isnan(rotated[j + 400,k - 200]) == False and rotated[j + 400,k - 200] > 10:
                    coord_mirror.append([j,k])
                    intens_mirror.append(rotated[j + 400,k - 200])
        #interpolation
        interp_mirror = interpolate.griddata(coord_mirror, intens_mirror, (grid_y_mirror, grid_x_mirror), method='linear')
        interp_mirror = interp_mirror.T

        preprocess = interp_mirror.copy()
        preprocess = np.where(np.isnan(preprocess), 1e-9, preprocess)
        preprocess = np.where(preprocess <= 0, 1e-9, preprocess)

# clustering on intensity image, estimates event center location
    dots = np.empty([0,2])
    pointweight = preprocess / np.max(preprocess) * 2

    if eventtype == 'central':
        for j in range(max(0, appy + 600 - 200), min(1200, appy + 600 + 200 + 1)):
            for k in range(max(0, appx + 600 - 200), min(1200, appx + 600 + 200 + 1)):
                if pointweight[j,k] >= 1:
                    dots = np.append(dots, np.tile(np.array([k - 600, j - 600]), (int(pointweight[j,k]), 1)), axis = 0)
        #print(dots[-1:])

        eventnum = 2
        weights = 0
        while eventnum > 0 and np.any(weights < multithreshold):
            dpgmm = BayesianGaussianMixture(n_components=eventnum, covariance_type='spherical', max_iter = 10000,weight_concentration_prior_type='dirichlet_distribution', weight_concentration_prior=1e-3).fit(dots)
            weights = dpgmm.weights_
            print(weights)
            eventnum -= 1

        eventnum += 1
        means = np.swapaxes(dpgmm.means_, 0, 1)

    else:
        for j in range(800):
            for k in range(800):
                if pointweight[j,k] >= 1:
                    dots = np.append(dots, np.tile(np.array([k + 200, j - 400]), (int(pointweight[j,k]), 1)), axis = 0)
            #print(dots[-1:])

        eventnum = 2
        weights = 0
        while eventnum > 0 and np.any(weights < multithreshold / 2):
            dpgmm = BayesianGaussianMixture(n_components=eventnum*2, covariance_type='spherical', n_init=10, max_iter = 10000,weight_concentration_prior_type='dirichlet_distribution', weight_concentration_prior=1e-3).fit(dots)
            weights = dpgmm.weights_
            print(weights)
            eventnum -= 1

        eventnum += 1
        means = dpgmm.means_

        '''
        bgm = BayesianGaussianMixture(n_components=eventnum*2, random_state=0, covariance_type='spherical', max_iter = 2000).fit(dots)
        #bgm = BayesianGaussianMixture(n_components=eventnum*2, random_state=0, max_iter = 2000).fit(dots)
        means = bgm.means_
        weights = bgm.weights_
        #print(means, weights)
        '''
        dellist = []
        for j in range(len(weights)):
            if means[j, 0] ** 2 + means[j, 1] ** 2 > 600 ** 2:
                dellist.append(j)
        means = np.delete(means, dellist, axis = 0)
        weights = np.delete(weights, dellist)
        weights *= 2
        means = np.swapaxes(means, 0, 1)
        meansinmirror = means.copy()

        #rotate to original frame
        angle = math.radians(angle)
        euler = np.array([[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]])
        means = np.dot(euler, means)

    resultsangle = 0
    if len(weights) != eventnum:
        print("===It seems that a margin event was clustered with asymmetric result.===")

    #bgm = BayesianGaussianMixture(n_components=2, random_state=0, covariance_type='spherical', max_iter = 2000).fit(dots)

# visualization
    #plt.gcf().set_size_inches(6, 12)
    fig = plt.figure(figsize=(16,5.5),dpi=300)
    ax2 = fig.add_subplot(1,3,2)

    plt.subplot(1,3,1)
    plt.imshow(interp, extent=(-600, 600, -600, 600), origin = 'lower', cmap = 'Blues')
    plt.colorbar()

    plt.scatter(x, y, s = 20, alpha = 0.8, c = [intens], cmap = 'gist_heat', label = 'Raw PMT intensity')

    plt.legend(loc = "lower left")
    plt.xlabel('x (mm)')
    plt.ylabel('y (mm)')
    plt.title('Interpolated Intensity')

    plt.text(x = 0, y = -800, s = zdata, ha = 'center')

    plt.subplot(1,3,2)
    textstr = 'BGMMweight:\n' + str(dpgmm.weights_)
    plt.text(0.05,0.9,textstr,size=10,transform=ax2.transAxes,bbox=dict(boxstyle="round",alpha=0.6,ec=(0.5,0.5,1.),fc=(0.8,0.8,1.)))

    if eventtype == 'central':
        plot_results(dots, dpgmm.predict(dots), dpgmm.means_, dpgmm.covariances_, 1,'Bayesian Gaussian Mixture with a Dirichlet process prior')
        plt.imshow(interp[appy + 600 - 200 : appy + 600 + 200, appx + 600 - 200 : appx + 600 + 200], extent=(appx - 200, appx + 200, appy - 200, appy + 200), origin = 'lower', cmap = 'Blues' )
    else:
        plot_results(dots, dpgmm.predict(dots), dpgmm.means_, dpgmm.covariances_, 1,'Bayesian Gaussian Mixture with a Dirichlet process prior')
        plt.imshow(interp_mirror, extent=(200, 1000, -400, 400), origin = 'lower', cmap = 'Blues' )

    # comparison with other algorithms
    ud = [appy + 600 - 200 , appy + 600 + 200]
    lr = [appx + 600 - 200 , appx + 600 + 200]
    if ud[0] < 0:
        ud = [0, 400]
    if ud[1] > 1200:
        ud = [800, 1200]
    if lr[0] < 0:
        lr = [0, 400]
    if lr[1] > 1200:
        lr = [800, 1200]

    plt.subplot(1,3,3)
    plt.scatter(x, y, s = 400, alpha = 0.8, c = [intens], cmap = 'gist_heat')
    plt.scatter(x = xCOG, y = yCOG, s = 150, alpha = 0.6, edgecolors = 'black', marker = '^', label = 'COG')
    plt.scatter(x = xTMs, y = yTMs, s = 150, alpha = 0.6, edgecolors = 'black', marker = 'o', label = 'TMs')
    plt.scatter(x = xPAF, y = yPAF, s = 150, alpha = 0.6, edgecolors = 'black', marker = 's', label = 'PAF')
    plt.scatter(means[0], means[1], s = 300 * weights, alpha = 0.6, edgecolors = 'orange', marker = 'X', label = 'BGMM')
    #plt.scatter(x = RLCOGx, y = RLCOGy, s = 150, alpha = 0.6, edgecolors = 'black', marker = '*', label = 'RL')
    plt.legend(loc = "lower left")
    plt.xlabel('x (mm)')
    plt.ylabel('y (mm)')
    plt.title('Comparison with Other Algorithms')
    plt.imshow(interp[ud[0] : ud[1], lr[0] : lr[1]], extent=(lr[0] - 600, lr[1] - 600, ud[0] - 600, ud[1] - 600), origin = 'lower', cmap = 'Blues')

    plt.suptitle('File Name:' + dataInProcess[i] + '\nEvent Type: ' + eventtype + '    ' + str(eventnum) + ' event(s) occured')

    plt.show()
    # Save plot. Requires folder "result" before running. Replaces '.txt' in output file name.
    #plt.savefig('result/multivalidity/' + dataInProcess[i][:-4] + '.png')

    plt.clf()

    # Save deconvoluted image in values
    #result = pd.DataFrame(decon)
    #result.to_csv("result.csv", index=False)

    processendtime = time.time()
    print(str(i + 1) + " finished! elapsed time: " + str(processendtime - processstarttime))

print("all finished!\nOversize events:\n" + '\n'.join(dataoversize) + "\nAsymmetric clusters:\n" + '\n'.join(dataasymmetric))


import asyncio
from typing import Any, Dict, List, Optional, TYPE_CHECKING
import random

from bot.сhain_responsibility.receivers.mixins import KeyboardMixin, MenuMixins
from bot.сhain_responsibility.receivers.receivers import ButtonReceiverAbstract
from bot_long_poll.dcs import Update
from vk_api.dcs import Message

if TYPE_CHECKING:
    from bot.state.state import State
    from store.quiz.models import QuestionModel
    from store.quiz.models import AnswerModel
    from store.game.models import GameModel
    from store.player.models import PlayerModel
    from store.player.models import Score

class GuessLetterCommandButtonReceiver(MenuMixins, KeyboardMixin, ButtonReceiverAbstract):
    def __init__(self, update: Update, state: "State"):
        super().__init__(update, state)
        self.answer: Optional["AnswerModel"] = None
        self.letter: str = ""
        self.result = ""
        self.started_game: Optional["GameModel"] = None
        self.question: Optional["QuestionModel"] = None
        self.score: Optional["Score"] = None
        self.word: List[Optional[str]] = []
        self.correct_answer_score: int = 0

    def set_buttons(self):
        if self.result == self.answer:
            self.buttons = self.get_menu()
        elif self.letter in self.answer.title:
            self.buttons = self.get_keyboard()

    async def execute(self) -> Optional[Dict[str, Any]]:
        self.started_game = await self.game_accessor.get_started_game_by_player(self.update)
        self.score = await self.player_accessor.get_score(self.started_game.id, self.update.from_id)
        self.who_next = self.started_game.who_next
        if self.update.from_id != self.who_next[0]:
            self.message = "Не Ваша очередь"
            return await self.send_message(self.update.from_id)
        self.question: "QuestionModel" = self.started_game.question
        self.letter: str = self.update.text
        self.answer: "AnswerModel" = self.question.answer
        if self.started_game:
            if self.letter in self.started_game.word:
                await self.send_unsuccessful_message()
            else:
                self.word = [letter for letter in self.started_game.word]
                indexes = self.find_indexes()
                if indexes:
                    self.refresh_result(indexes)
                    if self.result == self.answer.title:
                        await self.stop_game_player_won()
                    else:
                        await self.send_successful_message()
                else:
                    await self.send_unsuccessful_message()
                    await self.game_accessor.update_game_instance(self.started_game)

    async def stop_game_player_won(self):
        self.started_game.state = "Stoped"
        await asyncio.gather(
            self.send_winner_message(),
            self.game_accessor.update_game_instance(self.started_game))

    async def send_successful_message(self):
        self.set_buttons()
        self.correct_answer_score = random.randint(1, 100)
        self.score.score += self.correct_answer_score
        msgs = self.get_successful_messages()
        await asyncio.gather(
            self.player_accessor.update_score_instanse(self.score),
            self.send_messages(msgs),
            self.game_accessor.update_game_instance(self.started_game))

    def refresh_result(self, indexes):
        for index in indexes:
            self.word[index] = self.letter
        self.result = "".join(self.word)
        self.started_game.word = self.result

    def get_player(self, vk_id) -> "PlayerModel":
        for player in self.started_game.players:
            if player.vk_id == vk_id:
                return player

    async def send_winner_message(self):
        player = self.get_player(self.update.from_id)
        text = f"Победу одержал(а): {player.first_name} {player.last_name}\n Ответ: {self.answer.title}"
        msgs = [Message(vk_api, text, self.get_menu()) for vk_api in self.who_next]
        self.started_game.who_next = []
        await self.send_messages(msgs)

    def get_successful_messages(self):
        text = f"Буква {self.letter} в слове присутствует.\
                \nЗа правильный ответ начислено баллов: {self.correct_answer_score}\
                \nВсего баллов: {self.score.score}\
                \nСлово: {self.started_game.word}\
                \nВаш следующий ход."
        player = self.get_player(self.update.from_id)
        text2 = f"Текущий ход у игрока: {player.first_name} {player.last_name}\
                 Игрок назавал букву {self.letter}.\
                 \nСлово: {self.started_game.word}"
        msg = Message(self.update.from_id, text, self.buttons)
        msgs = [Message(vk_id, text2, "{}") for vk_id in self.who_next[1:]]
        msgs.append(msg)
        return msgs

    async def send_unsuccessful_message(self):
        self.change_player_queue()
        next_player_vk_id = self.who_next[0]
        next_player = self.get_player(next_player_vk_id)
        text = f"Неверный ответ. Ход переходит к игроку: \
{next_player.first_name} {next_player.last_name}."
        text2 = f"Ваш ход. \nСлово: {self.started_game.word}"
        msg = Message(self.update.from_id, text, "{}")
        msg2 = Message(self.who_next[0], text2, self.get_keyboard())
        await self.send_messages([msg, msg2])

    def change_player_queue(self):
        current_player = self.who_next.pop(0)
        self.who_next.append(current_player)

    def find_indexes(self):
        indexes = []
        index = self.answer.title.find(self.letter)
        while index >= 0:
            indexes.append(index)
            index = self.answer.title.find(self.letter, index+1)
        return indexes

    async def run(self):
        await self.execute()


import argparse
import ast
import os

import librosa
import numpy as np

import paddlehub as hub
from paddlehub.env import MODULE_HOME

parser = argparse.ArgumentParser(__doc__)
parser.add_argument("--wav", type=str, required=True, help="Audio file to infer.")
parser.add_argument("--sr", type=int, default=32000, help="Sample rate of inference audio.")
parser.add_argument("--model_type", type=str, default='panns_cnn14', help="Select model to to inference.")
parser.add_argument("--topk", type=int, default=10, help="Show top k results of audioset labels.")
args = parser.parse_args()

if __name__ == '__main__':
    label_file = os.path.join(MODULE_HOME, args.model_type, 'audioset_labels.txt')
    label_map = {}
    with open(label_file, 'r') as f:
        for i, l in enumerate(f.readlines()):
            label_map[i] = l.strip()

    model = hub.Module(name=args.model_type, version='1.0.0', task=None, label_map=label_map)

    data = [librosa.load(args.wav, sr=args.sr)[0]]  # (t, num_mel_bins)
    result = model.predict(data, sample_rate=args.sr, batch_size=1, feat_type='mel', use_gpu=True)

    msg = f'[{args.wav}]\n'
    for label, score in list(result[0].items())[:args.topk]:
        msg += f'{label}: {score}\n'
    print(msg)


from django.db import models
from .validators import validate_pdf_extension
from .validators import validate_positive_integer
from .validators import validate_credits
from .validators import validate_program_years
from .validators import validate_non_zero
from .validators import validate_days_month
from .validators import validate_years
from .validators import validate_max_hours
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from django.core.validators import RegexValidator

from datetime import datetime, date
import re

class Document(models.Model):
    # Document in PDF format to be uploaded to the page.

    RE_COURSE_CODE_A = '[A-Z]{2}[ \-]?[0-9]{4}'
    RE_COURSE_CODE_B = '[A-Z]{3}[ \-]?[0-9]{3}'

    # The date of the upload.
    date = models.DateTimeField(
        default=datetime.now,
        blank=True,
    )

    # Chosen name of the document.
    name = models.CharField(
        max_length=60,
        blank=True,
    )

    # The uploaded document. Must be in PDF format.
    docfile = models.FileField(
        upload_to='documents/%Y/%m/%d',
        validators=[validate_pdf_extension],
    )

    # HTML textring of the transcript PDF document given.
    html_text_string = models.TextField(
        null=True,
        blank=True,
    )

    # This field is False until the transcription is finished.
    ready_html = models.BooleanField(
        default=False,
    )

    # This field is True while the transcription is in process.
    processing_html = models.BooleanField(
        default=False,
    )

    # The name of the PDF document file.
    file_name = models.TextField(
        default="Error: You Need to get the Filename",
        blank=True,
    )

    # Path containing the PDF document file.
    file_path = models.TextField(
        null=True,
        blank=True,
    )

    # Returns a set of courses codes from an html file
    @staticmethod
    def course_codes(filename):
        html_file = open(filename, 'r')
        file_contents = html_file.read()
        possible_codes_a = re.findall(Document.RE_COURSE_CODE_A ,file_contents)
        possible_codes_b = re.findall(Document.RE_COURSE_CODE_B ,file_contents)
        possible_codes = set(possible_codes_a + possible_codes_b)
        return possible_codes

    # Avoids to mark the trancription as ready and processing at the same time.
    def clean(self):
        if self.ready_html and self.processing_html:
            raise ValidationError('You can\'t be ready when you\'re \
                                                     processing the html.')

    # Saves Document objects into database.
    def save(self, *args, **kwargs):
        self.full_clean()
        return super(Document, self).save(*args, **kwargs)

class Division(models.Model):
    # Divisions are the academic units in charge of the departments.

    # Name of the division.
    name = models.CharField(
        max_length=60,
        primary_key=True,
    )

    # Returns the name of the division.
    def __str__(self):
        return "{}".format(self.name)

class Department(models.Model):
    # Departments are academic units. They usually offer the assignatures.

    # Name of the department.
    name = models.CharField(
        max_length=60,
        primary_key=True,
    )

    # A department should be subscribed to one division.
    division = models.ForeignKey(
        Division,
        on_delete=models.CASCADE,
    )

    # Returns the name of the department.
    def __str__(self):
        return "{}".format(self.name)

class Deanery(models.Model):
    # Deaneries are the academic units in charge of the coordinations.

    # Name of the deanery.
    name = models.CharField(
        max_length=60,
        primary_key=True,
    )

    # Returns the name of the deanery.
    def __str__(self):
        return "{}".format(self.name)

class Coordination(models.Model):
    # Coordinations are academic units. They usually manage study programs.
    # They can offer assignatures in a few cases.

    # Name of the coordination.
    name = models.CharField(
        max_length=60,
        primary_key=True,
    )

    # A coordination can be subscribed to many deaneries.
    deanery = models.ManyToManyField(
        Deanery,
    )

    # Returns the name of the coordination.
    def __str__(self):
        return "{}".format(self.name)

class AdditionalName(models.Model):
    # Additional fields names to be added into programs.

    # Name of the field
    name = models.CharField(
        max_length=30,
        unique=True,
    )

    def __str__(self):
        return "{}".format(self.name)

class AdditionalField(models.Model):
    # Additional field text.

    # Description of the field.
    description = models.TextField(
        null=True,
        blank=True,
    )

    # Name of the field.
    name = models.ForeignKey(
        AdditionalName,
        on_delete=models.CASCADE,
    )

class Code(models.Model):
    # Code.
    code = models.CharField(
        max_length=3,
        primary_key=True,
        verbose_name='Código',
    )
    # A department is responsible for many codes.
    department = models.ForeignKey(
        Department,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
    )

    def __str__(self):
        return "{}".format(self.code)

# Autors of recommended sources.
class Author(models.Model):
    first_name = models.CharField(
        max_length=20,
        verbose_name='Primer nombre',
    )

    second_name = models.CharField(
        max_length=20,
        blank=True,
        verbose_name='Segundo nombre',
    )

    first_surname = models.CharField(
        max_length=20,
        verbose_name='Primer apellido',
    )

    second_surname = models.CharField(
        max_length=20,
        blank=True,
        verbose_name='Segundo apelido',
    )
    def __str__(self):
        return self.first_surname
    class Meta:
        ordering = ['first_surname','first_name']

# Recommended sources.
class Reference(models.Model):
    # Author of the author's book.
    author = models.ManyToManyField(
        Author,
        blank=True,
        verbose_name='Autor',
    )

    # Book's title.
    title = models.TextField(
        verbose_name='Título',
    )

    # Publishing house of the book.
    editorial = models.CharField(
        max_length=30,
        blank=True,
        verbose_name='Editorial',
    )

    # Recommended edition.
    edition_number = models.PositiveIntegerField(
        validators=[validate_non_zero],
        blank=True,
        null=True,
        verbose_name='No. Edición',
    )

    # Recommended year.
    year = models.PositiveIntegerField(
        validators=[validate_years],
        blank=True,
        null=True,
        verbose_name='Año',
    )

    def __str__(self):
        rep = str(self.title)
        if self.edition_number is not None and self.edition_number != "":
             rep += " Edicion Nro. " + str(self.edition_number)
        if self.year is not None and self.year != "":
             rep += " Año " + str(self.year)
        if self.editorial is not None and self.editorial != "":
             rep += " Editorial " + str(self.editorial)
        return "{}".format(rep)

class Program(models.Model):
    # The program of an assignature and all its related data.

    # All posible trimesters, including the summer intensive.
    TRIMESTER = (
        ('0Ene-Mar', 'Enero-Marzo'),
        ('1Abr-Jul', 'Abril-Julio'),
        ('2Jul-Ago', 'Julio-Agosto (Intensivo)'),
        ('3Sep-Dic', 'Septiembre-Diciembre'),
    )
    MONTH = (
        (1, 'Enero'),
        (2, 'Febrero'),
        (3, 'Marzo'),
        (4, 'Abril'),
        (5, 'Mayo'),
        (6, 'Junio'),
        (7, 'Julio'),
        (8, 'Agosto'),
        (9, 'Septiembre'),
        (10, 'Octubre'),
        (11, 'Noviembre'),
        (12, 'Diciembre'),
    )

    # PDF document associated to the program.
    document = models.OneToOneField(
        Document,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
    )

    # The code of the assignature, divided in its department code and a number.
    code = models.ForeignKey(
        Code,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
        verbose_name='Código Departamento',
    )
    number = models.CharField(
        max_length=4,
        blank=True,
        validators=[RegexValidator(regex='^\d{3,4}$',
                    message='Debe estar formado por 3 o 4 dígitos.')],
        verbose_name='Código Número',
    )

    # The suggested code is approved.
    approved_code = models.BooleanField(
        default=False,
    )

    # The name of the assignature.
    denomination = models.CharField(
        blank=True,
        max_length=60,
        verbose_name='Denominación',
    )

    # Date of validity.
    validity_date_y = models.PositiveIntegerField(
        null=True,
        blank=True,
        verbose_name='Año',
        validators=[validate_program_years]
    )
    validity_date_m = models.PositiveIntegerField(
        choices=MONTH,
        blank=True,
        null=True,
        verbose_name='Mes',
    )

    validity_date_d = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name='Día',
        validators=[validate_days_month],
    )

    # Proposed year of validity of the program.
    validity_year = models.PositiveIntegerField(
        null=True,
        blank=True,
        verbose_name='Año propuesto',
        validators=[validate_program_years],
    )

    # Proposed trimester of validity of the program.
    validity_trimester = models.CharField(
        max_length=10,
        choices=TRIMESTER,
        blank=True,
        null=True,
        verbose_name='Trimestre propuesto',
    )

    # Number of hours of theory in the assignature.
    theory_hours = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name='Horas de Teoría',
        validators=[validate_positive_integer, validate_max_hours],
    )

    # Number of hours of practice in the assignature.
    practice_hours = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name='Horas de Práctica',
        validators=[validate_positive_integer, validate_max_hours],
    )

    # Number of hours of laboratory in the assignature.
    laboratory_hours = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name='Horas de Laboratorio',
        validators=[validate_positive_integer, validate_max_hours],
    )

    # Number of crédits in the assignature. Must be a number between 0 and 16.
    credits = models.IntegerField(
        blank=True,
        null=True,
        verbose_name='Unidad de Créditos',
        validators=[validate_credits],
    )

    # Requirements to take the course.
    requirements = models.TextField(
        blank=True,
        null=True,
        verbose_name='Requisitos',
    )

    # General objectives of the assignature.
    objectives = models.TextField(
        blank=True,
        null=True,
        verbose_name='Objetivos Generales',
    )

    # Specific objectives of the assignature.
    specific_objectives = models.TextField(
        blank=True,
        null=True,
        verbose_name='Objetivos Específicos',
    )

    # Synoptic content of the program.
    synoptic_content = models.TextField(
        blank=True,
        null=True,
        verbose_name='Contenidos Sipnóticos',
    )

    # Methodological strategies suggested by the program.
    methodological_strategies = models.TextField(
        blank=True,
        null=True,
       verbose_name='Estrategias Metodológicas',
    )

    # Evaluation strategies suggested by the program.
    evaluation_strategies = models.TextField(
        blank=True,
        null=True,
        verbose_name='Estrategias de Evaluación',
    )

    # Recommended sources of information.
    recommended_sources = models.ManyToManyField(
        Reference,
        blank=True,
    )

    # Departament in charge of the assignature.
    department = models.ForeignKey(
        Department,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
        verbose_name='Departamento',
    )

    # Coordinations in chharge of the program.
    coordination = models.ManyToManyField(
        Coordination,
        blank=True,
        verbose_name='Coordinación',
    )

    # True if the document is ready.
    passes = models.BooleanField(
        default=False,
        verbose_name='Enviar para aprobar',
    )

    # Additional fields.
    additional_fields = models.ManyToManyField(
        AdditionalField,
        blank=True,
    )

    #Checks day, month, year to see if they form a valid date.
    def valid_date(self, d, m, y):
        if (m == None or y == None):
            return True
        try:
            d = date(y, m, d)
            return True
        except ValueError:
            return False

    #Checks if complete.
    def completed(self):
        return (self.code and self.number and self.denomination and \
                self.validity_year and self.validity_trimester and \
                (self.theory_hours or self.practice_hours or \
                self.laboratory_hours) and self.credits and \
                self.requirements and self.objectives and \
                self.synoptic_content and  self.methodological_strategies and \
                self.evaluation_strategies and self.recommended_sources and \
                self.department)

    #Checks that the code is all-righty.
    def right_code(self):
        if self.code:
            if (len(self.number) != 3 and len(self.code.code) == 3):
                return False
            elif (len(self.number) != 4 and len(self.code.code) == 2):
                return False
        return True

    # Checks that the sum of the hours is positive and less than forty.
    def clean(self):
        hours_sum = 0
        if self.theory_hours is not None:
            hours_sum = hours_sum + self.theory_hours
        if self.practice_hours is not None:
            hours_sum = hours_sum + self.practice_hours
        if self.laboratory_hours is not None:
            hours_sum = hours_sum + self.laboratory_hours
        if (hours_sum < 0 or hours_sum > 40) and \
            not (self.theory_hours is None and self.practice_hours is None and self.laboratory_hours is None):
            raise ValidationError('La suma de las horas debe ser no negativa y menor que cuarenta.')
        if not self.valid_date(self.validity_date_d, self.validity_date_m, self.validity_date_y):
            raise ValidationError('La fecha de validación del programa no es una fecha válida.')
        if self.passes and not self.completed():
            raise ValidationError('Faltan campos por ser llenados para pasar el programa.')
        if not self.right_code():
            raise ValidationError('Formato de código incorrecto.')

    # Saves Program objects into the database.
    def save(self, *args, **kwargs):
        self.full_clean()
        return super(Program, self).save(*args, **kwargs)

    # Returns the primary key for the program and the code.
    def __str__(self):
        return '%s %s' % (self.pk, self.code)

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

# Base de datos del repositorio SIGPAE.

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

class Programa(models.Model):
    # Crea una tabla con el programa completo asociado.

    TRIMESTRE = (
        ('0Ene-Mar', 'Enero-Marzo'),
        ('1Abr-Jul', 'Abril-Julio'),
        ('2Jul-Ago', 'Julio-Agosto (Intensivo)'),
        ('3Sep-Dic', 'Septiembre-Diciembre'),
    )

    codigo = models.CharField(
        max_length=6,
        verbose_name='Código',
    )

    #Nombre de la asignatura
    denominacion = models.TextField(
        blank=True,
        verbose_name='Denominación',
    )

    # Cantidad de créditos de la asignatura.
    creditos = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name='Créditos'
    )

    # Numero de horas de teoria de una asignatura.

    h_teoria = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name='Horas de Teoría',
    )

    # Numero de horas de practica de una asignatura.

    h_prac = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name='Horas de Práctica',
    )

    # Numero de horas de laboratorio de una asignatura.

    h_lab = models.PositiveIntegerField(
        blank=True,
        null=True,
        verbose_name='Horas de Laboratorio',
    )

    # Year of validity of the program.

    fecha_vigAno = models.IntegerField(
        null=True,
        blank=True,
        verbose_name='Año',
    )

    # Fecha de vigencia de un trimestre

    fecha_vigTrim = models.CharField(
        blank=True,
        null=True,
        choices=TRIMESTRE,
        max_length=8,
        verbose_name='Fecha Vigencia Trimestre',
    )

    # Objetivo general de la asignatura.
    obj_g = models.TextField(
        blank=True,
        null=True,
        verbose_name='Objetivo general',
    )

    # Objetivos especificos de la asignatura.
    obj_e = models.TextField(
        blank=True,
        null=True,
        verbose_name='Objetivo específico',
    )

    # Contenidos de la asignatura.
    contenidos = models.TextField(
        blank=True,
        null=True,
        verbose_name='Contenidos',
    )

    # Estrategias de la asignatura.
    estrategias = models.TextField(
        blank=True,
        null=True,
        verbose_name='Estrategias',
    )

    # Estrategias evaluativas de la asignatura.
    estrat_eval = models.TextField(
        blank=True,
        null=True,
        verbose_name='Estrategias evaluativas',
    )

    # Fuentes de la asignatura.
    fuentes = models.TextField(
        blank=True,
        null=True,
        verbose_name='Fuentes',
    )

    # Cronograma de la asignatura.
    cronograma = models.TextField(
        blank=True,
        null=True,
        verbose_name='Cronograma',
    )

    # Contenido Sinoptico de la asignatura.
    sinoptico = models.TextField(
        blank=True,
        null=True,
        verbose_name='Contenidos Sipnóticos',
    )

    # Returns the primary key for the program and the code.
    def __str__(self):
        return '%s %s %s %s' % (self.pk, self.codigo,self.fecha_vigAno,self.fecha_vigTrim)

    # Get Every field name and value
    def __iter__(self):
        for field in self._meta.fields:
            if field.verbose_name == "ID":
                continue
            elif field.verbose_name == "Fecha Vigencia Trimestre":
                out = False
                for choice in Programa.TRIMESTRE:
                    if field.value_to_string(self) == choice[0]:
                        yield (field.verbose_name, choice[1])
                        out = True
                if not out:
                    yield (field.verbose_name, field.value_to_string(self))
            else:
                yield (field.verbose_name, field.value_to_string(self))

class Solicitud(models.Model):

    # Crea una solicitud de un programa (entidad debil).

    # Nombre de la coordinacion asociada.
    nomcoord = models.CharField(
        max_length=50,
        verbose_name='Nombre Coordinacion',
    )

    # Programa por Asignar un profesor.
    porasignar = models.BooleanField(
        default=True,
    )

    # Programa por validar departamento.
    porvalidarD = models.BooleanField(
        default=True,
    )

    # Programa rechazado por coordinacion.
    rechazadoC = models.BooleanField(
        default=False,
    )

    # Programa validado por Coordinacion.
    validadoC = models.BooleanField(
        default=False,
    )

    # Programa enviado a Dace.

    enviadoD = models.BooleanField(
        default=False,
    )

    # Programa devuelto a Dace.
    devueltoDace = models.BooleanField(
        default=False,
    )

    # Fecha de elaboracion de la solicitud
    fechaelab = models.DateTimeField(
        default=datetime.now,
    )

    # Creditos del programa
    credits = models.BooleanField(
        verbose_name='Unidad de Créditos',
    )

    # Horas de teoria de una asignatura.

    h_teoria = models.BooleanField(
        default=False,
        verbose_name='Horas de Teoría',
    )

    # Hras de practica de una asignatura.

    h_prac = models.BooleanField(
        default=False,
        verbose_name='Horas de Práctica',
    )

    #Horas de laboratorio de una asignatura.

    h_lab = models.BooleanField(
        default=False,
        verbose_name='Horas de Teoría',
    )

    # Trimestre del programa.
    trime = models.CharField(
        max_length=8,
        verbose_name='Trimestre',
    )

    # Ano del programa.
    ano = models.CharField(
        max_length=8,
        verbose_name='Año',
    )

    # Creditos de requisito del programa.
    requisito_cre = models.BooleanField(
        default=False,
        verbose_name='Requisitos',
    )

    # Permisos de la coordinacion del programa.
    permiso_coord = models.BooleanField(
        default=False,
        verbose_name='Permisos',
    )

    # Tipo de las materias del programa.
    tipo_materia = models.CharField(
        max_length=20,
        verbose_name='Tipo',
    )

    # Toda solicitud se relaciona con un programa.
    programa = models.ForeignKey(
        Programa,
        on_delete=models.CASCADE,
    )


#!/usr/local/bin/python3

import json

DEFENSE = ["anticapitalism", "chasiness", "omniscience", "tenaciousness", "watchfulness"];
PITCHING = ["ruthlessness", "overpowerment", "unthwackability", "shakespearianism", "suppression", "coldness"];
BATTING = ["patheticism", "moxie", "divinity", "musclitude", "thwackability", "buoyancy", "martyrdom"];
BASE_RUNNING = ["base_thirst", "laserlikeness", "continuation", "ground_friction", "indulgence"];

HEADERS = ["name", "team"];

## Primary files
BATTING_FILE = open("../data/s14-batters.csv", "a")
PITCHING_FILE = open("../data/s14-pitching.csv", "a")
DEFENSE_FILE = open("../data/s14-defense.csv", "a")
BASE_RUNNING_FILE = open("../data/s14-base-running.csv", "a")
OFFENSE_FILE = open("../data/s14-offense.csv", "a")

with open('../data/players-20200314.json') as f:
  players = json.load(f)

prefix = "name,team,";
defense = "anticapitalism,chasiness,omniscience,tenaciousness,watchfulness";
pitching = "ruthlessness,overpowerment,unthwackability,shakespearianism,suppression,coldness";
batting = "patheticism,moxie,divinity,musclitude,thwackability,buoyancy,martyrdom";
base_running = "base_thirst,laserlikeness,continuation,ground_friction,indulgence";
offense = batting + "," + base_running;
BATTING_FILE.write(prefix + batting + "\n")
PITCHING_FILE.write(prefix + pitching + "\n")
DEFENSE_FILE.write(prefix + defense + "\n")
BASE_RUNNING_FILE.write(prefix + base_running + "\n")
OFFENSE_FILE.write(prefix + offense + "\n")

for player in players:
    team = player["team"];
    name = player["player_name"];
    if team is None or name is None:
        continue;

    #print(f"player={name}\tteam={team}");
    #print("\tBATTING");
    cur_prefix = name + "," + team;
    cur_batting = "";
    cur_pitching = "";
    cur_defense = "";
    cur_base_running = "";
    cur_offense = "";
    for x in BATTING:
        cur_batting = cur_batting + "," + player[x];
        #print(f"\t\t{x} = {player[x]}");
    for x in PITCHING:
        cur_pitching = cur_pitching + "," + player[x];
        #print(f"\t\t{x} = {player[x]}");
    for x in DEFENSE:
        cur_defense = cur_defense + "," + player[x];
        #print(f"\t\t{x} = {player[x]}");
    for x in BASE_RUNNING:
        cur_base_running = cur_base_running + "," + player[x];
        #print(f"\t\t{x} = {player[x]}");
    cur_offense = cur_batting + cur_base_running;

    BATTING_FILE.write(cur_prefix + cur_batting + "\n")
    PITCHING_FILE.write(cur_prefix + cur_pitching + "\n")
    DEFENSE_FILE.write(cur_prefix + cur_defense + "\n")
    BASE_RUNNING_FILE.write(cur_prefix + cur_base_running + "\n")
    OFFENSE_FILE.write(cur_prefix + cur_offense + "\n")


from typing import Optional

from bs4 import BeautifulSoup
from lxml.html import HTMLParser

from algernon.parser.abc import ParserABC
from algernon.common.exc import ParserError

class ParserSimple(ParserABC):

    async def parse(self, content: bytes, mime_type: str, encoding: Optional[str] = None) -> bool:
        self.error = None
        try:
            if mime_type == 'text/html':
                await self._parse_html(content, encoding)
            else:
                raise ParserError(f'Parsing of mime type "{mime_type}" is not implemented')
            return True
        except ParserError as e:
            self.error = e
            self.lgg.error('{}: {}'.format(type(e), str(e)))
            return False

    async def _parse_html(self, content: bytes, encoding: Optional[str]):
        self.lang, self.title, self.description, self.tags, self.meta = None, None, None, [], {}

        try:
            soup = BeautifulSoup(content, 'html.parser', from_encoding=encoding)
        except HTMLParser.HTMLParseError as e:
            raise ParserError() from e

        html = soup.html
        if html:
            self.lang = html.attrs.get('lang')

        head = soup.head
        if head:
            for e in head.find_all('meta'):
                # If the meta tag has attribute "content", we expect it to have one other attribute that tells the type
                # of content; basically, "content" and the other attribute are key-value pairs.
                mc = e.attrs.get('content')
                if mc:
                    # Get the "other" attribute. If we have more than one "other" attribute, we arbitrarily just take
                    # the first one. Although, this should not happen(tm).
                    aa = [a for a in e.attrs.keys() if a != 'content']
                    k = e[aa[0]].strip().lower()
                    # Just in case. Although, they should be unique.
                    while k in self.meta:
                        k += '_'
                    self.meta[k] = mc.strip()
                else:
                    # Not all meta tags have "content", they simply have one attribute that is the single
                    # key-value pair
                    for k, v in e.attrs.items():
                        k = k.lower()
                        while k in self.meta:
                            k += '_'
                        self.meta[k] = v.strip()
            if head.title:
                self.title = head.title.string.strip()
            if not self.title:
                self.title = self.meta.get('og:title', self.meta.get('twitter:title'))
            self.description = self.meta.get('description', self.meta.get('og:description',
                                                                          self.meta.get('twitter:description')))


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:

        # create a sentinel node
        sent = ListNode('#')
        head = sent

        head1 = list1
        head2 = list2

        # since there are only 2 nodes, so we can compare element by element
        # and merge them as we go along
        # 0 --> 3 --> 4 (list1)
        # 1 --> 2 --> 4 (list2)
        # we compare 0 (head1) and 1 (head2), pick 0, make head.next --> 0
        # move head1 ahead to 3 since it was picked, head2 remains where it is, at 1
        # move head always, head is at 0 now, now repeat, compare head1 and head2
        # until both lists have exhausted

        while head1 and head2:
            h1 = head1.val
            h2 = head2.val
            if h1 <= h2:
                # pick head 1
                head.next = head1
                head1 = head1.next
            else:
                head.next = head2
                head2 = head2.next

            head = head.next

        # at this point, one of list1 or list2 is complete
        # whichever is shorter is typically complete
        # only 1 of the 2 below while loops will execute
        while head1:
            head.next = head1
            head = head.next
            head1 = head1.next

        while head2:
            head.next = head2
            head = head.next
            head2 = head2.next

        # return start of the linked list
        return sent.next


# GRADED FUNCTION: sigmoid_derivative

def sigmoid_derivative(x):
    """
    Compute the gradient (also called the slope or derivative) of the sigmoid function with respect to its input x.
    You can store the output of the sigmoid function into variables and then use it to calculate the gradient.

    Arguments:
    x -- A scalar or numpy array

    Return:
    ds -- Your computed gradient.
    """

    ### START CODE HERE ### (≈ 2 lines of code)
    s = None
    ds = None
    s=sigmoid(x)
    ds = s*(1-s)
    ### END CODE HERE ###

    return ds

###################################
import time

x1 = [9, 2, 5, 0, 0, 7, 5, 0, 0, 0, 9, 2, 5, 0, 0]
x2 = [9, 2, 2, 9, 0, 9, 2, 5, 0, 0, 9, 2, 5, 0, 0]

### CLASSIC DOT PRODUCT OF VECTORS IMPLEMENTATION ###
tic = time.process_time()
dot = 0
for i in range(len(x1)):
    dot+= x1[i]*x2[i]
toc = time.process_time()
print ("dot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC OUTER PRODUCT IMPLEMENTATION ###
tic = time.process_time()
outer = np.zeros((len(x1),len(x2))) # we create a len(x1)*len(x2) matrix with only zeros
for i in range(len(x1)):
    for j in range(len(x2)):
        outer[i,j] = x1[i]*x2[j]
toc = time.process_time()
print ("outer = " + str(outer) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC ELEMENTWISE IMPLEMENTATION ###
tic = time.process_time()
mul = np.zeros(len(x1))
for i in range(len(x1)):
    mul[i] = x1[i]*x2[i]
toc = time.process_time()
print ("elementwise multiplication = " + str(mul) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

### CLASSIC GENERAL DOT PRODUCT IMPLEMENTATION ###
W = np.random.rand(3,len(x1)) # Random 3*len(x1) numpy array
tic = time.process_time()
gdot = np.zeros(W.shape[0])
for i in range(W.shape[0]):
    for j in range(len(x1)):
        gdot[i] += W[i,j]*x1[j]
toc = time.process_time()
print ("gdot = " + str(gdot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

# GRADED FUNCTION: L1

def L1(yhat, y):
    """
    Arguments:
    yhat -- vector of size m (predicted labels)
    y -- vector of size m (true labels)

    Returns:
    loss -- the value of the L1 loss function defined above
    """

    ### START CODE HERE ### (≈ 1 line of code)
    loss = None
    loss = sum(abs(yhat - y))
    ### END CODE HERE ###

    return loss
yhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print("L1 = " + str(L1(yhat,y)))

def L2(yhat, y):
    """
    Arguments:
    yhat -- vector of size m (predicted labels)
    y -- vector of size m (true labels)

    Returns:
    loss -- the value of the L2 loss function defined above
    """

    ### START CODE HERE ### (≈ 1 line of code)
    loss = None
    tmp  = yhat - y
    loss = np.dot(tmp, tmp)
    ### END CODE HERE ###

    return loss

yhat = np.array([.9, 0.2, 0.1, .4, .9])
y = np.array([1, 0, 0, 1, 1])
print("L2 = " + str(L2(yhat,y)))


import functools
import random
from card import Card

class Shoe(object):
  """Represents the shoe where all of the cards are stored."""
  def __init__(self, shoe_size, reshuffle_ratio):
    self._cards = self._create_shoe(shoe_size)
    self.reshuffle_ratio = reshuffle_ratio
    self._idx = 0
    self._hilo_count = 0
    self.shuffle()

  def shuffle(self):
    """Shuffles the cards and sets the current index back to 0."""
    random.shuffle(self._cards)
    self._idx = 0

  def depth(self):
    """Returns the percent of the shoe that has been used."""
    return self._idx / len(self._cards)

  def draw(self):
    """
    Draws and returns the top card from the shoe. If the shoe is empty it will
    reshuffle the shoe. Reshuffling will not happen if the reshuffle ratio is
    met. This is to ensure a hand is played without destroying the current
    count.
    """
    card = self._cards[self._idx]
    self._idx += 1
    self._hilo_count += card.hilo_count()

    if self._idx == len(self._cards):
      self.shuffle()
    return card

  def peek(self, length):
    """Returns the top-N cards. This does not change the current index."""
    return self._cards[self._idx:min(len(self._cards), self._idx + length)]

  def hilo_count(self):
    """Returns the hi-lo count of the shoe."""
    return self._hilo_count

  def _create_shoe(self, shoe_size):
    """
    Creates the shoe by appending 4x the number of allotted decks. This is to
    account for different suits.
    """
    cards = []
    for i in range(4 * shoe_size):
      cards.append(Card(1, 11, 'A'))
      cards.append(Card(10, 10, 'K'))
      cards.append(Card(10, 10, 'Q'))
      cards.append(Card(10, 10, 'J'))
      cards.append(Card(10, 10, '10'))
      cards.append(Card(9, 9, '9'))
      cards.append(Card(8, 8, '8'))
      cards.append(Card(7, 7, '7'))
      cards.append(Card(6, 6, '6'))
      cards.append(Card(5, 5, '5'))
      cards.append(Card(4, 4, '4'))
      cards.append(Card(3, 3, '3'))
      cards.append(Card(2, 2, '2'))
    return cards


from django.urls import path

from .views import home, about, contact, post_detail, send_email,PostListView

urlpatterns = [
    path('',  home, name="home"),
    path('about', about, name='about'),
    path('contact', contact, name='contact'),
    path('post_detail/<int:id>',post_detail, name='post_detail'),
    path('posts',PostListView.as_view(), name="posts"),
    path('send_mail', send_email, name="send_mail"),
   # path('thanks/', thanks, name="thanks"),
]


import os
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import ExecuteProcess
from scripts import GazeboRosPaths
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():

    ld = LaunchDescription()

    # urdf
    manipulator_simulation_pkg = get_package_share_directory("manipulator_simulation")
    urdf = os.path.join(manipulator_simulation_pkg,"urdf","manipulator.urdf")

    # fetch controller configuration guide
    controller_config = os.path.join(manipulator_simulation_pkg,"config","jtc.yaml")

    # robot description
    robot_description = {"robot_description":urdf}

    # gazebo docker parameters
    model_path, plugin_path, media_path = GazeboRosPaths.get_paths()
    gazebo_env = {
        "GAZEBO_MODEL_PATH":model_path,
        "GAZEBO_PLUGIN_PATH":plugin_path,
        "GAZEBO_RESOURCE_PATH":media_path
    }

    # create gazebo process (call gazebo)
    gazebo_cmd = ExecuteProcess(cmd=["gazebo","-s","libgazebo_ros_factory.so"],output="screen",additional_env=gazebo_env)

    # create gazebo node (bring robot into gazebo)
    gazebo_node = Node(package="gazebo_ros",executable="spawn_entity.py",arguments=["-entity","manipulator_robot","-b","-file", urdf])

    # call robot state publisher
    state_pub_node = Node(package="robot_state_publisher",executable="robot_state_publisher",name="robot_state_publisher",output ="screen",arguments=[urdf])

    # instance the controller manager
    controller_manager = Node(package="controller_manager",executable="ros2_control_node",parameters=[robot_description, controller_config],output={"stdout": "screen","stderr": "screen"})

    # spawn the joint state broadcaster
    joint_state_controller = Node(package="controller_manager",executable="spawner.py",arguments=["joint_state_broadcaster", "--controller-manager", "/controller_manager"])

    # spawn the trayectory controller
    joint_trayectory_controller = Node(package="controller_manager",executable="spawner.py",arguments=["joint_trajectory_controller", "-c", "/controller_manager"])

    # call my forward kinematics service node
    forward_kinematics_service = Node(package="manipulator_simulation",executable="publish_target")

    # add nodes
    ld.add_action(gazebo_cmd)
    ld.add_action(gazebo_node)
    ld.add_action(state_pub_node)
    ld.add_action(controller_manager)
    ld.add_action(joint_state_controller)
    ld.add_action(joint_trayectory_controller)
    ld.add_action(forward_kinematics_service)
    return ld


from casino.core import PatternMeta
from casino.utils import add_metaclass

@add_metaclass(PatternMeta)
class Normal(object):

    id = 1001
    POINT = 0

    @staticmethod
    def validate(handcard, combinations, properties):
        if not (combinations or
                handcard.fixed_cards or
                any(used for used in handcard.used_cards.values())):
            return False

        handcard.used_combs[:] = combinations
        return True

patterns = (Normal,)


#!/usr/bin/env python3
#
# modified by Loreto:           2017-03-10_14.50.01
# #####################################################

# updated by ...: Loreto Notarantonio
# Version ......: 11-12-2017 08.51.07

import LnLib as Ln
import os
import serial       # sudo pip3.4 install pyserial
import sys
import inspect
import string
import time

class LnClass():
    def __init__(self):
        self.rCode  = 0
        self.errMsg = None

####################
## Default values ##
####################
# Several instrument instances can share the same serialport
_SERIALPORTS = {}

BYTESIZE = 8
"""Default value for the bytesize (int)."""
PARITY   = serial.PARITY_NONE
"""Default value for the parity. See the pySerial module for documentation. Defaults to serial.PARITY_NONE"""

STOPBITS = 1
"""Default value for the number of stopbits (int)."""

read_TIMEOUT  = 0.05
"""Default value for the timeout value in seconds (float)."""

#####################
## Named constants ##
#####################

MODE_RTU   = 'rtu'
MODE_ASCII = 'ascii'

# -----------------------------------------------------------------------
# - con il gioco del complementedByte, gli unici byte che dovrebbero
# - circolare sono i seguenti al di là dello STX ed ETX
# -----------------------------------------------------------------------
LnRs485_validBytesHex = [
                '0x0F',
                '0x1E',
                '0x2D',
                '0x3C',
                '0x4B',
                '0x5A',
                '0x69',
                '0x78',
                '0x87',
                '0x96',
                '0xA5',
                '0xB4',
                '0xC3',
                '0xD2',
                '0xE1',
                '0xF0'
              ]

from . LnRs485_Formatter import Formatter485

#####################################################################
# - MAIN LnRS485 CLASS
#####################################################################
class LnRs485():
    def __init__(self, port, mode='ascii', baudrate=9600, logger=None, myDict=LnClass):

        if logger:
            self._setLogger = logger
        else:
            self._setLogger = self._internaLogger

        logger = self._setLogger(package=__package__)
        self._myDict = myDict

        if port not in _SERIALPORTS or not _SERIALPORTS[port]:
            try:
                logger.info('opening port...')
                self.serial = _SERIALPORTS[port] = serial.Serial(
                                                    port     = port,
                                                    baudrate = baudrate,
                                                    parity   = serial.PARITY_NONE,
                                                    bytesize = serial.EIGHTBITS,
                                                    stopbits = serial.STOPBITS_ONE,
                                                    rtscts   = False,
                                                    xonxoff  = False,
                                                    dsrdtr   = False,
                                                    timeout  = read_TIMEOUT)

            except (Exception) as why:
                print ('ERROR:  ', str(why))
                sys.exit()

        else:
            self.serial = _SERIALPORTS[port]
            if self.serial.port is None:
                logger.info('opening port...')
                self.serial.open()
                # - chissà se sono importanti....
                self.serial.reset_input_buffer()        # clear input  buffer
                self.serial.reset_output_buffer()       # clear output buffer

        self._validBytes=bytearray([int(i, 16) for i in LnRs485_validBytesHex]) # creiamo un array di integer

        self.mode = mode
        """Slave mode (str), can be MODE_RTU or MODE_ASCII.  Most often set by the constructor (see the class documentation).
        New in version 0.6.
        """

        self._printableChars                = list(range(31,126))
        self._sendCounter = 0

        self._STX = 0xF0
        self._ETX = 0xF1
        self._CRC = True

        self._close_port_after_each_call = False
        """If this is :const:'True', the serial port will be closed after each call. """
        if  self._close_port_after_each_call: self.serial.close()

            # classe per formattare i dati
        self.formatter = Formatter485

        # self._rs485RxRawData    = bytearray()    # contiene i dati letti o da scrivere sulla rs485
        self._rs485RxPayLoad    = bytearray()    # contiene i dati letti ripuliti da STX, CRC, ETX
        # self._rs485RxRawHexData = ''             # contiene i dati raw convertiti in Hex

        self._TxDataRaw         =  bytearray()   # raw data in uscita   dalla seriale
        self._TxDataHex         =  ''            # raw data in uscita   dalla seriale

        # self._Rx                = self._myDict()
        # self._Tx                = self._myDict()

        # self._cleanData(self._Rx)
        # self._cleanData(self._Tx)

        # self._RxDataRaw         =  bytearray()   # raw data in ingresso dalla seriale
        # self._RxDataHex         =  ''            # raw data in ingresso dalla seriale
        self._fld               =  None            # dict che contiene i nomi dei campi del payload e la loro posizione nel pacchetto

        # - clean delle variabili di RX e TX
    # def _cleanData(self, ptr):
    #     ptr.raw           = self._myDict()
    #     ptr.payload       = self._myDict()

    #     ptr.raw.data      = bytearray()
    #     ptr.raw.hexd      = None
    #     ptr.raw.hexm      = None
    #     ptr.raw.fmted     = False

    #     ptr.payload.data  = bytearray()
    #     ptr.payload.hexd  = None
    #     ptr.payload.hexm  = None
    #     ptr.payload.fmted = False

    def _internaLogger(self, package=None):
        ##############################################################################
        # - classe che mi permette di lavorare nel caso il logger non sia richiesto
        ##############################################################################
        class nullLogger():
                def __init__(self, package=None, stackNum=1):
                    pass
                def info(self, data): pass
                def debug(self, data): pass
                    # self._print(data)
                def error(self, data):  pass
                def warning(self, data):  pass

        return nullLogger()

    def __repr__(self):
        """String representation of the :class:'.Instrument' object."""
            # address                    = {ADDRESS},
        return """{MOD}.{CLASS}
            <class-id                  = 0x{ID:x},
            mode                       = {MODE},
            close_port_after_each_call = {CPAEC},
            CRC                        = {CRC},
            STX                        = 0x{STX:02x},
            ETX                        = 0x{ETX:02x},
            serial-id                  = {SERIAL},>
                """.format(
                        MOD=self.__module__,
                        CLASS=self.__class__.__name__,
                        ID=id(self),
                        MODE=self.mode,
                        CPAEC=self._close_port_after_each_call,
                        SERIAL=self.serial,
                        CRC=self._CRC,
                        STX=self._STX,
                        ETX=self._ETX
            )
                        # ADDRESS=self.address,

    # =====================================================
    # - _getCRC8
    # =====================================================
    def _getCRC8(self, byteArray_data):
        logger = self._setLogger(package=__package__)
        crcValue = 0
        for byte in byteArray_data:
            # if isinstance(byte, str): byte = ord(byte)            # onverte nel valore ascii
            logger.debug('byte: int:{0} hex: {0:02x} - crcValue int:{1} hex: {1:02x}'.format(byte, crcValue))
            b2 = byte
            if (byte < 0):
                b2 = byte + 256
            for i in range(8):
                odd = ((b2^crcValue) & 1) == 1
                crcValue >>= 1
                b2 >>= 1
                if (odd):
                    crcValue ^= 0x8C # this means crc ^= 140

        return crcValue

    #######################################################################
    # - by Loreto
    # - Scrittura dati basato sul protocollo:
    # -     RS485 protocol library by Nick Gammon
    # - STX - data - CRC - ETX
    # - A parte STX e ETX tutti gli altri byte sono inviati come due nibble
    # -  byte complemented (incluso il CRC)
    # -  only values sent would be (in hex):
    # -    0F, 1E, 2D, 3C, 4B, 5A, 69, 78, 87, 96, A5, B4, C3, D2, E1, F0
    #######################################################################
    def _prepareRs485Packet(self, payload):
        assert type(payload)==bytearray
        logger = self._setLogger(package=__package__)

             # - preparaiamo il bytearray con i dati da inviare
        dataToSend=bytearray()

            # - STX nell'array
        dataToSend.append(self._STX)

            # - Data nell'array
        for thisByte in payload:
            byte1, byte2 = self._splitComplementedByte(thisByte)
            dataToSend.append(byte1)
            dataToSend.append(byte2)

            # - CRC nell'array
        if self._CRC:
            CRC_value    = self._getCRC8(txData)
            byte1, byte2 = self._splitComplementedByte(CRC_value)
            dataToSend.append(byte1)
            dataToSend.append(byte2)

            # - ETX
        dataToSend.append(self._ETX)

        self._rs485TxRawData = dataToSend
        # return dataToSend

    # ---------------------------------------------
    # -     byte1 = aaaa !aaaa
    # -     byte2 = bbbb !bbbb
    # -     byte = byte1_HNibble * 16 + byte2_HNibble
    # ---------------------------------------------
    def _combineComplementedByte(self, byte1, byte2):
        logger = self._setLogger(package=__package__)

        logger.debug("complementedData: x{0:02X} + x{1:02X}".format(byte1, byte2))

            # - check first byte
        byte1_HighNibble = (byte1 >> 4) & 0x0F
        byte1_LowNibble = ~byte1 & 0x0F
        if byte1_LowNibble != byte1_HighNibble:
            logger.error("byte1 nibbles corrupted: x{0:02X} + x{1:02X}".format(byte1_LowNibble, byte1_HighNibble))
            return None

            # - check second byte
        byte2_HighNibble = (byte2 >> 4) & 0x0F
        byte2_LowNibble = ~byte2 & 0x0F
        if byte2_LowNibble != byte2_HighNibble:
            logger.error("byte2 nibbles corrupted: x{0:02X} + x{1:02X}".format(byte2_LowNibble, byte2_HighNibble))
            return None

            # re-build real byte
        realByte = byte1_HighNibble*16 + byte2_HighNibble
        logger.debug("  resulting data BYTE: x{0:02X} char:{1}".format(realByte, chr(realByte)))

        return realByte

    # ---------------------------------------------
    # - aaaa bbbb
    # -     byte1 = aaaa !aaaa
    # -     byte2 = bbbb !bbbb
    # -     byte = byte1_HNibble * 16 + byte2_HNibble
    # ---------------------------------------------
    def _splitComplementedByte(self, byte):
        logger = self._setLogger(package=__package__)
        logger.debug ("byte to be converted: {0} - type: {1}".format(byte, type(byte)))

            # first nibble
        c = byte >> 4;
        byteValue = (c << 4) | (c ^ 0x0F)
        highNibble = byteValue
        logger.debug  ("    x{0:02X}".format( highNibble))

            # second nibble
        c = byte & 0x0F;
        byteValue = (c << 4) | (c ^ 0x0F)
        lowNibble = byteValue
        logger.debug  ("    x{0:02X}".format(lowNibble))

            # second two bytes
        return highNibble, lowNibble

    #######################################################################
    # - Lettura dati dalla seriale
    # - Ritorna: una bytearray di integer con i dati ricevuti oppure vuoto
    #######################################################################
    def _serialRead(self, timeoutValue=1000):
        logger = self._setLogger(package=__package__)

        if self._close_port_after_each_call:
            logger.debug('opening port...')
            self.serial.open()

        # facciamo partire il timer
        timeStart = time.time()*1000
        timeEnd   = timeStart+timeoutValue
        TIMEOUT = True      # flag per indicare se siamo andati in timeout o meno
        logger.debug( "starting timer... for {} mSec".format(timeoutValue))

        # loop fino a che non abbiamo ricevuto dati
        _dataBuffer = bytearray()
        while True:
            elapsed = int((time.time()*1000)-timeStart)
                # - in attesa di un byte
            ch    = self.serial.read(1)       # ch e' un type->bytes

                # ------------------------------------------
                # - se riceviamo un NULL:
                # -     - se non abbiamo nulla:
                # -         - se scaduto timeOut... usciamo
                # -         - else continue
                # - quindi usciamo solo per timeOut oppure
                # - dopo un NULL dopo avere ricevuto qualcosa
                # ------------------------------------------
            if ch == b'':
                if _dataBuffer:
                    break
                elif elapsed >= timeoutValue:
                    logger.debug( "elapsed {0}/{1}".format(elapsed, timeoutValue))
                    break
                else:
                    continue

            chInt = int.from_bytes(ch, 'little')
            _dataBuffer.append(chInt)
            logger.debug("Received byte: {0:02x}".format(chInt))

        if self._close_port_after_each_call:
            logger.debug('closing port...')
            self.serial.close()

        logger.debug("data received: {}".format(' '.join('{0:02x}'.format(x) for x in _dataBuffer)))
        return _dataBuffer

    #######################################################################
    # - Scrittura dati sulla seriale
    #######################################################################
    def _serialWrite(self, txData):
        logger = self._setLogger(package=__package__)
        assert type(txData)==bytearray

        if self._close_port_after_each_call:
            self.serial.open()

            # INVIO dati
        _HexData = ' '.join('{0:02x}'.format(x) for x in txData)
        _HexMsg = '{DESCR:^10}:  <data>{DATA}</data>'.format(DESCR="hex", DATA=_HexData)
        logger.info('xmitting data on serial port: ')
        logger.info(_HexMsg)
        self.serial.write(txData)

        if self._close_port_after_each_call:
            self.serial.close()

    #######################################################################
    # - Scrittura dati sulla seriale
    #######################################################################
    def _rs485Read(self, timeoutValue=2000, FORMAT=False):
        logger = self._setLogger(package=__package__)

        rawDict = self._myDict()
        plDict  = self._myDict()
        rawData = self._serialRead(timeoutValue=timeoutValue) # return bytearray
        rawDict.data = rawData
        plDict.data = None

        if rawData:
            if FORMAT:
                _rawDataFMTed = self.formatter._fmtData(self, rawData)
                rawDict.hexd = _rawDataFMTed['HEXD']
                rawDict.hexm = _rawDataFMTed['HEXM']
                rawDict.text = _rawDataFMTed['TEXT']
                rawDict.char = _rawDataFMTed['CHAR']

            payload = self._extractPayload(rawData)
            plDict.data = payload
            if payload and FORMAT:
                _payloadFMTed = self.formatter._fmtData(self, payload)
                plDict.hexd = _payloadFMTed['HEXD']
                plDict.hexm = _payloadFMTed['HEXM']
                plDict.text = _payloadFMTed['TEXT']
                plDict.char = _payloadFMTed['CHAR']
                plDict.dict = self.formatter._payloadToDict(self, payload)

        return rawDict, plDict

    #######################################################################
    # - Scrittura dati sulla seriale
    #######################################################################
    def _rs485Write(self, payload, fDEBUG=False):
        logger = self._setLogger(package=__package__)
        assert type(payload)==bytearray
        logger.info('payload: {}'.format(Formatter485._toHex(payload)[0]))

            # - prepariamo il bytearray per i dati da inviare
        dataToSend=bytearray()

            # - STX nell'array
        dataToSend.append(self._STX)

            # - Data nell'array
        for thisByte in payload:
            byte1, byte2 = self._splitComplementedByte(thisByte)
            dataToSend.append(byte1)
            dataToSend.append(byte2)

            # - CRC nell'array
        if self._CRC:
            CRC_value    = self._getCRC8(payload)
            byte1, byte2 = self._splitComplementedByte(CRC_value)
            dataToSend.append(byte1)
            dataToSend.append(byte2)

            # - ETX
        dataToSend.append(self._ETX)

        logger.info('dataToSend: {}'.format(Formatter485._toHex(dataToSend)[0]))

        # INVIO dati
        self._serialWrite(dataToSend)
        return dataToSend

    ######################################################
    # - unpack data
    # - partendo dal rawData:
    # -    1. riconosce STX ed ETX
    # -    2. verifica la correttezza del pacchetto CRC
    # -    3. ricostruisce i byte originali (2bytes --> 1 byte)
    # -    4. estrae il payload
    # -    5. ritorna payload in un bytearray
    ######################################################
    def _extractPayload(self, rawData):
        assert type(rawData) == bytearray
        logger = self._setLogger(package=__package__)

        logger.error('analizing rawData: {}'.format(' '.join('{0:02x}'.format(x) for x in rawData)))
            # cerchiamo STX
        for index, byte in enumerate(rawData):
            if byte == self._STX:
                rawData = rawData[index:]
                logger.info('STX has been found')
                break

            # cerchiamo ETX
        for index, byte in enumerate(rawData):
            if byte == self._ETX:
                rawData = rawData[:index+1]
                logger.info('ETX has been found')
                break

        if not rawData or not rawData[0] == self._STX or not rawData[-1] == self._ETX:
            errMsg = 'STX or ETX missed'
            logger.error(errMsg)
            return bytearray()

            # ---------------------------------------------
            # - ricostruzione dei bytes originari
            # - byte = byte1_HighNibble*16 + byte2_HighNibble
            # il trick che segue ci permette di prelevare due bytes alla volta
            # ---------------------------------------------
        _payloadData = bytearray()
        xy = iter(rawData[1:-1]) # skip STX and ETX
        for byte1, byte2 in zip(xy, xy):
                # re-build real byte
            if byte1 in self._validBytes and byte2 in self._validBytes:
                byte1_HighNibble = (byte1 >> 4) & 0x0F
                byte2_HighNibble = (byte2 >> 4) & 0x0F
                realByte = byte1_HighNibble*16 + byte2_HighNibble
                _payloadData.append(realByte)

            else:
                errMsg = 'some byte corrupted byte1:{0:02x} byte2:{1:02x}'.format(byte1, byte2)
                logger.error(errMsg)
                return bytearray()

            # -----------------------------------------------------------------------
            # - Una volta ricostruiti i bytes origilali,
            # - calcoliamo il CRC sui dati (ovviamento escluso il byte di CRC stesso)
            # -----------------------------------------------------------------------
        _CRC_calculated  = self._getCRC8(_payloadData[:-1]) # skipping ETX
        _CRC_received    = _payloadData[-1]

        logger.debug("    CRC received  : x{0:02X}".format(_CRC_received))
        logger.debug("    CRC calculated: x{0:02X}".format(_CRC_calculated))

            # ---------------------------------
            # - check CRC (drop STX and ETX)
            # ---------------------------------
        if not _CRC_calculated == _CRC_received:
            errMsg = 'Il valore di CRC non coincide'
            logger.error ('-')
            logger.error ("    CRC received  : x{0:02X}".format(_CRC_received))
            logger.error ("    CRC calculated: x{0:02X}".format(_CRC_calculated))
            logger.error ('-')
            Ln.Exit(9999)
            return bytearray()

        return _payloadData[:-1] # drop CRC

    #######################################################################
    # # PUBLIC methods
    #######################################################################

    def getSeqCounter(self):
        self._sendCounter += 1
        yy = self._sendCounter.to_bytes(2, byteorder='big')
        return yy

    def SetPayloadFieldName(self, mydict):
        logger = self._setLogger(package=__package__)
        assert type(mydict) == self._myDict

            # ---- solo per logging ------------
            # - per fare il logging ordinato per value
            # - trasformiamo il dict in una LIST di tuple
            # ---- solo per logging ------------
        xx = sorted(mydict.items(), key=lambda x:x[1])
        logger.debug('Payload fields name:')
        for k, v in xx:
            logger.debug('  {:<15}:{}'.format(k,v))
        self._fld = mydict

    def SetSTX(self, value):
        logger = self._setLogger(package=__package__)
        if isinstance(value, str):
            value = int(value, 16)
        self._STX = value
        logger.info('setting STX to {}'.format(self._STX))

    def SetETX(self, value):
        logger = self._setLogger(package=__package__)
        if isinstance(value, str):
            value = int(value, 16)
        self._ETX = value
        logger.info('setting ETX to {}'.format(self._ETX))

    def SetCRC(self, bFlag):
        # assert type(bFlag) == bool or type(bFlag) == str
        logger = self._setLogger(package=__package__)
        if isinstance(bFlag, bool):
            self._CRC = bFlag
        elif isinstance(bFlag, str):
            self._CRC = eval(bFlag)
        else:
            self._CRC = True
        logger.info('setting CRC to {}'.format(self._CRC))

    def ClosePortAfterEachCall(self, bFlag):
        logger = self._setLogger(package=__package__)
        self._close_port_after_each_call = bFlag

        if bFlag:
            if self.serial.isOpen():
                logger.info('closing port...')
                self.serial.close()
        else:
            if not self.serial.isOpen():
                logger.info('opening port...')
                self.serial.open()

    def Close(self):
        logger = self._setLogger(package=__package__)
        if self.serial.isOpen():
            logger.info('closing port...')
            self.serial.close()

    # def formatData(self, rawData):
    #     _formattedData = self.formatter._fmtData(self, rs485data)
    #     _myData.payload.hexd = _formattedData['HEXD']
    #     _myData.payload.hexm = _formattedData['HEXM']
    #     _myData.payload.text = _formattedData['TEXT']
    #     _myData.payload.char = _formattedData['CHAR']

    ######################################################
    # - @property
    # - Utilizzo i metodi come fossero attributi
    # - se compare l'utput di __repr__ vuol dire che
    # - è stato omesso @property
    ######################################################

    def VerifyRs485Data(self, rawData):
        '''
            Prende in input un bytearray dei dati letti da seriale
            li valida per il protocollo RS485
            Se validi... formatta sia il payload che il formato raw
            ritornando un dictionary con due rami
        '''
        logger = self._setLogger(package=__package__)
        assert type(rawData) == bytearray
        _myData              = self._myDict()
        _myData.raw          = self._myDict()
        _myData.payload      = self._myDict()
            # default value
        _myData.raw.data     = bytearray()
        _myData.payload.data = bytearray()

        logger.debug('rawData: {}'.format(' '.join('{0:02x}'.format(x) for x in rawData)))
            # ritorna payload bytearray
        if rawData:
            rs485data = self._extractPayload(rawData)
            logger.debug('payload: {}'.format(' '.join('{0:02x}'.format(x) for x in rs485data)))

            if rs485data:
                _myData.raw.data     = rawData
                _myData.payload.data = rs485data

                _formattedData = self.formatter._fmtData(self, rs485data)
                _myData.payload.hexd = _formattedData['HEXD']
                _myData.payload.hexm = _formattedData['HEXM']
                _myData.payload.text = _formattedData['TEXT']
                _myData.payload.char = _formattedData['CHAR']

                _formattedData = self.formatter._fmtData(self, rawData)
                _myData.raw.hexd = _formattedData['HEXD']
                _myData.raw.hexm = _formattedData['HEXM']
                _myData.raw.text = _formattedData['TEXT']
                _myData.raw.char = _formattedData['CHAR']

        return _myData

    def FormatRawData(self, rawData):
        '''
            Prende in input un bytearray dei dati letti da seriale
            li formatta ritornando un dictionary con i diversi formati
        '''
        assert type(rawData) == bytearray
        _myData              = self._myDict()

            # default value
        _myData.data     = bytearray()

            # ritorna payload bytearray
        if rawData:
            _myData.data = rawData

            _formattedData = self.formatter._fmtData(self, rawData)
            _myData.hexd = _formattedData['HEXD']
            _myData.hexm = _formattedData['HEXM']
            _myData.text = _formattedData['TEXT']
            _myData.char = _formattedData['CHAR']

        return _myData

    # @property
    # def rawHex(self):
    #     hexData, hexMsg = self.formatter._toHex(self._RxDataRaw)
    #     return hexMsg

    # # @property
    # def RxRaw(self, text=False, hexd=False, hexm=False, char=False):
    #     if not self._RxDataCharMsg:
    #         data = self.formatter._fmtData(self, self._RxDataRaw)
    #         self._RxDataHexMsg  = data['HEXM']
    #         self._RxDataTextMsg = data['TEXT']
    #         self._RxDataCharMsg = data['CHAR']

    #     if   hexd:  return self._RxDataHex
    #     elif hexm:  return self._RxDataHexMsg
    #     elif text:  return self._RxDataTextMsg
    #     elif char:  return self._RxDataCharMsg
    #     else:
    #         return None

    # # @property
    # def RxPayload(self, text=False, hexd=False, hexm=False, char=False):
    #     data = self.formatter._fmtData(self, self._RxDataRaw)
    #     if hexd:
    #         return data['HEXD']
    #     elif hexm:
    #         return data['HEXM']
    #     elif text:
    #         return data['TEXT']
    #     elif char:
    #         return data['CHAR']
    #     return None

    # @property
    # def rawChr(self):
    #     text, char = self.formatter._toText(self)
    #     return char

    # @property
    # def payload(self):
    #     self.formatter._verifyData(self)
    #     return self._rs485RxPayLoad

    # @property
    # def payloadHex(self):
    #     self.formatter._verifyData(self)
    #     hexData, hexMsg = self.formatter._toHex(self._rs485RxPayLoad)
    #     return hexMsg

    # # @property
    # def getPayload(self, rawdata):
    #     self.formatter._extractPayload(self, rawdata)
    #     myDict = self.formatter._payloadToDict(self)
    #     return myDict

    # @property
    def PayloadToDict(self, payload):
        # self.formatter._verifyData(self)
        return self.formatter._payloadToDict(self, payload)
        # return myDict
        # return 'ciao'

    # @property
    # def toRs485(self, payload):
    #     self._prepareRs485Packet(self, payload)
        # self._rs485TxRawData.printDict()
        # _serialWrite(self, self._rs485TxRawData):

################################################################################
# - M A I N
# - Prevede:
# -  2 - Controllo parametri di input
# -  5 - Chiamata al programma principale del progetto
################################################################################
if __name__ == '__main__':
    import time
    Sintax = """
        Immettere:
            action.usbPortNO.EoD [EOD=endOfData, default=10='\n']

        es.:
            monitor.0   : per monitorare la porta /dev/ttyUSB0
            send.0      : per inviare messaggi sulla porta /dev/ttyUSB0
    """


from io import StringIO
import pytest
import kevlar
from kevlar.tests import data_file
from kevlar.seqio import KevlarPartitionLabelError
from kevlar.sequence import KmerOfInterest, Record
import khmer
import pysam
import screed
import shutil

@pytest.fixture
def bogusseqs():
    seq = '>seq1\nACGT\n>seq2 yo\nGATTACA\nGATTACA\n>seq3\tdescrip\nATGATGTGA'
    return seq.split('\n')

def test_parse_fasta(bogusseqs):
    seqs = {name: seq for name, seq in kevlar.seqio.parse_fasta(bogusseqs)}
    assert seqs == {
        '>seq1': 'ACGT',
        '>seq2 yo': 'GATTACAGATTACA',
        '>seq3\tdescrip': 'ATGATGTGA',
    }

def test_seq_dict(bogusseqs):
    d = kevlar.seqio.parse_seq_dict(bogusseqs)
    assert d == {
        'seq1': 'ACGT',
        'seq2': 'GATTACAGATTACA',
        'seq3': 'ATGATGTGA',
    }

def test_augfastx_reader():
    infilename = data_file('collect.beta.1.txt')
    infile = open(infilename, 'r')
    for n, record in enumerate(kevlar.parse_augmented_fastx(infile)):
        assert record.name.startswith('good')
        assert record.sequence == (
            'TTAACTCTAGATTAGGGGCGTGACTTAATAAGGTGTGGGCCTAAGCGTCT'
        )
        assert len(record.annotations) == 2
        for kmer in record.annotations:
            assert kmer.abund == (8, 0, 0)
    assert n == 7

def test_augfastx_reader_e1():
    infilename = data_file('example1.augfastq')
    infile = open(infilename, 'r')
    record = next(kevlar.parse_augmented_fastx(infile))

    assert record.name == 'e1'
    assert record.sequence == (
        'TTAACTCTAGATTAGGGGCGTGACTTAATAAGGTGTGGGCCTAAGCGTCT'
    )
    assert len(record.annotations) == 2

    ikmer = record.annotations[0]
    assert record.ikmerseq(ikmer) == 'AGGGGCGTGACTTAATAAG'
    assert ikmer.ksize == 19
    assert ikmer.offset == 13
    assert ikmer.abund == (12, 15, 1, 1)

    ikmer = record.annotations[1]
    assert record.ikmerseq(ikmer) == 'GGGCGTGACTTAATAAGGT'
    assert ikmer.ksize == 19
    assert ikmer.offset == 15
    assert ikmer.abund == (20, 28, 0, 1)

def test_augfastx_reader_e2():
    infilename = data_file('example2.augfastq')
    infile = open(infilename, 'r')
    record = next(kevlar.parse_augmented_fastx(infile))

    assert record.name == 'ERR894724.125497791/1'
    assert record.sequence == (
        'TAGCCAGTTTGGGTAATTTTAATTGTAAAACTTTTTTTTCTTTTTTTTTGATTTTTTTTTTTCAAGCAG'
        'AAGACGGCATACGAGCTCTTTTCACGTGACTGGAGTTCAGACGTGTGCTCTTCCGAT'
    )
    assert len(record.annotations) == 2

    ikmer = record.annotations[0]
    assert record.ikmerseq(ikmer) == 'GGCATACGAGCTCTTTTCACGTGACTGGAGT'
    assert ikmer.ksize == 31
    assert ikmer.offset == 74
    assert ikmer.abund == (23, 0, 0)

    ikmer = record.annotations[1]
    assert record.ikmerseq(ikmer) == 'GCTCTTTTCACGTGACTGGAGTTCAGACGTG'
    assert ikmer.ksize == 31
    assert ikmer.offset == 83
    assert ikmer.abund == (23, 0, 0)

def test_augfastx_reader_withmates():
    instream = kevlar.open(data_file('seqs-mates.augfastq'), 'r')
    reader = kevlar.parse_augmented_fastx(instream)

    record = next(reader)
    assert len(record.annotations) == 5
    assert len(record.mates) == 1
    assert record.mates[0].startswith('CTGATAAGCAACTTCAGCAAA')

    record = next(reader)
    assert len(record.annotations) == 4
    assert len(record.mates) == 1
    assert record.mates[0].startswith('ATTAGAAAAAAAAAGTGCATT')

    record = next(reader)
    assert len(record.annotations) == 21
    assert len(record.mates) == 0

    record = next(reader)
    assert len(record.annotations) == 2
    assert record.mates[0].startswith('CAGATGTGTCTTGTGGGCAGT')

    with pytest.raises(StopIteration):
        next(reader)

def test_augfastx_writer():
    output = StringIO()
    record = Record(
        name='BasiliscusVulgarisRead84467/1',
        sequence='TTAACTCTAGATTAGGGGCGTGACTTAATAAGGTGTGGGCCTAAGCGTCT',
        quality='BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB',
        annotations=[
            KmerOfInterest(ksize=19, offset=13, abund=(12, 1, 1)),
            KmerOfInterest(ksize=19, offset=15, abund=(20, 0, 1)),
        ],
    )
    kevlar.print_augmented_fastx(record, output)
    record = Record(
        name='BasiliscusVulgarisRead90577/2',
        sequence='CTGTAATCCCAGCACTTTGGGAGGCCGAGGCAAGCAGATGATGCGGTCAG',
        quality='BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB',
        annotations=[
            KmerOfInterest(ksize=19, offset=1, abund=(5, 7, 9)),
            KmerOfInterest(ksize=19, offset=2, abund=(7, 10, 9)),
        ],
        mates=['CAGATGTGTCTTGTGGGCAGTGCAGCGGAGAGGTGCAAATATGGGTTTGG']
    )
    kevlar.print_augmented_fastx(record, output)
    record = Record(
        name='BasiliscusVulgarisRead99037/1',
        sequence='AGCACTTTGGGAGGCCGAGGCAAGCAGATGATGCGGTCAGGATTACAGAT',
        quality='BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
    )
    kevlar.print_augmented_fastx(record, output)

    assert output.getvalue() == """@BasiliscusVulgarisRead84467/1
TTAACTCTAGATTAGGGGCGTGACTTAATAAGGTGTGGGCCTAAGCGTCT
+
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
             AGGGGCGTGACTTAATAAG          12 1 1#
               GGGCGTGACTTAATAAGGT          20 0 1#
@BasiliscusVulgarisRead90577/2
CTGTAATCCCAGCACTTTGGGAGGCCGAGGCAAGCAGATGATGCGGTCAG
+
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
 TGTAATCCCAGCACTTTGG          5 7 9#
  GTAATCCCAGCACTTTGGG          7 10 9#
#mateseq=CAGATGTGTCTTGTGGGCAGTGCAGCGGAGAGGTGCAAATATGGGTTTGG#
@BasiliscusVulgarisRead99037/1
AGCACTTTGGGAGGCCGAGGCAAGCAGATGATGCGGTCAGGATTACAGAT
+
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
"""

def test_partition_reader_simple():
    infile = data_file('part-reads-simple.fa')
    readstream = kevlar.parse_augmented_fastx(kevlar.open(infile, 'r'))
    partitions = list(kevlar.parse_partitioned_reads(readstream))
    partitions = [part for partid, part in partitions]
    assert len(partitions) == 2
    assert len(partitions[0]) == 4
    assert len(partitions[1]) == 2

def test_partition_reader_mixed():
    infile = data_file('part-reads-mixed.fa')
    readstream = kevlar.parse_augmented_fastx(kevlar.open(infile, 'r'))
    errormsg = r'with and without partition labels'
    with pytest.raises(KevlarPartitionLabelError, match=errormsg):
        partitions = list(kevlar.parse_partitioned_reads(readstream))

def test_parse_single_partition():
    infile = data_file('part-reads-simple.fa')

    readstream = kevlar.parse_augmented_fastx(kevlar.open(infile, 'r'))
    partitions = list(kevlar.parse_single_partition(readstream, '1'))
    partitions = [part for partid, part in partitions]
    assert len(partitions) == 1
    assert len(partitions[0]) == 4

    readstream = kevlar.parse_augmented_fastx(kevlar.open(infile, 'r'))
    partitions = list(kevlar.parse_single_partition(readstream, '2'))
    partitions = [part for partid, part in partitions]
    assert len(partitions) == 1
    assert len(partitions[0]) == 2

    readstream = kevlar.parse_augmented_fastx(kevlar.open(infile, 'r'))
    partitions = list(kevlar.parse_single_partition(readstream, 'alFrED'))
    partitions = [part for partid, part in partitions]
    assert partitions == []

def test_parse_single_partition_nonpartitioned_reads():
    infile = data_file('dup.augfastq')
    readstream = kevlar.parse_augmented_fastx(kevlar.open(infile, 'r'))
    partitions = list(kevlar.parse_single_partition(readstream, '42'))
    assert partitions == []

@pytest.mark.parametrize('basename', [
    ('example2.augfastq'),
    ('example2.augfastq.gz'),
])
def test_kevlar_open(basename):
    infilename = data_file(basename)
    infile = kevlar.open(infilename, 'r')
    record = next(kevlar.parse_augmented_fastx(infile))

    assert record.name == 'ERR894724.125497791/1'
    assert record.sequence == (
        'TAGCCAGTTTGGGTAATTTTAATTGTAAAACTTTTTTTTCTTTTTTTTTGATTTTTTTTTTTCAAGCAG'
        'AAGACGGCATACGAGCTCTTTTCACGTGACTGGAGTTCAGACGTGTGCTCTTCCGAT'
    )
    assert len(record.annotations) == 2

def test_ikmer_out_of_bounds():
    fh = kevlar.open(data_file('out-of-bounds.augfastq.gz'), 'r')
    reader = kevlar.parse_augmented_fastx(fh)
    with pytest.raises(AssertionError, match=r"('TACGACAGAC', 'TACGACAGACA')"):
        list(reader)


from django.db import transaction

from api.management.data_script import OperationalDataScript
from api.models.permission import Permission
from api.models.role import Role
from api.models.role_permission import RolePermission
from api.authorities import REQUIRED_AUTHORITIES

class AddRolesPermissions(OperationalDataScript):
    """
    Adds the Roles and Permissions
    """
    is_revertable = False
    comment = 'Adds the Roles and Permissions in the authorities file'

    def check_run_preconditions(self):
        return True

    @transaction.atomic
    def run(self):
        display_order = 1
        roles_added = 0
        permissions_added = 0

        for authority in REQUIRED_AUTHORITIES:
            if authority.root is None:
                continue

            (role, role_created) = Role.objects.get_or_create(
                role_code=authority.group,
                defaults={
                    'description': authority.group,
                    'is_government_role':
                        True if authority.root == 'IDIR' else False,
                    'display_order': display_order
                }
            )

            (permission, perm_created) = Permission.objects.get_or_create(
                permission_code=authority.role.replace(' ', '_').upper(),
                defaults={
                    'name': authority.role,
                    'description': authority.description
                }
            )

            RolePermission.objects.get_or_create(
                permission=permission,
                role=role
            )

            if role_created:
                roles_added += 1
                display_order += 1

            if perm_created:
                permissions_added += 1

        print("Added {} roles.".format(roles_added))
        print("Added {} permissions.".format(permissions_added))

script_class = AddRolesPermissions


import json

#To anyone reviewing this, please tell me where comments would be helpful

#I use the same name for the local variables of methods and the global variables declared after methods, if they have the same function.
#I'm not sure if this keeps consistency, or if it's just confusing.

#toSave = {}

def importSave():
    """Imports a save from another program"""
    filename = input("Please enter the name of the file you want to read: ")
    try:
        with open(filename) as file:
            copy = json.load(file)
            print("File successfully opened\n")
            return True, copy
    except FileNotFoundError:
        print("No file has been loaded\n")
        return False, False

def display():
    """Outputs the content of the file"""
    #for key in toSave:
    print(toSave)

def saveDict():
    """Adds data to the loaded-in dictionary"""
    category = input("Enter the category for the item: ")
    item = input("Enter the name of the item: ")
    toSave[category] = item
    return toSave

def deleteDict():
    """Deletes data from the dictionary"""
    #This currently works by removing the first category that matches the user inputted key
    #If I have time, I'll try to implement a system where the user can delete on a case by case basis
    catRemove = input("Enter the category you want to remove: ")
    removeKey = toSave.pop(catRemove, None)
    if (removeKey == None):
        print("Item could not be found\n")
    else:
        print(catRemove, "has been successfully removed\n")
        return toSave

def askDict():
    """Asks if the user would like to edit their save file"""
    checkLoop = True
    while (checkLoop == True):
        print("\nWould you like to add to a save file?\n")
        ans = input("Enter \"Yes\" or \"No\": ")
        firstChar = ans[0].upper()
        if (firstChar == 'Y'):
            toSave = saveDict()
        else:
            checkLoop = False

    checkLoop = True
    while (checkLoop == True):
        print("Would you like to remove from the save file?\n")
        ans = input("Enter \"Yes\" or \"No\": ")
        firstChar = ans[0].upper()
        if (firstChar == 'Y'):
            toSave = deleteDict()
        else:
            checkLoop = False

    return toSave

def exportSave(toSaveS):
    """Exports the saved file"""
    filename = input("Please enter the name of the file you want to write to: ")
    with open(filename, 'w') as file:
        json.dump(toSave, file)
        print("File successfully saved\n")

#Main Program

#I'm not sure if it's good or bad coding practice to initialize variables in Python; It might make it more readible, even if it's pointless in terms of making the program run.
checkLoop = True    #Used to determine if a loop should keep looping
checkFile = (False, False)   #Used to determine if a file has been properly loaded
ans = ""    #Used for all answers the user wants to input
firstChar = ""  #Used to contain the first character of the ans string

while (checkLoop == True):
    print("\nWould you like to edit a save file?\n")
    ans = input("Enter \"Yes\" or \"No\": ")
    firstChar = ans[0].upper()

    if (firstChar == 'N'):
        checkLoop = False
    elif (firstChar == 'Y'):
        toSave = {}
        checkFile = importSave()
        if (checkFile[0] == True):
            toSave = checkFile[1]
            toSave = askDict()
            exportSave(toSave)
            checkLoop = True    #Not necessary, but it seems prudent to set it to true; in more complicated programs, this would likely just increase runtime
    else:
        print("Please enter only yes or no answers\n")