from tools import *

#--------------------2. What are the groups/classification of drugs?--------------------
# We will be classifying the drugs based on their sufixes,
# Source: https://accesspharmacy.mhmedical.com/content.aspx?bookid=1549&sectionid=93411751
# Source: https://www.drugs.com/inn-stems.html
data = open("dane.txt")
drug_suffixes = {}
for line in data:
    k,v = line.rstrip().lstrip().split("\t")
    drug_suffixes[k] = v

def classify_drug(drugname): #function to classify the drug based on the suffix
    for i in drug_suffixes.keys():
        if drugname.endswith(i):
            return drug_suffixes[i]

df['drugClass'] = df['drugName'].apply(classify_drug) #applying the function to the drugName column

print(df[['drugName','drugClass']])

arr = np.array(df['drugClass'].unique()) #unique drug classes

print(len(arr)) #number of unique drug classes
# Result: 144

#Which class of drug is the most common?
#print(df['drugClass'].value_counts().head(10))
# Result:
# female hormone (progestin)                       9695
# Loop diuretics                                   3212
# Selective serotonin reuptake inhibitors          3061
# Antifungal                                       2083
# psychoactive                                     1920
# diazepam derivatives                             1819
# antibiotics, produced by Streptomyces strains    1590
# antiandrogens                                    1361
# analgesics                                       1216
# Nondepolarizing paralytics                       1186
# This shows that the most common drug that has the review is classified as female hormone (progestin)

plt.figure(figsize=(20,10))
df['drugClass'].value_counts().nlargest(20).plot(kind='bar') #plotting the top 20 drug classes
plt.title("Distribution of Drugs by Class")
plt.show()

#print(df['drugClass'].value_counts().nsmallest(20)) # the least common drug classes
#Result:
# acetylcholinesterase inhibitors, tacrine derivatives                                              1
# analogues of penicillanic acid antibiotics modified in the five-membered ring                     1
# hirudin derivatives                                                                               1
# Vasopressin receptor antagonist                                                                   1
# bradycardic agents                                                                                1
# antiallergics, cromoglicic acid derivatives                                                       1
# antineoplastics, topoisomerase I inhibitors                                                       1
# antibiotics, carbacepham derivatives                                                              1
# oxytocin derivatives                                                                              1
# aldosterone antagonists, spironolactone derivates                                                 2
# antineoplastic, alkylating agents, methanesulfonates                                              2
# antibiotics, kanamycin and bekanamycin derivatives (obtained from Streptomyces kanamyceticus);    2
# growth hormone release-stimulating peptides                                                       3
# N-methylated xanthine derivatives                                                                 3
# hormone-release inhibiting peptides                                                               3
# b-lactamase inhibitors                                                                            3

#Those are the least common drug classes

#Distribution of drugs per Drug Group based on size
drugs_Groups = df.groupby('drugClass').size()

#Converting the series to a dataframe
drug_group_df = pd.DataFrame({'drug_Class': drugs_Groups.index, 'count': drugs_Groups.values})

# Seaborn Plot
plt.figure(figsize=(20,10))
g = sns.barplot(x="drug_Class", y="count", data=drug_group_df) #plotting the drug classes
g.set_xticklabels(g.get_xticklabels(), rotation=90) #rotating the x-axis labels
plt.show()

#This concludes the analysis about classifications of drugs

#Which class of drugs has the highest average rating?
average_rating_per_class = df.groupby('drugClass')['rating'].mean()
plt.figure(figsize=(20,10))
average_rating_per_class.hist()
plt.title("Histogram of Average Rating per Drug Class")
plt.grid(True)
plt.show()
#Results show that most of the drugs classified by their classes have an average rating of 7-8

#which group of drugs has the highest average rating?
print(average_rating_per_class.nlargest(20))
#Result:
# acetylcholinesterase inhibitors, tacrine derivatives                    10.000000
# antiallergics, cromoglicic acid derivatives                             10.000000
# antineoplastic, alkylating agents, methanesulfonates                    10.000000
# bradycardic agents                                                      10.000000
# hirudin derivatives                                                     10.000000
# ll-2 derivatives                                                        10.000000
# oxytocin derivatives                                                    10.000000
# ribofuranil-derivatives of the pyrazofurin type                         10.000000
# benzodioxane derivatives                                                 9.800000
# mucolytics, other than bromhexine derivatives                            9.555556
# vasoconstrictors, vasopressin derivatives                                9.538462
# antineoplastic, alkylating agents, (b-chloroethyl) amine derivatives     9.250000
# heparin derivatives including low molecular mass heparins                9.222222
# analgesics, pethidine derivatives                                        9.106383
# Methylxanthine                                                           9.000000
# Vasopressin receptor antagonist                                          9.000000
# antibiotics, carbacepham derivatives                                     9.000000
# hormone-release inhibiting peptides                                      9.000000
# Barbiturates                                                             8.894737
# Benzodiazepinea                                                          8.837451


import re
import string
import ipaddress

from . import utils

class RequestProtocol(object):
    METHOD_GET = 'GET'
    METHOD_OPTIONS = 'OPTIONS'
    METHOD_HEAD = 'HEAD'
    METHOD_POST = 'POST'
    METHOD_PUT = 'PUT'
    METHOD_DELETE = 'DELETE'
    METHOD_TRACE = 'TRACE'
    METHOD_CONNECT = 'CONNECT'

    HTTP_VERSION = '1.1'

    CRLF = '\r\n'
    SP = ' '

    REQUEST_LINE = '{method}{sp}{request_uri}{sp}HTTP/{http_version}{crlf}'

    @classmethod
    def path(cls, uri):
        path = uri.path
        if uri.query:
            path = '{}?{}'.format(path, uri.query)
        return path

    @classmethod
    def header_fields(cls, headers):
        return '\r\n'.join(
            '{}: {}'.format(h, v) for h, v in headers.items())

    @classmethod
    def request_line(cls, method, request_uri):
        return cls.REQUEST_LINE.format(
            method=method,
            sp=cls.SP,
            request_uri=request_uri,
            http_version=cls.HTTP_VERSION,
            crlf=cls.CRLF)

class ResponseProtocol(object):
    COLON = ':'
    HTTP = 'HTTP/'

    REGEX_CHARSET = re.compile(r';\s*charset=([^;]*)', re.I)
    REGEX_TOKEN = re.compile(
        r'([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|'
        r'([^ \t",;]*)))?')

    @classmethod
    def parse_status(cls, status):
        if status.startswith(cls.HTTP):
            http_version, status_code, status_text = status.split(None, 2)
            status = '{} {}'.format(
                utils.smart_text(status_code),
                utils.smart_text(status_text))
        return status

    @classmethod
    def parse_status_code(cls, status):
        return int(status.split()[0])

    @classmethod
    def parse_charset(cls, header, charset):
        match = cls.REGEX_CHARSET.search(utils.smart_text(header))
        if match:
            charset = match.group(1)
        return charset

    @classmethod
    def parse_cache_control(cls, header):
        header = utils.smart_text(header)
        cache = {}
        for match in cls.REGEX_TOKEN.finditer(header):
            name = match.group(1)
            value = match.group(2) or match.group(3) or None
            if value and value.isdigit():
                value = int(value)
            cache[name] = value

        cache_control = {}
        for n in [
            'public',
            'no-store',
            'no-transform',
            'must-revalidate',
            'proxy-revalidate',
        ]:
            if n not in cache:
                continue
            cache_control[n] = None

        for n, v in cache.items():
            if n not in [
                'private',
                'no-cache',
                'max-age',
                's-maxage',
                'stale-while-revalidate',
                'stale-if-error',
            ]:
                continue
            cache_control[n] = v
        return cache_control

class URIProtocol(object):
    ALPHA = string.ascii_letters
    DIGIT = string.digits
    UNRESERVED = ALPHA + DIGIT + '-' '.' '_' '~'

    GEN_DELIMS = ':' '/' '?' '#' '[' ']' '@'
    SUB_DELIMS = '!' '$' '&' '\'' '(' ')' '*' '+' ',' ';' '='
    RESERVED = GEN_DELIMS + SUB_DELIMS

    PCT_ENCODED = '%' + string.hexdigits
    PCHAR = UNRESERVED + PCT_ENCODED + SUB_DELIMS + ':' + '@'

    # Parts
    SCHEME = ALPHA + DIGIT + '+' + '-' + '.'
    QUERY = PCHAR + '/' '?'
    FRAGMENT = PCHAR + '/' '?'

    # Authority
    USERINFO = UNRESERVED + PCT_ENCODED + SUB_DELIMS + ':'
    PORT = DIGIT

    # Host
    REG_NAME = UNRESERVED + PCT_ENCODED + SUB_DELIMS

    # Path
    SEGMENT = PCHAR
    SEGMENT_NZ_NC = UNRESERVED + PCT_ENCODED + SUB_DELIMS + '@'

    @classmethod
    def strip_scheme(cls, uri):
        if ':' not in uri:
            return None, uri

        scheme, hier_part = uri.split(':', 1)
        if scheme[0] not in cls.ALPHA:
            raise exc.SchemeException(uri)

        if any(c not in cls.SCHEME for c in scheme[1:]):
            raise exc.SchemeException(scheme)

        return scheme.lower(), hier_part

    @classmethod
    def strip_fragment(cls, hier_part):
        if '#' in hier_part:
            hier_part, fragment = \
                hier_part.rsplit('#', 1)
            if any(c not in cls.FRAGMENT for c in fragment):
                raise exc.FragmentException(fragment)
        else:
            fragment = None
        return fragment, hier_part

    @classmethod
    def strip_query(cls, hier_part):
        if '?' in hier_part:
            hier_part, query = hier_part.rsplit('?', 1)
            if any(c not in cls.QUERY for c in query):
                raise exc.QueryException(query)
        else:
            query = None
        return query, hier_part

    @classmethod
    def strip_authority(cls, hier_part):
        if hier_part.startswith('//'):
            hier_part = hier_part[2:]
        if '/' in hier_part:
            authority, hier_part = hier_part.split('/', 1)
            hier_part = '/{}'.format(hier_part)
        else:
            authority = hier_part
            hier_part = ''
        return authority, hier_part

    @classmethod
    def strip_userinfo(cls, authority):
        if '@' in authority:
            userinfo, authority = authority.split('@', 1)
            if any(c not in cls.USERINFO for c in userinfo):
                raise exc.UserInfoException(userinfo)
            if not userinfo:
                userinfo = None
        else:
            userinfo = None
        return userinfo, authority

    @classmethod
    def strip_port(cls, authority):
        if ':' in authority:
            authority, port = authority.rsplit(':', 1)
        else:
            return None, authority
        if port.isdigit():
            port = int(port)
        else:
            raise exc.PortException(port)
        return port, authority

    @classmethod
    def verify_reg_name(cls, host):
        return all(c in cls.REG_NAME for c in host)

    @classmethod
    def verify_ipv4_address(cls, host):
        if '.' not in host:
            return False

        try:
            ipaddress.IPv4Address(host)
        except ipaddress.AddressValueError:
            return False
        else:
            return True

    @classmethod
    def verify_ipv6_address(cls, host):
        if ':' not in host:
            return False

        try:
            ipaddress.IPv6Address(host)
        except ipaddress.AddressValueError:
            return False
        else:
            return True

    @classmethod
    def verify_path_abempty(cls, path):
        if not path:
            return True

        if not path.startswith('/'):
            return False

        segments = path.split('/')
        for segment in segments:
            if any(c not in cls.SEGMENT for c in segment):
                return False
        else:
            return True

    @classmethod
    def verify_path_absolute(cls, path):
        if not path.startswith('/'):
            return False

        segments = path.split('/')[1:]
        segment = segments[0]
        if not segment or any(c not in cls.SEGMENT for c in segment):
            return False

        for segment in segments[1:]:
            if any(c not in cls.SEGMENT for c in segment):
                return False
        else:
            return True

    @classmethod
    def verify_path_noscheme(cls, path):
        if path.startswith('/'):
            return False

        segments = path.split('/')
        segment = segments[0]
        if not segment or any(c not in cls.SEGMENT_NZ_NC for c in segment):
            return False

        for segment in segments[1:]:
            if any(c not in cls.SEGMENT for c in segment):
                return False
        else:
            return True

    @classmethod
    def verify_path_rootless(cls, path):
        if path.startswith('/'):
            return False

        segments = path.split('/')
        segment = segments[0]
        if not segment or any(c not in cls.SEGMENT for c in segment):
            return False

        for segment in segments[1:]:
            if any(c not in cls.SEGMENT for c in segment):
                return False
        else:
            return True

    @classmethod
    def verify_path_empty(cls, path):
        return bool(path)


from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Image, PageBreak, Table,TableStyle
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_JUSTIFY, TA_LEFT, TA_CENTER, TA_RIGHT
from reportlab.rl_config import defaultPageSize
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from django.http import FileResponse
from django.urls import reverse
from reportlab.pdfgen import canvas
from django.contrib import messages
from reportlab.lib import colors
from .forms import ClienteForm
from datetime import datetime
from .models import Cliente, Mantenimiento, Dispositivo, Precio
from datetime import date
import io
import os
from django.urls import reverse_lazy
from django.contrib.auth.views import LoginView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from num2words import num2words

# ------ VIEWS DISPOSITIVOS ------ #

class Agregar_Dispositivo(LoginRequiredMixin, CreateView):
    # Manda a llamar el Modelo Mantenimiento
    model = Dispositivo
    # Hace la eleccion de que inputs del Modelo tomar en cuenta
    fields = ['marca','titulo','cantidad','actividad','plan']
    # Se utiliza para regresar al usuario a una pagina en especifico despues de terminar
    success_url = reverse_lazy('lista_clientes')
    # Busca un html en especifico
    template_name = 'mantenimientos/agregar_dispositivo.html'

    def form_valid(self, form):
        form.instance.usuario = self.request.user
        form.instance.cliente = Cliente.objects.get(pk=self.kwargs['pk'])
        return super(Agregar_Dispositivo, self).form_valid(form)

    def get_success_url(self):
        return reverse('mostrar_cliente', kwargs={'pk':self.object.cliente.id})

class Update_Dispositivo(LoginRequiredMixin, UpdateView):
    model = Dispositivo
    fields =['marca','titulo','cantidad','actividad','plan']
    template_name = 'mantenimientos/modificar_dispositivo.html'
    def get_success_url(self):
        return reverse('mostrar_cliente', kwargs={'pk':self.object.cliente.id})

class Eliminar_Dispositivo(LoginRequiredMixin, DeleteView):
    model = Dispositivo
    context_object_name = 'dispositivo'
    template_name = 'mantenimientos/eliminar_dispositivo.html'
    def get_success_url(self):
        return reverse('mostrar_cliente', kwargs={'pk':self.object.cliente.id})

class Detalle_Dispositivo(LoginRequiredMixin, DetailView):
    model = Dispositivo
    context_object_name = 'dispositivo'
    template_name = 'mantenimientos/detalle_dispositivo.html'

# ------ VIEWS SERVICIOS ------ #

class Agregar_Servicio(LoginRequiredMixin, CreateView):
    # Manda a llamar el Modelo Mantenimiento
    model = Mantenimiento
    # Hace la eleccion de que inputs del Modelo tomar en cuenta
    fields = ['Titulo','periodisidadactividades', 'periodisidadadicional','tiempoejecucion', 'cantidaddispositivos', 'horasactividad']
    # Busca un html en especifico
    template_name = 'mantenimientos/agregar_servicio.html'

    def form_valid(self, form):
        form.instance.usuario = self.request.user
        form.instance.cliente = Cliente.objects.get(pk=self.kwargs['pk'])
        return super(Agregar_Servicio, self).form_valid(form)

    def get_success_url(self):
        return reverse('mostrar_cliente', kwargs={'pk':self.object.cliente.id})

class MttoUpdate(LoginRequiredMixin, UpdateView):
    model = Mantenimiento
    fields = ['Titulo','periodisidadactividades', 'periodisidadadicional','tiempoejecucion', 'cantidaddispositivos', 'horasactividad']
    template_name = 'mantenimientos/modificar_servicio.html'

    def get_success_url(self):
        return reverse('mostrar_cliente', kwargs={'pk':self.object.cliente.id})

class EliminarMantenimiento(LoginRequiredMixin, DeleteView):
    model = Mantenimiento
    context_object_name = 'servicio'
    template_name = 'mantenimientos/eliminar_servicio.html'

    def get_success_url(self):
        return reverse('mostrar_cliente', kwargs={'pk':self.object.cliente.id})

class Detalle_Servicio(LoginRequiredMixin, DetailView):
    model = Mantenimiento
    context_object_name = 'servicio'
    template_name = 'mantenimientos/detalle_servicio.html'

# ------ VIEWS CLIENTE ------ #

class CustomLoginView(LoginView):
    # Esta clase se encarga de verificar que el usuario este autenticado antes de poder
    # entrar a cualquier parte de la pagina.
    template_name = 'mantenimientos/login.html'
    fields = '__all__'
    redirect_authenticated_user = True

    def get_success_url(self) -> str:
        return reverse_lazy('lista_clientes')

class Home(LoginRequiredMixin, ListView):
    model = Cliente
    context_object_name = 'Cliente'
    template_name = 'mantenimientos/home.html'
    # Se encarga de manejar los datos observables por el usuario
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # compara los usuarios con su informacion y projecta solo informacion de usuario
        context['Cliente'] = context['Cliente'].filter(usuario=self.request.user)
        #context['count'] = context['mantenimientos'].filter(complete=False).count()
        return context

class Agregar_Cliente(LoginRequiredMixin, CreateView):
    model = Cliente
    fields = ['nombre', 'encargado', 'puesto_encargado',
            'numero_contacto', 'correo_contacto',
            'lugar_de_mantenimiento', 'descripcion_cotizacion'
            ,]
    success_url = reverse_lazy('lista_clientes')
    template_name = 'mantenimientos/agregar_cliente.html'

    def form_valid(self, form):
        form.instance.usuario = self.request.user
        return super(Agregar_Cliente, self).form_valid(form)
    def get_success_url(self):
        return reverse('mostrar_cliente', kwargs={'pk':self.object.pk})

class Modificar_Cliente (LoginRequiredMixin, UpdateView):
    model = Cliente
    fields = ['nombre', 'encargado', 'puesto_encargado',
            'numero_contacto', 'correo_contacto',
            'lugar_de_mantenimiento', 'descripcion_cotizacion',
            'fecha',]
    template_name = 'mantenimientos/modificar_cliente.html'
    def get_success_url(self):
        return reverse('mostrar_cliente', kwargs={'pk':self.object.pk})

class Eliminar_Cliente(LoginRequiredMixin, DeleteView):
    model = Cliente
    context_object_name = "cliente"
    success_url = reverse_lazy("lista_clientes")
    template_name = "mantenimientos/confirm_delete.html"

class Todos_Clientes(LoginRequiredMixin, ListView):
    model = Cliente
    context_object_name = 'lista_clientes'
    template_name = 'mantenimientos/Clientes.html'
    # Se encarga de manejar los datos observables por el usuario
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # compara los usuarios con su informacion y projecta solo informacion de usuario
        context['lista_clientes'] = context['lista_clientes'].filter(usuario=self.request.user)
        #context['count'] = context['mantenimientos'].filter(complete=False).count()
        return context

def buscar_clientes(request):
    if request.method == "POST":
        searched = request.POST["searched"]
        clientes = Cliente.objects.filter(nombre__contains=searched)
        return render(request,
                      'mantenimientos/buscar_clientes.html',
                      {'searched':searched,
                       'clientes':clientes,
                       })
    else:
        return render(request, 'mantenimientos/buscar_clientes.html',{})

class Mostrar_Cliente(LoginRequiredMixin, DetailView):
    model = Cliente
    object = "cliente"
    template_name = "mantenimientos/detalle_cliente.html"
    def get_context_data(self, **kwargs):
        ctx = super(Mostrar_Cliente, self).get_context_data(**kwargs)
        # del diccionario de Key Word ARGumentS obtiene el valor de object
        cat = kwargs.get("object")
        ctx['servicios'] = Mantenimiento.objects.filter(cliente = cat)
        ctx['dispositivos'] = Dispositivo.objects.filter(cliente = cat)
        return ctx

def cotizacion_pdf(request, cliente_id):

    cliente = Cliente.objects.get(pk=cliente_id)
    # mantenimientos = Cliente.mantenimiento.through.objects.
    buf = io.BytesIO()

    nombre=cliente.nombre
    encargado=cliente.encargado
    puesto_encargado=cliente.puesto_encargado
    numero_contacto=cliente.numero_contacto
    correo_contacto=cliente.correo_contacto
    lugar_de_mantenimiento=cliente.lugar_de_mantenimiento
    descripcion_cotizacion=cliente.descripcion_cotizacion
    fecha=cliente.fecha

    dateTimeObj = datetime.now()
    dateObj = dateTimeObj.date()
    dateStr = dateObj.strftime("%b %d , %Y")

    actyear = str(date.today().year)
    sigyear = str(date.today().year + 1)

    PAGE_HEIGHT = defaultPageSize[1];
    PAGE_WIDTH = defaultPageSize[0]
    styles = getSampleStyleSheet()
    styles.add(ParagraphStyle(name='Normal_R',
                              parent=styles['Normal'],
                              wordWrap='LTR',
                              alignment=TA_RIGHT,
                              fontSize=12,
                              textColor=colors.black,
                              ))
    styles.add(ParagraphStyle(name='Normal_C',
                              parent=styles['Normal'],
                              wordWrap='LTR',
                              alignment=TA_CENTER,
                              fontSize=12,
                              textColor=colors.black,
                              ))
    styles.add(ParagraphStyle(name='Normal_Right',
                              parent=styles['Normal'],
                              wordWrap='LTR',
                              alignment=TA_RIGHT,
                              fontSize=12,
                              textColor=colors.black,
                              fontName="Helvetica-bold",
                              ))

    styles.add(ParagraphStyle(name='Heading1_B',
                              parent=styles['Heading1'],
                              wordWrap='LTR',
                              alignment=TA_LEFT,
                              fontSize=12,
                              textColor=colors.HexColor("#3498DB"),
                              ))
    styles.add(ParagraphStyle(name='Heading1_BC',
                              parent=styles['Heading1'],
                              wordWrap='LTR',
                              alignment=TA_CENTER,
                              fontSize=12,
                              textColor=colors.HexColor("#3498DB"),
                              ))

    styles.add(ParagraphStyle(name='Normal_CB',
                              parent=styles['Normal'],
                              wordWrap='CJK',
                              alignment=TA_CENTER,
                              fontSize=12,
                              textColor=colors.black,
                              fontName="Helvetica-bold",
                              ))
    styles.add(ParagraphStyle(name='Normal_B',
                              parent=styles['Normal'],
                              wordWrap='CJK',
                              alignment=TA_LEFT,
                              fontSize=12,
                              textColor=colors.black,
                              fontName="Helvetica-bold",
                              ))
    styles.add(ParagraphStyle(name='Normal_Red',
                              parent=styles['Normal'],
                              wordWrap='CJK',
                              alignment=TA_LEFT,
                              fontSize=12,
                              textColor=colors.red,
                              fontName="Helvetica-bold",
                              ))
    styles.add(ParagraphStyle(name='Normal_Ye',
                              parent=styles['Normal'],
                              wordWrap='CJK',
                              alignment=TA_CENTER,
                              fontSize=12,
                              textColor=colors.black,
                              fontName="Helvetica-bold",
                              backColor = colors.yellow,
                              ))

    def myFirstPage(canvas, doc):
        path = os.getcwd()
        path = os.path.join(path,"RPA","img_pdf")
        canvas.saveState()
        canvas.setFont('Times-Bold', 16)
        canvas.setFont('Times-Roman', 14)
        canvas.drawImage(os.path.join(path,'logo.png'), 0.8 * inch, 660, width=160, height=80)
        canvas.drawImage(os.path.join(path,'lenellogo.png'), 6.5 * inch, 660, width=80, height=80)
        canvas.drawImage(os.path.join(path,'footer.png'), inch, 1, width=460, height=80)
        canvas.restoreState()

    def myLaterPages(canvas, doc):
        path = os.getcwd()
        path = os.path.join(path,"RPA","img_pdf")
        canvas.saveState()
        canvas.setFont('Times-Roman', 9)
        canvas.drawImage(os.path.join(path,'logo.png'), 0.8 * inch, 660, width=160, height=80)
        canvas.drawImage(os.path.join(path,'lenellogo.png'), 6.5 * inch, 660, width=80, height=80)
        canvas.drawImage(os.path.join(path,'footer.png'), inch, 1, width=460, height=80)
        canvas.restoreState()

    def go():
        cliente = Cliente.objects.get(pk=cliente_id)
        mantenimientos = Mantenimiento.objects.filter(cliente = cliente_id)
        dispositivos = Dispositivo.objects.filter(cliente = cliente_id)
        doc = SimpleDocTemplate(buf, pagesize=letter,
                                rightMargin=inch, leftMargin=inch,
                                topMargin=2 * inch, bottomMargin=inch)
        encargado = cliente.encargado
        puesto = cliente.puesto_encargado
        clienteTexto = cliente.nombre

        Story = []

        styleN = styles["Normal"]
        styleH4 = styles["Heading4"]
        styleH2 = styles["Heading2"]

        styleRight = styles["Normal_R"]
        styleCB = styles[("Normal_CB")]
        styleB = styles[("Normal_B")]
        styleHB = styles[("Heading1_B")]
        styleHBC = styles[("Heading1_BC")]
        styleNC = styles[("Normal_C")]
        styleNR = styles[("Normal_Red")]
        styleNY = styles[("Normal_Ye")]
        styleNRight = styles[("Normal_Right")]

        texto_fecha = ("Tijuana, B.C. a " + dateStr)
        texto_encargado = ("Attn. " + encargado)
        texto_asunto = ("Asunto:")

        p0 = Paragraph(texto_fecha, styleRight)
        p1 = Paragraph(texto_encargado, styleH4)
        p2 = Paragraph(puesto, styleN)
        p3 = Paragraph(clienteTexto, styleH2)
        p4 = Paragraph(texto_asunto, styleH2)
        p5 = Paragraph(""""""+descripcion_cotizacion+"""""", styleCB)
        p6 = Paragraph("Estimados señores, ", styleN)
        p7 = Paragraph("Según su solicitud, nos complace presentar la propuesta de mantenimiento, diagnóstico del sistema detección de incendios. en el documento, se especifican los requisitos generales para "+lugar_de_mantenimiento+" de "+nombre, styleN)
        pblank = Paragraph("""<para>
 </para>""")
        p8 = Paragraph("Índice de propuesta:, ", styleN)
        p9 = Paragraph("1.0 Fondo", styleN)
        p10 = Paragraph("2.0 Alcance de la descripción del trabajo", styleN)
        p11 = Paragraph("3.0 Resumen de propuestas económicas", styleN)
        p12 = Paragraph("4.0 Términos y condiciones", styleN)
        p13 = Paragraph("1.0 Fondo", styleHB)
        p14 = Paragraph("A continuación, se muestra una visión general de los equipos y condiciones actuales. Se presenta una lista de equipos instalados actualmente en el lugar.",styleN)
        p15 = Paragraph("1.1 Politica de mantenimiento preventivo",styleHB)
        p16 = Paragraph("Para aplicar el mantenimiento preventivo se entenderá que el sistema de detección de incendios debe estar en operación al 100%, si esto no se cumpliera así deberá realizarse primero el mantenimiento correctivo",styleN)
        listadispositivos = ''
        listdisp = list(dispositivos)
        lastdisp = listdisp[-1]

        for dispositivo in dispositivos:
            if len(dispositivos) == 1:
                listadispositivos = listadispositivos+" "+str(dispositivo.cantidad)+" "+str(dispositivo.titulo)+'.'

            elif dispositivo != lastdisp:
                listadispositivos = listadispositivos+" "+str(dispositivo.cantidad)+" "+str(dispositivo.titulo)+","

            elif dispositivo == lastdisp:
                listadispositivos = listadispositivos+" "+str(dispositivo.cantidad)+" "+str(dispositivo.titulo)+","
                listadispositivos = listadispositivos[:-1]
                listadispositivos = listadispositivos+"."

        p17 = Paragraph("Una politica de mantenimiento preventivo se considera valida para "+str(listadispositivos),styleN)
        p18 = Paragraph("Vigencia **"+actyear+"-"+sigyear+"**",styleB)
        p19 = Paragraph("En la siguiente tabla se muestran las actividades que se consideran.",styleB)
        p20 = Paragraph("2.0 Alcance de la descripción del trabajo",styleHB)
        palcances1 = Paragraph("Cada actividad de servicio de 1 año",styleNR)
        palcances2 = Paragraph("Limpieza de dispositivos 12-20 pies de altura.",styleN,bulletText="•")
        palcances3 = Paragraph("Limpieza de Panel (Pantallas lcd, conectores, terminales de cableado, limpieza,sellos silicón, limpiezageneral del Panel en sus partes de funcionalidad revisión de conectividad a panel o y actividad en lazo)",styleN,bulletText="•")
        palcances4 = Paragraph("Limpieza del sistema de gestión de energía exterior (filtros de aire, CSI· C., sellos de silicona de gabinete, conectores de conducto de ajuste, fuente de alimentación, baterías, cables de alimentación y conectores).",styleN,bulletText="•")
        palcances5 = Paragraph("Revisión de la comunicación de dispositivos con el PANEL",styleN,bulletText="•")
        palcances6 = Paragraph("Comprobar el funcionamiento de las fuentes de alimentación",styleN,bulletText="•")
        palcances7 = Paragraph("Verificar la prueba del lazo",styleN,bulletText="•")
        palcances8 = Paragraph("De forma programada, cada 1er día laborable de cada mes se limpiará el equipo antes mencionado.",styleN,bulletText="•")

        palcances9 = Paragraph("Monitoreo de revisiones de los puntos anteriores.",styleN,bulletText="•")
        palcances10 = Paragraph("Servicio profesional para aplicar los conocimientos de ingeniería especializada en Detección de incendios",styleN,bulletText="•")
        palcances11= Paragraph("De forma programada, una vez al año el equipo mencionado anteriormente se realizará el mmtto Preventivo. En caso de fallos en el sistema se propondrá realizar el Mmtto Correctivo ",styleN,bulletText="•")
        palcances12= Paragraph("El alcance es sólo para el sistema de detección de incendios, Panel y equipos instalados previamente en sitio mencionado en esta propuesta en la sección inicial fondo de este documento",styleN,bulletText="•")
        palcances13= Paragraph("Una vez completado el mantenimiento, el informe se entrega con la información resultante, el formato que especifica el estado actual de cada equipo.",styleN,bulletText="•")
        palcances14= Paragraph("El informe hará la recomendación de corrección, reparación o sustitución de cualquiera de los equipos.",styleN,bulletText="•")
        palcances15= Paragraph("El pago del mantenimiento es anual, debe ser pagado antes de ser realizado.",styleN,bulletText="•")
        palcances16= Paragraph("Incluye Maquinaria de elevacion.",styleN,bulletText="•")

        ppolitica = Paragraph("2.1 Política de apoyo técnico y diagnóstico",styleHB)
        ppolitica1 = Paragraph("Teléfono móvil disponible para emergencias durante las horas contratadas.",styleN,bulletText="•")
        ppolitica2 = Paragraph("Soporte técnico telefónico con un tiempo de respuesta de 4 horas.",styleN,bulletText="•")
        ppolitica3 = Paragraph("Soporte técnico in situ 4 horas de tiempo de respuesta, 5 días a la semana (de lunes a viernes de 8:00am a 5:00pm).",styleN,bulletText="•")
        ppolitica4 = Paragraph("30 (treinta) horas de servicio técnico incluyen por un período de 12 meses, Si el cliente hace uso de las 30 hrs de servicio, deberá renovarse la Póliza en una nueva cotización",styleN,bulletText="•")
        ppolitica5 = Paragraph("El alcance es sólo para el sistema de detección de incendios, hardware de DCI mencionado en esta propuesta en la sección inicial fondo de este documento",styleN,bulletText="•")
        ppolitica6 = Paragraph("Para la atención de:",styleN,bulletText="•")
        ppolitica7 = Paragraph("Fallos y diagnóstico",styleN,bulletText="-")
        ppolitica8 = Paragraph("Ajustes",styleN,bulletText="-")
        ppolitica9 = Paragraph("Actualizaciones",styleN,bulletText="-")
        ppolitica10 = Paragraph("Panel, configuraciones de equipo de detección",styleN,bulletText="-")
        ppolitica11 = Paragraph("Soporte técnico para problemas con el Panel",styleN,bulletText="-")
        ppolitica12 = Paragraph("Soporte técnico para problemas con los dispositivos",styleN,bulletText="-")
        ppolitica13 = Paragraph("Tarjetas loops, panel, estrobos, sensores fotoeléctricos, fuentes de poder, módulos de control. Monitores de flujo, resistencias de fin de línea.",styleN,bulletText="-")
        ppolitica14 = Paragraph("Emergencias del sistemas (1 hora)",styleN,bulletText="-")
        ppolitica15 = Paragraph("Si se detecta un dispositivo dañado durante el diagnóstico, se notificará en el relleno de informe para su posterior mmtto correctivo. ",styleN,bulletText="•")
        ppolitica16 = Paragraph("""Sistema base web para mejorar sus servicios y registros de mantenimiento""",styleN,bulletText="•")

        td_dispositivos =[["Marca","Nombre","Cantidad","Actvidad","Plan"]]
        for dispositivo in dispositivos:
            data_dispositivos = [dispositivo.marca,dispositivo.titulo,dispositivo.cantidad,dispositivo.actividad,dispositivo.plan]
            td_dispositivos.append(data_dispositivos)
        table_dis = Table(td_dispositivos)
        ts = TableStyle([("GRID",(0,0),(-1,-1),2,colors.black)])
        table_dis.setStyle(ts)

        td_mantenimientos = [["Mantenimiento","Acts. de mmnto por año",
                            "Acts. adicionales/Renta de equipo"
                            ,"Tiempo de ejecucion"]]
        for mantenimiento in mantenimientos:
            data_mantenimientos = [mantenimiento.Titulo,mantenimiento.periodisidadactividades,mantenimiento.periodisidadadicional,mantenimiento.tiempoejecucion]
            td_mantenimientos.append(data_mantenimientos)
        table_man = Table(td_mantenimientos)
        table_man.setStyle(ts)

        td_total = [["Total de HRS de servicio de soporte técnico de poliza",""]]
        suma_horas = 0
        for mantenimiento in mantenimientos:
            suma_horas = suma_horas + mantenimiento.horasactividad

        data_mantenimientos = ["", suma_horas]
        td_total.append(data_mantenimientos)
        table_tot = Table(td_total)
        ts_tot = TableStyle([("GRID",(0,0),(-1,-1),2,colors.black),
                             ("BACKGROUND",(0,0),(-1,-1),colors.yellow)])
        table_tot.setStyle(ts_tot)

        preciofinal = 0
        for mantenimiento in mantenimientos:
            preciofinal = preciofinal + mantenimiento.costomantenimientoregular
        preciofinal1 = num2words(preciofinal, to="currency", lang='es', currency='USD').upper()

        td_precio = [["Description","QTY","Unit","Amount"]]
        data_precio = ["Cuota anual del contrato de  mantenimiento", "1","Lot","${}".format(preciofinal)]
        td_precio.append(data_precio)
        table_pre = Table(td_precio)
        ts_pre = TableStyle([("GRID",(0,0),(-1,-1),2,colors.black),
                             ("BACKGROUND",(0,0),(-1,0),colors.lightsteelblue)])
        table_pre.setStyle(ts_pre)
        ppreciotexto = Paragraph(preciofinal1+" USD + IVA",styleNRight)
        p21 = Paragraph("3.0 Resumen de la propuesta económica",styleHB)
        p22 = Paragraph(actyear+"-"+sigyear+" Mantenimiento operativo regular y soporte técnico anual",styleB)

        p23 = Paragraph("Total de Propuesta Económica de Mantenimiento Preventivo",styleHBC)
        p24 = Paragraph("Mmto.....................................................{}".format(preciofinal),styleNY)
        p25 = Paragraph(preciofinal1+" USD + IVA",styleNY)
        p26 = Paragraph("**Incluye maquinaria de elevacion**",styleCB)

        ptitulotermino = Paragraph("4.0 Términos y condiciones",styleHB)
        pterminos1 = Paragraph("Los precios cotizados se expresan en dólares americanos.",styleN,bulletText="-")
        pterminos2 = Paragraph("El IVA del 16% no está incluido.",styleN,bulletText="-")
        pterminos3 = Paragraph("El tipo de cambio será el de Santander a la venta en la ventanilla vigente el día de la operación de pago efectivo. LOS PAGOS NO SE ACEPTAN UTILIZANDO EL TIPO DE CAMBIO DEL DIARIO OFICIAL DE LA FEDERACIÓN.",styleN,bulletText="-")
        pterminos4 = Paragraph("Válido de la oferta: 30 días naturales, posteriormente los precios están sujetos a cambios sin previo aviso.",styleN,bulletText="-")
        pterminos5 = Paragraph("El proceso comienza confirmando su pago total o anticipo según sea el caso y su colocación del pedido de compra.",styleN,bulletText="-")
        pterminos6 = Paragraph("Para proceder con el mantenimiento correctivo, es necesario cubrir la póliza anual al 100% en el primer día de atención.",styleN,bulletText="-")
        pterminos7 = Paragraph("Para proceder con el mantenimiento preventivo, es necesario cubrir la anualidad de la póliza al 100% el primer día de la primera visita programada.",styleN,bulletText="-")
        pterminos8 = Paragraph("Los precios indicados son ofrecidos por el Total de la Propuesta aquí citado, cualquier cambio de condiciones o equipo seleccionado debe ser citado de nuevo.",styleN,bulletText="-")

        pfin = Paragraph("Fin del documento",styleNC)
        pregards = Paragraph("Regards",styleNC)
        pdanieljara = Paragraph("Ing. Daniel Jara Osuna",styleNC)
        pdirector = Paragraph("Director General",styleNC)

        Story.append(p0)
        Story.append(p1)
        Story.append(p2)
        Story.append(p3)
        Story.append(p4)
        Story.append(p5)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(p6)
        Story.append(pblank)
        Story.append(p7)
        Story.append(pblank)
        Story.append(p8)
        Story.append(p9)
        Story.append(p10)
        Story.append(p11)
        Story.append(p12)
        Story.append(PageBreak())

        #Segunda pagina
        Story.append(p13)
        Story.append(p14)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(table_dis)
        Story.append(PageBreak())

        #Tercera pagina
        Story.append(p15)
        Story.append(p16)
        Story.append(p17)
        Story.append(PageBreak())

        #Cuarta pagina
        Story.append(p18)
        Story.append(p19)
        Story.append(pblank)
        Story.append(table_man)
        Story.append(table_tot)
        Story.append(pblank)
        Story.append(PageBreak())

        #Quinta pagina
        Story.append(p20)
        Story.append(pblank)
        Story.append(palcances1)
        Story.append(pblank)
        Story.append(palcances2)
        Story.append(palcances3)
        Story.append(palcances4)
        Story.append(palcances5)
        Story.append(palcances6)
        Story.append(palcances7)
        Story.append(palcances8)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(palcances1)
        Story.append(pblank)
        Story.append(palcances9)
        Story.append(palcances10)
        Story.append(palcances11)
        Story.append(palcances12)
        Story.append(palcances13)
        Story.append(palcances14)
        Story.append(palcances15)
        Story.append(palcances16)
        Story.append(pblank)

        Story.append(PageBreak())

        Story.append(ppolitica)
        Story.append(ppolitica1)
        Story.append(ppolitica2)
        Story.append(ppolitica3)
        Story.append(ppolitica4)
        Story.append(ppolitica5)
        Story.append(ppolitica6)
        Story.append(ppolitica7)
        Story.append(ppolitica8)
        Story.append(ppolitica9)
        Story.append(ppolitica10)
        Story.append(ppolitica11)
        Story.append(ppolitica12)
        Story.append(ppolitica13)
        Story.append(ppolitica14)
        Story.append(ppolitica15)
        Story.append(ppolitica16)

        Story.append(PageBreak())

        #Sexta pagina
        Story.append(p21)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(p22)
        Story.append(pblank)
        Story.append(table_pre)
        Story.append(ppreciotexto)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(p23)
        Story.append(p24)
        Story.append(p25)
        Story.append(p26)

        Story.append(PageBreak())

        #Septima pagina
        Story.append(ptitulotermino)
        Story.append(pterminos1)
        Story.append(pterminos2)
        Story.append(pterminos3)
        Story.append(pterminos4)
        Story.append(pterminos5)
        Story.append(pterminos6)
        Story.append(pterminos7)
        Story.append(pterminos8)
        Story.append(pblank)
        Story.append(pfin)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(pblank)
        Story.append(pregards)
        Story.append(pdanieljara)
        Story.append(pdirector)

        doc.build(Story, onFirstPage=myFirstPage, onLaterPages=myLaterPages)
        # doc.build(Story)
    go()
    buf.seek(0)
    return FileResponse(buf, as_attachment=True,  filename='cotizacion_'+nombre+'.pdf')

# Create your views here.


from db import db

def add_admin(user_name):
    sql = "UPDATE users SET admin=TRUE WHERE username = :user_name RETURNING id"
    result = db.session.execute(sql, {"user_name":user_name})
    db.session.commit()
    user = result.fetchone()
    if user:
        return True
    return False

def add_restaurant(restaurant_name, restaurant_address, description):
    try:
        sql = """
            INSERT INTO restaurants (name, description, visible, address)
            VALUES (:restaurant_name, :description, TRUE, :restaurant_address)
            """
        db.session.execute(sql, {"restaurant_name":restaurant_name, "description":description,
        "restaurant_address":restaurant_address})
        db.session.commit()
    except:
        return False
    return True

def add_dish(restaurant_id, dish_name, price):
    try:
        sql = """
        INSERT INTO dishes (restaurant_id, dish_name, visible, price)
        VALUES (:restaurant_id, :dish_name, TRUE, :price)
        """
        db.session.execute(sql, {"restaurant_id":restaurant_id, "dish_name":dish_name, "price":price})
        db.session.commit()
    except:
        return False
    return True

# Deletions are done by updating database column Visible to False.

def delete_reviews(review_id):
    sql = "UPDATE reviews SET visible=FALSE WHERE id = :review_id RETURNING id"
    result = db.session.execute(sql, {"review_id":review_id})
    db.session.commit()
    review = result.fetchone()
    if review:
        return True
    return False

def delete_restaurant(restaurant_id):
    sql = "UPDATE restaurants SET visible=FALSE WHERE id = :restaurant_id RETURNING id"
    result = db.session.execute(sql, {"restaurant_id":restaurant_id})
    db.session.commit()
    restaurant = result.fetchone()
    if restaurant:
        return True
    return False

def delete_dish(dish_id):
    sql = "UPDATE dishes SET visible=FALSE WHERE id = :dish_id RETURNING id"
    result = db.session.execute(sql, {"dish_id":dish_id})
    db.session.commit()
    dish = result.fetchone()
    if dish:
        return True
    return False

def delete_user(user_id):
    sql = "UPDATE users SET visible=FALSE WHERE id = :user_id RETURNING id"
    result = db.session.execute(sql, {"user_id":user_id})
    db.session.commit()
    user = result.fetchone()
    if user:
        return True
    return False

def get_user_id(username):
    sql = "SELECT id FROM users WHERE username = :username"
    result = db.session.execute(sql, {"username":username})
    user_id = result.fetchone()
    if user_id:
        return user_id[0]
    return 0


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

from copy import copy
import re

from limpyd import fields as limpyd_fields
from limpyd.exceptions import ImplementationError

from .model import ModelWithDynamicFieldMixin

class DynamicFieldMixin(object):
    """
    This mixin adds a main functionnality to each domain it's attached to: the
    ability to have an unlimited number of fields. If a field is asked in the
    model which not exists, it will ask to each of its dynamic fields if it
    can accepts the wanted field name. If True, a new field is created on the
    fly with this new name.
    The matching is done using the "pattern" argument to pass when declaring
    the dynamic field on the model. This argument must be a regular expression
    (or a string, but in both cases the "re.compile" method will be called).
    If not defined, the default pattern will be used: ^basefieldname_\d+$ (here,
    basefieldname is the name used to declare the field on the model)
    To to the reverse operation, ie get a field name based on a dynamic part,
    the "format" argument can be passed when declaring the dynamic field on the
    model. Both pattern and format must match. If not defined, the default
    format is 'basefieldname_%s'.
    """

    def __init__(self, *args, **kwargs):
        """
        Handle the new optional "pattern" attribute
        """
        self._pattern = kwargs.pop('pattern', None)
        if self._pattern:
            self._pattern = re.compile(self._pattern)

        self._format = kwargs.pop('format', None)

        self.dynamic_version_of = None

        super(DynamicFieldMixin, self).__init__(*args, **kwargs)

    def _attach_to_model(self, model):
        """
        Check that the model can handle dynamic fields
        """
        if not issubclass(model, ModelWithDynamicFieldMixin):
            raise ImplementationError(
                'The "%s" model does not inherit from ModelWithDynamicFieldMixin '
                'so the "%s" DynamicField cannot be attached to it' % (
                model.__name__, self.name))

        super(DynamicFieldMixin, self)._attach_to_model(model)

        if self.dynamic_version_of is not None:
            return

        if hasattr(model, self.name):
            return

        setattr(model, self.name, self)

    @property
    def pattern(self):
        """
        Return the pattern used to check if a field name can be accepted by this
        dynamic field. Use a default one ('^fieldname_(.+)$') if not set when
        the field was initialized
        """
        if self.dynamic_version_of is not None:
            return self.dynamic_version_of.pattern

        if not self._pattern:
            self._pattern = re.compile('^%s_(.+)$' % self.name)
        return self._pattern

    @property
    def format(self):
        """
        Return the format used to create the name of a variation of the current
        dynamic field. Use a default one ('fieldname_%s') if not set when the
        field was initialized
        """
        if self.dynamic_version_of is not None:
            return self.dynamic_version_of.format

        if not self._format:
            self._format = '%s_%%s' % self.name
        return self._format

    @property
    def dynamic_part(self):
        if not hasattr(self, '_dynamic_part'):
            self._dynamic_part = self.pattern.match(self.name).groups()[0]
        return self._dynamic_part

    def _accept_name(self, field_name):
        """
        Return True if the given field name can be accepted by this dynamic field
        """
        return bool(self.pattern.match(field_name))

    def __copy__(self):
        """
        Copy the _pattern attribute to the new copy of this field
        """
        new_copy = super(DynamicFieldMixin, self).__copy__()
        new_copy._pattern = self._pattern
        return new_copy

    def _create_dynamic_version(self):
        """
        Create a copy of the field and set it as a dynamic version of it.
        """
        new_field = copy(self)
        new_field.dynamic_version_of = self
        return new_field

    def _base_field(self):
        """
        Return the base field (the one without variable part) of the current one.
        """
        return self.dynamic_version_of or self

    @property
    def _inventory(self):
        """
        Return (and create if needed) the internal inventory field, a SetField
        used to track all dynamic versions used on a specific instance.
        """
        if self.dynamic_version_of:
            return self.dynamic_version_of._inventory

        if not hasattr(self, '_inventory_field'):
            self._inventory_field = limpyd_fields.SetField()
            self._inventory_field._attach_to_model(self._model)
            self._inventory_field._attach_to_instance(self._instance)
            self._inventory_field.lockable = True
            self._inventory.name = self.name

        return self._inventory_field

    def _call_command(self, name, *args, **kwargs):
        """
        If a command is called for the main field, without dynamic part, an
        ImplementationError is raised: commands can only be applied on dynamic
        versions.
        On dynamic versions, if the command is a modifier, we add the version in
        the inventory.
        """
        if self.dynamic_version_of is None:
            raise ImplementationError('The main version of a dynamic field cannot accept commands')
        try:
            result = super(DynamicFieldMixin, self)._call_command(name, *args, **kwargs)
        except:
            raise
        else:
            if name in self.available_modifiers and name not in ('delete', 'hdel'):
                self._inventory.sadd(self.dynamic_part)
            return result

    def delete(self):
        """
        If a dynamic version, delete it the standard way and remove it from the
        inventory, else delete all dynamic versions.
        """
        if self.dynamic_version_of is None:
            self._delete_dynamic_versions()
        else:
            super(DynamicFieldMixin, self).delete()
            self._inventory.srem(self.dynamic_part)

    def _delete_dynamic_versions(self):
        """
        Call the `delete` method of all dynamic versions of the current field
        found in the inventory then clean the inventory.
        """
        if self.dynamic_version_of:
            raise ImplementationError(u'"_delete_dynamic_versions" can only be '
                                      u'executed on the base field')
        inventory = self._inventory
        for dynamic_part in inventory.smembers():
            name = self.get_name_for(dynamic_part)
            # create the field
            new_field = self._create_dynamic_version()
            new_field.name = name
            new_field._dynamic_part = dynamic_part  # avoid useless computation
            new_field._attach_to_model(self._model)
            new_field._attach_to_instance(self._instance)
            # and delete its content
            new_field.delete()

        inventory.delete()

    def get_name_for(self, dynamic_part):
        """
        Compute the name of the variation of the current dynamic field based on
        the given dynamic part. Use the "format" attribute to create the final
        name.
        """
        name = self.format % dynamic_part
        if not self._accept_name(name):
            raise ImplementationError('It seems that pattern and format do not '
                                      'match for the field "%s"' % self.name)
        return name

    def get_for(self, dynamic_part):
        """
        Return a variation of the current dynamic field based on the given
        dynamic part. Use the "format" attribute to create the final name
        """
        if not hasattr(self, '_instance'):
            raise ImplementationError('"get_for" can be used only on a bound field')
        name = self.get_name_for(dynamic_part)
        return self._instance.get_field(name)
    __call__ = get_for

class DynamicStringField(DynamicFieldMixin, limpyd_fields.StringField):
    pass

class DynamicInstanceHashField(DynamicFieldMixin, limpyd_fields.InstanceHashField):
    pass

class DynamicListField(DynamicFieldMixin, limpyd_fields.ListField):
    pass

class DynamicSetField(DynamicFieldMixin, limpyd_fields.SetField):
    pass

class DynamicSortedSetField(DynamicFieldMixin, limpyd_fields.SortedSetField):
    pass

class DynamicHashField(DynamicFieldMixin, limpyd_fields.HashField):
    pass


import cherrypy
from sqlalchemy import event

from ._repo import RepoObject  # noqa
from ._session import DbSession, SessionObject  # noqa
from ._sshkey import SshKey  # noqa
from ._token import Token  # noqa
from ._user import DuplicateSSHKeyError, UserObject  # noqa

Base = cherrypy.tools.db.get_base()

@event.listens_for(Base.metadata, 'after_create')
def db_after_create(target, connection, **kw):
    """
    Called on database creation to update database schema.
    """

    def exists(column):
        table_name = column.table.fullname
        column_name = column.name
        if 'SQLite' in connection.engine.dialect.__class__.__name__:
            sql = "SELECT COUNT(*) FROM pragma_table_info('%s') WHERE LOWER(name)=LOWER('%s')" % (
                table_name,
                column_name,
            )
        else:
            sql = "SELECT COUNT(*) FROM information_schema.columns WHERE table_name='%s' and column_name='%s'" % (
                table_name,
                column_name,
            )
        data = connection.engine.execute(sql).first()
        return data[0] >= 1

    def add_column(column):
        if exists(column):
            return
        table_name = column.table.fullname
        column_name = column.name
        column_type = column.type.compile(connection.engine.dialect)
        connection.engine.execute('ALTER TABLE %s ADD COLUMN %s %s' % (table_name, column_name, column_type))

    if getattr(connection, '_transaction', None):
        connection._transaction.commit()

    # Add repo's Encoding
    add_column(RepoObject.__table__.c.Encoding)
    add_column(RepoObject.__table__.c.keepdays)

    # Create column for roles using "isadmin" column. Keep the
    # original column in case we need to revert to previous version.
    if not exists(UserObject.__table__.c.role):
        add_column(UserObject.__table__.c.role)
        UserObject.query.filter(UserObject._is_admin == 1).update({UserObject.role: UserObject.ADMIN_ROLE})

    # Add user's fullname column
    add_column(UserObject.__table__.c.fullname)

    # Add user's mfa column
    add_column(UserObject.__table__.c.mfa)

    # Re-create session table if Number column is missing
    if not exists(SessionObject.__table__.c.Number):
        SessionObject.__table__.drop()
        SessionObject.__table__.create()

    if getattr(connection, '_transaction', None):
        connection._transaction.commit()
    # Remove preceding and leading slash (/) generated by previous
    # versions. Also rename '.' to ''
    result = RepoObject.query.all()
    for row in result:
        if row.repopath.startswith('/') or row.repopath.endswith('/'):
            row.repopath = row.repopath.strip('/')
            row.commit()
        if row.repopath == '.':
            row.repopath = ''
            row.commit()
    # Remove duplicates and nested repositories.
    result = RepoObject.query.order_by(RepoObject.userid, RepoObject.repopath).all()
    prev_repo = (None, None)
    for row in result:
        if prev_repo[0] == row.userid and (prev_repo[1] == row.repopath or row.repopath.startswith(prev_repo[1] + '/')):
            row.delete()
        else:
            prev_repo = (row.userid, row.repopath)


from __future__ import unicode_literals

import tempfile
import shutil
from io import StringIO
import os

from django.test import TestCase
import mock

from archives.models import ArchiveArtifact
from archives.transports import LocalTransport, SshTransport
from jenkins.tests.factories import ArtifactFactory, BuildFactory
from projects.helpers import build_project
from projects.models import ProjectDependency, ProjectBuildDependency
from projects.tests.factories import ProjectFactory, DependencyFactory
from .factories import ArchiveFactory

class LocalTransportTest(TestCase):

    def setUp(self):
        self.basedir = tempfile.mkdtemp()
        self.archive = ArchiveFactory.create(
            transport="local", basedir=self.basedir)

    def tearDown(self):
        shutil.rmtree(self.basedir)

    def test_archive_file(self):
        """
        LocalTransport should copy the file from the supplied fileobj to a
        local path.
        """
        transport = LocalTransport(self.archive)
        fakefile = StringIO(u"This is the artifact")

        size = transport.archive_file(fakefile, "/temp/temp.gz")

        self.assertEqual(20, size)
        filename = os.path.join(self.basedir, "temp/temp.gz")
        self.assertEqual(file(filename).read(), "This is the artifact")

    def test_archive_from_url(self):
        """
        archive_from_url takes a valid URL and opens the file and then passes
        it to archive_file.
        """
        fakefile = StringIO(u"Entirely new artifact")

        mock_request = mock.Mock()
        with mock.patch("archives.transports.urllib2") as urllib2_mock:
            urllib2_mock.Request.return_value = mock_request
            transport = LocalTransport(self.archive)
            urllib2_mock.urlopen.return_value = fakefile
            transport.archive_url(
                "http://example.com/testing", "/temp/temp.gz",
                "username", "password")
        urllib2_mock.urlopen.assert_called_once_with(mock_request)
        urllib2_mock.Request.assert_called_once_with(
            "http://example.com/testing")
        mock_request.assert_has_calls(
            mock.call.add_header(
                "Authorization", "Basic dXNlcm5hbWU6cGFzc3dvcmQ="))
        filename = os.path.join(self.basedir, "temp/temp.gz")
        self.assertEqual(file(filename).read(), "Entirely new artifact")

    def test_start(self):
        """
        LocalTransport.start should ensure that the basedir exists.
        """
        dirname = os.path.join(self.basedir, "temp")
        self.archive.basedir = dirname
        transport = LocalTransport(self.archive)
        transport.start()

        self.assertTrue(os.path.exists(dirname))

    def test_link_filename_to_filename(self):
        """
        LocalTransport.link_filename_to_filename should hardlink the source to
        the destination.
        """
        transport = LocalTransport(self.archive)
        fakefile = StringIO("This is the artifact")

        transport.archive_file(fakefile, "/temp/temp.gz")
        transport.link_filename_to_filename("/temp/temp.gz", "/temp/temp1.gz")

        filename1 = os.path.join(self.basedir, "temp/temp.gz")
        # Test that the number of links to this file is 2
        # (the original, and the newly created hardlink)
        self.assertEqual(2, os.stat(filename1).st_nlink)
        filename2 = os.path.join(self.basedir, "temp/temp1.gz")
        self.assertEqual(file(filename2).read(), "This is the artifact")

    def test_link_artifact_to_current(self):
        """
        Create a link in the parent directory for this artifact,
        pointing to the directory of the artifact, with the name "current".
        """
        transport = LocalTransport(self.archive)
        fakefile = StringIO("This is the artifact")

        transport.archive_file(fakefile, "/temp/temp.gz")
        current_dir = transport.link_to_current("/temp/temp.gz")

        self.assertEqual(os.path.join(self.basedir, "current"), current_dir)
        self.assertTrue(
            os.path.islink(current_dir), "current is not a symlink")
        self.assertEqual(
            os.path.dirname(transport.get_relative_filename("/temp/temp.gz")),
            os.path.realpath(current_dir))

    def test_link_artifact_to_current_replaces_existing_current(self):
        """
        If we run link_artifact_to_current with a new path, it should ensure
        that the "current" directory is the new one.
        """
        transport = LocalTransport(self.archive)
        fakefile = StringIO("This is the artifact")

        transport.archive_file(fakefile, "/temp1/temp.gz")
        transport.link_to_current("/temp1/temp.gz")

        fakefile = StringIO("Another artifact")
        transport.archive_file(fakefile, "/temp2/temp.gz")
        current_dir = transport.link_to_current("/temp2/temp.gz")

        self.assertEqual(
            os.path.dirname(transport.get_relative_filename("/temp2/temp.gz")),
            os.path.realpath(current_dir))

class SshTransportTest(TestCase):

    def setUp(self):
        self.archive = ArchiveFactory.create(
            transport="ssh", basedir="/var/tmp")

    def test_get_ssh_clients(self):
        """
        _get_ssh_clients should return an SSHClient and SFTPClient configured
        to talk to the archive"s credentials.
        """
        with mock.patch.object(self.archive.ssh_credentials, "get_pkey", return_value="KEY"):  # noqa
            with mock.patch("archives.transports.SSHClient") as mock_client:
                mock_client.return_value.get_transport.return_value = "MockTransport"  # noqa
                with mock.patch("archives.transports.SFTPClient") as mock_sftp:
                    with mock.patch("archives.transports.WarningPolicy") as mock_hostpolicy:  # noqa
                        mock_hostpolicy.return_value = "MockWarningPolicy"
                        transport = SshTransport(self.archive)
                        transport._get_ssh_clients()

        mock_client.return_value.assert_has_calls([
            mock.call.set_missing_host_key_policy("MockWarningPolicy"),
            mock.call.connect(
                "archive.example.com", username="testing", pkey="KEY"),
            mock.call.get_transport()])
        mock_sftp.from_transport.assert_called_once_with("MockTransport")

    def test_archive_file(self):
        """
        archive_file should ensure that there's a directory relative to the
        base to hold the file, and then stream the file to the remote server.
        """
        mock_ssh = mock.Mock()
        mock_stdout = mock.Mock()
        mock_ssh.exec_command.return_value = None, mock_stdout, None
        mock_sftp = mock.Mock()
        fakefile = StringIO(u"This is the artifact")

        transport = SshTransport(self.archive)
        with mock.patch.object(
                transport, "_get_ssh_clients",
                return_value=(mock_ssh, mock_sftp)):
            transport.start()
            transport.archive_file(fakefile, "/temp/temp.gz")
        mock_ssh.exec_command.assert_called_once_with(
            "mkdir -p `dirname /var/tmp/temp/temp.gz`")

        mock_sftp.stream_file_to_remote.assert_called_once_with(
            fakefile, "/var/tmp/temp/temp.gz")

        mock_ssh.close.assert_called_once()

    def test_generate_checksums(self):
        """
        generate_checksums should send commands to the ssh client
        to generate an sha256sum for the passed in archived artifact.
        """
        # a project with a build and an archived artifact
        project = ProjectFactory.create()
        dependency = DependencyFactory.create()
        ProjectDependency.objects.create(
            project=project, dependency=dependency)
        projectbuild = build_project(project, queue_build=False)
        build = BuildFactory.create(
            job=dependency.job, build_id=projectbuild.build_key)
        projectbuild_dependency = ProjectBuildDependency.objects.create(
            build=build, projectbuild=projectbuild, dependency=dependency)
        artifact = ArtifactFactory.create(
            build=build, filename="artifact_filename")
        archived_artifact = ArchiveArtifact.objects.create(
            build=build, archive=self.archive, artifact=artifact,
            archived_path="/srv/builds/200101.01/artifact_filename",
            projectbuild_dependency=projectbuild_dependency)

        transport = SshTransport(self.archive)

        with mock.patch.object(transport, "_run_command") as mock_run:
            transport.generate_checksums(archived_artifact)

        mock_run.assert_called_once_with(
            "cd `dirname /var/tmp/srv/builds/200101.01/artifact_filename` "
            "&& sha256sum artifact_filename >> SHA256SUMS")

    def test_link_filename_to_filename(self):
        """
        archive_file should ensure that there's a directory relative to the
        base to hold the file, and then stream the file to the remote server.
        """
        mock_ssh = mock.Mock()
        mock_stdout = mock.Mock()
        mock_ssh.exec_command.return_value = None, mock_stdout, None
        mock_sftp = mock.Mock()

        transport = SshTransport(self.archive)
        with mock.patch.object(
                transport, "_get_ssh_clients",
                return_value=(mock_ssh, mock_sftp)):
            transport.start()
            transport.link_filename_to_filename(
                "/temp/temp.gz", "/temp2/temp.gz")
        mock_ssh.exec_command.assert_has_calls(
            [mock.call("mkdir -p `dirname /var/tmp/temp2/temp.gz`"),
             mock.call('ln "/var/tmp/temp/temp.gz" "/var/tmp/temp2/temp.gz"')])

        mock_ssh.close.assert_called_once()

    def test_link_artifact_to_current(self):
        """
        Create a link in the parent directory for this artifact,
        pointing to the directory of the artifact, with the name "current".
        """
        mock_ssh = mock.Mock()
        mock_stdout = mock.Mock()
        mock_ssh.exec_command.return_value = None, mock_stdout, None
        mock_sftp = mock.Mock()

        transport = SshTransport(self.archive)
        with mock.patch.object(
                transport, "_get_ssh_clients",
                return_value=(mock_ssh, mock_sftp)):
            transport.start()
            current_dir = transport.link_to_current("/project/1234/temp.gz")
        mock_ssh.exec_command.assert_has_calls(
            [mock.call('cd "/var/tmp/project" && rm -f current '
                       '&& ln -sf "1234" current')])
        self.assertEqual("/var/tmp/project/current", current_dir)
        mock_ssh.close.assert_called_once()


import extract_dataset
import path_cost
import prims_algorithm
import kruskals_algorithm

def print_tree(tree, city_list):
    for i in range(len(tree)):
        for j in range(len(tree)):
            if tree[i][j] == None:
                tree[i][j] = '-'
    for i in range(len(city_list)):
        print(f"{tree[i]} - {city_list[i]}")
    print('')

def main():
    norwegian_cities = extract_dataset.open_file()
    A, city_list = path_cost.find_path_costs(norwegian_cities)

    print("Prims's Algorithm:")
    tree = prims_algorithm.prim(A)
    print_tree(tree, city_list)

    tree = kruskals_algorithm.kruskal(A)
    print("Kruskal's Algorithm:")
    print_tree(tree, city_list)

if __name__ == '__main__':
    main()

Project_4/Problem 1 & 2/problem_2/main.py


#cliente
from socket import *

host = gethostname()
port = 11223

cliente = socket(AF_INET, SOCK_STREAM)
cliente.connect((host, port))

while True:
    msg = str(input('Digite alguma coisa: '))
    cliente.send(msg.encode())
    msg_receber = cliente.recv(1024)
    print(msg_receber.decode())


import json
import os
import shutil
import numpy as np

ID = "6cb6373befd7e1a7aa918b099faddaba"
IN = f'./temp_meshes/{ID}_sem.obj'
OUT = f"./temp_meshes/{ID}_sem_normalized.obj"
STAT = {"max": [0.79121, 0.933076, 0.9144], "centroid": [0.3977983202067827, 0.40019718530994164, 0.5265005023087718], "id": "6cb6373befd7e1a7aa918b099faddaba", "numVertices": 855, "min": [-0.00635, -0.00302059, -0.0065486]}

def obj2stats(obj):
    """
    Computes statistics of OBJ vertices and returns as {num,min,max,centroid}
    """
    minVertex = np.array([np.Infinity, np.Infinity, np.Infinity])
    maxVertex = np.array([-np.Infinity, -np.Infinity, -np.Infinity])
    aggVertices = np.zeros(3)
    numVertices = 0
    with open(obj, 'r') as f:
        for line in f:
            if line.startswith('v '):
                v = np.fromstring(line[2:], sep=' ')
                aggVertices += v
                numVertices += 1
                minVertex = np.minimum(v, minVertex)
                maxVertex = np.maximum(v, maxVertex)
    centroid = aggVertices / numVertices
    info = {}
    info['numVertices'] = numVertices
    info['min'] = minVertex
    info['max'] = maxVertex
    info['centroid'] = centroid
    return info

def normalizeOBJ(obj, out, stats=None):
    """
    Normalizes OBJ to be centered at origin and fit in unit cube
    """
    if not stats:
        stats = obj2stats(obj)
    diag = np.array(stats['max']) - np.array(stats['min'])
    norm = 1 / np.linalg.norm(diag)
    c = stats['centroid']
    outmtl = os.path.splitext(out)[0] + '.mtl'
    with open(obj, 'r') as f, open(out, 'w') as fo:
        for line in f:
            if line.startswith('v '):
                v = np.fromstring(line[2:], sep=' ')
                vNorm = (v - c) * norm
                vNormString = 'v %f %f %f\n' % (vNorm[0], vNorm[1], vNorm[2])
                fo.write(vNormString)
            elif line.startswith('mtllib '):
                fo.write('mtllib ' + os.path.basename(outmtl) + '\n')
            else:
                fo.write(line)
    return stats

normalizeOBJ(IN, OUT)


import torch
from torch.nn import functional as F
import torch.nn as nn
import numpy as np

# Reconstruction + KL divergence losses summed over all elements and batch
# note the change of var order!
def loss_bce_kld(x, recon_x, mu, logvar):
    BCE = F.binary_cross_entropy(recon_x.view(-1, 1), x.view(-1, 1), reduction='sum')

    # see Appendix B from VAE paper:
    # Kingma and Welling. Auto-Encoding Variational Bayes. ICLR, 2014
    # https://arxiv.org/abs/1312.6114
    # 0.5 * sum(1 + log(sigma^2) - mu^2 - sigma^2)
    KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())

    return BCE + KLD, KLD, BCE

# Note switch x, recon_x
def loss_rho_bce_kld(x, recon_x, mu, rho, logs, z_dim):

    BCE = F.binary_cross_entropy(recon_x.view(-1, 1), x.view(-1, 1), reduction='sum')
    ##
    KLD = 0.5 * (torch.sum(mu.pow(2)) + - z_dim * logs - (z_dim - 1) * torch.log(1 - rho**2) + z_dim * (logs.exp() - 1))
    KLD = torch.mean(KLD)

    return BCE + KLD, KLD, BCE

def reconstruction_example(model, use_rho, data_loader, img_shape, num_class, use_cuda):

    model.eval()
    img_shape = img_shape[1:]

    x, y = next(iter(data_loader))
    x = to_cuda(x) if use_cuda else x
    if use_rho:
        x_hat, _, _, _ = model(x)
    else:
        x_hat, _, _ = model(x)

    x = x[:num_class].cpu().view(num_class * img_shape[0], img_shape[1])
    x_hat = x_hat[:num_class].cpu().view(num_class * img_shape[0], img_shape[1])
    comparison = torch.cat((x, x_hat), 1).view(num_class * img_shape[0], 2 * img_shape[1])
    return comparison

def generation_example(model, latent_size, data_loader, img_shape, num_class, use_cuda):
    img_shape = img_shape[1:]

    draw = randn((num_class, latent_size), use_cuda)
    sample = model.decode(draw).cpu().view(num_class, 1, img_shape[0], img_shape[1])

    return sample

def to_cuda(tensor):
    if isinstance(tensor, torch.Tensor):
        tensor = tensor.cuda()
    return tensor

def init_weights(module):
    for m in module.modules():
        if isinstance(m, nn.Linear) or isinstance(m, nn.Conv2d):
            nn.init.xavier_uniform_(m.weight.data)
            if hasattr(m, 'bias') and m.bias is not None:
                nn.init.constant_(m.bias, 0.0)
        elif isinstance(m, nn.Sequential):
            for sub_mod in m:
                init_weights(sub_mod)

# https://github.com/jramapuram/helpers/utils.py
def randn(shape, cuda, mean=0, sigma=1, dtype='float32'):
    shape = list(shape) if isinstance(shape, tuple) else shape
    return type_map[dtype](cuda)(*shape).normal_(mean, sigma)

def type_tdouble(use_cuda=False):
    return torch.cuda.DoubleTensor if use_cuda else torch.DoubleTensor

def type_tfloat(use_cuda=False):
    return torch.cuda.FloatTensor if use_cuda else torch.FloatTensor

def type_tint(use_cuda=False):
    return torch.cuda.IntTensor if use_cuda else torch.IntTensor

def type_tlong(use_cuda=False):
    return torch.cuda.LongTensor if use_cuda else torch.LongTensor

def conv_size(H_in, k_size, stride, padd, dil=1):
    H_out = np.floor((H_in + 2 * padd - dil * (k_size - 1) - 1) / stride + 1)
    return np.int(H_out)

def save_checkpoint(state, filename):
    torch.save(state, filename)

# https://github.com/jramapuram/helpers/utils.py
type_map = {
    'float32': type_tfloat,
    'float64': type_tdouble,
    'double': type_tdouble,
    'int32': type_tint,
    'int64': type_tlong
}


"""
Rotate a Matrix 90 Degrees Clockwise
Create a function that receives a square n*n matrix and returns that matrix after it has been rotated 90 degrees in the clockwise direction.

Examples
rotate([
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]) ➞ [
  [7, 4, 1],
  [8, 5, 2],
  [9, 6, 3]
]

rotate([
  ["a", "b", "c", "d"],
  ["e", "f", "g", "h"],
  ["i", "j", "k", "l"],
  ["m", "n", "o", "p"]
]) ➞ [
  ["m", "i", "e", "a"],
  ["n", "j", "f", "b"],
  ["o", "k", "g", "c"],
  ["p", "l", "h", "d"]
]
"""

import numpy as np

def rotate(lst):

    # return [list(t) for t in zip(*reversed(lst))]

    # return np.rot90(np.array(lst), k=3).tolist()

    tpose = map(list, zip(*lst))
    return [i[::-1] for i in tpose]

    # lst = np.array(lst).T
    # return [i[::-1].tolist() for i in lst]

print(rotate([
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]])
)

44_hard_Rotate a Matrix 90 Degrees Clockwise.py


# THE MYSTICAL OCTOSPHERE!

# This game is based on a common toy. It is a
# round black ball with a clear plastic window.
# The ball is filled with murky blue liquid
# and you use it as a fortune teller. You ask
# a yes-or-no question and shake the ball. There
# is a white many-sided die inside with answers,
# and when you stop shaking, one of the sides
# floats up and is readable against the window.

import random
def number_to_fortune(number):
	'''Checks each of the numbers between 0 and 7 and returns the fortune as a string.'''
	if number == 0:
		return "Yes! for sure"
	elif number == 1:
		return "Definitely yes"
	elif number == 2:
		return "Probably yes..."
	elif number == 3:
		return "Maybe not"
	elif number == 4:
		return "Probably not..."
	elif number == 5:
		return "Definitely not"
	elif number == 6:
		return "I really doubt it."
	elif number == 7:
		return "Not sure, check back later."
	else:
		return "Something was wrong with the input"

#print ("")
#print (number_to_fortune(0))
#print (number_to_fortune(1))
#print (number_to_fortune(2))

def mystical_octosphere(question):

	print ("Your question was...." + question)
	print ("You shake the mystical octosphere.")
	print ("---------------------------------")

	#generate a random number to predict the fortune
	answer_number = random.randrange(0, 8)
	answer_fortune = number_to_fortune(answer_number)

	print ("The mystical octosphere says..." + answer_fortune)

	print ("")

question_1 = input("Enter your question: ")
mystical_octosphere(question_1)


from config import Config
from Projeto1.votos import Votos
from Projeto2.sort import Sort
from Projeto3.fatorial import Fatorial
from Projeto4.multiplos import Multiplos
class Startup():
    def __init__(self):
        try:
            while True:
                opcao = int(input('[1] - Rodar programa votos em relação ao total de eleitores\n'+
                '[2] - Rodar programa Bubble Sort\n'+
                '[3] - Rodar programa Fatorial\n'+
                '[4] - Rodar programa soma de multiplos de 3 e 5\n'
                '[5] - Sair [S/n]\n'))

                if opcao == 1:
                    self.projeto1()
                if opcao == 2:
                    self.projeto2()
                if opcao == 3:
                    self.projeto3()
                if opcao == 4:
                    self.projeto4()
                if opcao == 5:
                    break
                elif opcao < 1 and opcao > 5:
                    print('Comando inválido, programa continuará executando...')

        except Exception as e:
            print(e)

    def projeto1(self):
        #Projeto 1
        configuration = Config()
        self.general_config_projeto1 = configuration.get_general_config('Projeto1')

        #Totais
        total_eleitores = self.general_config_projeto1['total_eleitores']
        votos_validos = self.general_config_projeto1['votos_validos']
        votos_brancos = self.general_config_projeto1['votos_brancos']
        votos_nulos = self.general_config_projeto1['votos_nulos']

        #Calcula percentuais de votos
        votos = Votos(total_eleitores)
        votos.percentual_validos(votos_validos)
        votos.percentual_brancos(votos_brancos)
        votos.percentual_nulos(votos_nulos)

    def projeto2(self):
        sort = Sort()
        vetor = [5,3,2,4,7,1,0,6]
        sort.bubble_sort(vetor)

    def projeto3(self):
        fatorial = Fatorial()

        while True:
            numero = input('Digite um número para calcular o fatorial: ')

            if numero.isdigit() == False:
                print('Valor digitado não é um número')
                continue

            fatorial.n_fatorial(int(numero))
            parar = input('Gostaria de parar a execução? [S/n] ')

            if parar in ['S', 's', '']:
                break
            elif parar not in ['N', 'n', 'S', 's', '']:
                print('Comando inválido, programa continuará executando...')

    def projeto4(self):
        multiplos = Multiplos()
        while True:
            numero = input('Entre com um número para calculo do multiplos de 3 e 5: ')

            if numero.isdigit() == False:
                print('Valor digitado não é um número')
                continue

            multiplos.soma_multiplos(int(numero))
            parar = input('Gostaria de parar a execução? [S/n] ')

            if parar in ['S', 's', '']:
                break
            elif parar not in ['N', 'n', 'S', 's', '']:
                print('Comando inválido, programa continuará executando...')

st = Startup()


from math import *
from euclid import *
from omega import *
from cyclops import *

bboxes = []

root = SceneNode.create('bboxRoot')

# create a bounding box actor that will draw an axis-aligned bounding box
# around a target scene node
class BBox(Actor):
    box = None
    target = None
    def __init__(self, target):
        bboxes.append(self)
        super(BBox, self).__init__("BBox")
        self.box = BoxShape.create(1, 1, 1)
        # Customize the look of the bounding box here.
        self.box.setEffect('colored -e #ff8080 -w')
        self.target = target
        root.addChild(self.box)
        self.setUpdateEnabled(True)

    def dispose(self):
        bboxes.remove(self)
        root.removeChild(self.box)

    def onUpdate(self, frame, time, dt):
        self.box.setPosition(self.target.getBoundCenter())
        mn = self.target.getBoundMinimum()
        mx = self.target.getBoundMaximum()
        self.box.setScale(mx - mn)


#!/usr/bin/env python3
# Number plate detection

__author__ = "Cristian Chitiva"
__date__ = "September 17, 2021"
__email__ = "cychitivav@unal.edu.co"

import cv2
import numpy as np

if __name__ == '__main__':
    cap = cv2.VideoCapture(0)

    plateCascade = cv2.CascadeClassifier()
    plateCascade.load(
        'resources/haarcascade_russian_plate_number.xml')
    minArea = 200

    retval = -1
    while retval < 0:
        success, img = cap.read()
        # img = cv2.flip(img, flipCode=1)

        imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        plates = plateCascade.detectMultiScale(
            imgGray, scaleFactor=1.1, minNeighbors=4)

        for (x, y, w, h) in plates:
            area = w*h
            if area > minArea:
                cv2.rectangle(img, pt1=(x, y), pt2=(x+w, y+h),
                              color=(255, 0, 0), thickness=2)
                cv2.putText(img, text='Number plate', org=(x, y-5),
                            fontFace=cv2.FONT_HERSHEY_COMPLEX_SMALL,
                            fontScale=1, color=(255, 0, 0), thickness=2)

                imgROI = img[y:y+h, x:x+w]
                cv2.imshow('Plate', imgROI)

        cv2.imshow('Original', img)
        retval = cv2.waitKey(1)

    cv2.imwrite('outputs/numberPlate.jpg', imgROI)


from pico2d import *

class TileMap:

    def get_tile_image_rect(self, id):
        y = self.tile_rows - id // self.tile_cols - 1
        x = id % self.tile_cols
        return self.image_margin+x*(self.tile_width+self.image_spacing), \
               self.image_margin+y*(self.tile_height+self.image_spacing), \
               self.tile_width, self.tile_height

    def draw_to_origin(self, left, bottom, w=None, h=None):
        if w == None and h == None:
            w,h = self.map_width, self.map_height

        for y in range(h):
            for x in range(w):
                id = self.map2d[y][x]
                self.tileset_image.clip_draw_to_origin(*self.get_tile_image_rect(id), x=(x+left)*self.tile_width, y=(y+bottom)*self.tile_height)

    def clip_draw_to_origin(self, left, bottom, width, height, target_left, target_bottom, w=None, h=None):
        if w == None and h == None:
            w, h = width, height

        for y in range(h):
            for x in range(w):
                id = self.map2d[bottom+y][left+x]
                self.tileset_image.clip_draw_to_origin(*self.get_tile_image_rect(id), x=(x+target_left)*self.tile_width, y=(y+target_bottom)*self.tile_height)


from ..user_auth.models import UpgradeModel
from ..user_auth.user_auth import fetch_global_state_from_db, save_global_state_to_db, initialize_new_biome

def handle_unlock_upgrade(action):
    upgrade_id = action["upgrade_id"]

    # Fetch the upgrade from the database
    existing_upgrade_model = UpgradeModel.query.filter_by(id=upgrade_id).first()

    if existing_upgrade_model:
        user_id = existing_upgrade_model.user_id  # Get user_id from the upgrade model

        # Fetch the global state to get the current number of genetic markers
        global_state_model = fetch_global_state_from_db(user_id)
        genetic_markers = global_state_model.genetic_markers
        cost_modifier = global_state_model.cost_modifier

        cost = existing_upgrade_model.cost  # Get the cost from the upgrade model
        # Modify the cost based on the global cost modifier
        adjusted_cost = cost * (1 + cost_modifier)  # Adding 1 because base is 100% (or 1.0)
        adjusted_cost = round(adjusted_cost)

        secondary_cost = existing_upgrade_model.secondary_cost
        secondary_resource = existing_upgrade_model.secondary_resource

        # Check if player has enough of the primary and secondary resource
        if genetic_markers >= adjusted_cost and (not secondary_resource or getattr(global_state_model, secondary_resource) >= secondary_cost):
            if not existing_upgrade_model.unlocked:
                # Unlock the upgrade
                existing_upgrade_model.unlocked = True

                # Subtract the primary resource cost
                global_state_model.genetic_markers -= adjusted_cost

                upgrade_cost_modifier = existing_upgrade_model.cost_modifier
                if upgrade_cost_modifier:
                    global_state_model.cost_modifier += upgrade_cost_modifier

                    # Subtract the secondary resource cost if it exists
                if secondary_resource:
                    setattr(global_state_model, secondary_resource, getattr(global_state_model, secondary_resource) - secondary_cost)

                # Save changes to the database
                save_global_state_to_db(user_id, global_state_model)

                # Additional logic to initialize new biomes or plant parts
                if existing_upgrade_model.type == "biome":
                    initialize_new_biome(user_id, existing_upgrade_model.effect)
                print("Upgrade successfully unlocked.")
            else:
                print("Upgrade already unlocked.")
        else:
            print("Not enough resources to unlock this upgrade.")
    else:
        print(f"No upgrade found with id {upgrade_id}")


import streamlit as st
import constants as c
import pandas as pd
from utils import (display_all_sorting_algorithms,
                   display_algorithm_type, get_object_from_factory,
                   display_bar_chart)
import numpy as np

def main():

    hide_github_icon = """
            #GithubIcon {
            visibility: hidden;
        }
    """
    # Page layout configurations
    st.set_page_config(page_title="Algorithm Visualizer", layout="wide", initial_sidebar_state="expanded")

    st.title("🔍 Algorithm Visualizer")

    st.write("""
    Welcome to the **Algorithm Visualizer**! This tool helps you visualize various sorting algorithms in action.
    Use the dropdown below to select the type of sorting algorithm you'd like to visualize.
    """)

    # Create a sidebar for controls and info
    with st.sidebar:
        st.header("Menu")
        algorithm_type = st.selectbox("Algorithm Type:", display_algorithm_type())
        sorting_algorithm = None
        if algorithm_type == c.SORTING_ALGORITHM:
            sorting_algorithm = st.selectbox("Sorting Algorithm:", display_all_sorting_algorithms())
            array_len = st.slider("Array Size:", 5, 100, 20)

    # Main content
    with st.container():
        if not sorting_algorithm:  # If no sorting algorithm is selected
            st.header("Complexities of Common Sorting Algorithms")
            st.write("Below are the complexities of some common sorting algorithms for your reference.")
            df = pd.DataFrame.from_dict(c.ALGORITHM_COMPLEXITIES, orient='index')
            st.table(df)

        elif algorithm_type == c.SORTING_ALGORITHM:
            st.subheader(f"Visualizing: {sorting_algorithm}")
            array = list(np.random.randint(0, 250, array_len))

            if sorting_algorithm:
                display_bar_chart(array, is_initial=True)

                if array:
                    col1, col2, col3 = st.columns([1,1,1])

                    with col2:
                        sort_pressed = st.button("Sort")

                if sort_pressed:
                    algorithm_object = get_object_from_factory(sorting_algorithm, c.SORTING_ALGORITHM)
                    algorithm_object.sort(array, callback=algorithm_object.display_bars)
                    st.balloons()

        st.info("🔜 This site will soon move to [DSA Ground](https://dsaground.streamlit.app/)")

if __name__ == "__main__":
    main()


'''
bfs 돌리면 메모리 초과가 뜨므로 머리를 좀더 쓴다...
도착점에서 시작해서 거꾸로 가기
'''

l,r = map(int, input().split())
leftCnt = 0
rightCnt = 0
while(l>1 and r>1):
    if l>r:
        # 왼쪽이 더 크면, 오른쪽 위로 보낸다
        leftCnt += 1
        l -= r
    elif r>l:
        # 오른쪽이 더 크면
        rightCnt += 1
        r -= l

leftCnt += l-1
rightCnt += r-1

print(leftCnt, rightCnt)


import numpy as np
import pandas as pd

df = pd.read_excel("Raw-Text-Master.xlsx")

# I have to rename the column headers because Excel thinks if your column is
# ID, it is in SKYL format, whatever that means

df.columns = ['id', 'date', 'post']

df['day'] = df['date'].dt.day
df['month'] = df['date'].dt.month
df['year'] = df['date'].dt.year

df = df.groupby('id').agg(lambda x: x.tolist())

# Remove Brackets from CSV for cleaner dataset

df['id'] = df['id'].str[0]
df['date'] = df['date'].str[0]
df['post'] = df['post'].str[0]
df['day'] = df['day'].str[0]
df['month'] = df['month'].str[0]
df['year'] = df['year'].str[0]

df.to_csv("Cleaned-Text.csv")