#!/usr/bin/python3

from django.shortcuts import render, redirect, get_object_or_404
from django.core import serializers
from django.http import JsonResponse
from django.contrib import messages
from django.db.models import Max

from parametros.views import (ViewListView,
        ViewCreateView,
        ViewUpdateView,
        ViewDeleteView,
        )

from .models import (PeriodoProfesorModulo,
        Horario,
        HorarioTemp,
        ReservaBloqueProtegido,
        CursosGrupo,
        )

from parametros.models import (Periodo,
        Plan,
        Profesor,
        Modulo,
        ModuloEspejo,
        Carrera,
        Bloque,
        Actividad,
        )

from .forms import (PeriodoProfesorModuloForm,
        ReservaBloqueProtegidoForm,
        CursosGrupoForm,
        )

from django.views.generic.base import TemplateView
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse

from .valida import (valida_cantidad_horas,
        valida_choque_horario_profesor,
        valida_choque_horario_modulo_semestre,
        # valida_ppm_horario,
        valida_existe_grupos_cursos,
        )
import json
import collections

# Create your views here.

dic_dia_semana={"1": "Lunes",
        "2":"Martes",
        "3":"Miercoles",
        "4":"Jueves",
        "5":"Viernes",
        }

from parametros.views import StaffRequiredMixin

def create_dic_bloque():
    """
    Crea diccionario con todos los elementos de la clase bloque.
    Esto crea dos elementos uno de tipo string (key) y otro el tipo
    diccionario (value), que a su vez contiene la key de bloque y value
    por defecto como falso.
    ejemplo, dic={key:value{xx:vv}}

    Retorna:
        * Dic: Diccionario de datos
    """
    dia_semana = collections.OrderedDict(sorted(dic_dia_semana.items()))
    b = Bloque.objects.all().order_by("nombre")
    p = ReservaBloqueProtegido.objects.all()

    dic={}

    for i in dia_semana:
        dic_aux={}

        for t in b:
            dic_aux[t]= False

        for t in p:
            dic_aux[t.bloque]="X"
        dic[i]=dic_aux

    dic = collections.OrderedDict(sorted(dic.items()))

    return dic

def create_dic_bloque_title(context):
    """
    Crea los titulos y extensión de los bloques para ser dibujado en la tabla
    que realiza la interacción con el horario.
    Recibe:
        Objeto de tipo context (diccionario)
    Retorna:
        Objeto de tipo context (diccionario)
    """

    b = Bloque.objects.all().order_by("nombre")
    context["bloque_list"] = b

    #max de bloque
    b = b.aggregate(Max("nombre"))
    b = b["nombre__max"]
    context["bloque_max"] = range(0, b)

    return context

def create_dic_cursos_grupo(periodo):
    """
    Crea un diccionario con los objectos obtenidos de acuerdo a un periodo
    determinado

    Recibe:
        * Integer: codigo periodo

    Retorna:
        diccionario del modo:
        {
            codigo_periodo: [CursosGrupo, CursosGrupo, ...]
        }
    """

    cg = CursosGrupo.objects
    cg_values = cg.values('modulo').filter(periodo__id = periodo)
    cg_values = cg_values.distinct()

    cg_query = cg.all().filter(periodo__id = periodo)

    dic = {}
    aux = []

    for i in cg_values:
        for t in cg_query.filter(modulo__id=i['modulo']):
            aux.append(t)
        dic[i["modulo"]] = aux
        aux = []

    return dic

class PeriodoProfesorModuloListView(StaffRequiredMixin, ViewListView):
    model = PeriodoProfesorModulo
    template_name = "horario/base_horario.html"
    titulo = "Asignación Profesor Módulo"
    extra_context = {}

    def get_context_data(self, *args, **kwargs):

        context = super(PeriodoProfesorModuloListView, self).get_context_data(*args, **kwargs)

        periodo = self.request.GET.get("periodo")
        carrera = self.request.GET.get("carrera")
        plan = self.request.GET.get("plan")

        c = Carrera.objects.all().order_by("nombre")
        context['carrera'] = c

        if carrera is None or carrera == 0:
            queryset = None

        else:
            #habilito el select de periodo
            p = Periodo.objects.all().order_by("-nombre")
            context['periodo'] = p

            #habilito select de plan
            pl = Plan.objects.all().filter(carrera = carrera)
            pl = pl.order_by("-nombre")
            context["plan"] = pl

        if carrera is not None and carrera !=0:
            #filtro el query por carrera para ser listado
            queryset = PeriodoProfesorModulo.objects.all()
            queryset = queryset.filter(carrera=carrera)

        if periodo is not None and periodo !=0:
            # filtro el query por periodo
            # el resultando es de carrera + periodo
            queryset = queryset.filter(periodo=periodo)

        if plan is not None and plan !=0:
            #filtro el query por plan
            #el resultante es filtro de carrera + plan
            queryset = queryset.filter(plan=plan)

        context['object_list'] = queryset

        return context

class PeriodoProfesorModuloCreateView(StaffRequiredMixin, ViewCreateView):
    form_class = PeriodoProfesorModuloForm
    template_name = "horario/form_ppm.html"
    titulo = "Agrega Asignacion de periodo-profesor-modulo"
    success_message = "La Asignacion %(nombre)s ha sido creado"
    success_url = "/periodoprofesormodulo/"

    def get_context_data(self, **kwargs):

        context = super(PeriodoProfesorModuloCreateView, self).get_context_data(**kwargs)

        dic=create_dic_bloque()

        context["horario"] = dic
        context["dia_semana_list"] = dic_dia_semana

        create_dic_bloque_title(context)

        return context

    def get_success_message(self, cleaned_data):
        """
        cleaned_data is the cleaned data from the form which is used for string
        formatting
        """
        return self.success_message % dict(cleaned_data,
                nombre=self.object.profesor.nombre)

        def form_valid(self, form):
            form.save()
        ppm = form.instance
        #Aca se debe guardar el temporal
        a = HorarioTemp.objects.all()
        a = a.filter(modulo = ppm.modulo,
                carrera = ppm.carrera,
                profesor = ppm.profesor,
                )
        for i in a:
            h = Horario(periodoprofesormodulo = ppm,
                    dia_semana = i.dia_semana,
                    bloque = i.bloque,
                    actividad = i.actividad,
                    reservado = True,
                    )
            h.save()
            i.delete()

        return super(PeriodoProfesorModuloCreateView, self).form_valid(form)

class PeriodoProfesorModuloUpdateView(StaffRequiredMixin, ViewUpdateView):
    model = PeriodoProfesorModulo
    form_class = PeriodoProfesorModuloForm
    template_name = "horario/form_ppm.html"
    success_message = "El Profesor %(nombre)s ha sido actualizado"
    success_url = "/periodoprofesormodulo/"
    titulo = "Edita Asignacion de periodo-profesor-modulo"

    def get_context_data(self, **kwargs):

        context = super(PeriodoProfesorModuloUpdateView, self).get_context_data(**kwargs)
        context["dia_semana_list"] = dic_dia_semana

        h = None
        ppm = context["object"]

        if (ppm is not None):
            h = Horario.objects.all().filter(periodoprofesormodulo = ppm)
            h = h.order_by("dia_semana", "bloque__nombre")

            cg = CursosGrupo.objects.all()
            cg = cg.filter(periodo = ppm.periodo,
                    modulo = ppm.modulo)
            context["cursosgrupo"] = cg

        dic=create_dic_bloque()

        for i in h:
            """
            Actualizo los elementos del diccionario creado, esto es solo para
            los elementos que se encuentran en la clase horario.
            """
            x=dic[i.dia_semana]
            """
            Chequea si el modulo esta disponible o no
            Si reservado es Falso, la actividad es None o Null,
            Si reservado es Verdadero, la actividad tiene un objeto de tipo
            Actividad, y en este caso se asocia al identificador para poder
            mostrar en la tabla de horario de PPM
            """
            if (i.reservado is True):
                xx = x[i.bloque]=i.actividad.identificador

        context["horario"] = dic
        context = create_dic_bloque_title(context)
        create_dic_bloque_title(context)

        return context

    def get_success_message(self, cleaned_data):
        #cleaned_data is the cleaned data from the form which is used for string formatting
        return self.success_message % dict(cleaned_data,
                nombre=self.object.profesor.nombre)

class PeriodoProfesorModuloDeleteView(StaffRequiredMixin, ViewDeleteView):
    model = PeriodoProfesorModulo
    template_name = "parametros/elimina.html"
    success_message = 'El Profesor %(nombre)s ha sido Eliminado'
    success_url = "/periodoprofesormodulo/"

    # def delete(self, request, *args, **kwargs):
    #     object = self.get_object()
    #     messages.success(self.request, self.success_message %dict(nombre=object,))
    #     return super(PeriodoProfesorModuloDeleteView, self).delete(request, *args, **kwargs)

class ReservaBloqueProtegidoListView(StaffRequiredMixin, ViewListView):
    model = ReservaBloqueProtegido
    template_name = "horario/base_horario.html"
    titulo = "Reserva Bloques protegidos Módulo"
    extra_context = {}

    def get_context_data(self, *args, **kwargs):

        context = super(ReservaBloqueProtegidoListView, self).get_context_data(*args, **kwargs)

        bloque = Bloque.objects.all().order_by("nombre")
        context['bloque'] = bloque

        return context

class ReservaBloqueProtegidoCreateView(StaffRequiredMixin, ViewCreateView):
    form_class = ReservaBloqueProtegidoForm
    template_name = "parametros/form.html"
    titulo = "Agrega Reserva de Bloque Protegido"
    success_message = "Se han reservado los bloques"
    success_url = "/reservabloqueprotegido/"

    def get_success_message(self, cleaned_data):
        #cleaned_data is the cleaned data from the form which is used for string formatting
        return self.success_message

class ReservaBloqueProtegidoUpdateView(StaffRequiredMixin, ViewUpdateView):
    model = ReservaBloqueProtegido
    form_class = ReservaBloqueProtegido
    template_name = "parametros/form.html"
    success_message = "Se han Actualizado los bloques"
    success_url = "/reservabloqueprotegido/"

    def get_success_message(self, cleaned_data):
        #cleaned_data is the cleaned data from the form which is used for string formatting
        return self.success_message

class ReservaBloqueProtegidoDeleteView(StaffRequiredMixin, ViewDeleteView):
    model = ReservaBloqueProtegido
    template_name = "parametros/elimina.html"
    success_message = 'Se han eliminado los bloques protegidos'
    success_url = "/reservabloqueprotegido/"

    def delete(self, request, *args, **kwargs):
        obj = self.get_object()
        messages.success(self.request, self.success_message %dict(nombre=obj,))
        return super(ViewDeleteView, self).delete(request, *args, **kwargs)

class CursosGrupoListView(StaffRequiredMixin, ViewListView):
    model = CursosGrupo
    template_name = "horario/base_horario.html"
    titulo = "Cursos Grupo"
    extra_context = {}

    def get_context_data(self, *args, **kwargs):

        context = super(CursosGrupoListView, self).get_context_data(*args, **kwargs)

        carrera = Carrera.objects.all()
        context["carrera"]  = carrera

        periodo = Periodo.objects.all()
        context["periodo"] = periodo

        return context

class CursosGrupoCreateView(StaffRequiredMixin, ViewCreateView):
    form_class = CursosGrupoForm
    template_name = "horario/cursos_grupo_table.html"
    titulo = "Agrega Modulos Compartidos"
    success_message = "Se agregado los módulos compartidos"
    success_url = "/cursosgrupo/"

    def get_success_message(self, cleaned_data):
        #cleaned_data is the cleaned data from the form which is used for string formatting
        return self.success_message

class CursosGrupoUpdateView(StaffRequiredMixin, ViewUpdateView):
    model = CursosGrupo
    form_class = CursosGrupo
    template_name = "horario/cursos_grupo_table.html"
    success_message = "Se han Actualizado los modulos compartidos"
    success_url = "/cursosgrupo/"

    def get_success_message(self, cleaned_data):
        #cleaned_data is the cleaned data from the form which is used for string formatting
        return self.success_message

class CursosGrupoDeleteView(StaffRequiredMixin, ViewDeleteView):
    model = CursosGrupo
    template_name = "parametros/elimina.html"
    success_message = 'Se han eliminado los modulos compartidos'
    success_url = "/cursosgrupo/"

    def delete(self, request, *args, **kwargs):
        obj = self.get_object()
        messages.success(self.request, self.success_message %dict(nombre=obj,))
        return super(ViewDeleteView, self).delete(request, *args, **kwargs)

class HorarioListView(StaffRequiredMixin, ViewListView):
    #queryset = Periodo.objects.all().order_by("-id")

    template_name = "horario/base_horario.html"
    titulo = "Listado de Horarios"

    def get_queryset(self):
        # return Periodo.objects.all().order_by("-id")
        query = PeriodoProfesorModulo.objects.all()
        query = query.distinct('carrera', 'periodo', 'plan')
        return query

class HorarioTemplateView(StaffRequiredMixin, TemplateView):
    #edit
    template_name = "horario/base_horario.html"

    def get_context_data(self, **kwargs):

        context = super(HorarioTemplateView, self).get_context_data(**kwargs)
        context["titulo"] = "Horario"

        periodo = self.request.GET.get("periodo")
        query = Periodo.objects.all().order_by("nombre")
        context["queryset_periodo"] = query

        carrera = self.request.GET.get("carrera")
        query = Carrera.objects.all().filter()
        context["queryset_carrera"] = query

        dia_semana = collections.OrderedDict(sorted(dic_dia_semana.items()))
        context["dia_semana"] = dia_semana

        cg = create_dic_cursos_grupo(periodo)
        context["cursos_grupo"] = cg

        query = PeriodoProfesorModulo.objects.all()
        if periodo is not None:
            query = query.filter(periodo__id=periodo)
        if carrera is not None:
            query = query.filter(carrera__id=carrera)
        query = query.order_by("modulo__semestre__nombre")

        dic_ppm = {}
        for ppm in query:

            dic=create_dic_bloque()
            dic_temp = dic

            h = Horario.objects.all()
            h = h.filter(periodoprofesormodulo=ppm, reservado=True)
            h = h.order_by("dia_semana",
                    "periodoprofesormodulo__modulo__semestre__nombre",
                    "periodoprofesormodulo__profesor__nombre",
                    )

            for x in h:
                temp = dic_temp[x.dia_semana]
                xx = temp[x.bloque] = x.actividad.identificador

            #actualizo diccionario,
            #agrego como key a ppm para los valores de dic
            dic_ppm[ppm] = dic
            """
            Estructura del nuevo diccionario
            {ppm:
                {'1':
                    {bloque:identificador}
                }
            }
            """
        context["horario"] = dic_ppm

        context = create_dic_bloque_title(context)
        return context

@csrf_exempt
def HorarioSave(request):

    if request.method == "POST" and request.is_ajax():
        model = Horario
        dic = request.POST.get("diccionario")
        dic = json.loads(dic)
        valor = request.POST.get("valor") #ultimo valor insertado
        bloque1 = dic["accion bloque1"]
        bloque2 = dic["accion bloque2"]
        bloque3 = dic["accion bloque3"]
        bloque4 = dic["accion bloque4"]
        bloque5 = dic["accion bloque5"]
        bloque6 = dic["accion bloque6"]
        bloque7 = dic["accion bloque7"]
        bloque8 = dic["accion bloque8"]
        bloque9 = dic["accion bloque9"]
        bloque10 = dic["accion bloque10"]

        profesor = dic["profesor"];
        modulo = dic["modulo"]
        plan = dic["plan"]
        semestre = dic["semestre"]
        dia_semana = dic["dia_semana"]
        titulo_bloque = dic["titulo_bloque"]

        query_ppm = PeriodoProfesorModulo.objects.all().filter(
                profesor__nombre=profesor,
                modulo__nombre=modulo,
                modulo__plan__nombre = plan,
                )

        query_horario = Horario.objects.all()
        query_horario_ppm = query_horario.filter(periodoprofesormodulo=query_ppm[0])

        validar, msj = valida_cantidad_horas(query_horario_ppm, valor)

        if validar is False:
            return HttpResponse(msj)

        validar1, msj = valida_choque_horario(dia_semana, titulo_bloque,
                query_ppm[0].periodo,
                query_ppm[0].modulo.semestre,
                valor,
                )
        if validar1 is False:
            return HttpResponse(msj)

        if validar and validar1:
            # if valida:
            #     if validar1:
            #         msj = msj1
            query_horario = query_horario_ppm.filter(dia_semana=dia_semana)
            if query_horario.exists():
                print("existe")
                query_horario=query_horario.get()
                query_horario.bloque1=bloque1
                query_horario.bloque2=bloque2
                query_horario.bloque3=bloque3
                query_horario.bloque4=bloque4
                query_horario.bloque5=bloque5
                query_horario.bloque6=bloque6
                query_horario.bloque7=bloque7
                query_horario.bloque8=bloque8
                query_horario.bloque9=bloque9
                query_horario.bloque10=bloque10
                # query_horario.dia_semana=dia_semana
            else:
                print("no existe")
                query_horario=Horario(
                        periodoprofesormodulo=query_ppm[0],
                        bloque1=bloque1,
                        bloque2=bloque2,
                        bloque3=bloque3,
                        bloque4=bloque4,
                        bloque5=bloque5,
                        bloque6=bloque6,
                        bloque7=bloque7,
                        bloque8=bloque8,
                        bloque9=bloque9,
                        bloque10=bloque10,
                        dia_semana = dia_semana,
                        )
                query_horario.save()
            return HttpResponse(msj)
        else:

            return HttpResponse(msj)
        #return redirect("/horario/add/")

    else:
        return redirect("/horario/add/")

@csrf_exempt
def GetPlan(request):

    if request.method == "POST" and request.is_ajax():
        codigo = request.POST.get("codigo")
        query = Plan.objects.all().filter(carrera__id=codigo)
        query = query.order_by("-id")

        return JsonResponse(serializers.serialize('json', query), safe=False)

@csrf_exempt
def GetPeriodo(request):

    if request.method == "POST" and request.is_ajax():
        #codigo = request.POST.get("codigo")
        query = Periodo.objects.all().order_by("nombre")

        return JsonResponse(serializers.serialize('json', query), safe=False)

@csrf_exempt
def GetProfesor(request):

    if request.method == "POST" and request.is_ajax():
        #codigo = request.POST.get("codigo")
        query = Profesor.objects.all().order_by("-id")

        return JsonResponse(serializers.serialize('json', query), safe=False)

@csrf_exempt
def GetModulo(request):

    if request.method == "POST" and request.is_ajax():
        #plan #FIXME
        codigo = request.POST.get("codigo")
        p = request.POST.get("periodo")
        if codigo != "":
            cg = CursosGrupo.objects.values_list("curso_grupo").filter(periodo_id=p)
        e = ModuloEspejo.objects.values_list("espejo")
        query = Modulo.objects.all().filter(plan__id = codigo)
        query = query.exclude(id__in=e)
        query = query.exclude(id__in=cg)
        query = query.order_by("-id")

        return JsonResponse(serializers.serialize('json', query), safe=False)

@csrf_exempt
def GetCarrera(request):

    if request.method == "POST" and request.is_ajax():
        #codigo = request.POST.get("codigo")
        query = Carrera.objects.all()
        query = query.order_by("nombre")

        return JsonResponse(serializers.serialize('json', query), safe=False)

@csrf_exempt
def GetActividad(request):

    if request.method == "POST" and request.is_ajax():
        codigo = request.POST.get("codigo")
        query = Actividad.objects.all()
        query = query.order_by("nombre")

        return JsonResponse(serializers.serialize('json', query), safe=False)

@csrf_exempt
def GetValidaPpm(request):
    """
    Método que ejecuta un query con los datos de PeriodoProfesorModulo y retorna
    si existe o no el nuevo objecto en la clase
    Requiere los campos:
        * Periodo
        * Carrera
        * Plan
        * Modulo
        * Profesor
    """

    if request.method == "POST" and request.is_ajax():
        periodo = request.POST.get("periodo")
        carrera = request.POST.get("carrera")
        plan = request.POST.get("plan")
        modulo = request.POST.get("modulo")
        profesor = request.POST.get("profesor")

        query = PeriodoProfesorModulo.objects.all()
        query = query.filter(
                periodo__id = periodo,
                carrera__id = carrera,
                plan__id = plan,
                modulo__id = modulo,
                profesor__id = profesor,
                )

        if query.exists():
            msj = "El profesor %(profesor)s ya fue agendado con el modulo "
            msj +="%(modulo)s en la carrera %(carrera)s para el periodo %(periodo)s"
            msj = msj %{"profesor":query[0].profesor.nombre,
                    "modulo": query[0].modulo.nombre,
                    "carrera": query[0].carrera.nombre,
                    "periodo": query[0].periodo.nombre
                    }
            dic={"success": False,
                    "msj":msj}
        else:
            dic={"success": True,
                    "msj":""}

            dic = json.dumps(dic).encode('utf_8')

        return HttpResponse(dic)

# para salvar actividad en cierto bloque
@csrf_exempt
def SaveActividadBloque(request):

    if request.method == "POST" and request.is_ajax():
        codigo = request.POST.get("codigo")
        s = Horario.objects.all()
        # query = query.order_by("nombre")

        s = s.filter(dia = dia_semana)
        s = s.filter(bloque = bloque)
        s = s.filter(ppm = periodoprofesormodulo)

        s.save()
        s.update()

    return HttpResponse("")

@csrf_exempt
def SaveHorarioProtegido(request):

    if request.method == "POST" and request.is_ajax():
        bloque = request.POST.get("bloque")
        value = request.POST.get("value")

        b = Bloque.objects.all()
        b = b.filter(nombre=bloque)

        r = ReservaBloqueProtegido.objects.all()
        r = r.filter(bloque = b[0])

        if value == "X":
            value = True
        else:
            value = False

        if not r.exists():
            r = r(
                    bloque = b[0],
                    reservado = value,
                    )
            r.save()
        else:
            r.update(
                    reservado = value
                    )

            return HttpResponse("")

@csrf_exempt
def saveHorario(request):
    """
    POST trae como valores:
    row = Fila que refiere al día de la semana.
    col = Columna que referencia al bloque.
    value = Valor de texto de la celda clickeada.
    periodo = Valor del combo periodo
    carrera = Valor del combo carrera
    plan = Valor del combo plan
    modulo = Valor del combo modulo
    profesor = Valor del combo de profesor
    """
    if request.method == "POST" and request.is_ajax():

        #FIXME
        actividad = request.POST.get("value")
        dia = request.POST.get("row")
        bloque = request.POST.get("bloque")

        #datos de periodo prof modulo
        periodo = request.POST.get("periodo")
        carrera = request.POST.get("carrera")
        plan = request.POST.get("plan")
        modulo = request.POST.get("modulo")
        profesor = request.POST.get("profesor")

        block = Bloque.objects.all()
        #num = block.filter(id = bloque)
        block = block.filter(nombre = bloque)

        if actividad != "":
            actividad_query = Actividad.objects.all()
            actividad_query = actividad_query.filter(identificador = actividad)
            actividad=actividad_query[0]

            #valida si existe el mismo profesor en bloque seleccionado
            #para otro modulo
            v, msj = valida_choque_horario_profesor(periodo,
                    modulo,
                    profesor,
                    dia,
                    bloque,
                    carrera,
                    )
            if (not v):
                return HttpResponse(msj)

            v, msj = valida_choque_horario_modulo_semestre(block[0],
                    dia,
                    plan,
                    profesor,
                    )
            if (not v):
                return HttpResponse(msj)

        else:
            actividad = None

        #query de PPM a fin de actualizar horario, se obtiene un solo resultado
        query = PeriodoProfesorModulo.objects.all()
        query = query.filter(periodo__id = periodo)
        query = query.filter(carrera__id = carrera)
        query = query.filter(plan__id = plan)
        query = query.filter(modulo__id = modulo)
        query = query.filter(profesor__id = profesor)

        print("periodo: ", periodo)
        print("carrera: ", carrera)
        print("plan: ", plan)
        print("modulo: ", modulo)
        print("profesor ", profesor)
        print(query)

        #Si el query existe, quiere decir que esta actualizando un dato
        if query.exists():

            h = Horario.objects.all()
            h = h.filter(periodoprofesormodulo = query[0])

            #valido la cantidad de horas para la actividad
            v,msj = valida_cantidad_horas(actividad, query=h,
                    modulo_id=modulo, nuevo=False)

            if (not v):
                return HttpResponse(msj)

            #Filtro para chequear si en horario ya está reservado el bloque
            a = h.filter(dia_semana = dia, bloque = block[0])

            #Se actualiza un bloque de horario ya establecido
            if a.exists():
                a = a.get()
                #Si la actividad es texto blanco se cambia a reservado False
                if actividad is None:
                    a.reservado = False
                else:
                    a.reservado = True

                a.actividad = actividad
                a.save()
            else:
                a = Horario(periodoprofesormodulo = query[0],
                        dia_semana = dia,
                        reservado = True,
                        bloque = block[0],
                        actividad = actividad,
                        )
                a.save()
        else:
            #no existe está creando
            c = Carrera.objects.all()
            c = c.filter(id = carrera)

            p = Profesor.objects.all()
            p = p.filter(id = profesor)

            m = Modulo.objects.all()
            m = m.filter(id = modulo)

            h = HorarioTemp.objects.all()
            h = h.filter(carrera = c[0],
                    profesor = p[0],
                    modulo = m[0],
                    )

            #valido la cantidad de horas para la actividad
            v,msj = valida_cantidad_horas(actividad, query=h,
                    modulo_id=modulo,nuevo=False)

            if (not v):
                return HttpResponse(msj)

            a = h.filter(dia_semana = dia,
                    bloque = block[0]
                    )

            if a.exists():
                #Si la actividad es None, se debe eliminar el registro temporal
                if actividad is None:
                    a.delete()
                else:
                    a = a.get()
                    a.actividad = actividad
                    a.save()
            else:
                a = HorarioTemp(
                        dia_semana = dia,
                        reservado = True,
                        bloque = block[0],
                        actividad = actividad,
                        carrera = c[0],
                        profesor = p[0],
                        modulo = m[0],
                        )
                a.save()

    return HttpResponse(None)

@csrf_exempt
def deleteHorarioTemp(request):
    """
    Utilitario para eliminar objetos temporales de la clase HorarioTemp

    POST Trae valores:
        * carrera
        * modulo
        * profesor
    """
    if request.method == "POST" and request.is_ajax():
        #datos del formulario PPM
        carrera = request.POST.get("carrera")
        modulo = request.POST.get("modulo")
        profesor = request.POST.get("profesor")

        h = HorarioTemp.objects.all()
        h = h.filter(carrera__id = carrera,
                modulo__id = modulo,
                profesor__id = profesor,
                )
        h.delete()

    return HttpResponse(None)

@csrf_exempt
def saveCursosGrupo(request):

    if request.method == "POST" and request.is_ajax():
        #cursosgrupo
        cursosgrupo = request.POST.get("cursosgrupo")
        if cursosgrupo == "":
            return HttpResponse(None)

        #Datos de PPM
        periodo = request.POST.get("periodo")
        carrera = request.POST.get("carrera")
        plan = request.POST.get("plan")
        modulo = request.POST.get("modulo")
        profesor = request.POST.get("profesor")

        ppm = PeriodoProfesorModulo.objects.all()
        ppm = ppm.filter(periodo__id = periodo,
                carrera__id = carrera,
                plan__id = plan,
                modulo__id = modulo,
                profesor__id = profesor
                )

        cg = Modulo.objects.all().filter(id=cursosgrupo)

        if ppm.exists():
            v, msj = valida_existe_grupos_cursos(cg[0], ppm[0])
            if not v:
                return HttpResponse(msj)
            cg = CursosGrupo(periodoprofesormodulo = ppm[0],
                    modulo=cg[0])
            cg.save()

    return HttpResponse(None)

@csrf_exempt
def GetModuloEspejoGruposCurso(request):

    if request.method == "POST" and request.is_ajax():
        #get modulo id
        modulo = request.POST.get("modulo")

        if modulo == "":
            return HttpResponse(None)

        e = ModuloEspejo.objects.all().filter(modulo__id=modulo)

        cg = CursosGrupo.objects.all().filter(modulo__id=modulo)

        msj = ""
        table = ""

        if e.exists():
            msj = "%s tiene asociado lo siguiente:\n\n"%e[0].modulo.nombre
            msj += "Módulo Espejo:\n"
            for i in e:
                msj +="\t \t * %s "%i.espejo.nombre
                msj += "del plan %s "%i.espejo.plan.nombre
                msj += "de %s"%i.espejo.carrera.nombre

                #FIXME
                table +="<tr>"
                table +="<td name=id hidden>%s</td>"%i.id
                table +="<td width=30%%> %s </td>"%i.espejo.carrera.nombre
                table +="<td width=30%%>%s</td>"%i.espejo.plan.nombre
                table +="<td width=30%%>%s</td>"%i.espejo.nombre
                table +="""<td>
                <center>
                    <button class='btn btn-danger btn-sm delete-cursos-grupo'>
                    <span class='glyphicon glyphicon-minus'></span></button>
                    </center>
                </td>
                """

                table +="</tr>"

        if cg.exists():
            if msj == "":
                msj = "%s tiene asociado lo siguiente:"%e[0].modulo.nombre
            msj += "\n\n"
            msj += "Grupos Curso:\n"

            for i in cg:
                msj +="\t \t * %s "%i.curso_grupo.nombre
                msj += "del plan %s "%i.curso_grupo.plan.nombre
                msj += "de %s"%i.curso_grupo.carrera.nombre

        if msj != "":
            dic={"success": False,
                    "msj":msj,
                    "table":table}
        else:
            dic={"success": True,
                    "msj":"",
                    "table":table}

        dic = json.dumps(dic).encode('utf_8')

        return HttpResponse(dic)


def first_func():
    a=int(input("enter how many cm to convert "))
    b=a*2.54
    print(f'{a} cm = {b} ')

#могла использовать и return со значениями но пока что не обязательно,хотела оставить крассивую строку)
def second_func():
    a=int(input("enter how many dm to convert "))
    b=a%2.54
    print(f'{a} dm = {b} cm ')

def third_func():
    a=int(input("enter how many miles to convert "))
    b=a*1.61
    print(f'{a} miles = {b} km ')

def fourth_func():
    a=int(input("enter how many km to convert "))
    b=a%1.61
    print(f'{a} km = {b} miles ')

def fifth_func():
    a=int(input("enter how ft  to convert "))
    b=a*0.45
    print(f'{a} ft = {b} kg')

def sixth_func():
    a = int(input("enter  km to convert "))
    b = a%0.45
    print(f'{a} ft = {b} kg')

def seventh_func():
    a = int(input("enter  kп to convert "))
    b = a%28.35
    print(f'{a} кг = {b} unc')

def eighth_func():
    a = int(input("enter  unc to convert "))
    b = a % 28.35
    print(f'{a} unc = {b} kg')
def ninth_func():
    a = int(input("enter  gl to convert "))
    b = a*4.55
    print(f'{a} gl = {b} litres')
def tenth_func():
    a = int(input("enter  gl to convert "))
    b = a%4.55
    print(f'{a}  litres = {b} gl')
def eleventh_func():
    a = int(input("enter  pintes to convert "))
    b = a*0.568
    print(f'{a} pintes  = {b} liters')
def twelfth_func():
    a = int(input("enter  gl to convert "))
    b = a%0.568
    print(f'{a}  litres = {b} pintes')

while(True):
    print("enter right option:")
    print("1. Дюймы в сантиметры\n 2. Сантиметры в дюймы \n3. Мили в километры\n4. Километры в мили\n5. Фунты в килограммы\n6. Килограммы в фунты\n7. Унции в граммы\n8. Граммы в унции\n9. Галлон в литры\n10. Литры в галлоны\n11. Пинты в литры\n12. Литры в пинты")
    a=int(input())
    if a<0 or a>12:
        print("unright variiant")
    else:
        if a==1:
            first_func()
        elif a==2:
            second_func()
        elif a==3:
            third_func()
        elif a==4:
            fourth_func()
        elif a==5:
            fifth_func()
        elif a==6:
            sixth_func()
        elif a==7:
            seventh_func()
        elif a==8:
            eighth_func()
        elif a==9:
            ninth_func()
        elif a==10:
            tenth_func()
        elif a==11:
            eleventh_func()
        elif a==12:
            twelfth_func()
        else:
            break


import sys
"""
# Exejercicio1.py

# DESCRIPCION:

Es un algoritmo que dados los precios de los productos ingresados por el usuario, el programa calcula el promedio

# Versión de:

	Cesar Colina 13-10299

# Ultima modificacion: 25/10/2016

# CONSTANTES:

# VARIABLES:
lista: lista// Lista donde se almacena los precios de los productos
contador: int // contador que nos sirve para iterar
suma: float // variable donde se ira guardando el resultado de la suma
x: float // variable donde el usuario ingresa el precio
promedio: float // variable donde se guarda el promedio de la suma de los precios

"""

# Valores iniciales:
lista = []
cota = 100
contador = 0
suma = 0

#Precondicion:

while contador < cota:

	x = float(input("Introduzca los precios de los articulos: "))
	assert(x >= 0)
	if x == 0:
		break
	lista.append(x)
	contador = contador + 1

#Calculos

for i in lista:
	suma = suma + i

promedio = suma / len(lista)

# Postcondicion:

assert(suma == sum(x for x in lista) and (promedio== (sum(x for x in lista) / len(lista))) )

 # Salida:

print("El promedio es ",promedio)


"""
Provides a function for splitting videos into consecutive chunks at provided intervals or at exact locations.
"""
from typing import Union, Tuple, List, Optional, Iterable

import diplomat.processing.type_casters as tc
from diplomat.utils.pretty_printer import printer
import cv2
from pathlib import Path
from os import PathLike
import tqdm
import math

FALLBACK_CODEC = "mp4v"
FALLBACK_EXT = ".mp4"

@tc.typecaster_function
def split_videos(
    videos: tc.Union[tc.Path, tc.List[tc.Path]],
    seconds_per_segment: tc.Union[tc.List[int], int] = 300,
    output_fourcc_string: tc.Optional[str] = None,
    output_extension: tc.Optional[str] = None
) -> tc.List[tc.List[Path]]:
    """
    Split a video into even length segments. This will produce a list of videos with "-part{number}" appended to the
    original video name in the same directory as the original video.

    :param videos: Either a single path-like object (string or Path) or a list of path-like objects, being the
                   paths to the videos to split into several segments.
    :param seconds_per_segment: An integer or a list of integers. If a single integer, represents the length of each
                                split segment in seconds (Ex. if 30, split the clip every 30 seconds). If a list of
                                integers, represents the locations to split the video at in seconds. The list can be
                                out of order, as it will be automatically sorted. Also, values that are out of range
                                will be ignored.
                                (Ex. if [10, 400, 100, 30], split the video at 10s, 400s, 100s, and 30s].
    :param output_fourcc_string: Optional, the fourcc string to use for output videos. If not specified uses input video fourcc code.
    :param output_extension: Optional, the file extension to use for output videos (including the dot).
                             Defaults to the input file extension if not specified.

    :returns: A list of lists of Path objects, being the new split video paths for each and every video...
    """
    videos = _sanitize_path_arg(videos)

    if(videos is None):
        raise ValueError("No videos provided!!!")

    return [_split_single_video(video, seconds_per_segment, output_fourcc_string, output_extension) for video in videos]

def _split_single_video(
    video_path: Path,
    seconds_per_segment: Union[int, List[int]],
    output_fourcc_string: Optional[str] = None,
    output_extension: Optional[str] = None
) -> List[Path]:
    """
    PRIVATE: Splits a single video.

    :param video_path: The path of the original video to split.
    :param seconds_per_segment: The duration of each segment, in seconds.
    :param output_fourcc_string: Optional, the output fourcc string. If not specified uses input fourcc code.
    :param output_extension: Optional, the output file extension. Defaults to the input file extension if not specified.

    :returns: The paths of the newly split videos, as a list of "Path"s...
    """
    printer(f"Processing video: {video_path}")
    vid = cv2.VideoCapture(str(video_path))

    width, height = int(vid.get(cv2.CAP_PROP_FRAME_WIDTH)), int(vid.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps = vid.get(cv2.CAP_PROP_FPS)
    total_frames = int(vid.get(cv2.CAP_PROP_FRAME_COUNT))

    four_cc = int(vid.get(cv2.CAP_PROP_FOURCC))
    if(four_cc == 0):
        four_cc = -1
    else:
        four_cc = "".join([chr((four_cc >> i) & 255) for i in range(0, 32, 8)])
        four_cc = cv2.VideoWriter_fourcc(*four_cc)

    if(output_fourcc_string is not None):
        four_cc = cv2.VideoWriter_fourcc(*output_fourcc_string)

    extension = video_path.suffix if(output_extension is None) else output_extension

    writer = None
    segment = 0
    frame = 0

    if(isinstance(seconds_per_segment, int)):
        # Yes, a range can be indexed just like an array... :)
        split_loc = range(0, total_frames, int(seconds_per_segment * fps))
    else:
        split_loc = sorted(set([0] + [int(seg * fps) for seg in seconds_per_segment]))

    bar = tqdm.tqdm(total=total_frames)

    zero_pad_amt = int(math.ceil(math.log10(total_frames + 1)))
    paths = []

    while(vid.isOpened()):
        if(writer is None):
            try:
                start = _list_access(split_loc, [total_frames], segment)
                end = _list_access(split_loc, [total_frames], segment + 1) - 1
                writer, p = _new_video_writer(video_path, (start, end), zero_pad_amt, four_cc, fps, (width, height), extension)
                paths.append(p)
            except OSError:
                vid.release()
                bar.close()
                raise
            segment += 1

        res, frm = vid.read()

        if(not res):
            break

        if(writer.isOpened()):
            writer.write(frm)

        if((segment < len(split_loc)) and (frame >= split_loc[segment])):
            writer.release()
            writer = None

        frame += 1
        bar.update(1)

    if(writer is not None):
        writer.release()

    bar.close()
    vid.release()

    return paths

def _list_access(list1, list2, index):
    comb = (list1, list2)
    return comb[index // len(list1)][index % len(list1)]

def _sanitize_path_arg(
    paths: Union[None, Iterable[PathLike], PathLike]
) -> Optional[List[Path]]:
    """
    Sanitizes a pathlike or list of pathlike argument and returns a list of Path, or None if rogue data was passed...
    """
    if isinstance(paths, (PathLike, str)):
        return [Path(str(paths)).resolve()]
    elif isinstance(paths, Iterable):
        paths = list(paths)
        if len(paths) > 0:
            return [Path(str(path)).resolve() for path in paths]
        else:
            return None
    else:
        return None

def _new_video_writer(
    video_path: Path,
    segment: Tuple[int, int],
    padding: int,
    four_cc: int,
    fps: float,
    size: Tuple[int, int],
    ext: str
) -> Tuple[cv2.VideoWriter, Path]:
    """
    PRIVATE: Construct a new video writer. Will try to use the passed codec if possible, otherwise uses a fallback codec and
    format.
    """
    suffix = f"_part{segment[0]:0{padding}d}-{segment[1]:0{padding}d}"
    preferred_path = video_path.parent / f"{video_path.stem}{suffix}{ext}"
    writer = cv2.VideoWriter(str(preferred_path), four_cc, fps, size)
    if(writer.isOpened()):
        return (writer, preferred_path)

    writer.release()
    fallback_path = video_path.parent / f"{video_path.stem}{suffix}{FALLBACK_EXT}"
    writer = cv2.VideoWriter(str(fallback_path), cv2.VideoWriter_fourcc(*FALLBACK_CODEC), fps, size)
    if(writer.isOpened()):
        return (writer, fallback_path)

    writer.release()
    raise OSError("Can't find a codec to write with!!!")


from app import app, db, mail
from app.models import User, Post

from app.forms import LoginForm, RegistrationForm, UpdateForm, RequestResetForm, ResetPasswordForm, BookMassageForm
from flask import render_template, url_for, redirect,jsonify, flash, request
from flask_login import login_user,logout_user,  current_user, login_required
from werkzeug.urls import url_parse
import secrets
from PIL import Image
import os
from flask_mail import Message

@app.route("/terms")
def terms():
    return render_template("terms.html",title="Terms Page")

@app.route('/')
@app.route('/home')
def home():
	"""
	if current_user.is_authenticated:
		user= {
		'username': User.query.get(current_user.get_id()).lastname,
		'career': "Developer"
		}
	else:
		user = {
		"username": "Sample User",
		"career": "Sample Career"
		}

	posts = Post.query.order_by(Post.timestamp).all()
	print(posts)
	"""

	return render_template('home.html', title="Home Page")

@app.route('/login', methods=['GET', 'POST'])
def login():

	if current_user.is_authenticated:
		return redirect(url_for("home"))

	form = LoginForm()

	if form.validate_on_submit():
		user = User.query.filter_by(email = form.email.data).first()

		if user == None or not user.check_password(form.password.data):
			flash("Invalid credentials")
			return redirect(url_for('login'))
		login_user(user, remember = form.remember_me.data)

		#Ensures redirect to desired page after login verification
		next_page = request.args.get('next')

		if not next_page or url_parse(next_page).netloc != '':
			next_page = url_for('home')

		return redirect(next_page)

	return render_template('login.html', title="Login Page", form=form)

@app.route('/logout')
@login_required
def logout():
	logout_user()
	return redirect(url_for('login'))

@app.route('/admin', methods=['POST', 'GET'])
@login_required
def admin():

	if not current_user.is_authenticated :
		return redirect(url_for("login"))

	user_id = current_user.get_id()
	user = User.query.get(user_id)

	if user.email != app.config['ADMINISTRATOR_MAIL']:
		return redirect(url_for("home"))

	flash("Welcome Administrator!")

	return render_template("admin.html", title="Admin Page")

@app.route('/registration', methods=['GET', 'POST'])
def registration():
	if current_user.is_authenticated:
		return redirect(url_for('home'))

	form = RegistrationForm()

	if form.validate_on_submit():
		user = User(firstname=form.firstname.data, lastname=form.lastname.data, email=form.email.data, phone_number= form.phone_number.data)
		user.set_password(form.password.data)
		print(user.email)

		db.session.add(user)
		db.session.commit()
		flash('Registration successful.')

		return redirect(url_for('login'))

	return render_template("registration.html", title="Registration Page", form = form)

@app.errorhandler(404)
def not_found_error(error):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_error(error):
    db.session.rollback()
    return render_template('500.html'), 500

#Save profile picture logic
def save_picture(form_picture):
	random_hex = secrets.token_hex(8)
	_, f_ext = os.path.splitext(form_picture.filename)
	picture_fn = random_hex + f_ext
	picture_path = os.path.join(app.root_path, 'static/profile_images', picture_fn)

	#Resize Image
	output_size = (250, 250)
	i = Image.open(form_picture)
	i.thumbnail(output_size)
	i.save(picture_path)
	return picture_fn

@app.route('/profile', methods=['GET', 'POST'])
@login_required
def profile():
	if not current_user.is_authenticated:
		return redirect(url_for("login"))

	form = UpdateForm()

	if form.validate_on_submit():

		if form.picture.data:
			#flash("Picture Data Available!!")
			picture_file = save_picture(form.picture.data)
			current_user.image_pic = picture_file

		current_user.firstname = form.firstname.data
		current_user.lastname = form.lastname.data
		current_user.email = form.email.data
		current_user.phone_number = form.phone_number.data
		db.session.commit()

		flash("Profile updated!")
		return redirect(url_for('profile'))
	elif request.method == 'GET':

		form.firstname.data = current_user.firstname
		form.lastname.data = current_user.lastname
		form.phone_number.data = current_user.phone_number
		form.email.data = current_user.email
		print(form.picture.data)

	posts = Post.query.filter_by(user_id= current_user.get_id()).all()
	image = url_for('static', filename='profile_images/'+ current_user.image_pic)

	return render_template("profile.html", title='Profile Page', posts=posts, image=image, form=form)

@app.route('/about', methods=['GET', 'POST'])
def about():
	return render_template('about.html', title='About Page')

@app.route('/contact', methods=['GET', 'POST'])
def contact():
	return render_template('contact.html', title='Contact Page')

def send_reset_email(user):
	token = user.get_reset_token()
	msg = Message('Password Reset Request', sender='artmanafrica.com', recipients=[user.email])
	msg.body = f'''To reset your password, visit the following link: {url_for('reset_token', token=token, _external=True)}
	If you did not make this request then simply ignore this message and no changes will be made.
	'''
	mail.send(msg)

@app.route('/reset_password', methods=['GET', 'POST'])
def reset_request():
	if current_user.is_authenticated:
		return redirect(url_for('home'))
	form = RequestResetForm()
	if form.validate_on_submit():
		user = User.query.filter_by(email=form.email.data).first()
		send_reset_email(user)
		flash('Check your email for instructions to reset your password.')
		return redirect(url_for('login'))
	return render_template('reset_request.html',title='Reset Password', form=form)

@app.route('/reset_password/<token>', methods=['GET', 'POST'])
def reset_token(token):
	if current_user.is_authenticated:
		return redirect(url_for('home'))
	user = User.verify_token(token)
	if user is None:
		flash('This is an expired or invalid token.')
		return redirect(url_for('reset_request'))
	form = ResetPasswordForm()
	if form.validate_on_submit():
		user.set_password(form.password.data)
		db.session.commit()
		flash('Password updated successfully.')
		return redirect(url_for('login'))
	return render_template('reset_token.html', form=form, title='Reset Password ')

@app.route('/swedish', methods=['GET', 'POST'])
@login_required
def swedish():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('swedish.html', form=form, title= "Swedish Massage")

@app.route('/sports', methods=['GET', 'POST'])
@login_required
def sports():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('sports.html', form=form, title= "Sports Massage")

@app.route('/deep_tissue', methods=['GET', 'POST'])
@login_required
def deep_tissue():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('deep_tissue.html', form=form, title= "Deep Tissue Massage")

@app.route('/reflexology', methods=['GET', 'POST'])
@login_required
def reflexology():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('reflexology.html', form=form, title= "Reflexology Massage")

@app.route('/shiatsu', methods=['GET', 'POST'])
@login_required
def shiatsu():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('shiatsu.html', form=form, title= "Shiatsu Massage")

@app.route('/thai', methods=['GET', 'POST'])
@login_required
def thai():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('thai.html', form=form, title= "Thai Massage")

@app.route('/prenatal', methods=['GET', 'POST'])
@login_required
def prenatal():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('prenatal.html', form=form, title= "Prenatal Massage")

@app.route('/couples', methods=['GET', 'POST'])
@login_required
def couples():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('couples.html', form=form, title= "Couples Massage")

@app.route('/chair', methods=['GET', 'POST'])
@login_required
def chair():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('chair.html', form=form, title= "Chair Massage")

@app.route('/stone', methods=['GET', 'POST'])
@login_required
def stone():
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	form = BookMassageForm()
	if form.validate_on_submit() and current_user.is_authenticated:
		massage = form.massage.data
		scheduled_on = form.scheduled_on.data
		user_id = current_user.id
		booking = Post(massage=massage, scheduled_on=scheduled_on, user_id= user_id)

		db.session.add(booking)
		db.session.commit()
		flash(f"{massage} booked on {scheduled_on}.")

	return render_template('stone.html', form=form, title= "Hot Stone Massage")


###############################################################################
# Author: Miguel Castilho Oliveira
# Date:04/21/2021
# Description This project is the final project for the class, a wheel of fortune
###############################################################################
import math as m
import random as r

def selectSentence(filename): #reads all of the lines from the phrases file and outputs them to a list. The function will then return a random line from that list
    listLines = []
    with open(filename, 'r') as fid:
        for line in fid:
            listLines.append(line.strip())
    randNumber = r.randrange(len(listLines))
    randomLine = listLines[randNumber]
    return(randomLine) #random line is returned as a string

#Code to replace the string with underscores and return that
def underscoreString(textLine): #sentence in this case is the sentence read from the file
    listCharacters = []
    listUnderscore = []

    for i in range(len(textLine)):
        listCharacters.append(textLine[i])

    for j in range(len(listCharacters)):
        if (listCharacters[j] != "'" and listCharacters[j] != ' ' and listCharacters[j] != '-' and listCharacters[j] != '_' and listCharacters[j] != '!' and listCharacters[j] != "&"):
            listUnderscore.append("_")
        else:
            listUnderscore.append(listCharacters[j])

    return("".join(listUnderscore))

def spin_the_wheel():
    possibleValues = [500, 500, 500, 500, 500, 550, 600, 600, 600, 600, 650, 650, 650, 700, 700, 700,800, 900, 2500, 'BANKRUPT', 'BANKRUPT']
    listIndex = r.randrange(0,21)
    randValue = possibleValues[listIndex]

    return(randValue)

#when called, the function will merely display what is going on to the user
def displayAndNextStep(underscores, unusedVowels, unusedConsonants,currentMoney, currentRound):
    print(f':::::::::::::::::::::::::::::::::::::::::: ROUND {currentRound} of 4 ::')
    print(f':: {underscores:53s}::')
    print( '::::::::::::::::::::::::::::::::::::::::::::::::::::::::::')
    print(f'::   {unusedConsonants}   ::   {unusedVowels}   ::',str('$'+f'{currentMoney:,}').rjust(10,' '), '::')
    print( '::::::::::::::::::::::::::::::::::::::::::::::::::::::::::')
    print("What would you like to do?")
    print("  1 - Spin the wheel")
    print("  2 - Buy a vowel")
    print("  3 - Solve the puzzle")
    print("  4 - Quit the game")
    numberChoice = (input("Enter the number of your choice: "))
    while (numberChoice != str(1) and numberChoice != str(2) and numberChoice != str(3) and numberChoice != str(4)):
        print(f'{numberChoice} is an invalid choice.')
        numberChoice = (input("Enter the number of your choice: "))

    return(float(numberChoice)) #the number choice wil be used for a selection structure in MAIN to determine what will be done next

def optionOne(textLine, consonantsLeft, currentMoney):
    fortuneSpin = spin_the_wheel()

    if fortuneSpin == 'BANKRUPT':
        print('The wheel landed on BANKRUPT.')
        print(f'You lost ${currentMoney:,}!')
        cash = 0 #if bankrupt the cash will be zero and the function will return nothing at the end
        consonant = '_'
        output = [consonant, cash] #the fact that no consonat was returned means the player got the bankrupt option, when that happens we will end the turn and update his new amount of money to 0
    else: #if the cash is not zero  it will request the user to pick a consonant, which then will be used to see if it exists in the phrase
        print(f'The wheel landed on ${fortuneSpin:,}.')

        textLine = textLine.lower()
        consonantsLeft = consonantsLeft.lower()

        consonant = input("Pick a consonant: ")

        if (consonant.isdigit() == False):
            consonant = consonant.lower()

        while (len(consonant.lower()) != 1 or consonant.lower() == 'a' or consonant.lower() == 'e' or consonant.lower() == 'i' or consonant.lower() == 'o' or consonant.lower() == 'u' or consonant.isdigit() == True or consonant == '$' or consonant == '@' or consonantsLeft.lower().count(consonant.lower()) == 0):
           if (consonant.isdigit() == True or consonant == '$' or consonant == "@"):
               print(f"The character {consonant.upper()} is not a letter.")
               consonant = input("Pick a consonant: ")

           elif (consonant.lower() == 'a' or consonant.lower() == 'e' or consonant.lower() == 'i' or consonant.lower() == 'o' or consonant.lower() == 'u'):
               print("Vowels must be purchased.")
               consonant = input("Pick a consonant: ")

           elif len(consonant.lower()) != 1:
               print("Please enter exactly one character.")
               consonant = input("Pick a consonant: ")

           else: #(consonantsLeft.lower().count(consonant) == 0):
               print(f'The letter {consonant.upper()} has already been used.')
               consonant = input("Pick a consonant: ")

        #Here, after checking if the input is a consonant, it checks if the consonant is actually present in the text string. If present it will output the consonant and the money gotten
        if consonant.lower() in textLine.lower():

            appearances = textLine.count(consonant)

            cash = appearances * fortuneSpin #cash gained in turn will be fortune spin times the appearances

            output = [consonant, cash]

            if appearances == 1:
                print(f"There is 1 {consonant.upper()}, which earns you ${appearances * fortuneSpin:,}.")
            else:
                print(f"There are {appearances} {consonant.upper()}'s, which earns you ${appearances * fortuneSpin:,}.")
        else:
            cash = 0
            output = [consonant, cash]
            print(f"I'm sorry, there are no {consonant.upper()}'s.")
    return(output) #index 0 is the consonant chosen by the user and index 1 is the amount of money the user now has
#Case 1: goes bankrupt, returns 0 money and consonant = '-'
#Case 2: finds the letter. Prints the necessary statement and returns the chosen consonant as wellas the amount of money gained
#Case 3: selects consonant that is not there. Prints necessary statement and returns 0 money and the consonant chosen

def optionTwoBuyVowel(currentMoney, vowelsLeft, textLine):
    vowelsLeft = vowelsLeft.lower()
    textLine = textLine.lower()
    cash = currentMoney - 250

    vowel = input('Pick a vowel: ')

    if (vowel.isdigit() == False):
            vowel = vowel.lower()

    while (len(vowel.lower()) != 1 and vowel.lower() != 'a' and vowel.lower() != 'e' and vowel.lower() != 'i' and vowel.lower() != 'o' and vowel.lower() != 'u' or vowelsLeft.count(vowel) == 0):
        if (vowel.isdigit() == True or vowel == '$' or vowel == '@'):
            print(f"The character {vowel} is not a letter.")
            vowel = input('Pick a vowel: ').lower()

        elif (vowel.lower() == 'b' or vowel.lower() == 'c' or vowel.lower() == 'd' or vowel.lower() == 'f' or vowel.lower() == 'g' or vowel.lower() == 'h' or vowel.lower() == 'j' or vowel.lower() == 'k' or vowel.lower() == 'l' or vowel.lower() == 'm' or vowel.lower() == 'n' or vowel.lower() == 'p' or vowel.lower() == 'q' or vowel.lower() == 'r' or vowel.lower() == 's' or vowel.lower() == 't' or vowel.lower() == 'v' or vowel.lower() == 'w' or vowel.lower() == 'x' or vowel.lower() == 'y' or vowel.lower() == 'z'):
            print("Consonants cannot be purchased.")
            vowel = input('Pick a vowel: ').lower()

        elif (len(vowel) != 1):
            print("Please enter exactly one character.")
            vowel = input('Pick a vowel: ').lower()

        else: #(vowelsLeft.count(vowel) == 0):
             print(f"The letter {vowel.upper()} has already been purchased.")
             vowel = input('Pick a vowel: ').lower()

    if vowel in textLine:
        appearances = textLine.count(vowel)
        print(f"There are {appearances} {vowel.upper()}'s.")

    else:
        print(f"I'm sorry, there are no {vowel.upper()}'s.")

    return(vowel) #returns the new amount of cash for index 1 and the vowel chosen so we can update the vowels left

def optionThreeSolvePuzzle(underscoreHiddenText, currentMoney, textLine):
        print("Enter your solution.")
        print(f"Clues: {underscoreHiddenText}")
        guess = input('Guess: ')

        if guess == textLine:
            print("Ladies and gentlemen, we have a winner!")
            print(f'You earned ${currentMoney:,d} for this round.')
            result = 'win'

        else:
            print("I'm sorry. The correct solution was:")
            print(f'{textLine.upper()}')
            print("You earned $0 this round")
            result = 'lose'
        return(result)

# def optionFourQuitGame(cashOverFourRounds):
#     print("You earned $0 this round.")
#     print("Thanks for playing!")
#     print(f"You earned a total of ${cashOverFourRounds:,}.")
    #cash for the round will be zero

def transformHiddenText(hiddenText, phraseLine, letter): #letter can be a consonant or a vowel
    phraseLine = phraseLine.lower()
    phraseList = [] #creates list with every letter and space in the sentence

    letter = letter.lower()

    hiddenTextList = [] # creates list with every underscore in the sentence

    for i in range(len(phraseLine)):
        phraseList.append(phraseLine[i])

    for i in range(len(hiddenText)):
        hiddenTextList.append(hiddenText[i])

    for i in range(len(phraseList)):
        if phraseList[i] == letter:
            hiddenTextList[i] = letter
            if (hiddenTextList[i - 1] == " "):
                letter = letter.upper()
            if hiddenTextList[i - 1] == "-":
                letter = letter.upper()

    hiddenText = "".join(hiddenTextList)

    truetext = hiddenText.capitalize()

    return(truetext)

def main():
    totalRoundCash = 0
    theRound = 1
    while theRound < 5:
    #TAB ALL THAT IS DOWN BELOW
        currentRound = theRound #round 1 or 2 or 3 or 4

        theSentence = selectSentence('phrases.txt') #new phrase will be selected each loop

        hiddenSentence = underscoreString(theSentence)

        unusedVowels = "AEIOU" #unused vowels, consonants and current money for the round when it starts
        unusedConsonants = "BCDFGHJKLMNPQRSTVWXYZ"
        currentMoney = 0

        while theSentence != hiddenSentence:

            chosenOption = displayAndNextStep(hiddenSentence, unusedVowels, unusedConsonants,currentMoney, currentRound)

            if chosenOption == 1: #in case the user wants to find consonants
                if unusedConsonants == "                     ":
                    print("There are no more consonants to choose.")

                else:
                    listCashConsonant = optionOne(theSentence, unusedConsonants, currentMoney)

                    consonant = listCashConsonant[0]

                    currentMoney += listCashConsonant[1]

                    unusedConsonants = unusedConsonants.upper().replace(consonant.upper(), " ")

                if consonant == '_':
                    currentMoney = 0

                hiddenSentence = transformHiddenText(hiddenSentence, theSentence, consonant)

            elif chosenOption == 2: #in case the user =wants to find vowels
                if unusedVowels == "     ":
                    print('There are no more vowels to buy.')

                else:

                    if currentMoney >= 250:
                        vowel = optionTwoBuyVowel(currentMoney, unusedVowels, theSentence)
                        currentMoney -= 250

                        unusedVowels = unusedVowels.upper().replace(vowel.upper(), " ")

                        hiddenSentence = transformHiddenText(hiddenSentence, theSentence, vowel)

                    else:
                        print("You need at least $250 to buy a vowel.")

            elif chosenOption == 3:
                result = optionThreeSolvePuzzle(hiddenSentence, currentMoney, theSentence)
                if result == 'win':
                    break

                else:
                    currentMoney == 0
                    break

            else:
                # optionFourQuitGame(totalRoundCash)
                print("You earned $0 this round.")
                currentMoney = 0
                theRound = 4
                break

        theRound += 1

        totalRoundCash += currentMoney

    print("Thanks for playing!")
    print(f"You earned a total of ${totalRoundCash:,}.")

if __name__ == '__main__':
    main()


import numpy as np
import os
import sys

lib_path = os.path.abspath('../../python/')
sys.path.append(lib_path)

from bbo.distribution_gaussian import DistributionGaussian
from bbo.bbo_plotting import plotUpdate, plotLearningCurve, plotExplorationCurve, setColor, saveUpdate
from bbo.bbo_plotting import loadLearningCurve, loadExplorationCurve
from dmp_bbo.rollout import Rollout, loadRolloutFromDirectory

def containsNewDistribution(directory):
    if os.path.exists(directory+"/distribution_new_mean.txt"):
        return True
    if os.path.exists(directory+"/distribution_new_000_mean.txt"):
        return True
    return False

def plotOptimizationRollouts(directory,fig,plotRollout=None,plot_all_rollouts=False):

    if not fig:
        fig = plt.figure(1,figsize=(9, 4))

    # Determine number of updates
    n_updates = 1
    update_dir = '%s/update%05d' % (directory, n_updates)
    while containsNewDistribution(update_dir):
        n_updates += 1
        update_dir = '%s/update%05d' % (directory, n_updates)
    n_updates -= 1

    if n_updates<2:
        return None

    all_costs = []
    learning_curve = []
    exploration_curve = []

    i_samples = 0
    for i_update in range(n_updates):

        update_dir = '%s/update%05d' % (directory, i_update)

        # Read data
        mean = np.loadtxt(update_dir+"/distribution_mean.txt")
        covar = np.loadtxt(update_dir+"/distribution_covar.txt")
        distribution = DistributionGaussian(mean,covar)

        try:
            mean = np.loadtxt(update_dir+"/distribution_new_mean.txt")
            covar = np.loadtxt(update_dir+"/distribution_new_covar.txt")
            distribution_new = DistributionGaussian(mean,covar)
        except IOError:
            distribution_new = None

        try:
            covar_block_sizes = np.loadtxt(update_dir+"/covar_block_sizes.txt")
        except IOError:
            covar_block_sizes = len(distribution.mean)

        try:
            samples = np.loadtxt(update_dir+"/samples.txt")
        except IOError:
            samples = None
        costs = np.loadtxt(update_dir+"/costs.txt")
        weights = np.loadtxt(update_dir+"/weights.txt")

        try:
            cost_eval = np.loadtxt(update_dir+"/cost_eval.txt")
        except IOError:
            cost_eval = None

        n_rollouts = len(weights)
        rollouts = []
        for i_rollout in range(n_rollouts):
            rollout_dir = '%s/rollout%03d' % (update_dir, i_rollout+1)
            rollouts.append(loadRolloutFromDirectory(rollout_dir))

        rollout_eval = loadRolloutFromDirectory(update_dir+'/rollout_eval/')

        # Update learning curve
        # Bookkeeping and plotting
        # All the costs so far
        all_costs.extend(costs)
        # Update exploration curve
        i_samples = i_samples + n_rollouts
        cur_exploration = np.sqrt(distribution.maxEigenValue())
        exploration_curve.append([i_samples,cur_exploration])
        # Update learning curve
        learning_curve.append([i_samples])
        learning_curve[-1].extend(np.atleast_1d(cost_eval))

        n_subplots = 3
        i_subplot = 1
        if plotRollout:
            n_subplots = 4
            ax_rollout = fig.add_subplot(1,n_subplots,i_subplot)
            i_subplot += 1
            h = plotRollout(rollout_eval.cost_vars,ax_rollout)
            setColor(h,i_update,n_updates)

        ax_space = fig.add_subplot(1,n_subplots,i_subplot)
        i_subplot += 1
        highlight = (i_update==0)
        plotUpdate(distribution,cost_eval,samples,costs,weights,distribution_new,ax_space,highlight)

    plotExplorationCurve(exploration_curve,fig.add_subplot(1,n_subplots,i_subplot))
    plotLearningCurve(learning_curve,fig.add_subplot(1,n_subplots,i_subplot+1))

#def plotOptimizations(directories,axs):
#    n_updates = 10000000
#    for directory in directories:
#        cur_n_updates = loadNumberOfUpdates(directory)
#        n_updates = min([cur_n_updates, n_updates])
#
#    n_dirs = len(directories)
#    all_costs_eval      = np.empty((n_dirs,n_updates),   dtype=float)
#    all_eval_at_samples = np.empty((n_dirs,n_updates), dtype=float)
#    for dd in range(len(directories)):
#        (update_at_samples, tmp, eval_at_samples, costs_eval) = loadLearningCurve(directories[dd])
#        all_costs_eval[dd]      = costs_eval
#        all_eval_at_samples[dd] = eval_at_samples
#
#    ax = axs[1]
#    lines_lc = plotLearningCurves(all_eval_at_samples,all_costs_eval,ax)
#    plotUpdateLines(update_at_samples,ax)
#
#    all_sqrt_max_eigvals = np.empty((n_dirs,n_updates+1), dtype=float)
#    all_covar_at_samples = np.empty((n_dirs,n_updates+1), dtype=float)
#    for dd in range(len(directories)):
#        (covar_at_samples, sqrt_max_eigvals) = loadExplorationCurve(directories[dd])
#        all_sqrt_max_eigvals[dd] = sqrt_max_eigvals[:n_updates+1]
#        all_covar_at_samples[dd] = covar_at_samples[:n_updates+1]
#
#    ax = axs[0]
#    lines_ec = plotExplorationCurves(all_covar_at_samples,all_sqrt_max_eigvals,ax)
#    plotUpdateLines(update_at_samples,ax)
#
#return (lines_ec, lines_lc)

def saveUpdateRollouts(directory, i_update, distribution, rollout_eval, rollouts, weights, distribution_new):

    update_dir = '%s/update%05d' % (directory, i_update)
    if not os.path.exists(update_dir):
        os.makedirs(update_dir)

    # Save rollouts
    n_rollouts = len(rollouts)
    for i_rollout in range(n_rollouts):
         cur_dir = '%s/rollout%03d' % (update_dir, i_rollout+1)
         rollouts[i_rollout].saveToDirectory(cur_dir)

    if rollout_eval:
        rollout_eval.saveToDirectory(update_dir+'/rollout_eval')

    # use saveUpdate to save the rest
    cost_eval = None
    if rollout_eval:
        cost_eval = rollout_eval.cost

    if rollouts[0].total_cost():
        costs = [rollout.cost for rollout in rollouts]
    else:
        costs = None

    n_dims = len(rollouts[0].policy_parameters)
    samples = np.full((n_rollouts,n_dims),0.0)
    for i_rollout in range(n_rollouts):
        samples[i_rollout,:] = rollouts[i_rollout].policy_parameters

    saveUpdate(directory, i_update, distribution, cost_eval, samples, costs, weights, distribution_new)


import torch
import numpy as np
import scipy.sparse as sp
from attackers.base import AttackABC
from torch_sparse import SparseTensor

class RandomAttack(AttackABC):

    def __init__(self,
                 attack_config, pyg_data,
                 model, device, logger, **kwargs):
        super(RandomAttack, self).__init__(attack_config, pyg_data, model, device, logger)
        self.att_type = attack_config['att_type']

    def _attack(self, n_perturbations):
        adj = self.pyg_data.adj_t.to_scipy(layout='csr')
        modified_adj = adj.tolil()
        type = self.att_type.lower()
        assert type in ['add', 'remove', 'flip']

        if type == 'flip':
            # sample edges to flip
            edges = self.random_sample_edges(adj, n_perturbations, exclude=set())
            for n1, n2 in edges:
                modified_adj[n1, n2] = 1 - modified_adj[n1, n2]
                modified_adj[n2, n1] = 1 - modified_adj[n2, n1]

        if type == 'add':
            # sample edges to add
            nonzero = set(zip(*adj.nonzero()))
            edges = self.random_sample_edges(adj, n_perturbations, exclude=nonzero)
            for n1, n2 in edges:
                modified_adj[n1, n2] = 1
                modified_adj[n2, n1] = 1

        if type == 'remove':
            # sample edges to remove
            nonzero = np.array(sp.triu(adj, k=1).nonzero()).T
            indices = np.random.permutation(nonzero)[: n_perturbations].T
            modified_adj[indices[0], indices[1]] = 0
            modified_adj[indices[1], indices[0]] = 0

        self.adj_adversary = SparseTensor.from_dense(torch.tensor(modified_adj.todense()))

    def random_sample_edges(self, adj, n, exclude):
        itr = self.sample_forever(adj, exclude=exclude)
        return [next(itr) for _ in range(n)]

    def sample_forever(self, adj, exclude):
        """Randomly random sample edges from adjacency matrix, `exclude` is a set
        which contains the edges we do not want to sample and the ones already sampled
        """
        while True:
            # t = tuple(np.random.randint(0, adj.shape[0], 2))
            # t = tuple(random.sample(range(0, adj.shape[0]), 2))
            t = tuple(np.random.choice(adj.shape[0], 2, replace=False))
            if t not in exclude:
                yield t
                exclude.add(t)
                exclude.add((t[1], t[0]))


# -*— coding: utf-8 -*-
from aip import AipNlp
import config

client = AipNlp(config.BD_NLP_APP_ID, config.BD_NLP_API_KEY, config.BD_NLP_SECRET_KEY)

# 20000字节 词法分析
def divide_words(text):
    if len(text) == 0:
        return {
            'all': []
        }
    result = client.lexer(text)
    if 'error_code' in result.keys():
        raise Exception('\ndevide words error \n text:%s\nError code:' % text + str(
            result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        words = {
            'all': []
        }
        items = result['items']
        for item in items:
            content = item['item']
            words['all'].append(content)
            if not item['ne'] == '':
                if 'ne' in words.keys():
                    words['ne'].append(content)
                else:
                    words['ne'] = [content]
            if not item['pos'] == '':
                temp = item['pos']
                if temp in words.keys():
                    words[temp].append(content)
                else:
                    words[temp] = [content]
    return words

# 256字节 句法分析
def parser(text):
    if len(text) == 0:
        return {
            'all': []
        }
    options = {'mode': 1}
    result = client.depParser(text, options=options)
    if 'error_code' in result.keys():
        raise Exception('\n parse text error \n text:%s\nError code:' % text + str(
            result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        words = {
            'all': []
        }
        items = result['items']
        for item in items:
            content = item['word']
            words['all'].append(content)
            postag, deprel = item['postag'], item['deprel']
            if postag in words.keys():
                words[postag].append(content)
            else:
                words[postag] = [content]
            if deprel in words.keys():
                words[deprel].append(content)
            else:
                words[deprel] = [content]
        return words

# 512字节 文本流畅度
def smooth_of_text(text):
    if len(text) == 0:
        return 0
    result = client.dnnlm(text)
    if 'error_code' in result.keys():
        raise Exception('\nsmooth of text error\ntext:%s\nError code:' % text + str(
            result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        return result['ppl']

def similar_of_words(word1, word2):
    if len(word1) == 0 or len(word2) == 0:
        return 0
    result = client.wordSimEmbedding(word1, word2)
    if 'error_code' in result.keys():
        raise Exception('\nsimilar of words error \n word1:%s,word2:%s\nError code:' % (word1, word2) + str(
            result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        return result['score']

# 512字节 文本相似度
def similar_of_texts(text1, text2):
    if len(text1) == 0 or len(text2) == 0:
        return 0
    result = client.simnet(text1, text2)
    if 'error_code' in result.keys():
        if result['error_code'] == 282301 or result['error_code'] == 282302 or result['error_code'] == 28303:
            return 0
        else:
            raise Exception('\nsimilar of texts error \n text1:%s,text2:%s\nError code:' % (text1, text2) +
                            str(result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        return result['score']

# 2048字节 情感倾向
def text_classify(text):
    if len(text) == 0:
        return {
            'positive': 0,
            'negative': 0,
            'sentiment': 'neutral'
        }
    result = client.sentimentClassify(text)
    if 'error_code' in result.keys():
        raise Exception('\ntext classify error \n text:%s\nError code:' % text + str(
            result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        sentiment = result['items'][0]
        return {
            'positive': sentiment['positive_prob'],
            'negative': sentiment['negative_prob'],
            'sentiment': ['negative', 'neutral', 'positive'][sentiment['sentiment']]
        }

# 65535字节 文本关键词
def label_of_article(content, title='0'):
    if len(content) == 0:
        return ''
    result = client.keyword(title, content)
    if 'error_code' in result.keys():
        raise Exception('\nlabel of article error \n title:%s,content:%s\nError code:' % (content, title) + str(
            result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        return result['items']

# 511字节 文本错误数量，基本不可用
def wrongs_of_text(text):
    if len(text) == 0:
        return 0
    result = client.ecnet(text)
    if 'error_code' in result.keys():
        raise Exception('\nerror of article \n text: %s\nError code:' % text + str(
            result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        return len(result['item']['vec_fragment'])

# 512字节 文本对话情绪
def emotion(text):
    if len(text) == 0:
        return {
            'pessimistic': 0,
            'neutral': 0
        }
    result = client.emotion(text)
    if 'error_code' in result.keys():
        raise Exception('\nerror of article \n text: %s\nError code:' % text + str(
            result['error_code']) + '\nError Message:' + result['error_msg'])
    else:
        return {
            'pessimistic': result['items'][1]['prob'],
            'neutral': result['items'][0]['prob']
        }

if __name__ == '__main__':
    # print(divide_words(''))
    print(divide_words('我想吃饭'))
    # print(smooth_of_text('我想吃饭'))
    # print(similar_of_texts('的', '麦当劳'))
    # print(text_classify('我不想吃饭'))
    # print(label_of_article(
    #     '肯德基和麦当劳是世界快餐巨头。肯德基诞生于1952年，由创始人哈兰·山德士创建，'
    #     '在世界上115个国家和地区开设有18000多家肯德基餐厅，肯德基在1987 年进入中国，收到广大消费者的喜欢。麦当劳，1955年创立于美国芝加哥，在中国大陆早期译名是“麦克唐纳快餐”，'
    #     '直到后期才统一使用现在的名字。麦当劳遍布全球六大洲119个国家，在很多国家代表着一种美式生活方式。'
    #     '在中国，因为肯德基要比麦当劳更受欢迎，很多人会觉得肯德基是世界上最大的餐饮企业，但其实麦当劳才是。麦当劳在世界上拥有3万多家门店，而肯德基的门店数量只是拥麦当劳的三分之一。'))


# !/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/4/14 16:47
# @Author  : Yunhao Cao
# @File    : tool.py
import codecs
import os

import cv2
import numpy as np

import config

__author__ = 'Yunhao Cao'

level_list = config.LV_LIST
input_shape = config.TRAIN_SHAPE

compare_path = os.path.join

train_set_dir = config.TRAINSET_DIR
validation_set_dir = config.VALIDATION_DIR
sync_name = 'sync.txt'

def get_max_index(l):
    max_index = 0
    max_item = 0
    for i, item in enumerate(l):
        if item > max_item:
            max_item = item
            max_index = i

    return max_index

def get_v_range(level):
    start = level_list[level - 1] if level > 0 else 0
    if (level + 1) < len(level_list):
        end = level_list[level]
    else:
        end = None
    return start, end

def TRAIN_SET_DIR_i(i):
    return compare_path(train_set_dir, 'set_' + i)

def train_set_images(i):
    return compare_path(TRAIN_SET_DIR_i(i), 'images')

def get_all(dir_: str) -> list:
    return list(sorted([os.path.join(dir_, name) for name in os.listdir(dir_) if not name.startswith('.')]))

def read_text(filename):
    with codecs.open(filename, "r", 'utf8') as f:
        return [_.split('\n')[0] for _ in f.readlines() if _]

def write_text(filename, lines, end='\n'):
    with codecs.open(filename, 'w', 'utf8') as f:
        f.write(end.join([str(_) for _ in lines]))

def read_image(filename):
    print('[read_image]', filename)
    return cv2.imread(filename)

def image_cut(data, shape):
    return cv2.resize(data, shape, interpolation=cv2.INTER_CUBIC)

def image_save(filename, data):
    cv2.imwrite(filename, data)

def Array(i, dtype=None):
    return np.array(i, dtype=dtype)

def ArraySplit(array, rate):
    n = int(array.shape[0] * rate)
    return array[:n], array[n:]

def ArrayCut(array, out_shape, mode=5):
    """
    1 2 3
    4 5 6
    7 8 9
    :param array: np.ndarray
    :param out_shape: (height, width)
    :param mode: 1~9
    :return: cut array
    """
    in_shape = array.shape[:2]
    y_diff = in_shape[0] - out_shape[0]
    x_diff = in_shape[1] - out_shape[1]
    y_start = x_start = 0
    y_end = out_shape[0]
    x_end = out_shape[1]
    if mode in (4, 5, 6):
        y_start = y_diff // 2
        y_end = in_shape[0] - y_start - y_diff % 2
    if mode in (2, 5, 8):
        x_start = x_diff // 2
        x_end = in_shape[1] - x_start - x_diff % 2
    if mode in (7, 8, 9):
        y_start = y_diff
        y_end = None
    if mode in (3, 6, 9):
        x_start = x_diff
        x_end = None

    return array[y_start:y_end, x_start: x_end]

if __name__ == '__main__':
    pass


import os

from django.conf import settings

from rest_framework import pagination

class AutoDetectedPageNumberPagination(pagination.PageNumberPagination):
    template = os.path.join(os.path.dirname(__file__), 'templates/browsable_api/numbers.html')
    page_size = getattr(settings, 'REST_API_PAGE_SIZE', 20)
    page_size_query_param = getattr(settings,
                                    'REST_API_PAGE_SIZE_QUERY_PARAM',
                                    'page_size')
    max_page_size = getattr(settings,
                            'REST_API_MAX_PAGE_SIZE',
                            100)

    def get_page_size(self, request):
        if self.page_size_query_param:
            try:
                if int(request.query_params[self.page_size_query_param]) <= 0:
                    return None
                else:
                    return pagination._positive_int(
                        request.query_params[self.page_size_query_param],
                        strict=True,
                        cutoff=self.max_page_size
                    )
            except (KeyError, ValueError):
                pass

        return self.page_size


# Inputting various modules
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Loading the Iris dataset
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class']
dataset = pd.read_csv(url, names=names)

#Selecting specific rows and columns
X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, -1].values

# Splitting the data into training and testing data into a split 70-30 percentage
train_size = int(0.7 * len(X))
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]

# Scaling the Data
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# Building and training the Logistic Regression Model with the training data
def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def predict(X, theta):
    return sigmoid(np.dot(X, theta))

def cost_function(X, y, theta):
    m = len(y)
    h = predict(X, theta)
    J = (-1/m) * np.sum((y * np.log(h)) + ((1-y) * np.log(1-h)))
    return J

def gradient_descent(X, y, theta, alpha, num_iters):
    m = len(y)
    J_history = np.zeros((num_iters, 1))
    for i in range(num_iters):
        h = predict(X, theta)
        theta -= alpha * (1/m) * np.dot(X.T, (h - y))
        J_history[i] = cost_function(X, y, theta)
    return theta, J_history

X_train = np.insert(X_train, 0, 1, axis=1)
y_train = np.where(y_train == 'Iris-setosa', 0, np.where(y_train == 'Iris-versicolor', 1, 2))

num_iters = 1000
alpha = 0.1
theta = np.zeros((X_train.shape[1], 1))

theta, J_history = gradient_descent(X_train, y_train.reshape(-1, 1), theta, alpha, num_iters)

#Evaluating the model

X_test = np.insert(X_test, 0, 1)


import itertools
import warnings
import numpy as np

import bloopy.analysis.analysis_utils as anutil
from bloopy.individual import individual
import bloopy.utils as utils

def classify_points(bsize, bound_list, nidxs_dict, method='bounded'):
    if method not in ["circular", "bounded", "Hamming"]:
        raise Exception("Unknown neighbour generator given!")
    var_ranges = anutil.get_variable_ranges(bound_list)

    count_saddles = 0
    count_minima = 0
    count_maxima = 0
    regular_points = 0
    total = 0

    #A point is classified as type 0,1,2,3
    # 0 is regular, 1 is local minimum,
    # 2 is local maximum, and 3 is saddlepoint
    # we save points as tuple (type, fit, node_index) for convenience
    point_class = dict()
    for x in itertools.product(*var_ranges):
        nr_dims_is_minimal = 0
        isRegular = False
        xidx, xfit = nidxs_dict[x]
        if method == "circular":
            nbours = anutil.generate_circular_neighbours_perdim(x, var_ranges)
        elif method == "Hamming":
            nbours = anutil.generate_Hamming_neighbours_perdim(x, var_ranges)
        else:
            nbours = anutil.generate_bounded_neighbours_perdim(x, var_ranges)
        for dim in range(len(nbours)):
            nbours_larger = 0
            if len(nbours[dim]) == 0:
                raise Exception("Should already have been removed when processing space.")
            elif len(nbours[dim]) == 1:# Only one neighbour
                n1 = nbours[dim][0]
                n1_idxs, n1fit = nidxs_dict[n1]
                if n1fit == xfit:#This is for the failfit
                    if xfit > 10000:
                        isRegular = True
                        break
                    else:
                        print(xfit, "1")
                        warnings.warn("Equal fitness found")
                        #raise Exception("Equal fitness found")
                if n1fit >= xfit:
                    nbours_larger += 1
                    nr_dims_is_minimal += 1
            elif len(nbours[dim]) == 2:# Only one neighbour
                n1, n2 = nbours[dim]
                n1_idxs, n1fit = nidxs_dict[n1]
                n2_idxs, n2fit = nidxs_dict[n2]
                if n1fit == xfit or n2fit == xfit:#This is for the failfit
                    if xfit > 10000:
                        isRegular = True
                        break
                    else:
                        print(xfit, "2")
                        warnings.warn("Equal fitness found")
                        #raise Exception("Equal fitness found")
                if n1fit >= xfit:
                    nbours_larger += 1
                if n2fit >= xfit:
                    nbours_larger += 1
                if nbours_larger == 1:#Its not a critical point as it has
                    # a non-zero gradient in this dimension
                    isRegular = True
                    break
                elif nbours_larger == 2:
                    nr_dims_is_minimal += 1
            else:# More neighbours
                nbours_larger = 0
                for ni in nbours[dim]:
                    ni_idxs, nifit = nidxs_dict[ni]
                    if nifit == xfit:#This is for the failfit
                        if xfit > 10000:
                            isRegular = True
                            break
                        else:
                            warnings.warn("Equal fitness found")
                            print(xfit, "N")
                            #raise Exception("Equal fitness found")
                    if nifit >= xfit:
                        nbours_larger += 1
                if nbours_larger == len(nbours[dim]):#minimal in this dim
                    nr_dims_is_minimal += 1
                elif nbours_larger == 0:#maximal in this dim
                    pass
                else:#Its not a critical point as it has
                    # a non-zero gradient in this dimension
                    isRegular = True
                    break

        total += 1
        if x in point_class.keys():
            raise Exception("SOMETHING WRONG")

        if isRegular:
            regular_points += 1
            point_class[x] = [0, xfit, xidx]
            continue

        if nr_dims_is_minimal == 0:
            count_maxima += 1
            point_class[x] = [2, xfit, xidx]
        elif nr_dims_is_minimal == len(bound_list):
            count_minima += 1
            point_class[x] = [1, xfit, xidx]
        else:
            count_saddles += 1
            point_class[x] = [3, xfit, xidx]
    return total, count_minima, count_maxima, count_saddles, regular_points, point_class

def strong_local_minima(p, globfit, space_dict):
    loc_min_idxs = []
    for pt, value in space_dict.items():
        ptype, pfit, pidx = value
        if ptype != 1:
            continue
        if pfit <= (1+p)*globfit:
            loc_min_idxs.append(pidx)
    return loc_min_idxs

def strong_critical_points(p, globfit, space_dict):
    loc_min_idxs = []
    for pt, value in space_dict.items():
        ptype, pfit, pidx = value
        if ptype == 0:
            continue
        if pfit <= (1+p)*globfit:
            loc_min_idxs.append(pidx)
    return loc_min_idxs

def sizes_minima(sspace, bsize, bound_list, fitfunc, method="bounded"):
    if method not in ["circular", "bounded", "Hamming"]:
        raise Exception("Unknown neighbour generator given!")
    indiv = individual(bsize, boundary_list=bound_list)
    var_ranges = anutil.get_variable_ranges(bound_list)
    count_minima = 0
    total = 0
    hole_depths = []
    for x in itertools.product(*var_ranges):
        utils.set_bitstring(indiv, list(x))
        xfit = fitfunc(indiv.bitstring)

        if method == "circular":
            nbours = anutil.generate_circular_neighbours(x, var_ranges)
        elif method == "Hamming":
            nbours = anutil.generate_Hamming_neighbours(x, var_ranges)
        else:
            nbours = anutil.generate_bounded_neighbours(x, var_ranges)

        if xfit > 10000:
            is_minimal = False
        else:
            is_minimal = True
            nfits = []
            for nbour in nbours:
                utils.set_bitstring(indiv, nbour)
                nfit = fitfunc(indiv.bitstring)
                nfits.append(nfit)
                if nfit < xfit:# Neighbour has lower fitness
                    is_minimal = False
            if is_minimal:
                hole_depth = min(nfits) - xfit
                hole_depths.append([xfit, hole_depth])
                count_minima += 1
        total += 1
    return count_minima, total, np.array(hole_depths)


import json

class c2s():

    def __init__(self, pair_file_dev, pair_file_test, pair_file_train,
                 data_file_dev, data_file_test, data_file_train,
                 pair , out_true, out_false, json_file):

        self.pair_file = [pair_file_dev,pair_file_test,pair_file_train]
        self.data_file =[data_file_dev,data_file_test,data_file_train]
        self.pair = pair
        self.out_ture = out_true
        self.out_false = out_false
        self.json_file = json_file

    def get_pair(self):
        for file in self.pair_file:
            with open(file, encoding='utf-8') as f:
                self.pair.update(json.load(f))
        return self.pair

    def get_data(self):
        for file in self.data_file:
            with open(file, encoding='utf-8') as f:
                data = json.load(f)
                for line in data:
                    if line.get('label') == 'True' and line.get( "scenario") == 'causal':
                        self.out_ture[str(line.get('id'))] = line.get( "sent")
                    if line.get('label') == 'False' and line.get( "scenario") == 'causal':
                        self.out_false[str(line.get('id'))] = line.get("sent")

        return  self.out_ture, self.out_false

    def out_put(self):
        write = []
        i= 0
        for id, sent in self.out_ture.items():
            i = i+1
            write_sub = {'id' : i, 'True':sent, 'False':self.out_false[self.pair[id]]}
            write.append(write_sub)
        with open(self.json_file, 'w', encoding='utf-8', newline='\n') as fs:
            json.dump(write, fs, ensure_ascii=False,indent=1)
        return write

pair = {}
out_ture = {}
out_false = {}
a = c2s('cs2_convert/data/pair_id_dev.json','cs2_convert/data/pair_id_test.json','cs2_convert/data/pair_id_train.json',
        'cs2_convert/data/dev.json','cs2_convert/data/test.json','cs2_convert/data/train.json',
        pair, out_ture, out_false,'cs2_convert/cs2_convert.json')

pair = a.get_pair()
out = a.get_data()
result = a.out_put()


from bs4 import BeautifulSoup #you are only importing beautifulsoup module only
import urllib.request, urllib.parse, urllib.error
import ssl #you are importing the entire libray

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
url = "http://py4e-data.dr-chuck.net/known_by_Ciara.html"

position = 18

for x in range(7): #loop that repeats 7 times:
    links = list()  #list created so that you can get the 18th link , declared here so the loop will be fresh every loop
    html = urllib.request.urlopen(url, context=ctx).read()
    soup = BeautifulSoup(html, "html.parser")
    tags = soup('a')
    for tag in tags:
        links.append(tag.get('href' , None)) #add all the href in the links list
    url = links[position-1] #url takes the 18th link as the new varible and runs the next iteration of the loop

    #testing commit

print(url)


"""Test the inventory command"""

from pythonclass.adventure.adventure import (
    do_inventory,
    inventory_change,
)

from tests.adventure import read

def test_do_inventory_empty(capsys):
    inventory_change("gems", -50)

    do_inventory()
    output = read(capsys)

    assert "Inventory" in output, \
        "The title should be in output"

    assert "Empty." in output, \
        "An empty inventory should say so in output"

def test_do_inventory(capsys):
    do_inventory()
    output = read(capsys)

    assert "Inventory" in output, \
        "The title should be in output"

    assert "(x50)  gems" in output, \
        "Inventory items should be listed in output"


from flask import Flask, request, jsonify

app = Flask(__name__)
@app.route('/')
def home():
    return f'Hello there from Bonnie Flask API Endpoint Server'

@app.route('/hello', methods=['GET'])
def hello_get():
    name = request.args.get('name', 'World')
    middlename = request.args.get('middlename', 'no middle name provided')
    nameCapital = name.upper()
    middlenameCapital = middlename.upper()
    return f'Hello {nameCapital} {middlenameCapital}!'

@app.route('/hello', methods=['POST'])
def hello_post():
    data = request.get_json()
    if data is None:
        return jsonify({'error': 'Invalid JSON'}), 400

    name = data.get('name', 'World')
    return jsonify({'message': f'Hello {name}!'})

if __name__ == '__main__':
    app.run(debug=True)