# Import des modules/ packages utiles au fonctionnement des routes
# Relation templates et routes, manipulation requêtes et réponses HTTP, envoi de messages flash, redirection
from flask import render_template, request, flash, redirect
# Pour la gestion des comptes utilisateurs
from flask_login import login_user, logout_user, current_user, login_required
# Import de la variable app
from BibPart.app import app
# Import pour la pagination
from .constantes import RESULTATS_PAR_PAGE
# Import permettant d'utiliser l'opérateur booléen or
from sqlalchemy import or_
# Import de l'ensemble des modèles de classe utiles
from .modeles.donnees import Oeuvre, Partition, Compositeur, Type, Instrument, Forme, Institution_conservation
from .modeles.utilisateurs import Utilisateur

# ROUTES PERMETTANT L'AFFICHAGE DES PAGES ACCUEIL ET EN SAVOIR PLUS

@app.route("/")
def accueil():
    """
    Route permettant l'affichage de la page accueil
    :returns : affichage du template accueil.html
    :rtype: page html
    """
    oeuvres = Oeuvre.query.filter(Oeuvre.id_oeuvre).all()
    partitions = Partition.query.filter(Partition.id_partition).all()
    compositeurs = Compositeur.query.filter(Compositeur.id_compositeur).all()
    return render_template("pages/accueil.html", nom="BibPart", oeuvres=oeuvres, partitions=partitions,
                           compositeurs=compositeurs)

@app.route("/ensavoirplus")
def ensavoirplus():
    """ Route permettant l'affichage de la page En savoir plus
    :returns : affichage du template ensavoirplus.html
    :rtype: page html
    """
    return render_template("pages/ensavoirplus.html")

# ROUTES PERMETTANT L'AFFICHAGE DES INDEX

@app.route("/index_oeuvres")
def index_oeuvres():
    """ Route permettant l'affichage de l'index des oeuvres
    :returns: affichage du template index_oeuvres.html
    :rtype: page html
    """
    alloeuvres = Oeuvre.query.all()

    if len(alloeuvres) == 0:
        return render_template("pages/index_oeuvres.html", var_groupe_oeuvres=alloeuvres)
    else:
        page = request.args.get("page", 1)

        if isinstance(page, str) and page.isdigit():
            page = int(page)
        else:
            page = 1

    alloeuvres = Oeuvre.query.order_by(Oeuvre.titre_oeuvre).paginate(page=page, per_page=RESULTATS_PAR_PAGE)
    return render_template("pages/index_oeuvres.html", nom="BibPart", var_groupe_oeuvres=alloeuvres)

@app.route("/index_partitions")
def index_partitions():
    """ Route permettant l'affichage de l'index des partitions
    :returns: affichage du template index_partitions.html
    :rtype: page html
    """
    allpartitions = Partition.query.all()

    if len(allpartitions) == 0:
        return render_template("pages/index_oeuvres.html", var_groupe_partitions=allpartitions)
    else:
        page = request.args.get("page", 1)

        if isinstance(page, str) and page.isdigit():
            page = int(page)
        else:
            page = 1

    allpartitions = Partition.query.order_by(Partition.titre_partition).paginate(page=page, per_page=RESULTATS_PAR_PAGE)
    return render_template("pages/index_partitions.html", nom="BibPart", var_groupe_partitions=allpartitions)

@app.route("/index_compositeurs")
def index_compositeurs():
    """ Route permettant l'affichage de l'index des compositeurs
    :returns: affichage du template index_compositeurs.html
    :rtype: page html
    """
    allcompositeurs = Compositeur.query.all()

    if len(allcompositeurs) == 0:
        return render_template("pages/index_oeuvres.html", var_groupe_partitions=allcompositeurs)
    else:
        page = request.args.get("page", 1)

        if isinstance(page, str) and page.isdigit():
            page = int(page)
        else:
            page = 1

    allcompositeurs = Compositeur.query.order_by(Compositeur.nom_compositeur).paginate(page=page,
                                                                                per_page=RESULTATS_PAR_PAGE)
    return render_template("pages/index_compositeurs.html", nom="BibPart", var_groupe_compositeurs=allcompositeurs)

# ROUTES PERMETTANT L'AFFICHAGES DES NOTICES

@app.route("/notice_oeuvre/<int:id_oeuvre>")
def notice_oeuvre(id_oeuvre):
    """
    Route permettant d'afficher la notice d'une oeuvre
    :param id_oeuvre: id de l'oeuvre
    :type id_oeuvre: int
    :return: affichage du template notice_oeuvre.html
    :rtype: page html
    """
    unique_oeuvre = Oeuvre.query.get(id_oeuvre)
    compositeur = unique_oeuvre.compositeurs
    forme = unique_oeuvre.formes
    type = unique_oeuvre.types
    instrument = unique_oeuvre.instruments
    partition = unique_oeuvre.partitions
    return render_template("pages/notice_oeuvre.html", nom="BibPart", var_oeuvre_unique=unique_oeuvre,
                           var_compositeur=compositeur, var_forme=forme, var_type=type, var_instrument=instrument,
                           var_partition=partition)

@app.route("/notice_partition/<int:id_partition>")
def notice_partition(id_partition):
    """
    Route permettant d'afficher la notice d'une partition
    :param id_partition: id de la partition
    :type id_partition: int
    :returns: affichage du template notice_partition.html
    :rtype: page html
    """
    unique_partition = Partition.query.get(id_partition)
    audio = unique_partition.oeuvres
    institution = unique_partition.institutions_conservation
    oeuvre = unique_partition.oeuvres
    return render_template("pages/notice_partition.html", nom="BibPart", var_partition_unique=unique_partition,
                           var_audio=audio, var_institution=institution, var_oeuvre=oeuvre)

@app.route("/notice_compositeur/<int:id_compositeur>")
def notice_compositeur(id_compositeur):
    """
    Route permettant d'afficher la notice d'un compositeur
    :param id_compositeur: id du compositeur
    :type id_compositeur: int
    :returns: affichage du template notice_compositeur.html
    :rtype: page html
    """
    unique_compositeur = Compositeur.query.get(id_compositeur)
    oeuvrecompo = unique_compositeur.oeuvres
    return render_template("pages/notice_compositeur.html", nom="BibPart", var_compositeur_unique=unique_compositeur,
                           var_oeuvrecompo=oeuvrecompo)

# ROUTES PERMETTANT UNE RECHERCHE RAPIDE ET AVANCÉE

@app.route("/recherche", methods=["GET"])
def recherche():
    """
       Route permettant de faire une recherche rapide sur les notices d'oeuvre
       :returns : affichage des templates correspondant aux barres de recherches et aux résultats de la recherche rapide
       :rtype: pages html
       """
    # Gestion de la page courante
    page = request.args.get("page", 1)

    if isinstance(page, str) and page.isdigit():
        page = int(page)
    else:
        page = 1

    keyword = request.args.get("keyword", None)
    # Création d'une liste vide permettant de stocker les mots-clefs s'ils existent, sinon elle reste vide
    resultats = []

    # Méthode "GET" utilisée : les mots clefs recherchés apparaîssent dans l'URL
    if keyword:
        resultats = Oeuvre.query.filter(or_(
            Oeuvre.id_oeuvre.like("%{}%".format(keyword)),
            Oeuvre.titre_oeuvre.like("%{}%".format(keyword)),
            Oeuvre.date_oeuvre.like("%{}%".format(keyword)),
            Oeuvre.compositeurs.has(Compositeur.nom_compositeur.like("%{}%".format(keyword))),
            Oeuvre.types.has(Type.label_type.like("%{}%".format(keyword))),
            Oeuvre.formes.has(Forme.label_forme.like("%{}%".format(keyword))))
        ).paginate(page=page, per_page=RESULTATS_PAR_PAGE)
        titre = "Résultat pour la recherche `" + keyword + "`"
    return render_template("pages/recherche.html", resultats=resultats, titre=titre, keyword=keyword)

@app.route('/rechercheavancee', methods=["POST", "GET"])
def rechercheavancee():
    """
    Route permettant de faire une recherche avancée
    :returns : affichage des templates correspondant aux formulaires et aux résultats de la recherche avancée
    :rtype: pages html
    """
    # Gestion de la page courante
    page = request.args.get("page", 1)

    if isinstance(page, str) and page.isdigit():
        page = int(page)
    else:
        page = 1

    # Condition pour la méthode "POST" : cette méthode permet de ne pas inscrire les données dans l'URL, contrairement
    # à la méthode "GET"
    if request.method == "POST":
        # Création de 3 listes vides permettant de stocker par type de notice (oeuvre, partition, compositeur)
        # les mots-clefs s'ils existent, sinon elles restent vides
        resultatsA = []
        resultatsB = []
        resultatsC = []
        keyword = request.form.get("keyword", None)
        # Variable appelée dans le template des résultats pour la recherche avancée
        titre = "Résultat(s) de la recherche avancée"

        questionOeuvre = Oeuvre.query
        questionPartition = Partition.query
        questionCompositeur = Compositeur.query

        # Notice oeuvre
        titre_oeuvre = request.form.get("titreOeuvre", None)
        compositeur_oeuvre = request.form.get("compoOeuvre", None)
        date_oeuvre = request.form.get("dateOeuvre", None)
        type_oeuvre = request.form.get("typeOeuvre", None)
        forme_oeuvre = request.form.get("formeOeuvre", None)
        instrument_oeuvre = request.form.get("instrumentOeuvre", None)

        # Notice partition
        titre_partition = request.form.get("titrePartition", None)
        sous_titre_partition = request.form.get("soustitrePartition", None)
        format_partition = request.form.get("formatPartition", None)
        page_partition = request.form.get("nbpagePartition", None)
        statut_partition = request.form.get("statutPartition", None)
        institution_partition = request.form.get("nomInstitutionConservation", None)

        # Notice compositeur
        prenom_compo = request.form.get("prenomCompo", None)
        nom_compo = request.form.get("nomCompo", None)
        naissance_compo = request.form.get("naissanceCompo", None)
        mort_compo = request.form.get("mortCompo", None)

        # Notice oeuvre
        if titre_oeuvre:
            resultatsA = questionOeuvre.filter(Oeuvre.titre_oeuvre.like("%{}%".format(titre_oeuvre)))
        if compositeur_oeuvre:
            resultatsA = questionOeuvre.filter(
                Oeuvre.compositeurs.has(Compositeur.nom_compositeur.like("%{}%".format(compositeur_oeuvre))))
        if date_oeuvre:
            resultatsA = questionOeuvre.filter(Oeuvre.date_oeuvre.like("%{}%".format(date_oeuvre)))
        if type_oeuvre:
            resultatsA = questionOeuvre.filter(Oeuvre.types.has(Type.label_type.like("%{}%".format(type_oeuvre))))
        if forme_oeuvre:
            resultatsA = questionOeuvre.filter(Oeuvre.formes.has(Forme.label_forme.like("%{}%".format(forme_oeuvre))))
        if instrument_oeuvre:
            resultatsA = questionOeuvre.filter(Oeuvre.instruments.any(
                Instrument.label_instrument.like("%{}%".format(instrument_oeuvre))))

        # Notice partition
        if titre_partition:
            resultatsB = questionPartition.filter(Partition.titre_partition.like("%{}%".format(titre_partition)))
        if sous_titre_partition:
            resultatsB = questionPartition.filter(
                Partition.nom_sous_partie_partition.like("%{}%".format(sous_titre_partition)))
        if format_partition:
            resultatsB = questionPartition.filter(Partition.format_partition.like("%{}%".format(format_partition)))
        if page_partition:
            resultatsB = questionPartition.filter(Partition.page_partition.like("%{}%".format(page_partition)))
        if statut_partition:
            resultatsB = questionPartition.filter(Partition.statut_partition.like("%{}%".format(statut_partition)))
        if institution_partition:
            resultatsB = questionPartition.filter(Partition.institutions_conservation.has(
                Institution_conservation.nom_institution_conservation.like("%{}%".format(institution_partition))))

        # Notice compositeur
        if prenom_compo:
            resultatsC = questionCompositeur.filter(Compositeur.prenom_compositeur.like("%{}%".format(prenom_compo)))
        if nom_compo:
            resultatsC = questionCompositeur.filter(
                Compositeur.nom_compositeur.like("%{}%".format(nom_compo)))
        if naissance_compo:
            resultatsC = questionCompositeur.filter(
                Compositeur.annee_naissance_compositeur.like("%{}%".format(naissance_compo)))
        if mort_compo:
            resultatsC = questionCompositeur.filter(Compositeur.annee_mort_compositeur.like("%{}%".format(mort_compo)))

        if resultatsA:
            resultatsA = resultatsA.paginate(page=page)
        if resultatsB:
            resultatsB = resultatsB.paginate(page=page)
        if resultatsC:
            resultatsC = resultatsC.paginate(page=page)
        return render_template("pages/rechercheavancee.html", keyword=keyword, titre=titre, resultatsA=resultatsA,
                               resultatsB=resultatsB, resultatsC=resultatsC)
    return render_template("pages/rechercheavancee.html", nom="BibPart")

# ROUTES PERMETTANT L'INSCRIPTION, LA CONNEXION, LA DÉCONNEXION

@app.route("/register", methods=["GET", "POST"])
def inscription():
    """
    Route permettant l'inscription d'un utilisateur
    :returns: redirection vers template accueil.html si succès ou vers template inscription.html si erreur
    :rtype: pages html
    """
    if request.method == "POST":
        # Application de la fonction creer présente dans le fichier utilisateurs.py
        statut, donnees = Utilisateur.creer(
            login=request.form.get("login", None),
            email=request.form.get("email", None),
            nom=request.form.get("nom", None),
            motdepasse=request.form.get("motdepasse", None))

        if statut is True:
            flash("Enregistrement effectué. Identifiez-vous maintenant", "success")
            return redirect("/")
        else:
            flash("Les erreurs suivantes ont été rencontrées : " + ", ".join(donnees) + ".", "danger")
            return render_template("pages/inscription.html")
    else:
        return render_template("pages/inscription.html")

@app.route("/connexion", methods=["POST", "GET"])
def connexion():
    """
    Route permettant la connexion d'un utilisateur
    :returns: redirection vers template accueil.html si succès ou vers template connexion.html si erreur
    :rtype: pages html
    """
    if current_user.is_authenticated is True:
        flash("Vous êtes déjà connecté-e", "info")
        return redirect("/")

    if request.method == "POST":
        # Application de la fonction identification présente dans le fichier utilisateurs.py
        user = Utilisateur.identification(
            login=request.form.get("login", None),
            motdepasse=request.form.get("motdepasse", None))
        if user:
            flash("Connexion réussie", "success")
            login_user(user)
            return redirect("/")
        else:
            flash("Le login ou le mot de passe est incorrect.", "danger")

    return render_template("pages/connexion.html")

@app.route("/deconnexion", methods=["POST", "GET"])
def deconnexion():
    """
    Route permettant la déconnexion d'un utilisateur
    :returns: redirection vers template accueil.html
    :rtype: page html
    """
    if current_user.is_authenticated is True:
        logout_user()
    flash("Vous êtes déconnecté-e", "info")
    return redirect("/")

# ROUTES PERMETTANT L'AJOUT DE NOTICES

@app.route("/accueil_ajout", methods=["GET", "POST"])
def accueil_ajout():
    """
    Route permettant l'affichage de la page d'accueil pour l'ajout
    :return : affichage du template accueil_ajout.html
    :rtype : page html
    """
    return render_template("pages/accueil_ajout.html", nom="BibPart")

@app.route("/ajout_compositeur", methods=["GET", "POST"])
def ajout_compositeur():
    """
    Route permettant l'ajout d'un compositeur et les données qui lui sont associées dans la BDD
    :return: affichage du template ajout_compositeur.html
    :rtype: page html
    """
    if request.method == "POST":
        statut, donnees_compo = Compositeur.ajouter_compositeur(
            ajout_nom_compo=request.form.get("ajout_nom_compo", None),
            ajout_prenom_compo=request.form.get("ajout_prenom_compo", None),
            ajout_naissance_compo=request.form.get("ajout_naissance_compo", None),
            ajout_mort_compo=request.form.get("ajout_mort_compo", None),
            ajout_bio_compo=request.form.get("ajout_bio_compo", None),
            ajout_portrait_compo=request.form.get("ajout_portrait_compo", None))

        if statut is True:
            flash("Ajout réussi !", "success")
            return render_template("pages/ajout_compositeur.html", nom="BibPart")

        else:
            flash("Les erreurs suivantes ont été rencontrées : " + ", ".join(donnees_compo), "danger")
            return render_template("pages/ajout_compositeur.html")

    return render_template("pages/ajout_compositeur.html", nom="BibPart")

@app.route("/ajout_forme", methods=["GET", "POST"])
def ajout_forme():
    """
    Route permettant l'ajout d'une forme dans la BDD
    :return: affichage du template ajout_forme.html
    :rtype: page html
    """
    if request.method == "POST":
        statut, donnees_forme = Forme.ajouter_forme(
            ajout_label_forme=request.form.get("ajout_label_forme", None))

        if statut is True:
            flash("Ajout réussi !", "success")
            return render_template("pages/ajout_forme.html", nom="BibPart")

        else:
            flash("Les erreurs suivantes ont été rencontrées : " + ", ".join(donnees_forme), "danger")
            return render_template("pages/ajout_forme.html", nom="BibPart")

    return render_template("pages/ajout_forme.html", nom="BibPart")

@app.route("/ajout_institution", methods=["GET", "POST"])
def ajout_institution():
    """
    Route permettant l'ajout d'une institution de conservation dans la BDD
    :return: affichage du template ajout_institution.html
    :rtype: page html
    """
    if request.method == "POST":
        statut, donnees_insti = Institution_conservation.ajouter_institution(
            ajout_nom_institution=request.form.get("ajout_nom_institution", None),
            ajout_ville_institution=request.form.get("ajout_ville_institution", None))

        if statut is True:
            flash("Ajout réussi !", "success")
            return render_template("pages/ajout_institution.html", nom="BibPart")

        else:
            flash("Les erreurs suivantes ont été rencontrées : " + ", ".join(donnees_insti), "danger")
            return render_template("pages/ajout_institution.html", nom="BibPart")
    return render_template("pages/ajout_institution.html", nom="BibPart")

@app.route("/ajout_instrument", methods=["GET", "POST"])
def ajout_instrument():
    """
    Route permettant l'ajout d'un instrument dans la BDD
    :return : affichage du template ajout_instrument.html
    :rtype: page html
    """
    if request.method == "POST":
        labelInstrument = request.form.get("ajout_label_instrument", None)
        Instrument.ajouter_instrument(labelInstrument)

        flash("Ajout réussi !", "success")
        return render_template("pages/ajout_instrument.html", nom="BibPart")

    return render_template("pages/ajout_instrument.html", nom="BibPart")

@app.route("/ajout_oeuvre", methods=["GET", "POST"])
def ajout_oeuvre():
    """
    Route permettant l'ajout d'une oeuvre et les données qui lui sont associées dans la BDD
    :return: affichage du template ajout_oeuvre.html
    :rtype: page html
    """
    listeoeuvre = Oeuvre.query.order_by(Oeuvre.titre_oeuvre).all()
    listecompositeur = Compositeur.query.order_by(Compositeur.nom_compositeur).all()
    listetype = Type.query.order_by(Type.label_type).all()
    listeforme = Forme.query.order_by(Forme.label_forme).all()
    listeinstrument = Instrument.query.order_by(Instrument.label_instrument).all()

    if request.method == "POST":
        titreOeuvre = request.form.get("ajout_titre_oeuvre", None)
        dateOeuvre = request.form.get("ajout_date_oeuvre", None)
        audioOeuvre = request.form.get("ajout_audio_oeuvre", None)
        compoOeuvre = request.form.get("ajout_compositeur_oeuvre", None)
        typeOeuvre = request.form.get("ajout_type_oeuvre", None)
        formeOeuvre = request.form.get("ajout_forme_oeuvre", None)
        labelInstrument = request.form.get("ajout_label_instrument", None)
        recup = Compositeur.query.filter(Compositeur.nom_compositeur == compoOeuvre).first()
        recup2 = Type.query.filter(Type.label_type == typeOeuvre).first()
        recup3 = Forme.query.filter(Forme.label_forme == formeOeuvre).first()
        id_oeuvre = Oeuvre.ajouter_oeuvre(titreOeuvre, dateOeuvre, audioOeuvre, recup.id_compositeur, recup2.id_type,
                                          recup3.id_forme)
        id_instrument = Instrument.ajouter_instrument(labelInstrument)
        Instrument.association_Oeuvre_Instrument(id_oeuvre, id_instrument)

        flash("Ajout réussi !", "success")
        return render_template("pages/ajout_oeuvre.html", nom="BibPart", Listeoeuvre=listeoeuvre,
                               Listecompositeur=listecompositeur, Listetype=listetype, Listeforme=listeforme,
                               Listeinstrument=listeinstrument)

    return render_template("pages/ajout_oeuvre.html", nom="BibPart", Listeoeuvre=listeoeuvre,
                           Listecompositeur=listecompositeur, Listetype=listetype, Listeforme=listeforme,
                           Listeinstrument=listeinstrument)

@app.route("/ajout_partition", methods=["GET", "POST"])
def ajout_partition():
    """
    Route permettant l'ajout d'une partition et les données qui lui sont associées dans la BDD
    :return : affichage du template ajout_partition.html
    :rtype: page html
    """
    listepartition = Partition.query.all()
    listeoeuvre = Oeuvre.query.all()
    listeinstitution = Institution_conservation.query.all()

    if request.method == "POST":
        titrePartition = request.form.get("ajout_titre_partition", None)
        soustitrePartition = request.form.get("ajout_sous_titre_partition", None)
        formatPartition = request.form.get("ajout_format_partition", None)
        pagePartition = request.form.get("ajout_page_partition", None)
        statutPartition = request.form.get("ajout_statut_partition", None)
        visionneusePartition = request.form.get("ajout_visionneuse_partition", None)
        oeuvrePartition = request.form.get("ajout_oeuvre_partition", None)
        institutionPartition = request.form.get("ajout_institution_partition", None)
        recup = Oeuvre.query.filter(Oeuvre.titre_oeuvre == oeuvrePartition).first()
        recup2 = Institution_conservation.query.filter(
            Institution_conservation.nom_institution_conservation == institutionPartition).first()
        Partition.ajouter_partition(titrePartition, soustitrePartition, formatPartition, pagePartition, statutPartition,
                                    visionneusePartition, recup.id_oeuvre, recup2.id_institution_conservation)

        flash("Ajout réussi !", "success")
        return render_template("pages/ajout_partition.html", nom="BibPart", Listepartition=listepartition,
                               Listeoeuvre=listeoeuvre, Listeinstitution=listeinstitution)

    return render_template("pages/ajout_partition.html", nom="BibPart", Listepartition=listepartition,
                           Listeoeuvre=listeoeuvre, Listeinstitution=listeinstitution)

# ROUTES PERMETTANT LA MODIFICATION DES DONNÉES DES NOTICES

@app.route("/maj_oeuvre/<int:identifier>", methods=["GET", "POST"])
@login_required
def maj_oeuvre(identifier):
    """
    Route permettant la modification de la notice d'une oeuvre
    :param identifier: id de l'oeuvre
    :type identifier: int
    :return: redirection vers template index_oeuvres.html si succès ou vers template maj_oeuvre.html si échec
    :rtype: pages html
    """
    listecompositeur = Compositeur.query.all()
    listetype = Type.query.all()
    listeforme = Forme.query.all()
    listeinstrument = Instrument.query.all()

    # Si méthode "GET"
    if request.method == "GET":
        modif_oeuvre = Oeuvre.query.get(identifier)
        modif_oeuvre_compo = modif_oeuvre.compositeurs

        return render_template("pages/maj_oeuvre.html", oeuvre=modif_oeuvre, composi=modif_oeuvre_compo,
                               Listecompositeur=listecompositeur, Listetype=listetype, Listeforme=listeforme,
                               Listeinstrument=listeinstrument)

    # Si méthode "POST"
    else:
        # Application de la fonction modifier_oeuvre présente dans le fichier donnees.py
        statut, donnees = Oeuvre.modifier_oeuvre(
            Id_oeuvre=identifier,
            maj_titre=request.form.get("maj_titre", None),
            maj_compositeur=request.form.get("maj_compositeur", None),
            maj_date_oeuvre=request.form.get("maj_date_oeuvre", None),
            maj_forme=request.form.get("maj_forme", None),
            maj_type=request.form.get("maj_type", None),
            maj_audio=request.form.get("maj_audio", None),
            maj_instrument=request.form.get("maj_instrument", None))

        if statut is True:
            flash("Modification réussie !", "success")
            return redirect("/index_oeuvres")
        else:
            flash("Les erreurs suivantes ont été rencontrées : " + ",".join(donnees), "danger")
            modif_oeuvre = Oeuvre.query.get(identifier)
            modif_oeuvre_compo = modif_oeuvre.compositeurs

            return render_template("pages/maj_oeuvre.html", nom="BibPArt", oeuvre=modif_oeuvre,
                                   composi=modif_oeuvre_compo)

@app.route("/maj_partition/<int:identifier>", methods=["GET", "POST"])
@login_required
def maj_partition(identifier):
    """
    Route permettant la modification de la notice d'une partition
    :param identifier: id de la partition
    :type identifier: int
    :return: redirection vers template index_partitions.html si succès ou vers template maj_partition.html si échec
    :rtype: pages html
    """
    listeinstitution = Institution_conservation.query.all()
    listeoeuvre = Oeuvre.query.all()

    # Si méthode "GET"
    if request.method == "GET":
        modif_partition = Partition.query.get(identifier)

        return render_template("pages/maj_partition.html", partition=modif_partition, Listeinstitution=listeinstitution,
                               Listeoeuvre=listeoeuvre)

    # Si méthode "POST"
    else:
        # Application de la fonction modifier_partition présente dans le fichier donnees.py
        statut, donnees = Partition.modifier_partition(
            Id_partition=identifier,
            maj_titre=request.form.get("maj_titre", None),
            maj_sous_titre=request.form.get("maj_sous_titre", None),
            maj_format=request.form.get("maj_format", None),
            maj_page=request.form.get("maj_page", None),
            maj_statut=request.form.get("maj_statut", None),
            maj_institution_conservation=request.form.get("maj_institution_conservation", None),
            maj_notice_oeuvre=request.form.get("maj_notice_oeuvre", None),
            maj_visionneuse=request.form.get("maj_visionneuse", None))

        if statut is True:
            flash("Modification réussie !", "success")
            return redirect("/index_partitions")
        else:
            flash("Les erreurs suivantes ont été rencontrées : " + ", ".join(donnees), "danger")
            modif_partition = Partition.query.get(identifier)

            return render_template("pages/maj_partition.html", nom="BibPArt", partition=modif_partition)

@app.route("/maj_compositeur/<int:identifier>", methods=["GET", "POST"])
@login_required
def maj_compositeur(identifier):
    """
    Route permettant la modification de la notice d'un compositeur
    :param identifier: id du compositeur
    :type identifier: int
    :return: redirection vers template index_compositeurs.html si succès ou vers template maj_compositeur.html si échec
    :rtype: pages html
    """
    # Si méthode "GET"
    if request.method == "GET":
        modif_compositeur = Compositeur.query.get(identifier)

        return render_template("pages/maj_compositeur.html", compositeur=modif_compositeur)
    # Si méthode "POST"
    else:
        # Application de la fonction modifier_compositeur présente dans le fichier donnees.py
        statut, donnees = Compositeur.modifier_compositeur(
            Id_compositeur=identifier,
            maj_prenom=request.form.get("maj_prenom", None),
            maj_nom=request.form.get("maj_nom", None),
            maj_naissance=request.form.get("maj_naissance", None),
            maj_mort=request.form.get("maj_mort", None),
            maj_bio=request.form.get("maj_bio", None),
            maj_url=request.form.get("maj_url", None))

        if statut is True:
            flash("Modification réussie !", "success")
            return redirect("/index_compositeurs")
        else:
            flash("Les erreurs suivantes ont été rencontrées : " + ", ".join(donnees), "danger")
            modif_compositeur = Compositeur.query.get(identifier)

            return render_template("pages/maj_compositeur.html", nom="BibPArt", compositeur=modif_compositeur)

# ROUTES PERMETTANT LES SUPPRESSIONS DE NOTICES

@app.route("/supprimer_oeuvre/<int:id_oeuvre>", methods=["POST", "GET"])
@login_required
def supprimer_oeuvre(id_oeuvre):
    """
    Route permettant la suppression d'une oeuvre et de ses données dans la BDD
    :param id_oeuvre : id de l'oeuvre
    :type id_oeuvre: int
    :return: redirection vers template index_oeuvres.html si succès ou vers template supprimer_oeuvre.html si échec
    :rtype: pages html
    """
    suppr_oeuvre = Oeuvre.query.get(id_oeuvre)

    if request.method == "POST":
        # Application de la fonction supprimer_oeuvre présente dans le fichier donnees.py
        statut = Oeuvre.supprimer_oeuvre(id_oeuvre=id_oeuvre)

        if statut is True:
            flash("Suppression réussie !", "success")
            return redirect("/index_oeuvres")
        else:
            flash("La suppression a échoué. Réessayez !", "danger")
            return redirect("/")
    else:
        return render_template("pages/supprimer_oeuvre.html", nom="BibPart", suppr_oeuvre=suppr_oeuvre)

@app.route("/supprimer_partition/<int:id_partition>", methods=["POST", "GET"])
@login_required
def supprimer_partition(id_partition):
    """
    Route permettant la suppression d'une partition et de ses données dans la BDD
    :param id_partition : id de la partition
    :type id_partition: int
    :return: redirection vers template index_partitions.html si succès ou vers template supprimer_partition.html si échec
    :rtype: pages html
    """
    suppr_partition = Partition.query.get(id_partition)

    if request.method == "POST":
        # Application de la fonction supprimer_partition présente dans le fichier donnees.py
        statut = Partition.supprimer_partition(id_partition=id_partition)

        if statut is True:
            flash("Suppression réussie !", "success")
            return redirect("/index_partitions")
        else:
            flash("La suppression a échoué. Réessayez !", "danger")
            return redirect("/")
    else:
        return render_template("pages/supprimer_partition.html", nom="BibPart", suppr_partition=suppr_partition)

@app.route("/supprimer_compositeur/<int:id_compositeur>", methods=["POST", "GET"])
@login_required
def supprimer_compositeur(id_compositeur):
    """
    Route permettant la suppression d'un compositeur et de ses données dans la BDD
    :param id_compositeur : id du compositeur
    :type id_compositeur: int
    :return: redirection vers template index_compositeurs.html si succès ou vers template supprimer_compositeur.html si échec
    :rtype: pages html
    """
    suppr_compositeur = Compositeur.query.get(id_compositeur)

    if request.method == "POST":
        # Application de la fonction supprimer_compositeur présente dans le fichier donnees.py
        statut = Compositeur.supprimer_compositeur(id_compositeur=id_compositeur)

        if statut is True:
            flash("Suppression réussie !", "success")
            return redirect("/index_compositeurs")
        else:
            flash("La suppression a échoué. Réessayez !", "danger")
            return redirect("/")
    else:
        return render_template("pages/supprimer_compositeur.html", nom="BibPart", suppr_compositeur=suppr_compositeur)


# _*_ coding:utf-8 _*_
# @File  : short_message.py
# @Time  : 2020-09-15 13:40
# @Author: zizle

""" 短信通业务逻辑 """
import json
from datetime import datetime
from PyQt5.QtWidgets import qApp, QWidget, QVBoxLayout, QLabel
from PyQt5.QtCore import QTimer, Qt, QMargins, QUrl
from PyQt5.QtNetwork import QNetworkRequest
from settings import SERVER_API
from .short_message_ui import ShortMessageUI

class ContentWidget(QWidget):
    """ 内容控件 """
    def __init__(self, current_datetime, timer_start=False, *args, **kwargs):
        super(ContentWidget, self).__init__(*args, **kwargs)
        self.current_datetime = current_datetime
        self.auto_request_timer = QTimer(self)  # 定时请求数据
        self.auto_request_timer.timeout.connect(self._get_last_short_message)
        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(QMargins(3, 0, 5, 0))
        main_layout.addStretch()
        self.setLayout(main_layout)

        self._get_last_short_message()
        if timer_start:
            self.auto_request_timer.start(30000)
        self.setStyleSheet(
            "#contentLabel{background-color:rgb(240,240,240);padding:2px 3px 8px 8px;border-radius:5px;}"
            "#contentLabel:hover{background-color:rgb(230,230,230);padding:2px 3px 8px 8px;border-radius:5px;}"
        )

    def _get_last_short_message(self):
        """ 获取最新短信通 """
        # 请求比self.last_datetime大的数据(服务器仅返回当天的数据)
        # print("self.current_datetime: {}".format(self.current_datetime))
        network_message = getattr(qApp, "_network")
        url = SERVER_API + "short-message/?start_time={}".format(self.current_datetime)
        reply = network_message.get(QNetworkRequest(QUrl(url)))
        reply.finished.connect(self.latest_short_message_reply)

    def latest_short_message_reply(self):
        """ 最新的短信通数据返回 """
        reply = self.sender()
        if reply.error():
            pass
        else:
            data = json.loads(reply.readAll().data().decode("utf-8"))
            self.insert_latest_short_message(data["short_messages"])

    def insert_latest_short_message(self, contents):
        """ 新增最新短信通 """
        for index, content_item in enumerate(contents):
            content_label = QLabel(content_item["content"], self)
            content_label.setWordWrap(True)
            content_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
            content_label.setObjectName("contentLabel")

            self.layout().insertWidget(0, content_label)
            if index == len(contents) - 1:
                self.current_datetime = content_item["create_time"]

class ShortMessage(ShortMessageUI):
    def __init__(self, *args, **kwargs):
        super(ShortMessage, self).__init__(*args, **kwargs)
        self.animation_timer = QTimer(self)
        self.animation_timer.timeout.connect(self.refresh_animation_text)

        # 默认添加今日的内容控件
        current_datetime = datetime.today().strftime("%Y-%m-%dT00:00:00")
        content_widget = ContentWidget(current_datetime, timer_start=True)
        self.animation_timer.start(600)
        self.scroll_area.setWidget(content_widget)
        self.date_edit.dateChanged.connect(self.current_date_changed)

    def refresh_animation_text(self):
        """ 资讯持续更新中 """
        tips = self.animation_text.text()
        tip_points = tips.split(' ')[1]
        if len(tip_points) > 5:
            self.animation_text.setText("资讯持续更新中 ")
        else:
            self.animation_text.setText("资讯持续更新中 " + "·" * (len(tip_points) + 1))

    def current_date_changed(self, date):
        """ 当前时间发生改变 """
        date_edit_text = self.date_edit.text()
        current_date = datetime.strptime(date_edit_text, "%Y-%m-%d")
        current_date_str = current_date.strftime("%Y-%m-%dT00:00:00")
        week_name = self.WEEKS.get(current_date.strftime("%w"))
        self.current_date.setText(date_edit_text + week_name)

        if current_date_str == datetime.today().strftime("%Y-%m-%dT00:00:00"):
            timer_start = True
            self.animation_text.show()
            if not self.animation_timer.isActive():
                self.animation_timer.start(600)
        else:
            timer_start = False
            self.animation_text.hide()
            if self.animation_timer.isActive():
                self.animation_timer.stop()
        self.animation_text.setText("资讯持续更新中 ")
        content_widget = ContentWidget(current_date_str, timer_start=timer_start)
        self.scroll_area.setWidget(content_widget)


from itertools import combinations
from collections import Counter

def solution(orders, course):
    answer = []
    for c in course:
        lst = []
        for order in orders:
            for l in list(combinations(sorted(order), c)):
                lst.append(''.join(l))
        result = Counter(lst).most_common()
        if result and result[0][1] > 1:
            maximum = result[0][1]
            for r in result:
                if r[1] == maximum:
                    answer.append(r[0])
    answer.sort()
    return answer

프로그래머스/level2/메뉴리뉴얼.py


"""
题目描述

明明想在学校中请一些同学一起做一项问卷调查，为了实验的客观性，
他先用计算机生成了N个1到1000之间的随机整数（N≤1000），
对于其中重复的数字，只保留一个，把其余相同的数去掉，不同的数对应着不同的学生的学号。
然后再把这些数从小到大排序，按照排好的顺序去找同学做调查。
请你协助明明完成“去重”与“排序”的工作
(同一个测试用例里可能会有多组数据，希望大家能正确处理)。

Input Param
n               输入随机数的个数
inputArray      n个随机整数组成的数组
Return Value
OutputArray    输出处理后的随机整数
注：测试用例保证输入参数的正确性，答题者无需验证。测试用例不止一组。

输入描述:
输入多行，先输入随机整数的个数，再输入相应个数的整数

输出描述:
返回多行，处理后的结果

示例1

输入
11
10
20
40
32
67
40
20
89
300
400
15

输出
10
15
20
32
40
67
89
300
400
"""

while True:
    try:
        n = int(input())  # 读入第一行：随机整数的个数
        res = set()
        for i in range(n):
            res.add(int(input()))  # 读入第n行：n个随机整数组成的数组
        for i in sorted(res):
            print(i)
    except:
        break


from turtle import Turtle
from turtle import Screen
import random

donatello = Turtle()
donatello.shape("turtle")
donatello.speed(0)

sideCount = 3

def randomColor():
    r = random.randint(0, 255)
    g = random.randint(0, 255)
    b = random.randint(0, 255)
    return r, g, b

while sideCount < 11:
    angleDegree = 360 / sideCount
#    penColor = 255, 255, 255
    for i in range(sideCount):
        donatello.forward(100)
        donatello.right(angleDegree)
    sideCount += 1
#    donatello.pencolor(penColor)

#screen = Turtle().Screen()
screen.exitonclick()


import logging
import time
from functools import partial
from subprocess import call

from mininet.cli import CLI
from mininet.log import info, setLogLevel
from mininet.net import Mininet
from mininet.node import RemoteController, OVSKernelSwitch
from mininet.link import TCLink, OVSLink

logger = logging.getLogger(__name__)
logger.setLevel(level=logging.INFO)

CONTROLLER_IP = "127.0.0.1"
CONTROLLER_PORT = 6653
OPENFLOW_PROTOCOL = 'OpenFlow14'
IP_BASE = "10.0.88.0/24"
DPID_BASE = 1000
setLogLevel('info')

if __name__ == '__main__':

    # ---------- clean previous setup  -----------------------------
    call(["mn", "-c"])

    # ----------topology inputs -----------------------------
    # Core network topology
    # in
    # De Maesschalck, S., Colle, D., Lievens, I., Pickavet, M., Demeester, P., Mauz, C., ... & Derkacz, J.(2003).
    # Pan-European optical transport networks: An availability-based comparison.
    # Photonic Network Communications, 5(3), 203 - 225.
    switch_names = {1: "lon", 2: "ams", 3: "bru", 4: "par", 5: "ham",
                    6: "fra", 7: "str", 8: "zur", 9: "lyn", 10: "ber",
                    11: "mun", 12: "mil", 13: "pra", 14: "vie", 15: "zag",
                    16: "rom"}
    switch_link_matrix = [(1, 2), (1, 4), (2, 3), (2, 5), (3, 4),
                          (3, 6), (4, 7), (4, 9), (5, 6), (5, 10),
                          (6, 7), (6, 11), (7, 8), (8, 9), (8, 12),
                          (10, 11), (10, 13), (11, 12), (11, 14), (12, 16),
                          (13, 14), (14, 15), (15, 16)]
    host_count_per_switch = 1

    # ---------- initialize network  -----------------------------
    OpenFlow14Switch = partial(OVSKernelSwitch, protocols=OPENFLOW_PROTOCOL)

    net = Mininet(ipBase=IP_BASE)
    net.addController("c0", controller=RemoteController, link=OVSLink, ip=CONTROLLER_IP, port=CONTROLLER_PORT)

    try:
        # ----------switches and hosts -----------------------------
        switches = {}
        links = {}
        for sw_ind in switch_names:
            name = switch_names[sw_ind]
            dpid = DPID_BASE + sw_ind

            sw = net.addSwitch(name, dpid="%x" % dpid, cls=OpenFlow14Switch)
            switches[sw_ind] = sw
            for host_index in range(1, host_count_per_switch + 1):
                host = net.addHost(name + '%02d' % host_index)
                net.addLink(sw, host)

        # ---------- create links -----------------------------
        for item in switch_link_matrix:
            sw1 = switches[item[0]]
            sw2 = switches[item[1]]
            link = net.addLink(sw1, sw2)
            links[item] = link

        lon = net.getNodeByName("lon")
        nat = net.addNAT("nat", connect=lon)
        nat_ip = nat.params['ip'].split('/')[0]
        host = net.addHost('ids')
        net.addLink(lon, host)

        print(f'NAT ip: {nat_ip}')

        info('*** Starting network\n')
        net.start()

        time.sleep(2)

        for host in net.hosts:
            if host.inNamespace:
                host.setDefaultRoute('via %s' % nat_ip)
        nat.configDefault()
        info('*** Running CLI\n')
        CLI(net)

        info('*** Stopping network')
        net.stop()
    except Exception as err:
        info(err)

        net.stop()


import matplotlib.pylab as pl
import matplotlib.pyplot as plt
import numpy as np

index = list(range(1, 13))
values = list(range(3, 15))
plt.bar(index, values)
plt.plot(index, values, 'rD')
plt.plot(index, values, '+')
plt.title('Title')
plt.xlabel('xlabel')
plt.ylabel('ylabel')
plt.show()

t = np.arange(0., 4., 0.1)
plt.plot(t, t, t, t + 3, t, t ** 2, t, np.exp(t))
plt.show()

pl.plot(t, t, t, t + 3, t, t ** 2, t, np.exp(t))
pl.show()


import functools
import json

import jsonschema
import tornado.web

from .. import basehandler

class ApiBaseHandler(basehandler.BaseHandler):
    def check_xsrf_cookie(self):
        pass

    def prepare(self):
        """prepare function: it is called after initialize function"""
        if self.request.headers.get("Content-Type", "").startswith("application/json"):
            try:
                self.json_args = json.loads(self.request.body, encoding="utf-8")
            except ValueError:
                raise tornado.web.HTTPError(400, "JSON is not valid")

    def write_json_response(self, dictionary, cacheable = False):
        self.set_header("Content-Type", "application/json")
        self.set_header("Cache-Control", "public, no-transform, max-age=300" if cacheable else "no-cache")
        self.write(json.dumps(dictionary, default = lambda o: o.__dict__, encoding='utf-8'))

def validate_json(schema):
    #Decorate methods with this to validate input json.
    def decorator(method):
        @functools.wraps(method)
        def wrapper(self, *args, **kwargs):
            if self.json_args is None:
                raise tornado.web.HTTPError(403, "No JSON data received")

            try:
                jsonschema.validate(self.json_args, schema)
            except jsonschema.ValidationError as e:
                raise tornado.web.HTTPError(403, e.message)

            return method(self, *args, **kwargs)
        return wrapper
    return decorator

authenticated = basehandler.authenticated
run_asynchronous = basehandler.run_asynchronous


'''
This file impements cbc encryption using function from the ecb.py file.
It breaks up a string into blocks and either encrypts or decrypts it.
Author Cole Schumacher
'''

from Crypto.Cipher import XOR
import ecb
import sys
import binascii

iv = binascii.unhexlify('000102030405060708090a0b0c0d0e0f')

#encrypts an individual block by xoring it with the last blocks cipher and then encrypting
def encryptblock(lastcipher, plaintext):
    toXOR = XOR.new(lastcipher)
    if len(plaintext) != 16:
        plaintext = ecb.pad(plaintext)
    block = toXOR.encrypt(plaintext)
    return ecb.encrypt(ecb.key, block, False)

#decrypts the given blok and then xors it with the revious block
def decryptblock(lastcipher, ciphertext, unpad):
    block = ecb.decrypt(ecb.key, ciphertext, unpad)

    toXOR = XOR.new(lastcipher)
    block = toXOR.decrypt(block)
    return block

#gets the range of data in the current block
def getrange(first, last, length):
    return last, last + 16

#encryts the given data block by block
def encryptbinary(s, initializationVector):
    length = len(s)
    currentstart = 0
    currentend = 16

    if currentend > length:
        currentend = length

    ciphertext = binascii.unhexlify('')
    lastcipher = initializationVector

    #itterates of the raw data and blocks them
    while currentstart < length:

        plaintext = s[currentstart:currentend]
        currentcipher = encryptblock(lastcipher, plaintext)

        lastcipher = currentcipher

        #moves to the next block
        ciphertext += currentcipher
        currentstart, currentend = getrange(currentstart, currentend, length)

    if length % ecb.BLOCK_SIZE == 0:
        padding = ecb.pad(binascii.unhexlify(''))
        ciphertext += encryptblock(lastcipher, padding)

    return ciphertext

#decrypts the data given and unpads it if told
def decryptbinary(s, initializationVector, unpad):
    length = len(s)
    currentstart = 0
    currentend = 16

    if currentend > length:
        currentend = length

    plaintext = binascii.unhexlify('')
    lastcipher = initializationVector

    #iterates over the cipher and blocks it
    while currentstart < length:

        ciphertext = s[currentstart:currentend]

        #decrypt the current block, no reason to have it decrypted in ecb because
        #it would need to be added back in for all nonerminal blocks
        plaintext += decryptblock(lastcipher, ciphertext, False)

        #move to the next block
        lastcipher = ciphertext
        currentstart, currentend = getrange(currentstart, currentend, length)

    #removes padding from the string as a whole if requested
    if unpad:
        plaintext = ecb.unpad(plaintext)

    return plaintext

#the main function that executes all functions of the program
if __name__ == "__main__":
    myargs = ecb.getopts(sys.argv)

    if '-e' in myargs:
        plaintext = binascii.unhexlify(myargs['-e'])
        ciphertext = encryptbinary(plaintext, iv)
        print('Ciphertext: ' + binascii.hexlify(ciphertext))

    elif '-d' in myargs:
        ciphertext = binascii.unhexlify(myargs['-d'])
        plaintext = decryptbinary(ciphertext, iv, True)
        print('Plaintext: ' + binascii.hexlify(plaintext))

    elif '-s' in myargs:
        plaintext = binascii.a2b_qp(myargs['-s'])
        ciphertext = encryptbinary(plaintext, iv)
        print('Ciphertext: ' + binascii.hexlify(ciphertext))

    elif '-u' in myargs:
        ciphertext = binascii.unhexlify(myargs['-u'])
        plaintext = decryptbinary(ciphertext, iv, True)
        print('Plaintext: ' + binascii.b2a_qp(plaintext))


import requests
import uuid
import shutil
import re

HOST = 'https://rtex.probablyaweb.site'

def load_template():
    with open('template.tex', encoding = 'utf-8') as f:
        raw = f.read()
    # Remove any comments from the template
    cleaned = re.sub(r'%.*\n', '', raw)
    return cleaned

def render_latex(latex):
    template = load_template()
    id = str(uuid.uuid4())
    tempFit = template.replace("#CONTENT", latex)
    payload = {'code': tempFit, 'format': 'png'}
    response = requests.post(HOST + '/api/v2', data = payload)
    response.raise_for_status()
    jdata = response.json()
    if jdata['status'] != 'success':
        return None
    else:
        downloadUrl = HOST + '/api/v2/' + jdata['filename']
        response = requests.get(downloadUrl, stream = True)
        response.raise_for_status()
        with open('{}.png'.format(id), 'wb') as out_file:
            shutil.copyfileobj(response.raw, out_file)
        return id

def extract_inline_tex(content):
    parts = iter(content.split('$$'))
    latex = ''
    try:
        while True:
            it = next(parts)
            if (it == ''):
                word = ''
            else:
                word = " \\text{" + it + "} "
            if word != '':
                latex += word.replace('#', '\\#') \
                             .replace('$', '\\$') \
                             .replace('%', '\\%')
                latex += ' '
            word = next(parts)
            if word != '':
                latex += word.strip('`')
    except StopIteration:
        pass
    return latex.rstrip()


import matplotlib.pyplot as plt

def plot_metrics(history, show=False):
    plt.subplot(2, 1, 1)
    plt.title('Loss')
    plt.plot(history['loss'], '-o', label='train')
    plt.plot(history['val_loss'], '-o', label='val')
    plt.xlabel('epoch')
    plt.legend(loc='upper right')
    plt.subplot(2,1,2)
    plt.title('Accuracy')
    plt.plot(history['acc'], '-o', label='train')
    plt.plot(history['val_acc'], '-o', label='val')
    plt.xlabel('epoch')
    plt.legend(loc='upper left')
    plt.savefig('metrics.png')
    plt.gcf().set_size_inches(15, 12)
    if show:
        plt.show()
    else:
        plt.close()


import pytest

from flask import url_for
from pytest_flask import fixtures
from flask_login import login_user, current_user, logout_user

from mdt_app.models import *
from mdt_app.main.forms import *

@pytest.mark.usefixtures('client_class', 'db_session', 'populate_db')
class TestIndex:
    def setup(self):
        user1 = User.query.first()
        login_user(user1)

    def test_page_load(self):
        assert self.client.get(url_for('main.index')).status_code == 200

@pytest.mark.developing
@pytest.mark.usefixtures('client_class', 'db_session', 'populate_db')
class TestCaseList:
    def setup(self):
        self.meeting = Meeting.query.first()

    def test_page_load(self):
        request = self.client.get(url_for('main.case_list'))

        assert request.status_code == 200

        # Cases are listed with patient name
        assert b"PATIENT" in request.data
        assert b"ENTRY" in request.data

    def test_meeting_filter(self):
        request = self.client.get(url_for('main.case_list',
                                          meeting=self.meeting.date))
        html = str(request.data).replace('\\n', '').replace('\\t', '')

        # Cases are listed with patient name, without cases for 16th Oct)
        assert "PATIENT" in html
        assert "DUMMY" in html
        assert "16-Oct-2050" not in html

        # status bar
        assert "33% Discussed" in html
        assert "To be discussed: 2 / 3" in html
        assert "to be actioned: 1 / 3" in html
        assert "& actioned: 0 / 3" in html

    def test_push_cases_no_future(self):
        request = self.client.get(url_for('main.case_list',
                                          meeting=self.meeting.date,
                                          push_cases=1))

        assert b'no meetings exist after this one' in request.data

    def test_push_cases_patient_clash(self):
        early_meeting = Meeting.query.filter_by(date='2050-10-16').first()
        request = self.client.get(url_for('main.case_list',
                                          meeting=early_meeting.date,
                                          push_cases=1))

        assert b'was not moved as patient also has a case' in request.data

    def test_push_cases_success(self, db_session):
        all_meetings = Meeting.query.all()
        new_meeting = Meeting(date='2050-12-30',
                              id=all_meetings[-1].id + 1)
        db_session.add(new_meeting)
        db_session.commit()
        request = self.client.get(url_for('main.case_list',
                                          meeting=self.meeting.date,
                                          push_cases=1))

        assert b'Case for patient Third DUMMY was moved to ' in request.data

@pytest.mark.usefixtures('client_class', 'db_session', 'populate_db')
class TestCaseCreate:
    def setup(self):
        meeting = Meeting.query.filter_by(date='2050-10-16').first()
        consultant = User.query.filter_by(initials='AC').first()
        self.form = CaseForm(case_id=-1,
                             patient_id=1,
                             meeting=meeting.id,
                             consultant=consultant.id,
                             mdt_vcmg='MDT',
                             medical_history='another set of medical history',
                             question='another question here',
                             clinic_code='')

    def test_page_load(self):
        req_pass = self.client.get(url_for('main.case_create', patient_id=1))
        req_no_id = self.client.get(url_for('main.case_create', patient_id=''))

        assert req_pass.status_code == 200
        # title
        assert b"Cases for Test PATIENT 12345678" in req_pass.data
        # flashed message
        assert b"Date of birth (age):" in req_pass.data

        assert req_no_id.status_code == 404, 'no id, page not found'

    # login works within scope of function but not in the view
    # need to make a login fixture?
    @pytest.mark.xfail
    def test_case_add(self):
        # login user for created_by
        user1 = User.query.first()
        login_user(user1)
        print(current_user)
        # request
        request = self.client.post(url_for('main.case_create', patient_id=1),
                                   data=self.form.data)

        assert request.status_code == 302

        assert b"another set of medical history" in request.data


# -*- coding:utf-8 -*-
# editor: zzh
# date: 2020/12/11

import re_extract,syn_bert_classifer,WeatherClassifer,WeathreClassifer3
import os

config_path = r'D:\MyProject\天气灾害分类及信息提取\chinese_L-12_H-768_A-12\bert_config.json'
checkpoint_path = r'D:\MyProject\天气灾害分类及信息提取\chinese_L-12_H-768_A-12\bert_model.ckpt'
dict_path = r'D:\MyProject\天气灾害分类及信息提取\chinese_L-12_H-768_A-12\vocab.txt'

# bwc = WeatherClassifer.BertWeatherClassifer(config_path, checkpoint_path, dict_path, maxlen=400)
# bwc.model.load_weights("MODELS\\bert_masked_005.h5")
# #灾害类别分类模型

sbwr = syn_bert_classifer.SynBertWeatherRecongizer(config_path, checkpoint_path, dict_path, max_len=400)
sbwr.bert.load_weights("MODELS\\syn_model\\bert_short.h5")
sbwr.lstm_model.load_weights("MODELS\\syn_model\\lstm_model.h5")
#是否为灾害，二分类模型

classifications = ['低温灾害', '冰雹灾害', '台风灾害', '地质灾害', '城市内涝', '大雾灾害', '大风灾害', '干旱灾害', '暴雨洪涝', '森林火灾', '雪灾灾害', '雷电灾害']

if __name__ == '__main__':
    r = 0
    w = 0
    path = "D:\MyProject\天气灾害分类及信息提取\测试数据\第5次测试\测试文本"
    for classification in classifications:
        files = os.listdir(path + '\\' + classification)
        for file in files:
            with open(path + '\\' + classification + '\\' + file, 'r', encoding='utf8') as f:
                title = f.readline()
                time = f.readline()
                source = f.readline()
                contents = f.readlines()
                zw = ''.join([content.replace('\r', '').replace('\n', '').replace('\t', '').replace(' ',
                                                                                '').replace(
                    '\u3000', '') for content in contents if len(content) > 2])
                # print(len(zw))
                index1 = sbwr.predict_str(zw)
                # index = bwc.predict_str(title + zw)
                # infos = re_extract.info_extract(contents)
                try:
                    print("文件名：", file.strip())
                    print("新闻标题：", title.strip())
                except Exception as e:
                    pass
                # print("模型结果：", classifications[index], " 正确结果：", classification,
                #       classifications[index] == classification, '\t灾害？：', index1 == 0)
                print("灾害？：",index1 == 0)

                # print(infos)

                # if classifications[index] == classification and index1 == 0:
                if index1 == 0:
                    r += 1
                else:
                    w += 1
    print(r, w, r / (r + w))


#!/usr/bin/env python3

import argparse
import re

def removeSentencePunc(line):
    line = re.sub("[,.?;:!\"]|\[|\]", "", line) #remove sentence punctuations
    line = re.sub("--", " ", line) #removes all instances of double hyphens
    line = re.sub("[']([\w']+[-]?[\w']*)[']", r'\1', line) #removes instances of 'word' words
    line = line.lower() #allows for correct alphabetizing later
    return line

def characterDictionaryCreator(character, dictionary):
    if character not in dictionary:
        dictionary[character] = {}
    return dictionary

def wordCounter(block, dictionary, character):
    block = removeSentencePunc(block) #send dialogue to have punc removed
    for word in block.split():
        if word not in dictionary[character]:
            dictionary[character][word] = 1
        else:
            dictionary[character][word] += 1
    return dictionary

def dictionarySorter(dictionary):
    characterNameSort = sorted(dictionary)
    totalNumWords = 0
    for characterName in characterNameSort: #sort the character names
        totalCharWords = 0
        wordList = dictionary[characterName]
        sortedWordList = sorted(wordList)
        print (str(characterName) + ":")
        for word in sortedWordList: #sort the words spoken by the character
            totalCharWords += dictionary[characterName][word]
            totalNumWords += dictionary[characterName][word]
            print("\t" + str(word) + ": " + str(dictionary[characterName][word]) + "\n")
        print ("The total number of words spoken by this character is:\n\t" + str(totalCharWords))
    print("The total number of words spoken by all characters are:\n\t" + str(totalNumWords))
    return

def writeToCSV(dictionary):
    with open("word_count.csv", mode = 'w') as WRITE_FILE:
        characterNameSort = sorted(dictionary)
        for characterName in characterNameSort:
            wordList = dictionary[characterName]
            sortedWordList = sorted(wordList)
            for word in sortedWordList:
                WRITE_FILE.write("{0},{1},{2}\n".format(characterName, word, dictionary[characterName][word]))
    WRITE_FILE.close()
    return

def main():
    parser = argparse.ArgumentParser(description='Open .txt files')
    parser.add_argument('-r', '--readFile', metavar='FILE', type=str, nargs=1, help='One .txt file to be opened and word counted')

    args = parser.parse_args()

    with open(args.readFile[0]) as READ_FILE: #open file
        character_dict = {}
        characterName = ""

        for i, line in enumerate(READ_FILE):
            if i<4:
                continue
            if re.search("^\n", line) == None: #non-empty line
                if re.search("^\s+", line) == None: #the line is a character
                    index = len(line)-1
                    characterName = line[:index].lower()
                    character_dict = characterDictionaryCreator(characterName, character_dict)
                else: #block of dialogue
                    character_dict = wordCounter(line, character_dict, characterName)

        dictionarySorter(character_dict)
        writeToCSV(character_dict)

    READ_FILE.close()

    return

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


class Convert:
	def __init__(self, am=[]):
		self.am = am

	def masukan(self):
		self.am = str(self.am)
		while self.am.isdigit()==False:
			self.am = input('Masukkan Angka Saja :\n')
			if self.am.isdigit()==False:
				continue
			else:
				self.am = list(map(int, self.am))
				return self.am

	def potong(self):
		if type(self.am) != list:
			self.am = list(map(int, self.am))
		for i in self.am[::-1]:
			if len(st.am) < 3:
				st.am.append(i)
			elif len(rb.am) < 3:
				rb.am.append(i)
			else:
				jt.am.append(i)

#st, rb, jt = st[::-1], rb[::-1], jt[::-1]

#	def potong(self):
#		self.am = list(map(int, self.am))
#		for i in self.am[::-1]:
#			if len(self.st) < 3:
#				self.st.append(i)
#			elif len(self.rb) < 3:
#				self.rb.append(i)
#			else:
#				self.jt.append(i)
#		self.st, self.rb, self.jt = self.st[::-1], self.rb[::-1], self.jt[::-1]

#		def index1(self):

tes = Convert()
st = Convert()
rb = Convert()
jt = Convert()

print(tes.am)
tes.masukan()
tes.potong()
print(st.am)
print(rb.am)


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

player = int(input('请出拳： 0--石头；1--剪刀；2--布；'))

computer = random.randint(0, 2)
print(f'computer is {computer}')

if ((player == 0) and (computer == 1)) or ((player == 1) and (computer == 2)) or ((player == 2) and (computer == 0)):
    print('player is win! ')
elif player == computer:
    print('平局，再来一局! ')
else:
    print('computer is win! ')


#! the way to do funcorial
n =3
f =1

for i in range(1,n+1):
    f=f*i
print(f)

# prime number

n=13

for i in range(2,n):
    if n%i==0:#if the number / in a smoller num
        print("Not Prime")
        break
else:
    print("Prime")

#def functorial(n):
#    if n == 0:
#        return 1
#    return functorial(n-1)*n

#1.Create a Python script to calculate the deposit in 10 years
#deposit*(1+rate)**10
year = 2023
deposit = 2000
rate = 0.02
period = 3
counter=1

#while counter<period:
#    deposit =deposit*(1+rate)
#    counter +=1
#    print(deposit)

#year = 2023
#deposit = 2000
#rate = 0.02
#period = 10
#counter=year

#while counter<=year+period:
#  deposit=round(deposit*(1+rate),1)
#  counter+=1
#  print(counter,":",deposit)

#2.Create a Python script to play 7 Boom

#n=1
#
#while n<101:
#    if n%7==0 or '7' in str(n):
#        print("boom")
#    else:
#        print(n)
#    n+=1

#3 1.Create a Python script to ask if the user wants to continue to add numbers to a list. If not, print the numbers and the sum of them
listi = []
flag = True

while flag:
    ask = input("wanna add number to the list? yes/no: " ).lower().strip()
    if ask== "yes":
        add = int(input("enter the num:"))
        listi.append(add)
    else:
        flag= False

sumi = sum(listi)
print(f"the list include: {listi},\n the sum: {sumi}")

#1.Create a Python script that prints each item and its corresponding type from the following list
#datalist = [1452, 11.23, 1+2j, True, (0, -1), [5, 12],
list1 = [{"class":'V', "section":'A'},34,'jhvh']

for i in list1:
    print(i,type(i))

#2.Create a Python script that take a string from a given string where all occurrences of its first char
#have been changed to'$', except the first char itself

str1 = "alphabat"
new_str = ""
revers = str1[::-1]

for i,char in enumerate(revers):
    if i == revers.index("a"):
        new_str += char
    elif char == "a":
        new_str = new_str + "$"
    else:
        new_str = new_str + char
print(new_str[::-1])

# 0,a
# 1,l
# 2,p
# 3,h
# 4,a
# 5,b
# 6,a
# 7,t
#
# new word = "a"

str1 = "alphabat"
print(str1[0]+str1[1:].replace('a','$'))

statement = 'alphabat'
counter = 1

while counter<2:
    for i in statement:
        if i == "a":
            counter = counter + 1
        first_half = statement[:counter]
        second_half = statement[counter:]

print(first_half + second_half.replace('a','$'))


import cv2
import numpy as np
import os
import argparse
import math
from operator import xor

clear = lambda: os.system('cls')

class Scaler:
    angle = 0.0
    def __init__(self, min, max, a, b):
        self.min = min
        self.max = max
        self.a = a
        self.b = b
        print("Min: " + str(self.min))
        print("Max: " + str(self.max))
        print("A: " + str(self.a))
        print("B: " + str(self.b))
    def scaleX(self, x):
        angle = (((self.b-self.a)*(x-self.min))/(self.max-self.min))+self.a
        return angle

leftScaler = Scaler(min=0.0, max=160.0, a=-21.80140949, b=0)
rightScaler = Scaler(min=160.0, max=320.0, a=0, b=21.80140949)

def callback(value):
    pass

def setup_trackbars(range_filter):
    cv2.namedWindow("Trackbars", 0)

    for i in ["MIN", "MAX"]:
        v = 0 if i == "MIN" else 255
        for j in range_filter:
            cv2.createTrackbar("%s_%s" % (j, i), "Trackbars", v, 255, callback)
    cv2.createTrackbar("MIN_CANNY", "Trackbars", 0, 500, callback)
    cv2.createTrackbar("MAX_CANNY", "Trackbars", 280, 500, callback)

def get_arguments():
    ap = argparse.ArgumentParser()
    ap.add_argument('-f', '--filter', required=True,
                    help='Range Filter. RGB or HSV')
    ap.add_argument('-hsv', '--hsvvalues', required=False,
                    help='Filter Values')
    ap.add_argument('-i', '--image', required=False,
                    help='Path to the image')
    ap.add_argument('-w', '--webcam', required=False,
                    help='Use webcam', action='store_true')
    ap.add_argument('-cvinf', '--cvinformation', required=False,
                    help='Use if you want to apply the contours, centroids, and area',
                    action='store_true')
    ap.add_argument('-wi', '--webcamindex', required=False,
                    help='Webcam Index')
    ap.add_argument('-p', '--preview', required=False,
                    help='Show a preview of the image after applying the mask',
                    action='store_true')
    ap.add_argument('-cs', '--camerasetsettings', required=False,
                    help='Set camera settings',
                    action='store_true')
    ap.add_argument('-cg', '--cameragetsettings', required=False,
                    help='Get camera settings',
                    action='store_true')
    args = vars(ap.parse_args())

    if not xor(bool(args['image']), bool(args['webcam'])):
        ap.error("Please specify only one image source")

    if not args['filter'].upper() in ['RGB', 'HSV']:
        ap.error("Please speciy a correct filter.")

    return args

def get_trackbar_values(range_filter):
    values = []
    for i in ["MIN", "MAX"]:
        for j in range_filter:
            v = cv2.getTrackbarPos("%s_%s" % (j, i), "Trackbars")
            values.append(v)
    v = cv2.getTrackbarPos("MIN_CANNY", "Trackbars")
    values.append(v)
    v = cv2.getTrackbarPos("MAX_CANNY", "Trackbars")
    values.append(v)
    return values

def labelCenter(image, c):
    # Places a red circle on the centers of contours
    cx = 0
    M = cv2.moments(c)
    if M['m00'] is not 0 and M['m10'] is not 0 and M['m01']:
        cx = int(M['m10'] / M['m00'])
        cy = int(M['m01'] / M['m00'])
        cv2.circle(image,(cx,cy), 3, (0,0,255), -1)
    # Draw the countour number on the image
    return image, cx

def contoursFinding(image, canny_min_thresh, canny_max_thresh):

    #Grayscaling that original image
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    #Finding canny edges
    edged = cv2.Canny(gray, canny_min_thresh, canny_max_thresh)

    #Find the contours
    im2, contours, hierarchy = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    #Returning the contours

    return contours

def getCenterCentroid(c1x, c2x):
    minX = min(c1x,c2x)
    maxX = max(c1x,c2x)
    distance = maxX - minX
    center = distance/2 + minX
    return center

def labelingCentroidsAndAreas(image, contours):
    sortedContours =  sorted(contours, key=cv2.contourArea, reverse=True)
    cxs = []
    center = 0;
    for (i, c) in enumerate(sortedContours):
        if i is 0 or i is 1:
            blank, cx = labelCenter(image, c)
            area = cv2.contourArea(c)
            cv2.putText(image, "Area: " + str(area), (image.shape[0]-80, image.shape[1]-100 + i*15)
                        , cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2)
            cxs.append(cx)

    if len(cxs) >=  2:
            center = getCenterCentroid(cxs[0], cxs[1])
            center = int(center)
            angle = 0
            cv2.circle(image,(center,200), 3, (0,0,255), -1)
            cv2.putText(image, "Center X:  " + str(center), (image.shape[0]-250, image.shape[1]-100),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2)
            if center >= 160:
                angle = rightScaler.scaleX(x=center)
            else:
                angle = leftScaler.scaleX(x=center)
            cv2.putText(image, "Angle: " + str(angle), (image.shape[0]-320, image.shape[1]-85),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 2)

    cv2.drawContours(image, contours, -1, (0, 255, 0), 1)
    #dilation = cv2.dilate(blank_image, kernel, iterations = 3)
    cv2.imshow('CV Information', image)

def main():
    args = get_arguments()
    range_filter = args['filter'].upper()
    if args['image']:
        image = cv2.imread(args['image'])

        if range_filter == 'RGB':
            frame_to_thresh = image.copy()
        else:
            frame_to_thresh = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    else:
        if args['webcamindex']:
            int_webcam_index = int(args['webcamindex'])
            camera = cv2.VideoCapture(int_webcam_index)
            camera.set(3, 320)
            camera.set(4, 240)
            camera.set(5, 15)
            if args['camerasetsettings']:
                camera.set(11, 2)
                camera.set(12, 120)
                camera.set(13, 1)
                camera.set(15, -7)

        else:
            camera = cv2.VideoCapture(0)
            camera.set(3, 320)
            camera.set(4, 240)
            camera.set(5, 15)

            if args['camerasetsettings']:
                camera.set(11, 2)
                camera.set(12, 120)
                camera.set(13, 1)
                camera.set(15, -7)
    if args['hsvvalues'] is None:
        setup_trackbars(range_filter)

    while True:
        if args['webcam']:
            ret, image = camera.read()

            if range_filter == 'RGB':
                frame_to_thresh = image.copy()
            else:
                frame_to_thresh = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
        if args['hsvvalues']:
            arrvalues = args['hsvvalues'].split(',')
            v1_min = arrvalues[0]
            v2_min = arrvalues[1]
            v3_min = arrvalues[2]
            v1_max = arrvalues[3]
            v2_max = arrvalues[4]
            v3_max = arrvalues[5]
            min_canny = arrvalues[6]
            max_canny = arrvalues[7]
            min_canny = int(min_canny)
            max_canny = int(max_canny)

            mask = cv2.inRange(frame_to_thresh, (int(v1_min), int(v2_min), int(v3_min)), (int(v1_max), int(v2_max), int(v3_max)))
        else:
            v1_min, v2_min, v3_min, v1_max, v2_max, v3_max, min_canny, max_canny = get_trackbar_values(range_filter)
            mask = cv2.inRange(frame_to_thresh, (v1_min, v2_min, v3_min), (v1_max, v2_max, v3_max))

        blank_image_preview = np.zeros((image.copy().shape[0], image.shape[1], 3))
        blank_image_cvinfo = np.zeros((image.copy().shape[0]+100, image.shape[1]+100, 3))
        if args['preview']:
            preview = cv2.bitwise_and(image, image, mask=mask)
            cv2.imshow("Preview", preview)
        else:
            image = cv2.flip(image, 1)
            cv2.imshow("Original", image)

            thresh = cv2.flip(thresh, 1)
            cv2.imshow("Thresh", thresh)

        if args['cvinformation']:
            filtered_img = cv2.bitwise_and(image, image, mask=mask)
            contours = contoursFinding(filtered_img, min_canny, max_canny)
            labelingCentroidsAndAreas(blank_image_cvinfo, contours)
            if args['cameragetsettings']:
                print ( " CV_CAP_PROP_FORMAT:  "+str(camera.get(9)) + "" )
                print ( " CV_CAP_PROP_MODE:  "+str(camera.get(10)) + "" )
                print ( " CV_CAP_PROP_BRIGHTNESS:  "+str(camera.get(11)) + "" )
                print ( " CV_CAP_PROP_CONTRAST:  "+str(camera.get(12)) + "" )
                print ( " CV_CAP_PROP_SATURATION:  "+str(camera.get(13)) + "" )
                print ( " CV_CAP_PROP_HUE:  "+str(camera.get(14)) + "" )
                print ( " CV_CAP_PROP_GAIN:  "+str(camera.get(15)) + "" )
                print ( " CV_CAP_PROP_EXPOSURE:  "+str(camera.get(16)) + "" )
        if cv2.waitKey(1) == 13:
            break

    camera.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()


from django.shortcuts import render
from django.http import JsonResponse, HttpResponse

from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http  import require_GET, require_POST

from django.apps import apps

from .forms import UserForm, StudentForm, TeacherForm

# Create your views here.

@csrf_exempt
@require_POST
def create_user(request):
    User = apps.get_model('users', 'User')

    form = UserForm(request.POST)

    if form.is_valid():
        user = form.save()
        usr = {'id': user.id, 'username': user.username, 'first_name': user.first_name,
               'last_name': user.last_name, 'is_teacher': user.is_teacher}

        return JsonResponse({'user': usr})

    return JsonResponse({'error': form.errors}, status=400)

@csrf_exempt
@require_POST
def create_student(request):
    User = apps.get_model('users', 'User')
    Student = apps.get_model('users', 'Student')

    form = StudentForm(request.POST)

    if form.is_valid():
        student = Student.objects().filter(user_id=form.cleaned_data['user_id']).first()

        if student == None:
            student = form.save()

        stud = {'id': student.id, 'user_id': student.user.id, 'class_name_id': student.class_name.id}

        return JsonResponse({'student': student})

    return JsonResponse({'error': form.errors}, status=400)

@csrf_exempt
@require_POST
def create_teacher(request):
    User = apps.get_model('users', 'User')
    Teacher = apps.get_model('users', 'Student')

    form = TeacherForm(request.POST)

    if form.is_valid():
        teacher = Teacher.objects().filter(user_id=form.cleaned_data['user_id']).first()

        if teacher == None:
            teacher = form.save()

        teach = {'id': teacher.id, 'user_id': teacher.user.id, 'subject_id': teacher.subject.id}

        return JsonResponse({'teacher': teach})

    return JsonResponse({'error': form.errors}, status=400)

@require_GET
def students_list(request):
    User = apps.get_model('users', 'User')
    Student = apps.get_model('users', 'Student')
    Class = apps.get_model('classes', 'Class')

    students = Student.objects().all().values('id', 'user_id', 'class_id')

    result = []

    for s in students:
        user = User.objects().filter(id=s['user_id']).first()
        s_class = Class.objects().filter(id=s['class_name_id'])

        student = {'id': s.id, 'first_name': user.first_name, 'last_name': user.last_name,
                   'class_number': s_class.parallel, 'class_letter': s_class.letter}

        result.append(student)

    return JsonResponse({'students': result})

@require_GET
def teachers_list(request):
    User = apps.get_model('users', 'User')
    Teacher = apps.get_model('users', 'Student')
    Subject = apps.get_model('classes', 'Subject')

    teachers = Teacher.objects().all().values('id', 'user_id', 'subject_id')

    result = []

    for t in teachers:
        user = User.objects().filter(id=t['user_id']).first()
        subject = Subject.objects().filter(id=t['subject_id'])

        teacher = {'id': t.id, 'first_name': user.first_name, 'last_name': user.last_name,
                   'subject_name': subject.name, 'subject_class': subject.class_name.id}

        result.append(teacher)

    return JsonResponse({'teachers': result})

@require_GET
def search_by_name(request):
    User = apps.get_model('users', 'User')

    users = User.objects.filter(username__contains=request.GET['name']).values('id', 'username', 'first_name', 'last_name')[:int(request.GET['limit'])]
    return JsonResponse({'users': list(users)})

@require_GET
def search_by_id(request):
    User = apps.get_model('users', 'User')

    users = User.objects.filter(id=request.GET['id']).values('id', 'username', 'first_name', 'last_name')[:int(request.GET['limit'])]
    return JsonResponse({'users': list(users)})


from schemec.typs import *

__all__ = ['T_c']

################################################################################
## Conversion to CPS
################################################################################

def T_k(exp, k):
    """Transform an expression into CPS with a continuation lifted into the host
    language.

    @type exp: A Scheme expression
    @param exp: The expression to transform
    @type k: A *Python* function from SchemeExp -> SchemeExp
    @param k: The continuation to apply
    """
    if isinstance(exp, AtomicExp):
        return k(M(exp))
    elif isinstance(exp, AppExp):
        _rv = gensym('$rv')
        cont = LamExp([_rv], k(_rv))
        return T_c(exp, cont)
    elif isinstance(exp, IfExp):
        ce = exp.condExp
        te = exp.thenExp
        ee = exp.elseExp
        return T_k(ce, lambda _ce: IfExp(_ce, T_k(te, k), T_k(ee, k)))
    elif isinstance(exp, LetRecExp):
        bs = exp.bindings
        be = exp.bodyExp
        return LetRecExp([[ve, M(fe)] for ve, fe in bs], T_k(be, k))
    elif isinstance(exp, BeginExp):
        es = exp.exps
        if len(es) == 1:
            return T_k(es[0], k)
        else:
            return T_k(es[0], lambda _: T_k(BeginExp(*es[1:]), k))
    elif isinstance(exp, SetExp):
        ve = exp.varExp
        ee = exp.exp
        return T_k(ee, lambda _ee: SetThenExp(ve, _ee, k(void)))
    else:
        raise TypeError(exp)

def T_c(exp, c):
    """Transform an expression into CPS.

    @type exp: A Scheme expression
    @param exp: The expression to transform
    @type c: LamExp
    @param c: The continuation to apply
    """
    if isinstance(exp, AtomicExp):
        return AppExp(c, M(exp))
    elif isinstance(exp, AppExp):
        f = exp.funcExp
        es = exp.argExps
        return T_k(f, lambda _f:
                   Tx_k(es, lambda _es:
                        AppExp(_f, *(_es + [c]))))
    elif isinstance(exp, IfExp):
        ce = exp.condExp
        te = exp.thenExp
        ee = exp.elseExp
        _k = gensym('$k')
        return AppExp(LamExp([_k], T_k(ce, lambda _ce:
                                       IfExp(_ce, T_c(te, _k), T_c(ee, _k)))),
                             c)
    elif isinstance(exp, LetRecExp):
        bs = exp.bindings
        be = exp.bodyExp
        return LetRecExp([[ve, M(fe)] for ve, fe in bs], T_c(be, c))
    elif isinstance(exp, BeginExp):
        es = exp.exps
        if len(es) == 1:
            return T_c(es[0], c)
        else:
            return T_k(es[0], lambda _: T_c(BeginExp(*es[1:]), c))
    elif isinstance(exp, SetExp):
        ve = exp.varExp
        ee = exp.exp
        return T_k(ee, lambda _ee: SetThenExp(ve, _ee, AppExp(c, void)))
    else:
        raise TypeError(exp)

def Tx_k(exps, k):
    """Transform a list of expressions into CPS.

    @type exps: A List of SchemeExps
    @type k: A *Python* function from SchemeExp -> SchemeExp
    """
    if len(exps) == 0:
        return k([])
    else:
        return T_k(exps[0],
                   lambda hd: Tx_k(exps[1:],
                                   lambda tl: k([hd] + tl)))

def M(exp):
    """Transform an AtomicExp into CPS.

    @type exp: AtomicExp
    """
    if isinstance(exp, LamExp):
        args = exp.argExps
        body = exp.bodyExp
        _k = gensym('$k')
        return LamExp(args + [_k],
                      T_c(body, _k))
    elif isinstance(exp, AtomicExp):
        return exp
    else:
        raise TypeError(exp)

################################################################################
## Main
################################################################################

if __name__ == '__main__':
    exp = AppExp(LamExp([VarExp('g'), VarExp('h')], VarExp('g')),
                 BoolExp(True),
                 BoolExp(False))
    print(exp)
    print(T_c(exp, VarExp('halt')))

    exp = IfExp(IfExp(BoolExp(True),
                      BoolExp(False),
                      BoolExp(True)),
                NumExp(1),
                NumExp(0))
    print(exp)
    print(T_c(exp, VarExp('halt')))

    exp = LetRecExp([[VarExp('fact'),
                      LamExp([VarExp('x')],
                             IfExp(AppExp(VarExp('='),
                                          VarExp('x'),
                                          NumExp(0)),
                                   NumExp(1),
                                   AppExp(VarExp('*'),
                                          VarExp('x'),
                                          AppExp(VarExp('fact'),
                                                 AppExp(VarExp('-'),
                                                        VarExp('x'),
                                                        NumExp(1))))))]],
                    AppExp(VarExp('fact'), NumExp(5)))
    print(exp)
    print(T_c(exp, VarExp('halt')))

    exp = BeginExp(SetExp(VarExp('x'), NumExp(1)),
                   VarExp('x'))
    print(exp)
    print(T_k(exp, lambda x: AppExp(VarExp('halt'), x)))

    exp = LetRecExp([[VarExp('even?'),
                      LamExp([VarExp('n')],
                             IfExp(AppExp(VarExp('zero?'), VarExp('n')),
                                   true,
                                   AppExp(VarExp('odd?'),
                                          AppExp(VarExp('-'),
                                                 VarExp('n'),
                                                 NumExp(1)))))],
                     [VarExp('odd?'),
                      LamExp([VarExp('n')],
                             IfExp(AppExp(VarExp('zero?'), VarExp('n')),
                                   false,
                                   AppExp(VarExp('even?'),
                                          AppExp(VarExp('-'),
                                                 VarExp('n'),
                                                 NumExp(1)))))]],
                    AppExp(VarExp('even?'), NumExp(40)))
    print(exp)
    print(T_c(exp, VarExp('halt')))


import glob
import os
import subprocess
from pathlib import Path

def find_files():
    download_folder = Path(Path.home(), 'Downloads', 'Test')
    files = glob.glob('fmb_*.html', root_dir=download_folder)
    print(files)
    script_dir = Path(Path.home(), "work", "fmb")
    os.chdir(script_dir)
    for file in files:
        file_with_path = Path(download_folder, file)
        pdf_file = str(file_with_path).replace(".html", ".pdf")
        if not Path(pdf_file).exists():
            script = Path(os.getcwd(), "jsscript.js")
            script = "jsscript.js"
            cmd = f"node {script} {file_with_path}"
            print(cmd)
            result = subprocess.run(["node", script, str(file_with_path)], capture_output=True, text=True)
            print(result)
        else:
            print(f"{pdf_file} : already processed")

if __name__ == "__main__":
    find_files()


import torch
import torch.nn as nn

from ..builder import (ALGORITHMS, build_backbone, build_head, build_memory,
                       build_neck)
from .base import BaseModel

@ALGORITHMS.register_module()
class NPID(BaseModel):
    """NPID.

    Implementation of `Unsupervised Feature Learning via Non-parametric
    Instance Discrimination <https://arxiv.org/abs/1805.01978>`_.

    Args:
        backbone (dict): Config dict for module of backbone.
        neck (dict): Config dict for module of deep features to compact feature
            vectors. Defaults to None.
        head (dict): Config dict for module of loss functions.
            Defaults to None.
        memory_bank (dict): Config dict for module of memory banks.
            Defaults to None.
        neg_num (int): Number of negative samples for each image.
            Defaults to 65536.
        ensure_neg (bool): If False, there is a small probability
            that negative samples contain positive ones. Defaults to False.
    """

    def __init__(self,
                 backbone,
                 neck=None,
                 head=None,
                 memory_bank=None,
                 neg_num=65536,
                 ensure_neg=False,
                 init_cfg=None):
        super(NPID, self).__init__(init_cfg)
        self.backbone = build_backbone(backbone)
        if neck is not None:
            self.neck = build_neck(neck)
        assert head is not None
        self.head = build_head(head)
        assert memory_bank is not None
        self.memory_bank = build_memory(memory_bank)

        self.neg_num = neg_num
        self.ensure_neg = ensure_neg

    def extract_feat(self, img):
        """Function to extract features from backbone.

        Args:
            img (Tensor): Input images of shape (N, C, H, W).
                Typically these should be mean centered and std scaled.

        Returns:
            tuple[Tensor]: backbone outputs.
        """
        x = self.backbone(img)
        return x

    def forward_train(self, img, idx, **kwargs):
        """Forward computation during training.

        Args:
            img (Tensor): Input images of shape (N, C, H, W).
                Typically these should be mean centered and std scaled.
            idx (Tensor): Index corresponding to each image.
            kwargs: Any keyword arguments to be used to forward.

        Returns:
            dict[str, Tensor]: A dictionary of loss components.
        """
        feature = self.extract_feat(img)
        idx = idx.cuda()
        if self.with_neck:
            feature = self.neck(feature)[0]
        feature = nn.functional.normalize(feature)  # BxC
        bs, feat_dim = feature.shape[:2]
        neg_idx = self.memory_bank.multinomial.draw(bs * self.neg_num)
        if self.ensure_neg:
            neg_idx = neg_idx.view(bs, -1)
            while True:
                wrong = (neg_idx == idx.view(-1, 1))
                if wrong.sum().item() > 0:
                    neg_idx[wrong] = self.memory_bank.multinomial.draw(
                        wrong.sum().item())
                else:
                    break
            neg_idx = neg_idx.flatten()

        pos_feat = torch.index_select(self.memory_bank.feature_bank, 0,
                                      idx)  # BXC
        neg_feat = torch.index_select(self.memory_bank.feature_bank, 0,
                                      neg_idx).view(bs, self.neg_num,
                                                    feat_dim)  # BxKxC

        pos_logits = torch.einsum('nc,nc->n',
                                  [pos_feat, feature]).unsqueeze(-1)
        neg_logits = torch.bmm(neg_feat, feature.unsqueeze(2)).squeeze(2)

        losses = self.head(pos_logits, neg_logits)

        # update memory bank
        with torch.no_grad():
            self.memory_bank.update(idx, feature.detach())

        return losses


#!/usr/bin/env python3

from configparser import SafeConfigParser
import socket
import ssl

parser = SafeConfigParser()
parser.read('config.ini')
server_ip = parser.get('server', 'ip')
server_port = int(parser.get('server', 'port'))

certfile = parser.get('ssl','ssl_certfile')
print(certfile)

'''
ssl_sock = ssl.wrap_socket(sock,
                           ca_certs=certfile,
                           cert_reqs=ssl.CERT_REQUIRED)

ssl_sock.connect((server_ip, server_port))
'''
context = ssl.create_default_context()
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_REQUIRED

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(sock)
ssl_sock.connect((server_ip, server_port))


# cython: language_level=3
from flask import session
from flask_jwt_extended import verify_jwt_in_request, get_jwt_identity
from flask_jwt_extended.exceptions import (NoAuthorizationError,
                                           InvalidHeaderError)
from flask_socketio import disconnect, emit

def init_socketio_api(app):
    """Initialize SocketIO APIs"""
    from flask_socketio import SocketIO
    app.socketio = SocketIO(
        app,
        cors_allowed_origins=app.config['ALLOWED_ORIGIN'])

    @app.socketio.on('connect')
    def connect_handler():
        try:
            verify_jwt_in_request()
        except (NoAuthorizationError, InvalidHeaderError):
            emit('error', {
                'event': 'connect',
                'status': 'error',
                'error_message': 'Invalid or not provided access token.'
            })
            disconnect()
        session['current_user_email'] = get_jwt_identity()

    from .livestream import livestream  # noqa