"""RPA generator views"""

from django import forms
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView
from django.views.generic.edit import DeleteView, CreateView
from django.urls import reverse, reverse_lazy
from django.views.generic.list import ListView
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import TemplateView
from django.shortcuts import redirect, get_object_or_404

from django_weasyprint import WeasyTemplateResponseMixin

from extra_views import ModelFormSetView

from .models import (
    Rpa,
    ProcessingActivityName,
    DataController,
    JointController,
    DataProtectionOfficer,
    InternallyResponsibleDept,
    CategoryOfPersonalData,
    CategoriesOfPersonalDataOrigin,
    PurposeAndLegalBasis,
    DataSubject,
    TimeLimitForErasure,
    CategoryOfRecipients,
    TransferToThirdCountry,
    AccessGroup,
    Transparency,
    DataProcessor,
    PrivacyImpactAssessment,
    TOM,
    RPAAnnex,
)

from .forms import (
    RpaForm,
    ProcessingActivityNameForm,
    DataControllerForm,
    JointControllerForm,
    DataProtectionOfficerForm,
    InternallyResponsibleDeptForm,
    CategoryOfPersonalDataForm,
    CategoryOfPersonalDataFormSet,
    CategoriesOfPersonalDataOriginForm,
    PurposeAndLegalBasisForm,
    DataSubjectForm,
    TimeLimitForErasureForm,
    TimeLimitForErasureFormSet,
    CategoryOfRecipientsForm,
    CategoryOfRecipientsFormSet,
    TransferToThirdCountryForm,
    AccessGroupForm,
    AccessGroupFormSet,
    TransparencyForm,
    DataProcessorForm,
    PrivacyImpactAssessmentForm,
    TOMForm,
    RPAAnnexForm,
    RPAAnnexFormSet,
)

from .forms import (
    CpdModelMultipleChoiceField,
    CPD_CHOICES,
)

class RPAGenUserPassesMixin(UserPassesTestMixin):
    def test_func(self):
        """Override test_func() method to ensure proper access control
        over given Rpa object
        """
        is_allowed = False
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        current_user = rpa.user or None
        if (
            self.request.user.is_staff
            and self.request.user.groups.filter(name="dpo").exists()
        ):
            is_allowed = True
        if self.request.user.is_superuser:
            is_allowed = True
        if self.request.user and self.request.user == current_user:
            is_allowed = True
        return is_allowed

class RPAHintsView(LoginRequiredMixin, TemplateView):
    """User information about records of processing activities (RPAs)
    and how to create them; view is accessible to authenticated users
    only
    """

    template_name = "rpa/rpa_hints.html"

class MyRPAsView(LoginRequiredMixin, ListView):
    """Allow authenticated users to view a list of their own RPAs, if
    any
    """

    model = Rpa
    template_name = "rpa/rpa_view.html"
    context_object_name = "rpa"
    paginate_by = 12

    def get_queryset(self):
        return Rpa.objects.filter(user=self.request.user).order_by("slug")

class AllRPAsView(LoginRequiredMixin, UserPassesTestMixin, ListView):
    """List of all RPAs in the database; view is accessible only to
    staff users that are also members of group "dpo" (and superusers)
    """

    model = Rpa
    template_name = "rpa/rpa_view_all.html"
    context_object_name = "rpa"
    # paginate_by = 12

    def test_func(self):
        is_allowed = False
        if (
            self.request.user.is_staff
            and self.request.user.groups.filter(name="dpo").exists()
        ):
            is_allowed = True
        if self.request.user.is_superuser:
            is_allowed = True
        return is_allowed

    def get_queryset(self):
        return Rpa.objects.all

class RPADetailView(LoginRequiredMixin, RPAGenUserPassesMixin, DetailView):
    """HTML document view of a single RPA
    (RPAGenUserPassesMixin-restricted)
    """

    model = Rpa
    template_name = "rpa/rpa_htmltemplate.html"
    context_object_name = "rpa"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        rpanm_dpoc = self.object.rpa_names.values_list("dpo_comment").exclude(
            dpo_comment__exact=""
        )
        dcon_dpoc = self.object.datacontrollers.values_list("dcon_dpo_comment").exclude(
            dcon_dpo_comment__exact=""
        )
        jcon_dpoc = self.object.jointcontrollers.values_list(
            "jcon_dpo_comment"
        ).exclude(jcon_dpo_comment__exact="")
        dpo_dpoc = self.object.dpos.values_list("dpo_dpo_comment").exclude(
            dpo_dpo_comment__exact=""
        )
        ird_dpoc = self.object.internally_resp_depts.values_list(
            "ird_dpo_comment"
        ).exclude(ird_dpo_comment__exact="")
        cpd_dpoc = self.object.datacategories.values_list("cpd_dpo_comment").exclude(
            cpd_dpo_comment__exact=""
        )
        cpdo_dpoc = self.object.datacategories_origin.values_list(
            "cpdo_dpo_comment"
        ).exclude(cpdo_dpo_comment__exact="")
        plb_dpoc = self.object.purposes_legalbases.values_list(
            "plb_dpo_comment"
        ).exclude(plb_dpo_comment__exact="")
        dsub_dpoc = self.object.datasubjects.values_list("dsub_dpo_comment").exclude(
            dsub_dpo_comment__exact=""
        )
        tle_dpoc = self.object.timelimits_erasure.values_list(
            "tle_dpo_comment"
        ).exclude(tle_dpo_comment__exact="")
        crec_dpoc = self.object.categories_of_rec.values_list(
            "crec_dpo_comment"
        ).exclude(crec_dpo_comment__exact="")
        ttc_dpoc = self.object.transfers_to_3rdc.values_list("ttc_dpo_comment").exclude(
            ttc_dpo_comment__exact=""
        )
        agrp_dpoc = self.object.accessgroups.values_list("agrp_dpo_comment").exclude(
            agrp_dpo_comment__exact=""
        )
        tran_dpoc = self.object.transparencies.values_list("tran_dpo_comment").exclude(
            tran_dpo_comment__exact=""
        )
        dpro_dpoc = self.object.dataprocessors.values_list("dpro_dpo_comment").exclude(
            dpro_dpo_comment__exact=""
        )
        pia_dpoc = self.object.pias.values_list("pia_dpo_comment").exclude(
            pia_dpo_comment__exact=""
        )
        tom_dpoc = self.object.toms.values_list("tom_dpo_comment").exclude(
            tom_dpo_comment__exact=""
        )
        annex_dpoc = self.object.rpa_annexes.values_list("annex_dpo_comment").exclude(
            annex_dpo_comment__exact=""
        )
        context["rpanm_dpoc"] = True if rpanm_dpoc else False
        context["dcon_dpoc"] = True if dcon_dpoc else False
        context["jcon_dpoc"] = True if jcon_dpoc else False
        context["dpo_dpoc"] = True if dpo_dpoc else False
        context["ird_dpoc"] = True if ird_dpoc else False
        context["cpd_dpoc"] = True if cpd_dpoc else False
        context["cpdo_dpoc"] = True if cpdo_dpoc else False
        context["plb_dpoc"] = True if plb_dpoc else False
        context["dsub_dpoc"] = True if dsub_dpoc else False
        context["tle_dpoc"] = True if tle_dpoc else False
        context["crec_dpoc"] = True if crec_dpoc else False
        context["ttc_dpoc"] = True if ttc_dpoc else False
        context["agrp_dpoc"] = True if agrp_dpoc else False
        context["tran_dpoc"] = True if tran_dpoc else False
        context["dpro_dpoc"] = True if dpro_dpoc else False
        context["pia_dpoc"] = True if pia_dpoc else False
        context["tom_dpoc"] = True if tom_dpoc else False
        context["annex_dpoc"] = True if annex_dpoc else False
        return context

class RPADetailPDFView(WeasyTemplateResponseMixin, RPADetailView):
    """Allow a single RPA to be downloaded as PDF file
    (RPAGenUserPassesMixin-restricted via RPADetailView)
    """

    template_name = "rpa/rpa_pdftemplate.html"
    pdf_attachment = False

    def get_pdf_filename(self):
        rpaname = _("rpa")
        if self.object:
            rpaname += "-" + str(self.object)
        return "{rpaname}-{at}.pdf".format(
            at=timezone.now().strftime("%Y%m%d"), rpaname=rpaname
        )

class RPADeleteView(LoginRequiredMixin, RPAGenUserPassesMixin, DeleteView):
    """Allow a single RPA to be deleted
    (RPAGenUserPassesMixin-restricted)
    """

    model = Rpa
    template_name = "rpa/rpa_delete_confirmation.html"
    success_url = reverse_lazy("rpa:my_rpas")

    def post(self, request, *args, **kwargs):
        if "cancel" in request.POST:
            return redirect("rpa:my_rpas")
        return super().post(request, *args, **kwargs)

class AllRPADeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    """Allow superusers and staff users with dpo membership to delete
    any single breach report
    """

    model = Rpa
    template_name = "rpa/rpa_delete_confirmation.html"
    success_url = reverse_lazy("rpa:all_rpas")

    def test_func(self):
        is_allowed = False
        if (
            self.request.user.is_staff
            and self.request.user.groups.filter(name="dpo").exists()
        ):
            is_allowed = True
        if self.request.user.is_superuser:
            is_allowed = True
        return is_allowed

    def post(self, request, *args, **kwargs):
        if "cancel" in request.POST:
            return redirect("rpa:all_rpas")
        return super().post(request, *args, **kwargs)

class RPAEditView(LoginRequiredMixin, RPAGenUserPassesMixin, DetailView):
    """General edit overview page with links to all edit views of
    RPA-related objects (such as categories of personal data, technical
    and organisational measures, ...); also shows status of objects in
    terms of RPA completeness (RPAGenUserPassesMixin-restricted)
    """

    model = Rpa
    template_name = "rpa/rpa_edit.html"
    context_object_name = "rpa"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        rpanm_dpoc = self.object.rpa_names.values_list("dpo_comment").exclude(
            dpo_comment__exact=""
        )
        dcon_dpoc = self.object.datacontrollers.values_list("dcon_dpo_comment").exclude(
            dcon_dpo_comment__exact=""
        )
        jcon_dpoc = self.object.jointcontrollers.values_list(
            "jcon_dpo_comment"
        ).exclude(jcon_dpo_comment__exact="")
        dpo_dpoc = self.object.dpos.values_list("dpo_dpo_comment").exclude(
            dpo_dpo_comment__exact=""
        )
        ird_dpoc = self.object.internally_resp_depts.values_list(
            "ird_dpo_comment"
        ).exclude(ird_dpo_comment__exact="")
        cpd_dpoc = self.object.datacategories.values_list("cpd_dpo_comment").exclude(
            cpd_dpo_comment__exact=""
        )
        cpdo_dpoc = self.object.datacategories_origin.values_list(
            "cpdo_dpo_comment"
        ).exclude(cpdo_dpo_comment__exact="")
        plb_dpoc = self.object.purposes_legalbases.values_list(
            "plb_dpo_comment"
        ).exclude(plb_dpo_comment__exact="")
        dsub_dpoc = self.object.datasubjects.values_list("dsub_dpo_comment").exclude(
            dsub_dpo_comment__exact=""
        )
        tle_dpoc = self.object.timelimits_erasure.values_list(
            "tle_dpo_comment"
        ).exclude(tle_dpo_comment__exact="")
        crec_dpoc = self.object.categories_of_rec.values_list(
            "crec_dpo_comment"
        ).exclude(crec_dpo_comment__exact="")
        ttc_dpoc = self.object.transfers_to_3rdc.values_list("ttc_dpo_comment").exclude(
            ttc_dpo_comment__exact=""
        )
        agrp_dpoc = self.object.accessgroups.values_list("agrp_dpo_comment").exclude(
            agrp_dpo_comment__exact=""
        )
        tran_dpoc = self.object.transparencies.values_list("tran_dpo_comment").exclude(
            tran_dpo_comment__exact=""
        )
        dpro_dpoc = self.object.dataprocessors.values_list("dpro_dpo_comment").exclude(
            dpro_dpo_comment__exact=""
        )
        pia_dpoc = self.object.pias.values_list("pia_dpo_comment").exclude(
            pia_dpo_comment__exact=""
        )
        tom_dpoc = self.object.toms.values_list("tom_dpo_comment").exclude(
            tom_dpo_comment__exact=""
        )
        annex_dpoc = self.object.rpa_annexes.values_list("annex_dpo_comment").exclude(
            annex_dpo_comment__exact=""
        )
        context["rpanm_dpoc"] = True if rpanm_dpoc else False
        context["dcon_dpoc"] = True if dcon_dpoc else False
        context["jcon_dpoc"] = True if jcon_dpoc else False
        context["dpo_dpoc"] = True if dpo_dpoc else False
        context["ird_dpoc"] = True if ird_dpoc else False
        context["cpd_dpoc"] = True if cpd_dpoc else False
        context["cpdo_dpoc"] = True if cpdo_dpoc else False
        context["plb_dpoc"] = True if plb_dpoc else False
        context["dsub_dpoc"] = True if dsub_dpoc else False
        context["tle_dpoc"] = True if tle_dpoc else False
        context["crec_dpoc"] = True if crec_dpoc else False
        context["ttc_dpoc"] = True if ttc_dpoc else False
        context["agrp_dpoc"] = True if agrp_dpoc else False
        context["tran_dpoc"] = True if tran_dpoc else False
        context["dpro_dpoc"] = True if dpro_dpoc else False
        context["pia_dpoc"] = True if pia_dpoc else False
        context["tom_dpoc"] = True if tom_dpoc else False
        context["annex_dpoc"] = True if annex_dpoc else False
        return context

class RPACreateSimpleFormView(CreateView):
    """Used to create and edit RPA-related objects that require just a
    single form without data from other database objects (namely
    category of personal data objects)
    """

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        try:
            existing_instance = self.model.objects.get(rpa=rpa)
        except self.model.DoesNotExist:
            existing_instance = None
        if existing_instance:
            kwargs["instance"] = existing_instance
        return kwargs

    def form_valid(self, form):
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        form.instance.rpa = rpa
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        rpaslug = self.kwargs.get("slug")
        context["rpa"] = get_object_or_404(Rpa, slug=rpaslug)
        return context

    def get_success_url(self):
        return reverse("rpa:rpa_detail_edit", args=[self.kwargs["slug"]])

class RPACreateSimpleFormsetView(ModelFormSetView):
    """Used to create and edit RPA-related objects that require a
    formset without data from other database objects (namely category of
    personal data objects)
    """

    def get_queryset(self):
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        return super().get_queryset().filter(rpa=rpa)

    def formset_valid(self, formset):
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        for form in formset:
            form.instance.rpa = rpa
        return super().formset_valid(formset)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        rpaslug = self.kwargs.get("slug")
        context["rpa"] = get_object_or_404(Rpa, slug=rpaslug)
        return context

    def get_success_url(self):
        return reverse("rpa:rpa_detail_edit", args=[self.kwargs["slug"]])

class RPACreateChoiceFormsetView(ModelFormSetView):
    """Used to create and edit RPA-related objects that require a
    formset with data from other database objects (namely category of
    personal data) in every single form of the formset (currently data
    subject, time limit for erasure, category of recipients, and access
    group)
    """

    def construct_formset(self):
        formset = super().construct_formset()
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        choice_field = self.kwargs.get("choice_field", None)
        for form in formset:
            form.fields[choice_field] = CpdModelMultipleChoiceField(
                queryset=CategoryOfPersonalData.objects.filter(rpa=rpa),
                widget=forms.CheckboxSelectMultiple,
                label=CPD_CHOICES,
                required=False,
            )
            if form.instance.id:
                previously_selected = []
                for i in form.instance.cpd.all():
                    previously_selected.append(i.pk)
                form.initial[choice_field] = previously_selected
        return formset

    def get_queryset(self):
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        return super().get_queryset().filter(rpa=rpa)

    def formset_valid(self, formset):
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        for form in formset:
            form.instance.rpa = rpa
        return super().formset_valid(formset)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        rpaslug = self.kwargs.get("slug")
        rpa = get_object_or_404(Rpa, slug=rpaslug)
        cpd = CategoryOfPersonalData.objects.filter(rpa=rpa)
        context["rpa"] = rpa
        context["cpd"] = cpd
        return context

    def get_success_url(self):
        return reverse("rpa:rpa_detail_edit", args=[self.kwargs["slug"]])

class RPACreateView(LoginRequiredMixin, CreateView):
    """Used to create an RPA object (basically an empty RPA, that is
    supposed to be completed afterwards); view is accessible for
    authenticated users only; redirects to MyRPAsView
    """

    form_class = RpaForm
    template_name = "rpa/rpa_create_slug.html"
    model = Rpa

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

    def get_success_url(self):
        return reverse("rpa:my_rpas")

class RPACreateRpanmView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = ProcessingActivityNameForm
    model = ProcessingActivityName
    template_name = "rpa/rpa_create_name.html"

class RPACreateDconView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = DataControllerForm
    model = DataController
    template_name = "rpa/rpa_create_dcon.html"

class RPACreateJconView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = JointControllerForm
    model = JointController
    template_name = "rpa/rpa_create_jcon.html"

class RPACreateDpoView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = DataProtectionOfficerForm
    model = DataProtectionOfficer
    template_name = "rpa/rpa_create_dpo.html"

class RPACreateIrdView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = InternallyResponsibleDeptForm
    model = InternallyResponsibleDept
    template_name = "rpa/rpa_create_ird.html"

class RPACreateCpdView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormsetView
):
    model = CategoryOfPersonalData
    form_class = CategoryOfPersonalDataForm
    formset_class = CategoryOfPersonalDataFormSet
    factory_kwargs = {
        "min_num": 1,
        "max_num": 9,
        "extra": 8,
        "can_order": False,
        "can_delete": True,
    }
    template_name = "rpa/rpa_create_cpd.html"

class RPACreateCpdoView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = CategoriesOfPersonalDataOriginForm
    model = CategoriesOfPersonalDataOrigin
    template_name = "rpa/rpa_create_cpdo.html"

class RPACreatePlbView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = PurposeAndLegalBasisForm
    model = PurposeAndLegalBasis
    template_name = "rpa/rpa_create_plb.html"

class RPACreateDSubView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateChoiceFormsetView
):
    model = DataSubject
    form_class = DataSubjectForm
    factory_kwargs = {
        "min_num": 1,
        "max_num": 9,
        "extra": 8,
        "can_order": False,
        "can_delete": True,
    }
    template_name = "rpa/rpa_create_dsub.html"

class RPACreateTleView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateChoiceFormsetView
):
    model = TimeLimitForErasure
    form_class = TimeLimitForErasureForm
    formset_class = TimeLimitForErasureFormSet
    factory_kwargs = {
        "min_num": 1,
        "max_num": 5,
        "extra": 4,
        "can_order": False,
        "can_delete": True,
    }
    template_name = "rpa/rpa_create_tle.html"

class RPACreateCrecView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateChoiceFormsetView
):
    model = CategoryOfRecipients
    form_class = CategoryOfRecipientsForm
    formset_class = CategoryOfRecipientsFormSet
    factory_kwargs = {
        "min_num": 1,
        "max_num": 5,
        "extra": 4,
        "can_order": False,
        "can_delete": True,
    }
    template_name = "rpa/rpa_create_crec.html"

class RPACreateTtcView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = TransferToThirdCountryForm
    model = TransferToThirdCountry
    template_name = "rpa/rpa_create_ttc.html"

class RPACreateAgrpView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateChoiceFormsetView
):
    model = AccessGroup
    form_class = AccessGroupForm
    formset_class = AccessGroupFormSet
    factory_kwargs = {
        "min_num": 1,
        "max_num": 5,
        "extra": 4,
        "can_order": False,
        "can_delete": True,
    }
    template_name = "rpa/rpa_create_agrp.html"

class RPACreateTranView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = TransparencyForm
    model = Transparency
    template_name = "rpa/rpa_create_tran.html"

class RPACreateDproView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = DataProcessorForm
    model = DataProcessor
    template_name = "rpa/rpa_create_dpro.html"

class RPACreatePiaView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = PrivacyImpactAssessmentForm
    model = PrivacyImpactAssessment
    template_name = "rpa/rpa_create_pia.html"

class RPACreateTomView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormView
):
    form_class = TOMForm
    model = TOM
    template_name = "rpa/rpa_create_tom.html"

class RPACreateAnnexView(
    LoginRequiredMixin, RPAGenUserPassesMixin, RPACreateSimpleFormsetView
):
    model = RPAAnnex
    form_class = RPAAnnexForm
    formset_class = RPAAnnexFormSet
    factory_kwargs = {
        "min_num": 0,
        "max_num": 9,
        "extra": 9,
        "can_order": False,
        "can_delete": True,
    }
    template_name = "rpa/rpa_create_annex.html"


import os
from binance.client import Client
from make_trades import make_trade

api_key = os.getenv('BINANCE_API_KEY')
api_secret = os.getenv('BINANCE_API_SECRET')
client = Client(api_key, api_secret)

def execute_trade():
    decision = make_trade()
    if decision == 'buy':
        order = client.create_order(
            symbol='BTCUSDT',
            side=Client.SIDE_BUY,
            type=Client.ORDER_TYPE_MARKET,
            quantity=0.001
        )
        print("Bought 0.001 BTC")
    elif decision == 'sell':
        order = client.create_order(
            symbol='BTCUSDT',
            side=Client.SIDE_SELL,
            type=Client.ORDER_TYPE_MARKET,
            quantity=0.001
        )
        print("Sold 0.001 BTC")
    else:
        print("No trade made")

if __name__ == '__main__':
    execute_trade()


#-------------------------------------------------------------------------------
# Name:        at_jobs_carver.py
# Purpose:     To carve out Windows schedule task (.JOB) files from BLOBs of data,
#              such as a memory dump or a page file. The script relies on two
#              observations:
#                1) AT job files have the same comment,
#                2) the value for Error Code field is always 0x00000000, while
#                   Status field is one of three values in format 0x0004130?.
#
# Author:      Bartosz Inglot
#
# Created:     2015-09-03
# Licence:     GNU General Public License v2.0 (GPL-2.0)
#-------------------------------------------------------------------------------

import sys, os, mmap, re

# Hard-coded values that the code relies on:
JOB_COMMENT = 'Created by NetScheduleJobAdd.'
FIXED_SECTION_LEN = 68
EXIT_CODE_OFFSET = 40
EXIT_CODE_AND_STATUS_REGEX = re.compile(r'\x00\x00\x00\x00.\x13\x04\x00')

"""
  We assume that the variable section's length is not larger than 320 bytes,
  it's an arbitrary number. If the job failes to parse correctly, increase it.
"""
MAX_JOB_FILE_SIZE = FIXED_SECTION_LEN + 512 #: increase if .JOB fails to parse

def find_beginning(buf, offset):
    """
    There should be 5 variable length values before the fixed length section,
    see https://msdn.microsoft.com/en-us/library/cc248287.aspx

    Each of them terminates with double null, let's jump 5 x double-nulls back,
    we'll land somewhere in the fixed length section (can't land exactly
    where it ends because there's no unique value separating the two
    sections), read a chunk of memory before and after where we landed and
    find in this chunk a unique value that is always at a given offset in the
    fixed length section.

    The unique value that was used is '0000 0000 ??13 0400', which are Exit
    Code (offset: 40-44) and Status (offset: 44-48). Once identified, we just
    jump back to the beginning of the fix length section and grab enough bytes
    to carve the entire job (the excess bytes are ignored by the parser).

    """
    def go_back_to_nulls(buf, offset):
        buf.seek(offset)
        previous = None
        while True:
            current = buf.read_byte()
            buf.seek(buf.tell() - 1) # return to where we read from
            if current == '\x00' and previous == '\x00':
                return buf.tell()
            buf.seek(buf.tell() - 1) # jump back by 1
            previous = current

    new_offset = offset + 2 # adding 2 because we'll subtract 2 in the loop
    for _ in xrange(5):
        # subtracting 2 to avoid '\x00\x??\x00\x00\x00' being hit on twice
        new_offset = go_back_to_nulls(buf, new_offset - 2)

    # grab a chunk of memory that will be searched for EXIT_CODE_AND_STATUS_REGEX
    if new_offset - FIXED_SECTION_LEN < 0:
        return None
    buf.seek(new_offset - FIXED_SECTION_LEN)

    snippet = buf.read(FIXED_SECTION_LEN + 8)
    match = EXIT_CODE_AND_STATUS_REGEX.search(snippet)
    if not match:
        # failed verification, probably an FP
        return None
    status_code_offset = match.start()

    return (new_offset - FIXED_SECTION_LEN + status_code_offset - EXIT_CODE_OFFSET)

def carve_out(buf, offset):
    """
    Flush the job file.
    """
    buf.seek(offset)
    return buf.read(MAX_JOB_FILE_SIZE)

def main(args):
    if len(args) != 3:
        print('Usage: %s BLOB.BIN OUT_DIR' % os.path.basename(args[0]))
        exit(1)

    in_file, out_dir = args[1:]

    if not os.path.isdir(out_dir):
        os.makedirs(out_dir)
        print('[*] Created output folder: ' + os.path.abspath(out_dir))

    # The magic string is a unicode comment that's preceded by its size
    # (including the bytes for the size)
    magic_string = ('%c%s' % (len(JOB_COMMENT)+1, JOB_COMMENT)).encode('utf-16-le')

    i = 1
    with open(args[1], 'r+b') as i_file:
        print('[*] Searching...')
        mm = mmap.mmap(i_file.fileno(), 0)
        offset = mm.find(magic_string)
        while offset >= 0:
            job_offset = find_beginning(mm, offset)
            if job_offset:
                print('[+] Found hit: 0x%x' % job_offset)
                data = carve_out(mm, job_offset)
                o_file = file(os.path.join(out_dir, 'carved_%s.job' % i), 'wb')
                o_file.write(data)
                o_file.close()
                i += 1
            else:
                print('[-] Failed verification')
            mm.seek(offset+1)
            offset = mm.find(magic_string)
        print('[*] Done')

if __name__ == '__main__':
    main(sys.argv)


# File: nn.py
#
from math import sqrt

import torch
from torch.nn import Module, Parameter, init

ACTIVATIONS = {'tanh': torch.nn.Tanh, 'relu': torch.nn.ReLU}

class LNMLP(torch.nn.Module):

    def __init__(self, input_size, hidden_sizes, output_size, activation='relu', gain=1.0,
                 ln=False):
        self._hidden_sizes = hidden_sizes
        self._gain = gain
        self._ln = ln
        super().__init__()
        if len(hidden_sizes) > 0:
            activation = ACTIVATIONS[activation]
            layers = [torch.nn.Linear(input_size, hidden_sizes[0])]
            layers.append(activation())
            if ln:
                layers.append(torch.nn.LayerNorm(hidden_sizes[0]))

            for i in range(len(hidden_sizes) - 1):
                layers.append(torch.nn.Linear(hidden_sizes[i], hidden_sizes[i + 1]))
                layers.append(activation())
                if ln:
                    layers.append(torch.nn.LayerNorm(hidden_sizes[i + 1]))

            layers.append(torch.nn.Linear(hidden_sizes[-1], output_size))
        else:
            layers = [torch.nn.Linear(input_size, output_size)]

        self._layers = layers
        self.mlp = torch.nn.Sequential(*layers)
        self.reset_params(gain=gain)

    def forward(self, inp):
        return self.mlp(inp)

    def reset_params(self, gain=1.0):
        self.apply(lambda x: weights_init_mlp(x, gain=gain))

def weights_init_mlp(m, gain=1.0):
    classname = m.__class__.__name__
    if classname.find('Linear') != -1:
        init_normc_(m.weight.data, gain)
        if m.bias is not None:
            m.bias.data.fill_(0)

def init_normc_(weight, gain=1.0):
    weight.normal_(0, 1)
    weight *= gain / torch.sqrt(weight.pow(2).sum(1, keepdim=True))


# --------------------------------------------
# Plots for cross validation
# Mark van der Plaat
# September 2020 -- Update: November 2021
# --------------------------------------------

# --------------------------------------------
# Import Packages
# --------------------------------------------

# Data manipulation
import pandas as pd
import numpy as np

# Plotting
import matplotlib.pyplot as plt
import seaborn as sns

sns.set(style='whitegrid', font_scale=2)

# Set WD
import os
os.chdir(r'D:\RUG\PhD\Materials_papers\01-Note_on_securitization')

#--------------------------------------------
# Load data
#--------------------------------------------

# Get file names from the directory
lst_directory = os.listdir('Results/Cross_validation')
lst_fitfiles = [file for file in lst_directory if '_fit_' in file]
lst_r2files = [file for file in lst_directory if '_r2_' in file]

# Load data and concat
def readFiles(files):
    data_lst = list()

    for file in files:
        # Load file
        data = pd.read_csv('Results/Cross_validation/' + file, index_col = 0).T

        # Append to list
        data_lst.append(data)

    # Make df and reset index
    dataframe = pd.concat(data_lst)
    dataframe.reset_index(drop = True, inplace = True)

    return dataframe

df_fit = readFiles(lst_fitfiles)
df_r2 = readFiles(lst_r2files)

#--------------------------------------------
# Plot fit indices
#--------------------------------------------

# Plot SRMR (absolute fit)
fig, ax = plt.subplots(figsize=(8,8))
ax.set(ylabel='Value', xlabel = 'SRMR')
sns.violinplot(y = 'srmr',
               data = df_fit,
               inner = None,
               alpha=0.1)
sns.boxplot(y = 'srmr',
            data = df_fit,
            boxprops={'zorder': 2}).set(ylabel = '')
plt.tight_layout()

fig.savefig('Results/Cross_validation/Box_absolute_fit.png')

# Plot RMSEA and RNI (parsimonious fit)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,8))
ax1.set(ylabel='Value', xlabel = 'RMSEA')
ax2.set(ylabel='', xlabel = 'RNI')
sns.violinplot(ax=ax1,
               y = 'rmsea.robust',
               data = df_fit,
               inner = None,
               alpha=0.1)
sns.boxplot(ax=ax1,
            y = 'rmsea.robust',
            data = df_fit,
            boxprops={'zorder': 2}).set(ylabel = '')
sns.violinplot(ax=ax2,
               y = 'rni.robust',
               data = df_fit,
               inner = None,
               alpha=0.1)
sns.boxplot(ax=ax2,
            y = 'rni.robust',
            data = df_fit,
            boxprops={'zorder': 2}).set(ylabel = '')
plt.tight_layout()
fig.savefig('Results/Cross_validation/Box_parsimonious_fit.png')

# Plot CFI and TLI (comparative and relative fit)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16,8))
ax1.set(ylabel='Value', xlabel = 'CFI')
ax2.set(ylabel='', xlabel = 'TLI')
sns.violinplot(ax=ax1,
               y = 'cfi.robust',
               data = df_fit,
               inner = None,
               alpha=0.1)
sns.boxplot(ax=ax1,
            y = 'cfi.robust',
            data = df_fit,
            boxprops={'zorder': 2}).set(ylabel = '')
sns.violinplot(ax=ax2,
               y = 'tli.robust',
               data = df_fit,
               inner = None,
               alpha=0.1)
sns.boxplot(ax=ax2,
            y = 'tli.robust',
            data = df_fit,
            boxprops={'zorder': 2}).set(ylabel = '')
plt.tight_layout()
fig.savefig('Results/Cross_validation/Box_comparative_fit.png')

#--------------------------------------------
# Plot communalities
#--------------------------------------------

# Set labels
lst_vars = df_r2.columns.tolist()
lst_labels = ['Small Bus. Obl. Transf.','Sec. Residential Loans',
              'Sec. Other Assets','Sec. Residential Mortgages',
              'TA Sec. Vehicles' ,
              'Sec. Income', 'Servicing Fees',
              'CDSs Purchased','TA ABCP Conduits',
              'Un. Com. Own ABCP Conduits',
              'Credit Exp. Own ABCP Conduits','Un. Com. Other ABCP Conduits']

# Plot
fig = plt.figure(figsize=(24,24))
for i in range(len(lst_vars)):
    ax = fig.add_subplot(4,3,i+1)
    ax.set(ylabel='', xlabel=lst_labels[i])
    sns.violinplot(ax=ax,
                   y=lst_vars[i],
                   data=df_r2,
                   inner=None,
                   alpha=0.1)
    sns.boxplot(ax=ax,
                y=lst_vars[i],
                data=df_r2,
                boxprops={'zorder': 2}).set(ylabel='')
plt.tight_layout()
fig.savefig('Results/Cross_validation/Box_communalities.png')


from django.contrib import admin

# Register your models here.

from .models import City, OWM, OWMForecast, Yahoo, YahooForecast

class OWMAdmin(admin.ModelAdmin):
    model = OWM
    #list_display = ('wine', 'rating', 'user_name', 'comment', 'pub_date')
    list_filter = ['req_date', 'name', 'city']
    #search_fields = ['comment']

class OWMForecastAdmin(admin.ModelAdmin):
    model = OWMForecast
    #list_display = ('wine', 'rating', 'user_name', 'comment', 'pub_date')
    #list_filter = ['owm']
    search_fields = ['forecast_text']

class YahooAdmin(admin.ModelAdmin):
    model = Yahoo
    #list_display = ('wine', 'rating', 'user_name', 'comment', 'pub_date')
    list_filter = ['req_date', 'name', 'city']
    #search_fields = ['comment']

class YahooForecastAdmin(admin.ModelAdmin):
    model = YahooForecast
    #list_display = ('wine', 'rating', 'user_name', 'comment', 'pub_date')
    #list_filter = ['owm']
    search_fields = ['forecast_text']

admin.site.register(City)
admin.site.register(OWM, OWMAdmin)
admin.site.register(OWMForecast, OWMForecastAdmin)
admin.site.register(Yahoo, YahooAdmin)
admin.site.register(YahooForecast, YahooForecastAdmin)


import pandas as pd
from bs4 import BeautifulSoup
import requests
import re
import os
import calendar
import time
import csv
from fuzzywuzzy import process
from fuzzywuzzy import fuzz

cfbr_folder_path = 'cfbr_scrape\\csv\\'
pos_group_df = pd.read_csv(cfbr_folder_path + 'cfbr_pos_group.csv', header = 0)

header = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.2 (KHTML, like Gecko) Chrome/22.0.1216.0 Safari/537.2'}

remove_char = '([\\t\'\.\,]+)|([^\x00-\x7F]+)| (i+(v*)$|(j|s)r)'

def team_info_cfbr_scrape():
    try:
        team_info_df = pd.read_csv(cfbr_folder_path + 'cfbr_team_info.csv', header = 0)

        modified_time = os.path.getmtime(cfbr_folder_path + 'cfbr_team_info.csv')
        current_time = calendar.timegm(time.gmtime())
        if float(current_time - modified_time)/(60*60*24) > 365:
            pass
        else:
            return team_info_df
    except:
        pass

    team_info_df = pd.DataFrame(columns = ['team_fullname', 'team_schoolname','team_href', 'capacity', 'city'])

    cap_re = re.compile('(?<=cap\. ).*(?=\))')
    city_re = re.compile('(?<=Location:).*(?= )')

    url = 'https://www.sports-reference.com/cfb/schools/'
    req = requests.get(url, headers = header)
    soup = BeautifulSoup(req.content, 'lxml')

    teams = soup.find('table', {'id': 'schools'}).find('tbody').find_all('tr', {'class': None})
    for team in teams:
        max_year = int(team.contents[3].text)
        if max_year > 1980:
            name = team.contents[1].text
            href = team.contents[1].contents[0].get('href')
            print(name,href)

            info_url = 'https://www.sports-reference.com' + href
            info_req = requests.get(info_url, headers = header)
            info_soup = BeautifulSoup(info_req.content, 'lxml')

            school_info = info_soup.find('div', {'id': 'info'}).contents[1].contents[3]
            full_name = school_info.find('h1').contents[1].text
            cap = int(re.sub(',','',cap_re.search(school_info.text).group(0))) if cap_re.search(school_info.text) else None
            city = city_re.search(school_info.text).group(0).strip() if city_re.search(school_info.text) else None

            team_info_df.loc[len(team_info_df),] = [full_name,name,href,cap,city]

    for index, row in team_info_df.iterrows():
        name_split = row['team_schoolname'].split()
        abv = ''
        if len(name_split) > 1:
            for split in name_split:
                abv += split[0]
        abv = abv + ' ' + re.sub(row['team_schoolname'] + ' ','',row['team_fullname'])
        team_info_df.set_value(index,'team_abvname', row['team_fullname'] if (len(name_split) < 2) else abv)

    team_info_df.to_csv(cfbr_folder_path + 'cfbr_team_info.csv', index = False)
    return team_info_df

def roster_scrape(season, team_href, team_name):
    roster_df = pd.DataFrame(columns = ['season', 'team_href', 'team_schoolname', 'player_name', 'player_href', 'class', 'pos'])

    roster_url = 'https://www.sports-reference.com' + team_href + str(season) + '-roster.html'
    for i in range(0,100):
        try:
            roster_req = requests.get(roster_url, headers = header)
            break
        except requests.exceptions.ConnectionError:
            time.sleep(2)
            pass
    roster_soup = BeautifulSoup(roster_req.content, 'lxml')

    try:
        players = roster_soup.find('table', {'id': 'roster'}).find('tbody').find_all('tr', {'class': None})
    except:
        return
    for player in players:
        player_name = player.contents[0].text[:-1] if player.contents[0].text[-1] == '*' else player.contents[0].text.strip()
        if (' ' in player_name):
            player_name = re.sub(remove_char,'',player_name.lower())
        else:
            continue

        try:
            player_href = player.contents[0].contents[0].get('href')
        except:
            player_href = None
        class_ = None if player.contents[1].text == '' else player.contents[1].text
        pos = None if player.contents[2].text == '' else player.contents[2].text

        roster_df.loc[len(roster_df),] = [season, team_href, team_name, player_name, player_href, class_, pos]

    for index2, row2 in roster_df.loc[pd.isnull(roster_df['player_href'])].iterrows():
        match = process.extractOne(row2['player_name'], roster_df.loc[(pd.isnull(roster_df['player_href']) == False),'player_name'])
        if match[1] > 90:
            roster_df.drop(index2, inplace = True)

    roster_df = roster_df.reset_index(drop = True)
    return roster_df

def stats_scrape(roster_df,team_name,skip_stats):
    team_href = roster_df.iloc[0]['team_href']
    season = int(roster_df.iloc[0]['season'])

    stats_url = 'https://www.sports-reference.com' + team_href + str(season) + '.html'
    for i in range(0,100):
        try:
            stats_req = requests.get(stats_url, headers = header)
            break
        except requests.exceptions.ConnectionError:
            time.sleep(2)
            pass
    stats_soup = BeautifulSoup(stats_req.content, 'lxml')

    for table_type in ['passing','rushing_and_receiving','defense_and_fumbles','returns','kicking_and_punting']:
        try:
            table_soup = BeautifulSoup(stats_soup.find('div', {'id': 'all_' + table_type}).contents[-2], 'lxml')
        except:
            continue
        player_rows = table_soup.find('tbody').find_all('tr')
        for player_row in player_rows:
            try:
                player_loc = player_row.contents[1].contents[0].get('href')
                var = 'player_href'
            except:
                player_loc = player_row.contents[1].text
                player_loc = re.sub(remove_char,'',player_loc.lower().strip())
                var = 'player_name'
            if player_loc not in list(roster_df[var]):
                player_href = player_loc if var == 'player_href' else None
                player_name = re.sub(remove_char,'',player_row.contents[1].contents[0].text.lower().strip())\
                    if (var == 'player_href') else player_loc
                if (' ' in player_name):
                    row_list = [season,team_href,team_name,player_name,player_href]
                    roster_df.loc[len(roster_df)] = row_list + [None] * (len(roster_df.columns) - 5)
                else:
                    continue
            index = roster_df.loc[roster_df[var] == player_loc].iloc[0].name
            for stat in player_row.contents[2:]:
                roster_df.set_value(index,stat.get('data-stat'),float(0 if ((stat.text == '') or (skip_stats == True)) else stat.text))

    stats_df = roster_df.drop_duplicates()
    stats_df['dedupe'] = 0
    return stats_df

def active_roster(min_season, current_date):
    try:
        active_roster_df = pd.read_csv(cfbr_folder_path + 'cfbr_active_rosters.csv', header = 0)

        modified_time = os.path.getmtime(cfbr_folder_path + 'cfbr_team_info.csv')
        roster_year = current_date[0] if (current_date[1] > 7) else current_date[0] - 1
        new_roster_time = calendar.timegm(time.strptime(str(roster_year)+str(8),'%Y%m'))
        current_time = calendar.timegm(time.gmtime())

        time_since_modify = current_time - modified_time
        time_since_roster = current_time - new_roster_time
        if time_since_modify > time_since_roster:
            pass
        else:
            return active_roster_df
    except:
        pass

    active_roster_df = pd.DataFrame(columns = ['season','team_href'])

    school_re = re.compile('.*(?=[0-9]{4}\.html)')

    for season in range(min_season, roster_year + 1):
        url = 'https://www.sports-reference.com/cfb/years/' + str(season) + '-standings.html'
        req = requests.get(url, headers = header)
        soup = BeautifulSoup(req.content, 'lxml').find('table', {'id': 'standings'})

        teams = soup.find('tbody').find_all('tr')
        for team in teams:
            try:
                href = school_re.search(team.contents[1].contents[0].get('href')).group(0)
                active_roster_df.loc[len(active_roster_df)] = [season,href]
            except:
                continue

    active_roster_df.to_csv(cfbr_folder_path + 'cfbr_active_rosters.csv', index = False)
    return active_roster_df

def href_dedupe_process(seasons,team_href,match_list):
    temp_df = pd.DataFrame(columns = ['player_href','player_name','season','team_href','class','class_ind','pos_group_list','phys'])
    for href in match_list:
        if 'custom_href' in href:
            continue
        player_url = 'https://www.sports-reference.com' + href
        for i in range(0,100):
            try:
                player_req = requests.get(player_url, headers = header)
                break
            except requests.exceptions.ConnectionError:
                time.sleep(2)
                pass
        player_soup = BeautifulSoup(player_req.content, 'lxml')

        name = player_soup.find('div', {'id': 'info'}).contents[1].contents[1].contents[1].text.strip().lower()
        name = re.sub(remove_char,'',name)
        try:
            pos_list = re.sub(': ','',
                              player_soup.find('div', {'id': 'info'}).contents[1].contents[1].contents[4].contents[2].strip()).split('/')
            pos_group_list = []
            for pos in pos_list:
                if pos in list(pos_group_df['pos']):
                    pos_group_list.append(pos_group_df.loc[pos_group_df['pos'] == pos,'pos_group'].iloc[0])
                else:
                    pos_group_list.append('unknwn')
        except:
            pos_group_list = ['unknwn']
        try:
            phys = True if player_soup.find('div', {'id': 'info'}).contents[1].contents[1].contents[6].text.strip() != '' else False
        except:
            phys = False

        player_tables = player_soup.find_all('tbody')
        for table in player_tables:
            player_rows = table.find_all('tr')
            for player_row in player_rows:
                season = int(player_row.contents[0].text) if player_row.contents[0].text[0] != '*'\
                            else int(player_row.contents[0].text[1:])
                new_team_href = re.sub('[0-9]{4}\.html','',player_row.contents[1].contents[0].get('href'))
                class_ = None if player_row.contents[3].text == '' else player_row.contents[3].text
                class_ind = 0 if class_ == None else 1
                temp_df.loc[len(temp_df)] = [href,name,season,new_team_href,class_,class_ind,pos_group_list,phys]

    rem_href = []
    for href in match_list:
        prev_list = []
        prev_class = None
        for index, row in temp_df.loc[temp_df['player_href'] == href].iterrows():
            if row['class'] in prev_list:
                if row['class'] == prev_class:
                    continue
                else:
                    rem_href.append(href)
            else:
                prev_list.append(row['class'])
                prev_class = row['class']
    temp_df = temp_df.loc[~temp_df['player_href'].isin(rem_href)]

    for season in list(temp_df['season'].drop_duplicates()):
        temp_rows = temp_df.loc[temp_df['season'] == season]
        if len(temp_rows) > 2:
            raise ValueError('too many players in one season')
        elif len(temp_rows) == 2:
            pos_list1, pos_list2 = temp_rows['pos_group_list'].iloc[0], temp_rows['pos_group_list'].iloc[1]
            class1, class2 = temp_rows['class'].iloc[0], temp_rows['class'].iloc[1]
            if ((class1 != class2) & (None not in [class1,class2]))\
                | ((len(list(set(pos_list1) & set(pos_list2))) == 0) & ('unknwn' not in (pos_list1 + pos_list2))):
                raise ValueError('likely not same player')
            else:
                break

    if (len(temp_df['player_href'].drop_duplicates()) == 0):
        winner = match_list[-1]
        losers = list(set(match_list) - set([winner]))
        return winner, losers
    elif len(temp_df['player_href'].drop_duplicates()) == 1:
        winner = temp_df['player_href'].iloc[0]
        losers = list(set(match_list) - set([winner]))
        return winner, losers
    elif len(temp_df['player_href'].drop_duplicates()) > 2:
        if len(temp_df['player_name'].drop_duplicates()) == 2:
            names_hrefs = temp_df[['player_href','player_name']].drop_duplicates()
            names_hrefs = names_hrefs.groupby('player_name').agg(lambda x: x.nunique())
            dedup_href_name = names_hrefs.loc[names_hrefs['player_href'] == 2].index[0]

            temp_df2 = temp_df.loc[temp_df['player_name'] == dedup_href_name]
            href1 = temp_df2['player_href'].drop_duplicates().iloc[0]
            href1_df = temp_df2.loc[temp_df2['player_href'] == href1]
            href2 = temp_df2['player_href'].drop_duplicates().iloc[1]
            href2_df = temp_df2.loc[temp_df2['player_href'] == href2]

            if len(href1_df) > len(href2_df):
                winner = href1
                losers = list(set(match_list) - set([winner]))
            elif len(href1_df) < len(href2_df):
                winner = href2
                losers = list(set(match_list) - set([winner]))
            else:
                raise ValueError('too many player_hrefs2')
            return winner, losers
        elif len(temp_df['player_name'].drop_duplicates()) == 1:
            hrefs_w_class = temp_df.groupby('player_href').agg({"class_ind": lambda x: x.sum()})
            class_max = hrefs_w_class['class_ind'].max()

            if len(hrefs_w_class.loc[hrefs_w_class['class_ind'] == class_max]) == 1:
                winner = hrefs_w_class.loc[hrefs_w_class['class_ind'] == class_max].index[0]
                losers = list(set(match_list) - set([winner]))
                return winner, losers
            elif len(hrefs_w_class.loc[hrefs_w_class['class_ind'] == class_max]) == 2:
                href1 = hrefs_w_class.loc[hrefs_w_class['class_ind'] == class_max].index[0]
                href1_df = temp_df.loc[temp_df['player_href'] == href1]
                href1_name = href1_df['player_name'].iloc[0]

                href2 = hrefs_w_class.loc[hrefs_w_class['class_ind'] == class_max].index[1]
                href2_df = temp_df.loc[temp_df['player_href'] == href2]
                href2_name = href2_df['player_name'].iloc[0]
                pass
            else:
                raise ValueError('too many player_hrefs3')
        else:
            raise ValueError('too many player_hrefs')
    else:
        href1 = temp_df['player_href'].drop_duplicates().iloc[0]
        href1_df = temp_df.loc[temp_df['player_href'] == href1]
        href1_name = href1_df['player_name'].iloc[0]

        href2 = temp_df['player_href'].drop_duplicates().iloc[1]
        href2_df = temp_df.loc[temp_df['player_href'] == href2]
        href2_name = href2_df['player_name'].iloc[0]

    href1_pos_set = set(pos for sublist in href1_df['pos_group_list'] for pos in sublist)
    href2_pos_set = set(pos for sublist in href2_df['pos_group_list'] for pos in sublist)
    if (len(list(set(href1_pos_set - set(['unknwn'])) & set(href2_pos_set - set(['unknwn'])))) == 0)\
        & (href1_pos_set != set(['unknwn'])) & (href2_pos_set != set(['unknwn'])):
        if href1_name == href2_name:
            raise ValueError('same names and mismatch pos_group')
        else:
            raise ValueError('mismatching names and pos_group')
    else:
        if (len(href1_df) == len(href2_df)) | (team_href not in list(href1_df['team_href']))\
                | (team_href not in list(href2_df['team_href'])):
            href1_df = href1_df.loc[href1_df['team_href'] == team_href]
            href2_df = href2_df.loc[href2_df['team_href'] == team_href]
        if len(href1_df) == len(href2_df):
            href1_df = href1_df.loc[pd.isnull(href1_df['class']) == False]
            href2_df = href2_df.loc[pd.isnull(href2_df['class']) == False]

        if len(href1_df) > len(href2_df):
            winner = href1
            losers = list(set(match_list) - set([href1]))
        elif len(href1_df) < len(href2_df):
            winner = href2
            losers = list(set(match_list) - set([href2]))
        elif (True in list(href1_df['phys'])) and (False in list(href2_df['phys'])):
            winner = href1
            losers = list(set(match_list) - set([href1]))
        elif (True in list(href2_df['phys'])) and (False in list(href1_df['phys'])):
            winner = href2
            losers = list(set(match_list) - set([href2]))
        else:
            winner = href2
            losers = list(set(match_list) - set([href2]))
        return winner, losers

def player_stats_deduped(stats_df):
    try:
        matches = pd.read_csv(cfbr_folder_path + 'cfbr_player_matches.csv', header = None)
        skip_list = [set(re.sub('\[|\]|\'|,','',x).split()) for x in matches.loc[pd.isnull(matches[3]) == False,0].head()]
    except:
        skip_list = []

    for min_season in range(stats_df['season'].min(),stats_df['season'].max() - 3):
        seasons = range(min_season,min_season + 5)
        print(seasons)
        for team_href in list(stats_df.loc[stats_df['season'].isin(seasons) & (stats_df['dedupe'] == 0),'team_href'].drop_duplicates()):
            print('\t' + team_href)
            players_df = stats_df.loc[stats_df['season'].isin(seasons) & (stats_df['team_href'] == team_href),
                                      ['player_name','player_href']].drop_duplicates()
            for index, row in players_df.iterrows():
                name_list = [row['player_name']]
                fuzzymatches = process.extract(row['player_name'],
                                   list(players_df.loc[players_df['player_name'] != row['player_name'],'player_name'].drop_duplicates()),
                                   limit = 2,scorer = fuzz.token_set_ratio)
                for fuzzymatch in fuzzymatches:
                    if (fuzzymatch[1] >= 87):
                        name_list += [fuzzymatch[0]]
                match_list = list(players_df.loc[players_df['player_name'].isin(name_list),'player_href'].drop_duplicates())
                if (len(match_list) >= 2) and (set(match_list) not in skip_list):
                    try:
                        winner,losers = href_dedupe_process(seasons,team_href,match_list)
                        error_msg = None
                    except Exception as e:
                        error_msg = str(e)
                        skip_list.append(set(match_list))

                    match = 'likely' if error_msg == None else 'unsure'
                    with open(cfbr_folder_path + 'cfbr_player_matches.csv', 'ab') as matchcsv:
                        matchwriter = csv.writer(matchcsv, delimiter = ',', quotechar = '"', quoting = csv.QUOTE_MINIMAL)
                        matchwriter.writerow([match_list,match,error_msg])

                    if error_msg != None:
                        continue

                    stats_df.loc[(stats_df['season'].isin(seasons) & (stats_df['team_href'] == team_href))
                            & (stats_df['player_href'].isin(losers) | stats_df['player_name'].isin(name_list)),'player_href'] = winner
                    players_df.loc[players_df['player_href'].isin(losers),'player_href'] = winner
                elif (len(match_list) == 1) and (set(match_list) not in skip_list) and (name_list > 1):
                    stats_df.loc[stats_df['season'].isin(seasons) & (stats_df['team_href'] == team_href)
                            & stats_df['player_name'].isin(name_list),'player_href'] = match_list[0]
                    players_df.loc[players_df['player_name'].isin(name_list),'player_href'] = match_list[0]
            stats_df.loc[stats_df['season'].isin(seasons) & (stats_df['dedupe'] == 0) & (stats_df['team_href'] == team_href),'dedupe'] = 1
    return stats_df

def player_stats_scrape(min_season, current_date):
    try:
        player_stats_df = pd.read_csv(cfbr_folder_path + 'cfbr_player_stats.csv', header = 0)
    except:
        player_stats_df = pd.DataFrame(columns = ['season', 'team_schoolname'])

    team_info_df = team_info_cfbr_scrape()
    active_rosters = active_roster(min_season, current_date)

    season = None
    for index, row in active_rosters.sort_values(['season','team_href']).iterrows():
        if int(row['season']) != season:
            season = int(row['season'])
            print(season)
        team_schoolname = team_info_df.loc[team_info_df['team_href'] == row['team_href'],'team_schoolname'].iloc[0]
        if len(player_stats_df.loc[(player_stats_df['team_schoolname'] == team_schoolname) & (player_stats_df['season'] == season),]) < 1:
            print('\t' + team_schoolname)
            roster_df = roster_scrape(season, row['team_href'],team_schoolname)
            try:
                roster_df.iloc[0]
            except:
                continue

            skip_stats = (season >= (current_date[0] - (1 if current_date[1] == 1 else 0)))
            stats_df = stats_scrape(roster_df,team_schoolname,skip_stats)

            if len(player_stats_df) == 0:
                player_stats_df = stats_df
            else:
                player_stats_df = pd.concat([stats_df,player_stats_df])

    player_stats_df = pd.merge(player_stats_df, pos_group_df, how = 'left', on = 'pos')
    player_stats_df['pos_group'] = player_stats_df['pos_group'].fillna('unknwn')

    player_stats_df.loc[:,player_stats_df.columns[7:-2]] = player_stats_df.loc[:,player_stats_df.columns[7:-2]].fillna(0)
    player_stats_df = player_stats_df.drop_duplicates().reset_index(drop = True)
    i, prev_team, prev_name = 1, None, None
    for index, row in player_stats_df.loc[pd.isnull(player_stats_df['player_href'])].sort_values(['player_name','team_href']).iterrows():
        if (row['team_href'] == prev_team) & (row['player_name'] == prev_name):
            pass
        elif (row['player_name'] == prev_name):
            i += 1
            prev_team = row['team_href']
        else:
            i, prev_team, prev_name = 1, row['team_href'], row['player_name']
        player_stats_df.set_value(index,'player_href','custom_href/' + re.sub(' ','-',row['player_name']) + '-' + str(i))
    player_stats_df.to_csv(cfbr_folder_path + 'cfbr_player_stats.csv', index = False)

    dedupe_in = pd.read_csv(cfbr_folder_path + 'cfbr_player_stats.csv', header = 0)
    if len(dedupe_in.loc[dedupe_in['dedupe'] == 0]) > 0:
        dedupe_out = player_stats_deduped(dedupe_in).drop_duplicates().reset_index(drop = True)
        dedupe_out.to_csv(cfbr_folder_path + 'cfbr_player_stats_dedupe.csv', index = False)

        player_stats_df['dedupe'] = 1
        player_stats_df.to_csv(cfbr_folder_path + 'cfbr_player_stats.csv', index = False)
        return dedupe_out
    else:
        return pd.read_csv(cfbr_folder_path + 'cfbr_player_stats_dedupe.csv', header = 0)


questions = {
    'Как дела?': 'Хорошо',
    'Будешь чай?': 'Нет, я машина. Мне нельзя'
}

while True:
    a = input('Задайте вопрос:')
    if a in questions:
        print(questions[a])
    elif a == 'Пока':
        break

    else:
        print('Такого вопроса нет')


#!../../../../../../bin/python
__author__ = 'eduardo'
import sys, getopt
from lbbulk.lib.csv import CSVFileHandler

class Convert(object):
    """
    Classe para o comando de conversão
    """
    def __init__(self, parameters):
        """
        Construtor
        """
        self.parameters = parameters

    def __doc__(self):
        """
        Documentação dos comandos
        """
        return "Comandos válidos são: " \
               "-i arquivo de entrada " \
               "-o arquivo de saída"

    def csv2json(self):
        """
        Converte o arquivo CSV para o JSON
        """
        csv_handler = CSVFileHandler(**self.parameters)
        csv_handler.csv2json()
        return

if __name__ == '__main__':
    parameters = dict()
    parameters['outfile'] = "/tmp/saida.xml"
    # Faz o parsing dos argumentos
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hi:o:d:a:q:f:", ["ifile=", "ofile=", "help=", "delimiter=", "as_dict=", "quotechar=", "fieldnames="])
    except getopt.GetoptError:
        print('convert.py -i <inputfile> -o <outputfile>')
        sys.exit(2)
    for opt, arg in opts:
        if opt in ('-h', "--help"):
            convert = Convert(parameters=parameters)
            print(convert.__doc__())
            sys.exit()
        elif opt in ("-i", "--ifile"):
            parameters['filename'] = arg
        elif opt in ("-o", "--ofile"):
            parameters['outfile'] = arg
        elif opt in ("-d", "--delimiter"):
            parameters['delimiter'] = arg
        elif opt in ("-a", "--as_dict"):
            parameters['as_dict'] = arg
        elif opt in ("-q", "--quotechar"):
            parameters['quotechar'] = arg
        elif opt in ("-f", "--fieldnames"):
            parameters['fieldnames'] = arg

    # Executa o comando
    convert = Convert(parameters=parameters)
    convert.csv2json()


# -*- coding: utf-8 -*-
import json
import time
import requests
import hashlib
from common                 import config
from bs4                    import BeautifulSoup
from datetime               import datetime
from handle.mongo           import mongo
from updates.upload         import Upload
from handle.datamanager  import Datamanager
from handle.replace         import _replace

class FlixFling():
    def __init__(self, ott_site_uid, ott_site_country, type):
        self._config                = config()['ott_sites'][ott_site_uid]
        self._created_at            = time.strftime("%Y-%m-%d")
        self.mongo                  = mongo()
        self._platform_code         = self._config['countries'][ott_site_country]
        self.titanScraping          = config()['mongo']['collections']['scraping']
        self.titanScrapingEpisodios = config()['mongo']['collections']['episode']
        self.sesion                 = requests.session()
        self.skippedEpis            = 0
        self.skippedTitles          = 0

        if type == 'scraping':
            self._scraping()

        if type == 'return':
            '''
            Retorna a la Ultima Fecha
            '''

            params = {"PlatformCode" : self._platform_code}
            lastItem = self.mongo.lastCretedAt(self.titanScraping, params)
            if lastItem.count() > 0:
                for lastContent in lastItem:
                    self._created_at = lastContent['CreatedAt']

            self._scraping()

    def _scraping(self):
        listaCategorias = [
            "hotflix",
            "subscriber%20picks",
            "animated",
            "classic",
            "concerts",
            "drama",
            "comedy",
            "fitness",
            "action%20&%20adventure",
            "holiday",
            "horror",
            "lgbt",
            "music",
            "musical",
            "mystery",
            "romance",
            "scifi",
            "special%20interests",
            "sports",
            "thriller",
            "western"
        ]

        listPayload = []
        listDBMovie = Datamanager._getListDB(self,self.titanScraping)
        for x in range(0,len(listaCategorias)):
            soup = Datamanager._getSoup(self,"https://www.flixfling.com/browse/{}".format(listaCategorias[x]))

            for item in soup.findAll('div',{'class':'movie_item col-sm-2 col-xs-4'}):
                listDirector = []
                listCast = []
                listGenre = []

                link = item.find('a').get('href')
                contenidoId = str(link).split("/")[2]
                link = "https://www.flixfling.com{}".format(link)
                soupMovie = Datamanager._getSoup(self,link)

                if soupMovie.find('span',{'class':'btn_premium_button'}):
                    buyPrice = None
                    rentPrice = None

                    rentButton = soupMovie.find('span',{'class':'rentBtnPrice'})
                    if rentButton:
                        rentPrice = float(rentButton.text.strip().replace('FROM','').replace(' ','').replace('$',''))

                    buyButton = soupMovie.find('span',{'class':'buyBtnPrice'})
                    if buyButton:
                        buyPrice = float(buyButton.text.strip().replace('FROM','').replace(' ','').replace('$',''))

                    packages = [
                        {
                            'Type' : 'transaction-vod',
                            'RentPrice': rentPrice,
                            'BuyPrice': buyPrice,
                            'Currency': 'USD'
                        }
                    ]

                    if not buyPrice and not rentPrice:
                        continue

                else:
                    packages = [
                        {
                            'Type' : 'subscription-vod'
                        }
                    ]

                print(packages)

                try:
                    title = soupMovie.find('a',{'itemprop':'url'}).find('span').text
                except:
                    continue

                try:
                    duracion = int(int(soupMovie.find('meta',{'property':'video:duration'}).get('content'))/60)
                except:
                    duracion = None

                try:
                    anio = int(str(soupMovie.find('span',{'itemprop':'releasedEvent'}).text)[0:4])
                except:
                    anio = None

                try:
                    int(duracion)
                except:
                    duracion = None

                descripcion = str(soupMovie.find('meta',{'name':'twitter:description'}).get('content'))

                for x in soupMovie.findAll('a',{'itemprop':'director'}):
                    listDirector.append(x.text)

                for x in soupMovie.findAll('a',{'itemprop':'actor'}):
                    listCast.append(x.text)

                for x in soupMovie.findAll('span',{'itemprop':'genre'}):
                    listGenre.append(x.text)

                imageLink = soupMovie.find('img',{'itemprop':'image'}).get('src')
                images = []
                images.append(imageLink)

                payload = {
                'PlatformCode'      : self._platform_code,
                'Id'                : contenidoId,
                'Type'              : 'movie',
                'Title'             : title,
                'CleanTitle'        : _replace(title),
                'OriginalTitle'     : None,
                'Year'              : anio,
                'Duration'          : duracion,
                'Deeplinks'         :  {
                    'Web'     : link,
                    'Android' : None,
                    'iOS'     : None
                },
                'Synopsis'          : descripcion,
                'Rating'            : None,
                'Provider'          : None,
                'Genres'            : listGenre,
                'Cast'              : listCast,
                'Directors'         : listDirector,
                'Availability'      : None,
                'Download'          : None,
                'IsOriginal'        : None,
                'IsAdult'           : None,
                'Image'             : images,
                'Country'           : None,
                'Packages'          : packages,
                'Timestamp'         : datetime.now().isoformat(),
                'CreatedAt'         : self._created_at
                }

                Datamanager._checkDBandAppend(self,payload,listDBMovie,listPayload)

        Datamanager._insertIntoDB(self,listPayload, self.titanScraping)
        '''
        Upload
        '''
        self.sesion.close()
        Upload(self._platform_code, self._created_at, testing=True, has_episodes=False)


"""
Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 231 - 1.

Example 1:

Input: 123
Output: "One Hundred Twenty Three"
Example 2:

Input: 12345
Output: "Twelve Thousand Three Hundred Forty Five"
Example 3:

Input: 1234567
Output: "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven"
Example 4:

Input: 1234567891
Output: "One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One"
"""

class Solution:
    def numberToWords(self, num: int) -> str:
        if num == 0: return "Zero"
        less_than_20 = ["", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"]
        tens = ["", "Ten", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"]
        thousands = ["", "Thousand", "Million", "Billion"]

        i = 0
        words = ""

        def helper(n):
            if n == 0: return ""
            if n < 20:
                return " " + less_than_20[n]
            if n < 100:
                return tens[int(n/10)] + helper(n % 10)
            else:
                return less_than_20[int(n/100)] + " Hundred " + helper(n % 100)

        while num > 0:
            if num % 1000 > 0:
                words = helper(num % 1000) + " " + thousands[i] + " " + words
            num = int(num/1000)
            i+=1
        return words.strip()

s = Solution()
print(s.numberToWords(1234567891))

Leetcode/src/Leetcode - Integer to English Words.py


from django import forms
from .models import URL_Short
from django.utils.translation import ugettext_lazy as _

class UrlForm(forms.ModelForm):

    class Meta:
        model = URL_Short
        fields = ('short_url', 'long_url')
        labels = {
            'short_url': _('Token'),
        }
        widgets = {
            'long_url': forms.TextInput(attrs=({'class': 'url-input'})),
            'short_url': forms.TextInput(attrs=({'class': 'url-input'}))
        }

    def __init__(self, *args, **kwargs):
        super(UrlForm, self).__init__(*args, **kwargs)
        self.fields['short_url'].required = False


"""
Structura alternativa IF - este o modalitate prin care putem sa acoperim situatiile in care vrem sa
executam un set de instructiuni sau un altul in functie de rezultatul evaluarii unei conditii

Structura unei decizii (IF):
- Inceputul deciziei (If)
- Ramura din dreapta (TRUE) a deciziei -> reprezentata de primul bloc de cod dupa if
- Marcarea instructiunii alternative, cu conditie aditionala, atunci cand avem mai mult de doua situatii posibile (elif)
- Marcarea isntructiunii alternative finale - ultimul set de instructiuni,
in cazul in care niciuna dintre conditii nu este indeplinita.
Blocul de cod aferent fiecarei ramuri decizionale este marcat de indentare
Ramura decizionala = blocul de cod care se executa in cazul in care conditia este evaluata ca fiind adevarata si respectiv falsa
Indentare = spatiul lasat intre marginea fisierului si linia de cod

FORMA SIMPLA, GENERALA:

                        if expresie_1:
                            instructiune_1
                        elif expresie_2:
                            instructiune_2
                        else:
                            instructiune_3
"""

nr_1 = 5
nr_2 = 7

# IF SIMPLU (Fara alternative)
if nr_1 < nr_2:
    print(f"Am intrat pe ramura IF: {nr_1} este mai mic decat {nr_2}")

# IF CU CONDITIE ADITIONALA ELSE-IF
if nr_1 > nr_2:
    print(f"Am intrat pe ramura IF: {nr_1} este mai mare decat {nr_2}")
elif nr_2 == nr_1:
    print(f"Am intrat pe prima ramura ELSE-IF: {nr_2} este egal cu {nr_1}")
elif nr_2 > nr_1:
    print(f"Am intrat pe a doua ramura ELSE-IF: {nr_2} este strict mai mare decat {nr_1}")

# IF - ELSE (Conditie initiala + alternativa finala)
if nr_1 < nr_2:
    print(f"Am intrat pe ramura IF: {nr_1} este strict mai mic decat {nr_2}")
else:
    print(f"Am intrat pe ramura ELSE: {nr_2} este mai mare (sau egal) decat {nr_1}")

# IF - ELSE-IF - ELSE (Conditie initiala + conditie alternativa  + alternativa finala)
nr_3 = 5
nr_4 = 5

if nr_3 < nr_4:
    print(f"Am intrat pe ramura IF: {nr_3} este mai mic decat {nr_4}")
elif nr_3 > nr_4:
    print(f"Am intrat pe ramura ELSE-I: {nr_3} este mai mare decat {nr_4}")
else:
    print(f"Am intrat pe ramura ELSE: {nr_3} este egal cu {nr_4}")

# CONCEPTUL NESTED IF (ÎMBRICAT, ADICĂ IF ÎN IF)

# IF CU CONDITIE ADITIONALA ELSE-IF
if nr_1 < nr_2:
    print(f"Am intrat pe ramura IF: {nr_1} este mai mic decat {nr_2}")
    if nr_1 % 2 == 0:
        print(f"{nr_1} este numar par")
    else:
        print(f"{nr_1} este numar impar")
elif nr_2 < nr_1:
    print(f"Am intrat pe ramura ELSE-IF {nr_2} este strict mai mic decat {nr_1}")

"""
Exercitiu:
Intre lunile noiembrie (inclusiv) si februarie (inclusiv), factura la curent se va calcula dupa urmatoarea formula:
- 0.68 lei pe kWh daca s-au consumat sub 100kWh pe luna
- 0.8 lei pe kWh daca s-au consumat intre 100kWh si 255kWh pe luna
- 1 leu pe kWh daca s-au consumat peste 250kWh
- in restul anului, pretul este unic, de 0.7 lei pe kWh

Daca persoana care plateste factura are peste 65 (inclusiv) de ani, i se aplica o reducere de 10%.

Se va scrie un program care face urmatoarele:
- citeste luna curenta reprezentata printr-un nr de la 1 la 12
- citeste varsta persoanei care plateste factura
- citeste numarul de kWh consumati pe luna respectiva
- afiseaza pretul total a facturii si daca s-a aplicat reducerea
"""

luna = int(input("Introduceti numarul lunii pentru care se plateste factura: "))
varsta = int(input("Introduceti varsta: "))
consum = float(input("Introduceti nr-ul de kWh: "))

valoare_factura = 0  # declaram variabila si o initializam cu 0
if luna >= 11 or luna <= 2:
    if consum < 100:
        valoare_factura = consum * 0.68
    elif 100 <= consum < 255:
        valoare_factura = consum * 0.8
    else:
        valoare_factura = consum * 1
else:
    valoare_factura = consum * 0.7

if varsta >= 65:
    valoare_factura -= valoare_factura * 0.1  # valoare_factura = valoare_factura - (valoare_factura * 0.1)
    print("Ati beneficiat de o reducere de 10%")

print(f"Factura este de {valoare_factura} RON")


from collections import namedtuple
from random import choice

import os

import scipy.spatial.distance
import spotipy
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

import pickle

TrackInfo = namedtuple('TrackInfo', ['id', 'track_href', 'danceability', 'energy', 'loudness', 'speechiness',
                                     'acousticness', 'instrumentalness', 'liveness', 'valence', 'tempo'])

PARAMETERS_DNN = ['danceability', 'energy', 'loudness', 'speechiness', 'acousticness',
                  'instrumentalness', 'liveness', 'valence']

train = True
training_epochs = 40000
hidden_layer_size = 150
display_times = 10
display_step = 2000
evaluation_step = 500
batch_size = 50

def load_data():
    with open('tracks.db', 'rb') as file:
        tracks = pickle.load(file)

    with open('playlists.db', 'rb') as file:
        playlists = pickle.load(file)

    return tracks, playlists

def generate_training_data(playlists, songs):
    x = []
    y = []

    for playlist in filter(lambda pl: len(pl) > 1, playlists.values()):
        for i in range(len(playlist) - 1):
            id = playlist[i]

            song = [songs[id]._asdict()[category] for category in PARAMETERS_DNN]
            next_song = [songs[id]._asdict()[category] for category in PARAMETERS_DNN]

            x.append(song)
            y.append(next_song)

    return np.array(x), np.array(y)

def get_closest_song(prediction, songs):
    nodes = np.asarray(songs)
    dist_2 = scipy.spatial.distance.cdist(np.array([prediction]), nodes, 'euclidean')
    return np.argmin(dist_2), np.min(dist_2)

input = tf.placeholder(tf.float32, shape=(None, len(PARAMETERS_DNN)))
correct_output = tf.placeholder(tf.float32, shape=(None, len(PARAMETERS_DNN)))

weight_1 = tf.Variable(tf.random_normal(shape=(len(PARAMETERS_DNN), hidden_layer_size)))
bias_1 = tf.Variable(tf.random_normal(shape=(1, hidden_layer_size)))

layer1 = tf.matmul(input, weight_1) + bias_1

h_weight_2 = tf.Variable(tf.random_normal(shape=(hidden_layer_size, hidden_layer_size)))
h_bias_2 = tf.Variable(tf.random_normal(shape=(1, hidden_layer_size)))

layer2 = tf.matmul(layer1, h_weight_2) + h_bias_2

h_weight_3 = tf.Variable(tf.random_normal(shape=(hidden_layer_size, len(PARAMETERS_DNN))))
h_bias_3 = tf.Variable(tf.random_normal(shape=(1, len(PARAMETERS_DNN))))

layer3 = tf.matmul(layer2, h_weight_3) + h_bias_3

loss = tf.div(tf.reduce_sum(tf.nn.l2_loss(layer3 - correct_output)), batch_size)
optimizer = tf.train.AdamOptimizer(learning_rate=0.0005, beta1=0.9, beta2=0.9999).minimize(loss)

init = tf.global_variables_initializer()
tracks, playlists = load_data()
train_x, train_y = generate_training_data(playlists, tracks)

with tf.Session() as sess:
    saver = tf.train.Saver()
    best_loss = float('inf')

    sess.run(init)

    if train:
        datapoints = []

        for epoch in range(training_epochs):
            random_ids = np.random.random_integers(0, len(train_x)-1, 50)

            training_input = train_x[random_ids]
            training_output = train_y[random_ids]

            sess.run(optimizer, feed_dict={input: training_input, correct_output: training_output})

            if epoch % evaluation_step == 0:
                cost = sess.run(loss, feed_dict={input: train_x, correct_output: train_y})
                datapoints.append(cost)

                if cost < best_loss:
                    saver.save(sess, os.getcwd() + '/best_model.ckpt')
                    best_loss = cost

            if epoch % display_step == 0:
                cost = sess.run(loss, feed_dict={input: train_x, correct_output: train_y})

                print('Epoch: {0}, loss: {1:.9f}'.format(epoch, cost))

        print('Optimization finished! Best loss: {}'.format(best_loss))

        plt.semilogy(datapoints)
        plt.show()

    spotify = spotipy.Spotify()
    saver.restore(sess, os.getcwd() + '/best_model.ckpt')
    tracks_modified = [[track._asdict()[category] for category in PARAMETERS_DNN] for track in tracks.values()]

    songs = choice(list(playlists.values()))
    previous_song = tracks[choice(songs)]
    print('Starting to create playlist out of {}'.format(spotify.track(previous_song.id)['name']))

    previous_songs = []

    for i in range(display_times):
        network_input = [previous_song._asdict()[category] for category in PARAMETERS_DNN]
        previous_songs.append(network_input)

        pred = sess.run(layer3, feed_dict={input: [network_input]})
        predicted_song, cost = get_closest_song(np.squeeze(pred), [x for x in tracks_modified if x not in previous_songs])

        track_key = list(tracks.keys())[np.asscalar(predicted_song)]

        predicted = spotify.track(track_key)
        previous_song = tracks[track_key]

        print('{}: {} (loss {:.9}) - {}'.format(i+1, predicted['name'], cost, predicted['external_urls']['spotify']))


# (1) https://openaccess.thecvf.com/content_ECCV_2018/papers/Rahaf_Aljundi_Memory_Aware_Synapses_ECCV_2018_paper.pdf
# (2) https://openaccess.thecvf.com/content_CVPR_2019/papers/Aljundi_Task-Free_Continual_Learning_CVPR_2019_paper.pdf

import torch
from tfm import ImgData
from torch.nn.functional import binary_cross_entropy_with_logits as bce
import torch.nn as nn

def compute_importance(model:nn.Module,
                      data:ImgData,
                      device:str,
                      normalize:bool = True) -> dict:
  """
  Importance estimation as described in the paper
  https://openaccess.thecvf.com/content_ECCV_2018/papers/Rahaf_Aljundi_Memory_Aware_Synapses_ECCV_2018_paper.pdf

  """

  grads = {name:torch.zeros(param.shape,device=device) \
        for name,param in model.named_parameters() if param.requires_grad}
  N = len(data)

  for X,y in data:
    X = X.unsqueeze(0).to(device)
    model.eval()
    output = torch.sigmoid(model(X)) # compute output of learned function
    model.zero_grad() # reset gradient to zero
    output.backward() # compute gradient of output
    # Gradients are accumulated over the given data points to obtain importance weight Ωij for parameter θij
    for name,param in model.named_parameters():
      if param.requires_grad:
        grads[name] += param.grad.abs() # update gradient for each param

  # average gradient is obtained for each parameter
  omega = {name:sum_grad/N for name,sum_grad in grads.items()} # calculate gradient mean

  # vector normalization with l2 norm
  if normalize:
    omega_norm = torch.sqrt(sum([mean_grad.pow(2).sum() for name,mean_grad in omega.items()]))
    omega = {name:mean_grad/omega_norm for name,mean_grad in omega.items()}

  return omega

def update_importance(prev_omega,
                      model:nn.Module,
                      data:ImgData,
                      device:str,
                      normalize:bool = True) -> dict:
  """
  Importance updating as described in the paper
  https://openaccess.thecvf.com/content_CVPR_2019/papers/Aljundi_Task-Free_Continual_Learning_CVPR_2019_paper.pdf

  """
  # compute Ω for new domain
  curr_omega = compute_importance(model,data,device,normalize=True)
  # cumulative moving average
  for name in curr_omega.keys():
    curr_omega[name] = (prev_omega[name] + curr_omega[name])/2

    return curr_omega

class MASLoss(nn.Module):
  """
  Complete loss function as described in the paper
  https://openaccess.thecvf.com/content_ECCV_2018/papers/Rahaf_Aljundi_Memory_Aware_Synapses_ECCV_2018_paper.pdf

  """
  def __init__(self,
              model:nn.Module,
              lambd:float,
              importance:dict,
              loss_function:nn.Module) -> None:

    super().__init__()
    self.model = model
    self.old_params = {name:param.data.detach().clone() for name,param in model.named_parameters() if param.requires_grad}
    self.lambd = lambd # regularization hyper-parameter λ
    self.omega = importance
    self.loss = loss_function

  def forward(self,
             input:torch.Tensor,
             target:torch.Tensor) -> torch.Tensor:

    reg = 0. # regularization term
    for name,param in self.model.named_parameters():
      if param.requires_grad:
        reg += (self.omega[name]*(param - self.old_params[name])**2).sum()

    return self.loss(input,target) + self.lambd*reg


import numpy as np
from pyevolver.ctrnn import BrainCTRNN
import matplotlib.pyplot as plt
from tqdm import tqdm

def run_ctrnn_and_get_states(brain, run_duration, input_func=None, plot=False):
    # simulate_plot_output brain
    step_size = brain.step_size
    num_steps = int(run_duration/step_size)
    num_states = len(brain.states)
    states_series = np.zeros((num_steps, num_states))
    state_derivative_series = np.zeros((num_steps, num_states))
    time_series = np.arange(step_size, run_duration+step_size, step_size)
    for step in range(num_steps):
        states_series[step] = brain.get_state()
        if input_func is not None:
            brain.input = input_func(brain.num_neurons)
        brain.euler_step()
        state_derivative_series[step] = brain.dy_dt
        step += 1

    # plot output
    if plot:
        for i in range(brain.num_neurons):
            plt.plot(np.arange(0,run_duration+step_size,step_size),states_series[:,i])
        plt.xlabel('Time')
        plt.ylabel('Neuron states')
        plt.show()
    return time_series, states_series, state_derivative_series

def plot_phase_space_traj():
    """ Plot the phase portrait
    We'll use matplotlib quiver function, which wants as arguments the grid of x and y coordinates,
    and the derivatives of these coordinates.
    In the plot we see the locations of stable and unstable equilibria,
    and can eyeball the trajectories that the system will take through
    the state space by following the arrows.
    """
    # Define the sample space (plotting ranges)
    # ymin = np.amin(net_history)
    # ymax = np.amax(net_history)
    ymin = -5
    ymax = 5
    num_steps = 10
    y1 = np.linspace(ymin, ymax, num_steps)
    y2 = np.linspace(ymin, ymax, num_steps)

    plt.figure(figsize=(10,6))

    pbar = tqdm(total=num_steps**2)
    input_func = np.zeros

    for i in y1:
        for j in y2:
            # print(i,j)
            pbar.update()
            brain = BrainCTRNN(
                num_neurons=2,
                step_size=0.01,
                states = np.array([i, j]),
                taus=np.array([1.0, 1.0]),
                gains=np.array([1.0, 1.0]),
                biases=np.array([-2.75, -1.75]),
                weights=np.array([4.5, -1, 1, 4.5]) # will be converted to np.array([[4.5, -1], [1, 4.5]])
            )
            # brain.input = np.array([1.,1.])
            brain.compute_output()
            # input_func = np.zeros
            _, states_series, _ = run_ctrnn_and_get_states(brain, 100, input_func)
            plt.plot(states_series[:, 0], states_series[:, 1], color='r')
            plt.scatter(states_series[0][0], states_series[0][1], color='orange', zorder=1)

    plt.xlabel('y1', fontsize=14)
    plt.ylabel('y2', fontsize=14)
    plt.title('Multi-trajectory for agent brain', fontsize=16)
    plt.show()

def test_control_phase_plot():
    from control.phaseplot import phase_plot

    state_ctrnn_brain = {} # state_tuple -> state_derivative_series of ctrnn_brain
    input_func = np.zeros

    step_size = 0.1
    run_duration = 1
    num_steps = int(run_duration/step_size)

    time_series = np.arange(0, run_duration, step_size)

    xmin = -5
    xmax = 5
    xsteps = 10

    x0 = np.linspace(xmin, xmax, xsteps)
    x1 = np.linspace(xmin, xmax, xsteps)

    def get_ctrnn_brain_dydt(state_tuple, t):
        if type(state_tuple) == np.ndarray:
            state_tuple = tuple(state_tuple.tolist())
        if state_tuple in state_ctrnn_brain:
            result =  state_ctrnn_brain[state_tuple]
        else:
            ctrnn = \
                BrainCTRNN(
                    num_neurons=2,
                    step_size=step_size,
                    states = np.array(state_tuple),
                    taus=np.array([1.0, 1.0]),
                    gains=np.array([1.0, 1.0]),
                    biases=np.array([-2.75, -1.75]),
                    weights=np.array([4.5, -1, 1, 4.5]), # will be converted to np.array([[4.5, -1], [1, 4.5]])
                )
            ctrnn.compute_output()
            _, _, state_derivative_series = run_ctrnn_and_get_states(ctrnn, run_duration, input_func)
            result = state_ctrnn_brain[state_tuple] = state_derivative_series
        idx = (np.abs(time_series - t)).argmin()
        return result[idx]

    phase_plot(
        get_ctrnn_brain_dydt,
        [-5, 5, 10],
        [-5, 5, 10],
        # X0=[(i,j) for i in x0 for j in x1],
        # scale=5,
        T=time_series,
        # timepts=[0,1]
    )
    plt.show()

if __name__ == "__main__":
    # run_test_params(250)
    # run_test_random(2,250)
    # run_test_random(5, 250)
    # plot_phase_space_traj()
    test_control_phase_plot()


import cv2
import numpy as np

img = cv2.imread("img.png")

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

_,valor = cv2.threshold(gris, 50, 255, cv2.THRESH_BINARY)

kernel = np.ones((3,3), np.uint8)
figura = cv2.morphologyEx(valor, cv2.MORPH_CLOSE, kernel)
contorno, _ = cv2.findContours(
    figura,
    cv2.RETR_EXTERNAL,
    cv2.CHAIN_APPROX_SIMPLE)

lista_contornos = []

for index in range(len(contorno)):
    area = cv2.contourArea(contorno[index])
    if area > 500:
        objecto = contorno[index]
        lista_contornos.append(objecto)

cv2.drawContours(img, contorno[index], -1, (0,255,0), 5)
cv2.namedWindow("original", cv2.WINDOW_NORMAL)
cv2.imshow("original", img)

cv2.waitKey()
cv2.destroyAllWindows()


# -*-coding:utf-8 -*-
__author__ = 'Yemilice_lau'
import threading
import time
import random
def work_func():
    print('worker thread is %s' % threading.current_thread())
    random.seed()
    time.sleep(random.random())
    print('worker finished at %s' % threading.current_thread())
# def simple_thread_done():
#     for i in range(10):
#         threading.Thread(target=work_func()).start()
def worker_func_loop(lock):
    lock.acquire()
    work_func()
    lock.release()
gLock = threading.Lock()

def thread_worker():
    for i in range(10):
        threading.Thread(target=worker_func_loop,args=[gLock]).start()
if __name__ == '__main__':
    thread_worker()
    # worker_func_loop()


# 个人主页功能
__author__ = 'zhangxp'
import tornado.web
from controller.base import BaseHandler
from tornado import gen

# 发帖子
class PublishHandler(BaseHandler):
    @tornado.web.asynchronous
    @gen.coroutine
    def get(self, *args, **kwargs):
        cursor = self.db.post_category.find()
        colls = []
        i = 0
        while (yield cursor.fetch_next):
                coll = cursor.next_object()
                colls.append({})
                for k,v in coll.items():
                    colls[i][k]=v
                print(colls)
                i+=1
        self.render("Publish.html",Message="欢迎发帖",colls = colls)
    @tornado.web.asynchronous
    @gen.coroutine
    def post(self, *args, **kwargs):
        username = self.get_current_user()
        print(username)
        articleTitle = self.get_body_argument("articleName")
        print(articleTitle)
        articleText = self.get_body_argument("editor")
        print(articleText)
        articleCategory = self.get_body_argument("articleCategory")
        print(articleCategory)
        # "sername":发表用户姓名
        # "ArticleTitle":文章标题
        # "ArticleText":文章内容
        # "ZambisCount":赞次数
        # "CollectionCount":收藏次数
        # "Comment":[{"name":"","text":""}]
        yield self.db.user_publish.insert({"username":username,
                                           "ArticleTile":articleTitle,
                                           "ArticleText":articleText,
                                           "ArticleCategory":articleCategory,
                                           "ZambisCount":0,
                                           "CollectionCount":0,
                                           "Comment":[{}],
                                           "PublishTime":self.get_current_time()})
        self.render("Publish.html",Message = "发表成功!",colls = self.category_colls)


import Crossfire
import random

def sell_is_restricted():
    map = Crossfire.WhoAmI().ReadKey("punish_sell_in")
    if map == "":
        return 1

    current = Crossfire.WhoIsActivator().Map.Path

    if len(current) < len(map):
        return 0

    if map == current[0:len(map)]:
        return 1

    return 0

def handle_sell():
    if not sell_is_restricted():
        return

    guard = None

    map = Crossfire.WhoIsActivator().Map
    for h in range(0, map.Height):
        for w in range(0, map.Width):
            top = map.ObjectAt(w, h)
            while top != None:
                if top.Type == 69:
                    count = random.randint(2, 8)
                    while count > 0:
                        guard = Crossfire.CreateObjectByName("guard")
                        guard.StandStill = 0
                        guard.Unaggressive = 0
                        map.InsertAround(guard, w, h)
                        count = count - 1
                    break
                top = top.Above

    if guard != None:
        Crossfire.WhoIsActivator().Message("You thief!")
    Crossfire.SetReturnValue(1)

handle_sell()


def main():
    filename = "input.txt"
    trees = 0
    x = 0
    y = 0
    dx = 3
    dy = 1
    with open(filename) as file:
        for line in file:
            line = line.rstrip()
            if(y and y % dy == 0):
                x += dx
                if(line[x%len(line)] == '#'):
                    trees += 1
            y += 1
    print(trees)

if __name__ == "__main__":
    main()


import appdaemon.plugins.hass.hassapi as hass

#
# Notification system
#
# Args:
#
# Release Notes
#
# Version 1.0:
#   Initial Version

class BaseNotifyTarget():
  def notify(self, hass, message, person='*'):
    hass.log('notifying person {} with message: {}'.format(person, message))

class AliceNotifyTarget(BaseNotifyTarget):
  alice = 'media_player.yandex_station'
  def notify(self, hass, message, person='*'):
    msg = message
    if person == 'danil':
      msg = "Данил, " + msg
    elif person == 'sveta':
      msg = "Света, " + msg
    hass.log('notifying over alice person {} with message: {}'.format(target, message))
    self.say(hass, msg)

  def say(self, hass, message):
    hass.log('message = {}'.format(message))
    hass.call_service('media_player/play_media', entity_id=self.alice, media_content_type='text', media_content_id=message)

class TelegramNotifyTarget(BaseNotifyTarget):
  target_default = 'telegram'
  target_sveta = 'telegram_sveta'
  target_danil = 'telegram_monster'

  def notify(self, hass, message, person='*'):
    target = self.target_default
    if person == 'danil':
      target = self.target_danil
    elif person == 'sveta':
      target = self.target_sveta

    hass.log('notifying over telegram person {} with message: {}'.format(target, message))
    hass.notify(message, name=target)

class Notification(hass.Hass):
  home_targets = [AliceNotifyTarget()]
  away_targets = [TelegramNotifyTarget()]

  def initialize(self):
    self.log('Init')

  def notify_person(self, message, target='*', repeat = 1, delay = 60, onEvent = '', at=None):
    notifyTarget = None
    away_mode = True
    if (away_mode):
      notifyTarget = self.away_targets[0]
    else:
      notifyTarget = self.home_targets[0]

    self.log('message: {}'.format(message))
    notifyTarget.notify(self, message, person=target)


from sys import argv
import math
import sys
# set a global counter
inv_count = 0
def inversions(numbers):
    # establish the base case
    global inv_count
    if len(numbers) == 2:
        new_numbers = []
        if numbers[0] < numbers[1]:
            new_numbers.append(numbers[0])
            new_numbers.append(numbers[1])
            return new_numbers
        elif numbers[0] > numbers[1]:
            new_numbers.append(numbers[1])
            new_numbers.append(numbers[0])
            # count inversions
            inv_count += 1
            return new_numbers
    elif len(numbers) == 1:
        new_numbers = []
        new_numbers.append(numbers[0])
        return new_numbers

    else:
        first_half = inversions(numbers[0:math.ceil(len(numbers) / 2)])
        second_half = inversions(numbers[math.ceil(len(numbers) / 2):])
        i = j = k = 0
        results = [0] * len(numbers)
        # merge two arrays
        while i < len(first_half) and j < len(second_half):
            if first_half[i] < second_half[j]:
                results[k] = first_half[i]
                i += 1
            elif first_half[i] > second_half[j]:
            	# count the split inversions
                inv_count = inv_count + len(first_half) - i
                results[k] = second_half[j]
                j += 1
            k += 1
        while i < len(first_half):
            results[k] = first_half[i]
            i += 1
            k += 1
        while j < len(second_half):
            results[k] = second_half[j]
            j += 1
            k += 1
    return results

def main():
    if len(sys.argv) == 2:
        texts = sys.argv[1]
        numbers = []
        # read the numbers from the file and store them in a list
        with open(texts, 'r') as file:
            for line in file:
                numbers.append(line.rstrip("\n"))
        # convert strings to numbers
        numbers = [int(i) for i in numbers]
        i = numbers[0]
        # call the inversion function
        inversions(numbers)
        print(inv_count)
    else:
        print("Error: Add a file")

if __name__ == "__main__":
    main()