# This file is part of django-ca (https://github.com/mathiasertl/django-ca).
#
# django-ca is free software: you can redistribute it and/or modify it under the terms of the GNU General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# django-ca is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along with django-ca. If not, see
# <http://www.gnu.org/licenses/>.
"""Form widgets for django-ca admin interface."""

import logging
import typing
from typing import Any, Dict, Iterable, List, Optional, Tuple, Type, Union

from cryptography import x509
from cryptography.x509.oid import AuthorityInformationAccessOID, ExtensionOID

from django import forms
from django.forms import widgets
from django.utils.translation import gettext as _

from django_ca import ca_settings
from django_ca.constants import (
    EXTENDED_KEY_USAGE_NAMES,
    EXTENSION_DEFAULT_CRITICAL,
    KEY_USAGE_NAMES,
    REVOCATION_REASONS,
)
from django_ca.extensions.utils import certificate_policies_is_simple
from django_ca.utils import ADMIN_SUBJECT_OIDS, format_general_name

log = logging.getLogger(__name__)

ExtensionWidgetsType = Tuple[Union[Type[forms.Widget], forms.Widget], ...]

class DjangoCaWidgetMixin:
    """Widget mixin with some generic functionality.

    This class is *not* intended for MultiWidget instances.

    Classes using this mixin will have a ``django-ca-widget`` CSS class and can define further classes using
    the ``css_classes`` attribute.
    """

    css_classes: Iterable[str] = ("django-ca-widget",)

    def get_css_classes(self) -> typing.Set[str]:
        """Get set of configured CSS classes."""
        css_classes = set()
        for cls in reversed(self.__class__.__mro__):
            css_classes |= set(getattr(cls, "css_classes", set()))
        return css_classes

    def add_css_classes(self, attrs: Dict[str, str]) -> None:
        """Add CSS classes to the passed attributes."""
        css_classes = " ".join(sorted(self.get_css_classes()))

        if "class" in attrs:
            attrs["class"] += f" {css_classes}"
        else:
            attrs["class"] = css_classes

    def get_context(self, *args: Any, **kwargs: Any) -> Dict[str, Any]:
        """Get the context."""
        # TYPEHINT NOTE: This is a mixin, not worth creating a protocol just for this
        ctx: Dict[str, Any] = super().get_context(*args, **kwargs)  # type: ignore[misc]
        self.add_css_classes(ctx["widget"]["attrs"])
        return ctx

class CheckboxInput(DjangoCaWidgetMixin, widgets.CheckboxInput):
    """CheckboxInput that uses the DjangoCaWidgetMixin."""

class MultiWidget(DjangoCaWidgetMixin, widgets.MultiWidget):  # pylint: disable=abstract-method
    """MultiWidget that uses the DjangoCaWidgetMixin."""

    css_classes = ("django-ca-multiwidget",)
    template_name = "django_ca/forms/widgets/multiwidget.html"
    labels: Tuple[Optional[str], ...] = ()
    help_texts: Tuple[Optional[str], ...] = ()

    class Media:
        css = {
            "all": ("django_ca/admin/css/multiwidget.css",),
        }

    def get_context(self, *args: Any, **kwargs: Any) -> Dict[str, Any]:
        """Get the context."""
        # TYPEHINT NOTE: This is a mixin, not worth creating a protocol just for this
        ctx: Dict[str, Any] = super().get_context(*args, **kwargs)
        for widget, label in zip(ctx["widget"]["subwidgets"], self.labels):
            widget["label"] = label
        for widget, help_text in zip(ctx["widget"]["subwidgets"], self.help_texts):
            widget["help_text"] = help_text
        return ctx

class SelectMultiple(DjangoCaWidgetMixin, widgets.SelectMultiple):
    """SelectMultiple field that uses the DjangoCaWidgetMixin."""

class Textarea(DjangoCaWidgetMixin, widgets.Textarea):
    """Textarea field that uses the DjangoCaWidgetMixin."""

class TextInput(DjangoCaWidgetMixin, widgets.TextInput):
    """TextInput field that uses the DjangoCaWidgetMixin."""

class LabeledCheckboxInput(CheckboxInput):
    """CheckboxInput widget that adds a label and wraps everything in a <span />.

    This is necessary because widgets in MultiValueFields don't render with a label."""

    template_name = "django_ca/forms/widgets/labeledcheckboxinput.html"

    def __init__(self, label: str, wrapper_classes: Iterable[str] = tuple()) -> None:
        self.wrapper_classes = tuple(wrapper_classes) + ("labeled-checkbox",)
        self.label = label
        super().__init__()

    def get_context(self, *args: Any, **kwargs: Any) -> Dict[str, Any]:
        ctx = super().get_context(*args, **kwargs)
        ctx["widget"]["wrapper_classes"] = " ".join(self.wrapper_classes)
        ctx["widget"]["label"] = self.label

        # Tell any wrapping widget (like a MultiWidget) that this widget displays its own label.
        ctx["widget"]["handles_label"] = True
        return ctx

    class Media:
        css = {
            "all": ("django_ca/admin/css/labeledcheckboxinput.css",),
        }

class CriticalInput(LabeledCheckboxInput):
    """Widget for setting the `critical` value of an extension."""

    css_classes = ("critical",)
    template_name = "django_ca/forms/widgets/critical.html"

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        self.oid = kwargs.pop("oid")
        super().__init__(label=_("critical"), wrapper_classes=("critical",))

    def get_context(self, *args: Any, **kwargs: Any) -> Dict[str, Any]:
        ctx = super().get_context(*args, **kwargs)
        ctx["widget"]["oid"] = self.oid.dotted_string
        return ctx

class LabeledTextInput(widgets.TextInput):
    """CheckboxInput widget that adds a label and wraps everything in a <span />.

    This is necessary because widgets in MultiValueFields don't render with a label."""

    template_name = "django_ca/forms/widgets/labeledtextinput.html"

    def __init__(self, label: str, *args: Any, **kwargs: Any):
        self.label = label
        super().__init__(*args, **kwargs)

    def get_context(self, *args: Any, **kwargs: Any) -> Dict[str, Any]:
        ctx = super().get_context(*args, **kwargs)
        ctx["widget"]["label"] = self.label
        ctx["widget"]["cssid"] = self.label.lower().replace(" ", "-")
        return ctx

    class Media:
        css = {
            "all": ("django_ca/admin/css/labeledtextinput.css",),
        }

class SubjectTextInput(LabeledTextInput):
    """Widget used in :py:class:`~django_ca.widgets.SubjectWidget`."""

    template_name = "django_ca/forms/widgets/subjecttextinput.html"

class ProfileWidget(widgets.Select):
    """Widget for profile selection."""

    template_name = "django_ca/forms/widgets/profile.html"

    def get_context(self, *args: Any, **kwargs: Any) -> Dict[str, Any]:
        ctx = super().get_context(*args, **kwargs)
        ctx["desc"] = ca_settings.CA_PROFILES[ca_settings.CA_DEFAULT_PROFILE].get(
            "description", ca_settings.CA_PROFILES[ca_settings.CA_DEFAULT_PROFILE].get("desc", "")
        )
        return ctx

    class Media:
        js = (
            "admin/js/jquery.init.js",
            "django_ca/admin/js/extensions.js",
            "django_ca/admin/js/profilewidget.js",
        )

class CustomMultiWidget(widgets.MultiWidget):  # pylint: disable=abstract-method; decompress() in subclasses
    """Wraps the multi widget into a <p> element (base class for other widgets)."""

    template_name = "django_ca/forms/widgets/custommultiwidget.html"

class SubjectWidget(CustomMultiWidget):
    """Widget for a :py:class:`~django_ca.subject.Subject`."""

    def __init__(self, attrs: Optional[Dict[str, str]] = None) -> None:
        _widgets = (
            SubjectTextInput(label=_("Country"), attrs={"placeholder": "2 character country code"}),
            SubjectTextInput(label=_("State")),
            SubjectTextInput(label=_("Location")),
            SubjectTextInput(label=_("Organization")),
            SubjectTextInput(label=_("Organizational Unit")),
            SubjectTextInput(label=_("CommonName"), attrs={"required": True}),
            SubjectTextInput(label=_("E-Mail")),
        )
        super().__init__(_widgets, attrs)

    def decompress(self, value: Optional[x509.Name]) -> List[str]:
        if not value:
            return ["" for attr in ADMIN_SUBJECT_OIDS]

        attr_mapping = {attr.oid: attr.value for attr in value}
        return [attr_mapping.get(oid, "") for oid in ADMIN_SUBJECT_OIDS]  # type: ignore[misc]

class GeneralNamesWidget(Textarea):
    """Widget for a list of :py:class:`~cg:cryptography.x509.GeneralName` instances."""

    def format_value(self, value: Optional[Union[str, Iterable[x509.GeneralName]]]) -> str:
        if isinstance(value, str):  # Received during form rendering for a bound form with errors
            return value
        if not value:
            return ""
        return "\n".join([format_general_name(name) for name in value])

class ExtensionWidget(MultiWidget):  # pylint: disable=abstract-method  # is an abstract class
    """Base class for widgets that display a :py:class:`~cg:cryptography.Extension`.

    Subclasses of this class are expected to set the `extension_widgets` attribute or implement `get_widgets`.
    """

    extension_widgets: Optional[ExtensionWidgetsType]
    oid: x509.ObjectIdentifier
    css_classes = ("extension",)

    def __init__(self, attrs: Optional[Dict[str, str]] = None, **kwargs: Any) -> None:
        sub_widgets = self.get_widgets(**kwargs) + (CriticalInput(oid=self.oid),)
        super().__init__(widgets=sub_widgets, attrs=attrs)

    def get_widgets(self, **kwargs: Any) -> ExtensionWidgetsType:
        """Get sub-widgets used by this widget."""
        if self.extension_widgets is not None:  # pragma: no branch
            return self.extension_widgets
        raise ValueError(  # pragma: no cover
            "ExtensionWidget is expected to either set widgets or implement get_widgets()."
        )

class DistributionPointWidget(ExtensionWidget):
    """Widgets for extensions that use a DistributionPoint."""

    extension_widgets = (
        GeneralNamesWidget(attrs={"class": "full-name", "rows": 3}),
        TextInput(attrs={"class": "relative-name"}),
        GeneralNamesWidget(attrs={"class": "crl-issuer", "rows": 3}),
        SelectMultiple(choices=REVOCATION_REASONS, attrs={"class": "reasons"}),
    )
    labels = (
        _("Full name"),
        _("Relative name"),
        _("CRL issuer"),
        _("Reasons"),
    )

    def decompress(
        self, value: Optional[x509.Extension[x509.CRLDistributionPoints]]
    ) -> Tuple[str, str, str, List[str], bool]:
        full_name = relative_name = crl_issuer = ""
        reasons: List[str] = []

        if value is None:
            return full_name, relative_name, crl_issuer, reasons, EXTENSION_DEFAULT_CRITICAL[self.oid]
        if len(value.value) > 1:
            log.warning(
                "Received multiple DistributionPoints, only the first can be changed in the web interface."
            )

        dpoint = value.value[0]
        if dpoint.relative_name:
            relative_name = dpoint.relative_name.rfc4514_string()
        if dpoint.reasons:
            reasons = [reason.name for reason in dpoint.reasons]

        return dpoint.full_name, relative_name, dpoint.crl_issuer, reasons, value.critical

class MultipleChoiceExtensionWidget(  # pylint: disable=abstract-method  # is an abstract class
    ExtensionWidget
):
    """Base class for widgets that can be displayed with a simple SelectMultiple widget."""

    def get_widgets(  # type: ignore[override]  # we are more specific here
        self, choices: typing.Sequence[Tuple[str, str]]
    ) -> Tuple[widgets.SelectMultiple]:
        return (widgets.SelectMultiple(choices=choices),)

class AuthorityInformationAccessWidget(ExtensionWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.AuthorityInformationAccess` extension."""

    extension_widgets = (
        GeneralNamesWidget(attrs={"class": "ca-issuers", "rows": 3}),
        GeneralNamesWidget(attrs={"class": "ocsp", "rows": 3}),
    )
    help_texts = (
        _("Location(s) of the CA certificate."),
        _("Location(s) of the OCSP responder."),
    )
    labels = (
        _("CA issuers"),
        _("OCSP"),
    )
    oid = ExtensionOID.AUTHORITY_INFORMATION_ACCESS

    def decompress(
        self, value: Optional[x509.Extension[x509.AuthorityInformationAccess]]
    ) -> Tuple[List[x509.GeneralName], List[x509.GeneralName], bool]:
        if value is None:
            return [], [], EXTENSION_DEFAULT_CRITICAL[self.oid]

        ocsp = [
            ad.access_location for ad in value.value if ad.access_method == AuthorityInformationAccessOID.OCSP
        ]
        ca_issuers = [
            ad.access_location
            for ad in value.value
            if ad.access_method == AuthorityInformationAccessOID.CA_ISSUERS
        ]

        return ca_issuers, ocsp, value.critical

class CertificatePoliciesWidget(ExtensionWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.CertificatePolicies` extension."""

    oid = ExtensionOID.CERTIFICATE_POLICIES
    extension_widgets = (
        forms.TextInput(),  # policy identifier
        forms.Textarea(attrs={"rows": 3}),  # practice statement
        forms.Textarea(attrs={"rows": 3}),  # explicit text
    )
    help_texts = (
        "",
        _(
            "A pointers (e.g. URLs) to a certification practice statement (CPS). Separate multiple pointers "
            "with a newline."
        ),
        _("A textual statement that can be displayed to the user"),
    )
    labels = (
        _("Policy Identifier"),
        _("Certificate Practice Statement(s)"),
        _("Explicit Text"),
    )

    def decompress(
        self, value: Optional[x509.Extension[x509.CertificatePolicies]]
    ) -> Tuple[str, str, str, bool]:
        if value is None:
            return "", "", "", EXTENSION_DEFAULT_CRITICAL[ExtensionOID.CERTIFICATE_POLICIES]

        ext_value = value.value

        # COVERAGE NOTE: ruled out by the admin interface
        if certificate_policies_is_simple(ext_value) is False:  # pragma: no cover
            raise ValueError("This widget only supports a simple certificate policy values.")

        policy_information = ext_value[0]
        practice_statement: List[str] = []
        explicit_text = ""
        for policy_qualifier in policy_information.policy_qualifiers:
            if isinstance(policy_qualifier, str):
                practice_statement.append(policy_qualifier)
            else:  # UserNotice object
                explicit_text = policy_qualifier.explicit_text

        return (
            policy_information.policy_identifier.dotted_string,
            "\n".join(practice_statement),
            explicit_text,
            value.critical,
        )

class CRLDistributionPointsWidget(DistributionPointWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.CRLDistributionPoints` extension."""

    help_texts = (
        _("Location(s) where to retrieve the CRL."),
        _(
            "X.500 Relative name to retrieve the CRL. RFC 5280 does not recommend setting this field. Cannot "
            "be set together with Full name."
        ),
        _("Distinguished name of the issuer of the CRL."),
        _("Revocation reasons that are included in this CRL, leave empty for all reasons (recommended)."),
    )
    oid = ExtensionOID.CRL_DISTRIBUTION_POINTS

class ExtendedKeyUsageWidget(MultipleChoiceExtensionWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.ExtendedKeyUsage` extension."""

    oid = ExtensionOID.EXTENDED_KEY_USAGE

    def decompress(self, value: Optional[x509.Extension[x509.ExtendedKeyUsage]]) -> Tuple[List[str], bool]:
        if value is None:
            return [], EXTENSION_DEFAULT_CRITICAL[self.oid]
        choices = [EXTENDED_KEY_USAGE_NAMES[usage] for usage in value.value]
        return choices, value.critical

class FreshestCRLWidget(DistributionPointWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.FreshestCRL` extension."""

    oid = ExtensionOID.FRESHEST_CRL

class KeyUsageWidget(MultipleChoiceExtensionWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.KeyUsage` extension."""

    oid = ExtensionOID.KEY_USAGE

    def decompress(self, value: Optional[x509.Extension[x509.KeyUsage]]) -> Tuple[List[str], bool]:
        if value is None:
            return [], EXTENSION_DEFAULT_CRITICAL[self.oid]
        choices = []

        # Cannot use a list comprehension here, because cryptography raises ValueError for some attributes
        for choice in KEY_USAGE_NAMES:
            try:
                chosen = getattr(value.value, choice)
            except ValueError:
                # cryptography raises ValueError for decipher/encipher_only if key_agreement is not set
                chosen = False

            if chosen:
                choices.append(choice)

        return choices, value.critical

class IssuerAlternativeNameWidget(ExtensionWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.IssuerAlternativeName` extension."""

    extension_widgets = (GeneralNamesWidget(attrs={"rows": 3}),)
    oid = ExtensionOID.ISSUER_ALTERNATIVE_NAME

    def decompress(
        self, value: Optional[x509.Extension[x509.IssuerAlternativeName]]
    ) -> Tuple[List[x509.GeneralName], bool]:
        if value is None:
            return [], EXTENSION_DEFAULT_CRITICAL[self.oid]
        return list(value.value), value.critical

class OCSPNoCheckWidget(ExtensionWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.OCSPNoCheck` extension."""

    extension_widgets = (LabeledCheckboxInput(label=_("included"), wrapper_classes=["include"]),)
    oid = ExtensionOID.OCSP_NO_CHECK

    def decompress(self, value: Optional[x509.Extension[x509.OCSPNoCheck]]) -> Tuple[bool, bool]:
        if value is None:
            return False, EXTENSION_DEFAULT_CRITICAL[self.oid]
        return True, value.critical

class SubjectAlternativeNameWidget(ExtensionWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.IssuerAlternativeName` extension."""

    extension_widgets = (
        GeneralNamesWidget(attrs={"rows": 3}),
        LabeledCheckboxInput(label="Include CommonName"),
    )
    oid = ExtensionOID.SUBJECT_ALTERNATIVE_NAME

    # COVERAGE NOTE: In Django 4.1, decompress is not called if compress() returns a tuple
    #       https://github.com/django/django/commit/37602e49484a88867f40e9498f86c49c2d1c5d7c
    def decompress(
        self,
        value: Optional[
            Union[
                Tuple[List[x509.GeneralName], bool, bool],
                Tuple[x509.Extension[x509.SubjectAlternativeName], bool],
            ]
        ],
    ) -> Tuple[List[x509.GeneralName], bool, bool]:  # pragma: no cover
        if value is None:
            default_cn_in_san = ca_settings.CA_PROFILES[ca_settings.CA_DEFAULT_PROFILE]["cn_in_san"]
            return [], default_cn_in_san, EXTENSION_DEFAULT_CRITICAL[self.oid]

        if len(value) == 3:
            # TYPE NOTE: mypy does not eliminate two-tuple from union in length check
            return typing.cast(Tuple[List[x509.GeneralName], bool, bool], value)

        ext, cn_in_san = value  # type: ignore[misc]
        if ext is None:
            return [], cn_in_san, EXTENSION_DEFAULT_CRITICAL[self.oid]

        return list(ext.value), cn_in_san, ext.critical

class TLSFeatureWidget(MultipleChoiceExtensionWidget):
    """Widget for a :py:class:`~cg:cryptography.x509.TLSFeature` extension."""

    oid = ExtensionOID.TLS_FEATURE

    def decompress(self, value: Optional[x509.Extension[x509.TLSFeature]]) -> Tuple[List[str], bool]:
        if value is None:
            return [], EXTENSION_DEFAULT_CRITICAL[self.oid]
        return [feature.name for feature in value.value], value.critical


# modulo de fecha
import datetime

# fecha actualcon hora minutos y segundos
fecha_actual = datetime.datetime.today()
print(fecha_actual)

# fecha actual hora minutos y segundos
fecha_actual2 = datetime.datetime.now()
print(fecha_actual2)

# obtener año
ano = fecha_actual2.year
print(ano)

# obtener mes
mes = fecha_actual2.month
print(mes)

# obtener dia
dia = fecha_actual2.day
print(dia)

# strftime(param) se le pasa un parametro (ver documentacion) y arroja un resultado
# ver nombre del dia completo ejemplo
dia_completo = fecha_actual2.strftime("%A")
print(dia_completo)

# importando modulo
from mi_modulo import Suma, saludo_cordial

Suma(10, 19)
saludo_cordial("Diana Laura")


# Importação das bibliotecas do SQLAlchemy
import sqlalchemy

from sqlalchemy import Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session

# Criar Conexão com Banco SQLITE
# caso o arquivo de banco não exista, ele será criado
engine = sqlalchemy.create_engine("sqlite:///server.db")
connection = engine.connect()

# Criar sessão com o Banco de Dados
Base = declarative_base(engine)
session = Session()

# Criar tabela no banco de dados, caso não exista
connection.execute("""CREATE TABLE IF NOT EXISTS FUNCIONARIO (
                        ID INTEGER PRIMARY KEY,
                        NOME VARCHAR(255) NOT NULL,
                        IDADE INT NOT NULL,
                        SALARIO FLOAT NOT NULL)
                    """)

class Funcionario(Base):
    __tablename__ = 'FUNCIONARIO'
    id = Column('ID', Integer, primary_key=True, autoincrement=True)
    nome = Column('NOME', String(255), nullable=False)
    idade = Column('IDADE', Integer, nullable=False)
    salario = Column('SALARIO', Float, nullable=False)

    def __init__(self, nome, idade, salario):
        self.nome = nome
        self.idade = idade
        self.salario = salario

'''
lista = []
while True:
    nome = input("Nome do funcionario (Digite 'SAIR' para finalizar): ")
    if nome == 'SAIR':
        break
    idade = int(input('Idade do Funcionário: '))
    salario = float(input('Salário do funcionario: '))
    func = Funcionario(nome, idade, salario)
    lista.append(func)

session.add_all(lista)
session.commit()
'''
lista = session.query(Funcionario).order_by(Funcionario.nome)
for n in lista:
    print('ID: ', n.id)
    print('Nome: ', n.nome)
    print('Idade: ', n.idade)
    print('Salário: ', n.salario)
    print('-------------------------')

print('FUNCIONARIO COM SALARIO SUPERIOR A R$ 2000.00')
lista = session.query(Funcionario).filter(Funcionario.salario > 2000).order_by(Funcionario.nome)
for n in lista:
    print('ID: ', n.id)
    print('Nome: ', n.nome)
    print('Idade: ', n.idade)
    print('Salário: ', n.salario)
    print('-------------------------')


import math
import torch
from torch import nn
from detector.nets.commons import Focus, CBR, SPP, BottleNeckCSP, width_grow, depth_grow, model_scale

def fuse_conv_and_bn(conv, bn):
    # https://tehnokv.com/posts/fusing-batchnorm-and-conv/
    with torch.no_grad():
        # init
        fusedconv = nn.Conv2d(conv.in_channels,
                              conv.out_channels,
                              kernel_size=conv.kernel_size,
                              stride=conv.stride,
                              padding=conv.padding,
                              groups=conv.groups,
                              bias=True).to(conv.weight.device)

        # prepare filters
        w_conv = conv.weight.clone().view(conv.out_channels, -1)
        w_bn = torch.diag(bn.weight.div(torch.sqrt(bn.eps + bn.running_var)))
        fusedconv.weight.copy_(torch.mm(w_bn, w_conv).view(fusedconv.weight.size()))

        # prepare spatial bias
        b_conv = torch.zeros(conv.weight.size(0), device=conv.weight.device) if conv.bias is None else conv.bias
        b_bn = bn.bias - bn.weight.mul(bn.running_mean).div(torch.sqrt(bn.running_var + bn.eps))
        fusedconv.bias.copy_(torch.mm(w_bn, b_conv.reshape(-1, 1)).reshape(-1) + b_bn)

        return fusedconv

default_anchors = [
    [10, 13, 16, 30, 33, 23],
    [30, 61, 62, 45, 59, 119],
    [116, 90, 156, 198, 373, 326],
]
default_strides = [8., 16., 32.]

class YOLOv5Backbone(nn.Module):
    def __init__(self, in_channel=3, depth_multiples=0.33, width_multiples=0.50):
        super(YOLOv5Backbone, self).__init__()
        channel_64 = width_grow(64, width_multiples)
        channel_128 = width_grow(128, width_multiples)
        channel_256 = width_grow(256, width_multiples)
        channel_512 = width_grow(512, width_multiples)
        channel_1024 = width_grow(1024, width_multiples)
        self.out_channels = [channel_256, channel_512, channel_1024]
        self.stem = Focus(in_channel, channel_64, 3)
        self.layer1 = nn.Sequential(
            CBR(channel_64, channel_128, 3, 2),
            BottleNeckCSP(channel_128, channel_128, depth_grow(3, depth_multiples))
        )

        self.layer2 = nn.Sequential(
            CBR(channel_128, channel_256, 3, 2),
            BottleNeckCSP(channel_256, channel_256, depth_grow(9, depth_multiples))
        )

        self.layer3 = nn.Sequential(
            CBR(channel_256, channel_512, 3, 2),
            BottleNeckCSP(channel_512, channel_512, depth_grow(9, depth_multiples))
        )

        self.layer4 = nn.Sequential(
            CBR(channel_512, channel_1024, 3, 2),
            SPP(channel_1024, channel_1024, (5, 9, 13)),
            BottleNeckCSP(channel_1024, channel_1024, depth_grow(3, depth_multiples), shortcut=False)
        )

    def forward(self, x):
        x = self.stem(x)
        x = self.layer1(x)
        c3 = self.layer2(x)
        c4 = self.layer3(c3)
        c5 = self.layer4(c4)
        return [c3, c4, c5]

class YOLOv5Neck(nn.Module):
    def __init__(self, c3, c4, c5, blocks=1):
        super(YOLOv5Neck, self).__init__()
        self.latent_c5 = CBR(c5, c4, 1, 1)
        self.c4_fuse = BottleNeckCSP(c4 * 2, c4, blocks=blocks, shortcut=False)
        self.latent_c4 = CBR(c4, c3)
        self.c3_out = BottleNeckCSP(c3 * 2, c3, blocks=blocks, shortcut=False)
        self.c3_c4 = CBR(c3, c3, 3, 2)
        self.c4_out = BottleNeckCSP(c3 * 2, c4, blocks=blocks, shortcut=False)
        self.c4_c5 = CBR(c4, c4, 3, 2)
        self.c5_out = BottleNeckCSP(c4 * 2, c5, blocks=blocks, shortcut=False)

    def forward(self, xs):
        c3, c4, c5 = xs
        latent_c5 = self.latent_c5(c5)
        f4 = torch.cat([nn.UpsamplingNearest2d(scale_factor=2)(latent_c5), c4], dim=1)
        c4_fuse = self.c4_fuse(f4)
        latent_c4 = self.latent_c4(c4_fuse)
        f3 = torch.cat([nn.UpsamplingNearest2d(scale_factor=2)(latent_c4), c3], dim=1)
        c3_out = self.c3_out(f3)
        c3_c4 = self.c3_c4(c3_out)
        c4_out = self.c4_out(torch.cat([c3_c4, latent_c4], dim=1))
        c4_c5 = self.c4_c5(c4_out)
        c5_out = self.c5_out(torch.cat([c4_c5, latent_c5], dim=1))
        return [c3_out, c4_out, c5_out]

class YOLOv5Head(nn.Module):
    def __init__(self, c3, c4, c5, num_cls=80, strides=None, anchors=None):
        super(YOLOv5Head, self).__init__()
        self.num_cls = num_cls
        self.output_num = num_cls + 5
        if anchors is None:
            anchors = default_anchors
        self.anchors = anchors
        if strides is None:
            strides = default_strides
        self.strides = strides
        assert len(self.anchors) == len(self.strides)
        self.layer_num = len(self.anchors)
        self.anchor_per_grid = len(self.anchors[0]) // 2
        self.grids = [torch.zeros(1)] * self.layer_num
        a = torch.tensor(self.anchors, requires_grad=False).float().view(self.layer_num, -1, 2)
        normalize_anchors = a / torch.tensor(strides, requires_grad=False).float().view(3, 1, 1)
        self.register_buffer("normalize_anchors", normalize_anchors.clone())
        self.register_buffer("anchor_grid", a.clone().view(self.layer_num, 1, -1, 1, 1, 2))
        self.heads = nn.ModuleList(
            nn.Conv2d(x, self.output_num * self.anchor_per_grid, 1) for x in [c3, c4, c5]
        )
        for mi, s in zip(self.heads, strides):  # from
            b = mi.bias.view(self.anchor_per_grid, -1)  # conv.bias(255) to (3,85)
            b[:, 4] += math.log(8. / (640. / s) ** 2)  # obj (8 objects per 640 image)
            b[:, 5:] += math.log(0.6 / (self.num_cls - 0.99))  # cls
            mi.bias = torch.nn.Parameter(b.view(-1), requires_grad=True)

    def forward(self, xs):
        z = list()
        assert len(xs) == self.layer_num
        for i in range(self.layer_num):
            xs[i] = self.heads[i](xs[i])
            bs, _, ny, nx = xs[i].shape
            xs[i] = xs[i].view(bs, self.anchor_per_grid, self.output_num, ny, nx).permute(0, 1, 3, 4, 2).contiguous()
            if not self.training:  # inference
                if self.grids[i].shape[2:4] != xs[i].shape[2:4]:
                    self.grids[i] = self._make_grid(nx, ny).to(xs[i].device)
                # grid: bs,anchor_per_grid,ny,nx,2
                # xs[i]:bs,anchor_per_grid,ny,nx,output
                y = xs[i].sigmoid()
                y[..., 0:2] = (y[..., 0:2] * 2. - 0.5 + self.grids[i]) * self.strides[i]
                y[..., 2:4] = (y[..., 2:4] * 2) ** 2 * self.anchor_grid[i]
                z.append(y.view(bs, -1, self.output_num))
        return (xs, self.normalize_anchors) if self.training else torch.cat(z, 1)

    @staticmethod
    def _make_grid(nx=20, ny=20):
        yv, xv = torch.meshgrid([torch.arange(ny), torch.arange(nx)])
        return torch.stack((xv, yv), 2).view((1, 1, ny, nx, 2)).float()

class YOLOv5(nn.Module):
    def __init__(self, in_channel=3,
                 num_cls=80,
                 scale_name="s",
                 strides=None,
                 anchors=None):
        super(YOLOv5, self).__init__()
        depth_multiples, width_multiples = model_scale(scale_name)
        self.backbones = YOLOv5Backbone(in_channel, depth_multiples, width_multiples)
        c3, c4, c5 = self.backbones.out_channels
        self.neck = YOLOv5Neck(c3, c4, c5, blocks=depth_grow(3, depth_multiples))
        self.head = YOLOv5Head(c3, c4, c5, num_cls=num_cls, strides=strides, anchors=anchors)

    def forward(self, x):
        x = self.head(self.neck(self.backbones(x)))
        return x

    def fuse(self):  # fuse model Conv2d() + BatchNorm2d() layers
        print('Fusing layers... ')
        for m in self.modules():
            if type(m) is CBR:
                m._non_persistent_buffers_set = set()  # pytorch 1.6.0 compatability
                m.conv = fuse_conv_and_bn(m.conv, m.bn)  # update conv
                delattr(m, 'bn')  # remove batchnorm
                m.forward = m.fuseforward  # update forward
        return self

if __name__ == '__main__':
    input_tensor = torch.rand(size=(1, 3, 416, 416))
    net = YOLOv5(in_channel=3, scale_name='s')
    out, norm_anchors = net(input_tensor)
    for item in out:
        print(item.shape)
    # print(norm_anchors)
    # print(norm_anchors.requires_grad)
    # with torch.no_grad():
    #     net.eval()
    #     out = net(input_tensor)
    #     print(out.shape)
    #     print(out.requires_grad)
    # with open("yolov5s_cvt.txt", 'w') as wf:
    #     weights = net.state_dict()
    #     for i, name in enumerate(weights):
    #         item = weights[name]
    #         print(i, name, item.shape)
    #         print(name, file=wf)


import cv2
import numpy as np
if __name__ == "__main__":
    img = cv2.imread("tower.jpeg")
    # cv2.imshow("input", img)
    # cv2.waitKey(0)
    w, h, _ = img.shape
    src = np.float32([[180,94],[377,39],[242,312],[436,265]])
    dis = np.float32([[0,0],[w,0],[0,h],[w,h]])
    matrix = cv2.getPerspectiveTransform(src,dis)
    result = cv2.warpPerspective(img,matrix,(w,h))
    cv2.imshow("input",img)
    cv2.imshow("output",result)
    cv2.waitKey(0)


#!/usr/bin/env python
# encoding: utf-8
import cv2
import numpy as np

"""ease_motion_detector.
This is ease motion detection algorithm.

Example:
        $ python ease_motion_detector.py

Todo:
    * cca function

"""
__author__ = "Kevin Lee"
__affiliate__ = "lidengju.com"
__copyright__ = "Copyright 2018, Kevin"
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Kevin Lee"
__email__ = "kevinleeex@foxmail.com"
__status__ = "Development"

class EaseMotionDetector():
    def onChanged(self, val):
        self.diff_thresh = val

    def __init__(self, diff_thresh=25, move_sense=0.05, show_window=True):
        self.writer = None
        self.font = None
        self.diff_thresh = diff_thresh
        self.move_sense = move_sense
        self.init_flag = True
        self.show_window = show_window
        self.frame = None
        self.capture = cv2.VideoCapture(0)
        self.frame = self.capture.read()[1]
        self.frame_w = self.frame.shape[1]  # frame width
        self.frame_h = self.frame.shape[0]  # frame height
        self.frame_area = self.frame_w * self.frame_h  # frame area
        self.gray_frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
        self.fusion_frame = np.float32(self.frame)
        self.absdiff_frame = None
        self.previous_frame = None

        self.cur_contour = None
        self.cur_area = 0

        # show window with track bar.
        if show_window:
            self.window_name = "Motion Detection Result"
            cv2.namedWindow(self.window_name)
            cv2.createTrackbar("Difference Threshold", self.window_name, self.diff_thresh, 100, self.onChanged)

    def run(self):
        while True:
            cur_frame = self.capture.read()[1]
            self.processFrame(cur_frame)

            if self.hasMoved():
                print("Object moved")
            cv2.imshow("Diff", self.gray_frame)
            cv2.drawContours(cur_frame, self.cur_contour, -1, (0, 0, 255), 2)

            if self.show_window:
                cv2.imshow(self.window_name, cur_frame)
            key = cv2.waitKey(50) % 0x100
            if key == 27:
                break

    def processFrame(self, cur_frame):
        """
        Image processing, blur--> compute diff--> gray_frame--> dilation--> eroding
        :param cur_frame: current frame
        :return: result
        """
        cv2.blur(cur_frame, (3, 3), cur_frame)
        # first time to compute
        if self.init_flag:
            self.init_flag = False
            self.absdiff_frame = cur_frame.copy()
            self.previous_frame = cur_frame.copy()
            # self.average_frame = cv2.convertScaleAbs(cur_frame)
        else:
            cv2.accumulateWeighted(cur_frame, self.fusion_frame, 0.05)  # compute average
        self.previous_frame = cv2.convertScaleAbs(self.fusion_frame)
        self.absdiff_frame = cv2.absdiff(cur_frame, self.previous_frame)  # abs(average - cur_frame)

        self.gray_frame = cv2.cvtColor(self.absdiff_frame, cv2.COLOR_BGR2GRAY)
        cv2.threshold(self.gray_frame, self.diff_thresh, 255, cv2.THRESH_BINARY, self.gray_frame)

        # define kernels
        dilate_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15))
        erode_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
        cv2.dilate(self.gray_frame, dilate_kernel, self.gray_frame)  # dilation
        result = cv2.erode(self.gray_frame, erode_kernel, self.gray_frame)  # eroding
        return result

    def hasMoved(self):
        """
        Judge the object is moving or not.
        :return: is_moved(boolean)
        """
        out, contours, hierarchy = cv2.findContours(self.gray_frame, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        self.cur_contour = contours
        max_contour = []
        for i in range(len(contours)):
            c = cv2.contourArea(contours[i])
            if c < 0.005 * self.frame_area:
                # fill small white blob in black
                cv2.drawContours(self.gray_frame, contours, i, (0, 0, 0), -1)
            else:
                max_contour.append(contours[i])
            self.cur_area += c
        self.cur_contour = max_contour
        val_area = self.cur_area / self.frame_area  # calculate the ratio of cur_area/frame_area
        self.cur_area = 0

        if val_area > self.move_sense:
            return True
        else:
            return False

    def cca(self, src_img):
        """
        connected component analysis
        :param src_img: source image to analysis
        :return:
        """
        contours = self.cur_contour
        for i in range(len(contours)):
            pass

if __name__ == '__main__':
    detect = EaseMotionDetector(diff_thresh=40)
    detect.run()


import pandas as pd
import json
import urllib3
from datetime import datetime, timedelta
import io
import boto3
import boto3.session
from codeguru_profiler_agent import with_lambda_profiler

class Request:

    def request_surveys(self):
        is_empty = False
        id = ""
        surveys = {'hasMore':False, 'items':[]}
        while not is_empty:
            query = f"https://api.movidesk.com/public/v1/survey/responses?token=&startingAfter={id}"
            http = urllib3.PoolManager()
            response = http.request('GET', query)
            if response.status == 200:

                parcial_survey = json.loads(response.data.decode('utf-8'))
                if parcial_survey["items"] == []:
                    is_empty = True
                else:
                    id = parcial_survey["items"][-1]["id"]
                    surveys["items"].extend(parcial_survey["items"])
        return surveys

class Survey:
    class Item:
        column = ("id", "question_id", "type", "client_id", "ticket_id", "response_data", "commentary", "value")
        def __init__(self, id, questionId, type , clientId, ticketId, responseDate, commentary, value, *args, **kwargs):
            self.id = id
            self.question_id = questionId
            self.type = type
            self.client_id = clientId
            self.ticket_id = ticketId
            self.response_data = responseDate
            self.commentary = commentary
            self.value = value

        def get(self):
            return (self.id, self.question_id, self.type, self.client_id, self.ticket_id, self.response_data, self.commentary, self.value)
        def __str__(self):
            return f"{self.id} {self.question_id} {self.response_data} {self.value}"
        def __repr__(self):
            return self.__str__()

    column = ("has_more")
    def __init__(self, hasMore, items, *args, **kwargs):
        self.has_more = hasMore
        self.items = [self.Item(**item) for item in items if item != [] or item is not None]

    def get(self):
        return [(self.has_more, *item.get()) for item in self.items]
    def __str__(self):
        return f"{self.has_more}"
    def __repr__(self):
        return self.__str__()

def alert_error_sns(client, text, is_failed):
    # Se der erro manda publica mensagem no SNS
    if is_failed:
        response = client.publish(
            TopicArn="arn:aws:sns:us-east-2:686836150544:dados-movidesk-topic",
            Message=text,
            Subject='Erro de atualização',
        )
    else:
        response = client.publish(
            TopicArn="arn:aws:sns:us-east-2:686836150544:dados-movidesk-topic",
            Message=text,
            Subject='Sucesso na atualização.',
        )

@with_lambda_profiler(profiling_group_name="aws-lambda-dados-movidesk")
def lambda_handler(event, context):

    buffer_report = io.BytesIO()
    aws_region = "us-east-2"
    s3 = boto3.client('s3', region_name=aws_region)

    sns = boto3.client('sns',   region_name=aws_region)

    cont_attempts = 0
    while True:
        cont_attempts += 1
        buffer_report.seek(0)
        update_report(s3)
        is_failed = False
        if cont_attempts > 5:
            break

    if is_failed:
        alert_error_sns(sns, f"Erro ao dar load no relatório de surveys do Movidash. Dia de referencia: {datetime.today() - timedelta(days=1)}", is_failed)
    else:
        alert_error_sns(sns, f"Sucesso na atualização do relatório de surveys.. Dia de referencia: {datetime.today() - timedelta(days=1)}", is_failed)
    return 0

def update_report(s3):

    dayli_buffer = io.BytesIO()
    dayli_buffer.write(json.dumps(Request().request_surveys()).encode())
    dayli_buffer.seek(0)
    arquivo = json.load(dayli_buffer)
    dayli_buffer.close()
    surveys = Survey(**arquivo)
    csv_buffer = io.StringIO()
    dataframe = pd.DataFrame([item.get() for item in surveys.items], columns=surveys.items[0].column)
    dataframe = dataframe.query('type == 3')
    pd.DataFrame(dataframe).to_csv(csv_buffer, index=False, header=dataframe.columns, sep=';', encoding="utf-8")
    content = csv_buffer.getvalue()
    csv_buffer.close()
    s3.put_object(Bucket='dados.datalake.movidesk', Body=content, Key="ticket-surveys/surveys.csv")

movidesk api/Códigos Python de extração do movidesk/Consulta Survey API/lambda_survey.py


from django.urls import path
from . import views
from django.contrib.auth.views import LogoutView

urlpatterns = [
    path('', views.index, name='index'),
    path('profile/', views.profile_view, name='profile'),
    path('logout/', LogoutView.as_view(), name='logout'),
    path('cars/', views.car_list, name='car_list'),
    path('cars/<int:pk>/', views.car_detail, name='car_detail'),
    path('orders/', views.OrderListView.as_view(), name='order_list'),
    path('orders/<int:pk>/', views.OrderDetailView.as_view(), name='order_detail'),
    path('myorders/', views.UserOrdersListView.as_view(), name='my_orders'),
    path('mycars/', views.UserCarListView.as_view(), name='my_cars'),
    path('myorders/<int:pk>', views.UserOrderDetailView.as_view(), name='my_order'),
    path('myorders/new', views.UserOrderCreateView.as_view(), name='my-order-new')
]


import test

from collections import defaultdict

def count(s):
  c = defaultdict(int)
  for x in s:
    if x >= 'a' and x <= 'z':
      c[x] += 1
  return c

def mix(s1, s2):
  c1 = count(s1)
  c2 = count(s2)
  letters = set(c1.keys() + c2.keys())
  answer = []
  for let in letters:
    k1 = c1[let]
    k2 = c2[let]
    if k1 > 1 or k2 > 1:
      if k1 > k2:
        answer.append('1:%s' % (let * k1))
      elif k1 < k2:
        answer.append('2:%s' % (let * k2))
      else:
        answer.append('=:%s' % (let * k1))

  answer = sorted(answer, key=lambda x: (-len(x), x))
  return '/'.join(answer)

test.assert_equals(mix("Are they here", "yes, they are here"), "2:eeeee/2:yy/=:hh/=:rr")
test.assert_equals(mix("looping is fun but dangerous", "less dangerous than coding"), "1:ooo/1:uuu/2:sss/=:nnn/1:ii/2:aa/2:dd/2:ee/=:gg")
test.assert_equals(mix(" In many languages", " there's a pair of functions"), "1:aaa/1:nnn/1:gg/2:ee/2:ff/2:ii/2:oo/2:rr/2:ss/2:tt")
test.assert_equals(mix("Lords of the Fallen", "gamekult"), "1:ee/1:ll/1:oo")
test.assert_equals(mix("codewars", "codewars"), "")
test.assert_equals(mix("A generation must confront the looming ", "codewarrs"), "1:nnnnn/1:ooooo/1:tttt/1:eee/1:gg/1:ii/1:mm/=:rr")


import pprint

from stable_baselines3 import PPO

from di import register
from environments.Snake.SnakeGym import SnakeGym
from trainers.BaseTrainer import BaseTrainer

@register
class SnakeTrainer(BaseTrainer):

    def __init__(self):
        super().__init__()
        self._name = "snake"
        self.env = SnakeGym

        self.training_algorithm = PPO

        self.config = {
            "death_penalty": -10,
            "dist_reward": 10,
            "ent_coef": 0.02,
            "food_distance_growth_rate": 1.05,
            "food_reward": 25,
            "gae_lambda": 0.95,
            "gamma": 0.99,
            "learning_rate": 1.5e-4,
            "living_bonus": -0.1,
            "max_step": 4096,
            "n_steps": 1024,
            "num_envs": 1,
            "policy": "MlpPolicy",
            "total_timesteps": 100000,
            "vf_coef": 0.5
        }

        self.model_parameters = [
            "ent_coef",
            "gae_lambda",
            "gamma",
            "learning_rate",
            "n_steps",
            "policy",
            "vf_coef",
        ]

        self.game_parameters = [

        ]

    def play(self):
        env = self._create_env()()
        env.unwrapped.play()


#!/usr/bin/env python
import logging
import time
from proxy5 import (MitmProxy, utils)

if __name__ == "__main__":
    import optparse
    try:
        import __pypy__
        __pypy__
    except ImportError:
        __pypy__ = False

    parser = optparse.OptionParser()
    parser.add_option(
        '-p', '--performance', help="Disable Logger for performance",
        default=__pypy__, action="store_true")
    parser.add_option(
        '-t', '--timeout', help="disable after n seconds",
        default=float('inf'), type='int')
    parser.add_option(
        '-a', '--all',
        help='show all logger messages (enables logging on PyPy at a cost!)',
        action="store_true", default=False)
    parser.add_option(
        '--port', default=0,
        help='set a port or let it be dynamic', type='int')
    options, args = parser.parse_args()

    if options.performance and not options.all:
        logging  # shut up the linter
        logging = \
            utils.FakeLogging()

    logger = logging.getLogger('trollius')
    logger.addHandler(logging.StreamHandler())
    logger.handlers[0].setLevel(logging.DEBUG)
    logger.setLevel(logging.DEBUG)

    logger = logging.getLogger('proxy5')
    handler = logging.StreamHandler()
    handler.setFormatter(
        logging.Formatter(
            '[%(asctime)s] [%(levelname)s] [%(name)s]  %(message)s'))
    logger.addHandler(handler)
    handler.setLevel(logging.INFO)
    if options.all:
        handler.setLevel(logging.DEBUG)
    logger.setLevel(logging.DEBUG)

    proxy = MitmProxy(logger, port=options.port)
    logger.info("Port {0!r}".format(proxy.port))
    proxy.start()
    try:
        ts = time.time()
        while time.time() - ts < options.timeout:
            time.sleep(0.1)
        proxy.stop()
    except KeyboardInterrupt:
        pass
    proxy.stop()
    ts = time.time()
    while proxy.is_alive():
        time.sleep(0.1)
    print("Took {0:.2f} s".format(time.time() - ts))


from women.models import *
from django.db import connection
connection.queries
from django.db.models import Min, Max, Count
def look():
    print(Women.objects.all().count())
    print(Women.objects.all()[3:8])
    Women.objects.order_by('-pk')
    Women.objects.all().reverse()
    Women.objects.filter(pk__lte=2)# less then equal
    w = Women.objects.get(pk=2) #строго одна запись
    c3 = Category.objects.get(pk=1)
    print(c3.women_set.exists())# count() и exists() применяются к любой выборке
    c2 = Category.objects.get(pk=2)
    print(c2.women_set.count())
    Women.objects.filter(cat__name__contains='цы')
    Category.objects.filter(women__title__contains='ли')
    Women.objects.aggregate(cat_min=Min('cat_id'), cat_max=Max('cat_id'))
    Women.objects.values('title', 'cat_id').get(pk=1) # values запрашивает не все поля
    c = Category.objects.annotate(total=Count('women')).filter(total__gt=0)
    Women.objects.raw('SELECT * FROM women_women')


import numpy as np
from numpy import vstack
from numpy import sqrt
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torch.utils.data import random_split
from torch import Tensor
from torch.nn import Linear
from torch.nn import ReLU, Sigmoid
from torch.nn import Module
from torch.optim import SGD
from torch.nn import MSELoss
from torch.nn.init import kaiming_uniform_
from torch.nn.init import xavier_uniform_

# Model hyper-parameters
num_epochs = 100

# Dataset definition: Data loading
class CSVDataset(Dataset):
    # load the dataset
    def __init__(self, path):
        # load csv file as a dataframe using pandas
        df = read_csv(path, header=None)
        # store inputs and outputs
        self.X = df.values[:,:-1]
        self.y = df.values[:,-1]
        #print("Input data shape:", np.shape(self.X))
        #print("Input label shape:", np.shape(self.y))
        # Ensure input X and y values are floats
        self.X = self.X.astype('float32')
        self.y = self.y.astype('float32')
        self.y = self.y.reshape(len(self.y), 1)
        print("input data shape:", np.shape(self.X))

    # Number of rows in dataset
    def __len__(self):
        return len(self.X)

    # Get a row at an index
    def __getitem__(self, idx):
        return [self.X[idx], self.y[idx]]

    # Get indices for train and test rows
    def get_splits(self, n_train=0.7):
        train_split = round(n_train * len(self.X))
        test_split = len(self.X) - train_split
        return random_split(self, [train_split, test_split])

# Model definition
class MLP(Module):
    # define model architecture
    def __init__(self, n_inputs):
        super(MLP,self).__init__()
        # input to first MLP hidden layer
        self.hiddenlayer1 = Linear(n_inputs, 10)
        xavier_uniform_(self.hiddenlayer1.weight)
        self.activation1 = Sigmoid()
        # input to second MLP hidden layer
        self.hiddenlayer2 = Linear(10, 8)
        xavier_uniform_(self.hiddenlayer2.weight)
        self.activation2 = Sigmoid()
        # input tp third MLP hidden layer (last layer)
        self.hiddenlayer3 = Linear(8, 1)
        xavier_uniform_(self.hiddenlayer3.weight)

    # forward propagate input
    def forward(self, X):
        # input to first MLP hidden layer
        X = self.hiddenlayer1(X)
        X = self.activation1(X)
        # input to second MLP hidden layer
        X = self.hiddenlayer2(X)
        X = self.activation2(X)
        # input to third MLP hidden layer
        X = self.hiddenlayer3(X)
        return X

# prepare dataset
def prepare_data(path):
    # Load dataset
    dataset = CSVDataset(path)
    # Calculate split
    train, test = dataset.get_splits()
    train_dl = DataLoader(train, batch_size=32, shuffle=True)
    test_dl = DataLoader(test, batch_size=32, shuffle=False)
    return train_dl, test_dl

# model training
def train_model(train_dl, model):
    # define optimization
    loss_fn = MSELoss()
    optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)

    # enumerate epochs
    for epoch in range(num_epochs):
        # enumerate mini batches
        for i, (inputs, targets) in enumerate(train_dl):
            # clear gradients
            optimizer.zero_grad()
            # compute model output
            yhats = model(inputs)
            # calculate loss
            loss = loss_fn(yhats, targets)
            # back propagate
            loss.backward()
            # update model weights
            optimizer.step()

# evaluate model
def evaluate_model(test_dl, model):
    predictions, actuals = list(), list()
    # enumerate mini batches
    for i, (inputs, targets) in enumerate(test_dl):
        yhats = model(inputs)
        # retrieve numpy array from pytorch tensor
        yhats = yhats.detach().numpy()
        ys = targets.numpy()
        predictions.append(yhats)
        actuals.append(ys)

   # stack arrays vertically that are stored in batches
    predictions, actuals = vstack(predictions), vstack(actuals)
    # calculate performance metric
    acc = mean_squared_error(predictions, actuals)
    return acc

# predict class for a given input
def predict(row, model):
    # convert row to data
    row = Tensor([row])
    # predict input
    yhat = model(row)
    # retrieve numpy array by detaching from pytorch tensor
    yhat = yhat.detach().numpy()
    return yhat

# Driver functions
# prepare data
dataset_path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
train_dl, test_dl = prepare_data(dataset_path)
print("Number of samples in train and test set:", len(train_dl.dataset), len(test_dl.dataset))
# define network architecture
mlpregression_model = MLP(13)
# train the model
train_model(train_dl, mlpregression_model)
# evaluate model
mse = evaluate_model(test_dl, mlpregression_model)
print("Mean square error: %3f. Root mean square error: %f"%(mse, sqrt(mse)))
# predict class for a given input
row = [0.00632,18.00,2.310,0,0.5380,6.5750,65.20,4.0900,1,296.0,15.30,396.90,4.98]
yhat = predict(row, mlpregression_model)
print("Predicted: %.3f"%yhat)


import json
import tempfile
import zipfile
from contextlib import contextmanager
from functools import wraps
from traceback import TracebackException

import boto3

codepipeline_client = boto3.client("codepipeline")
ec2_client = boto3.client("ec2")
sts_client = boto3.client("sts")

def codepipeline_lambda_handler(func):
    """
    Decorates a lambda handler function to set up logging and error handling.
    Sends a failure result to CodePipeline if the decorated function raises
    an exception, otherwise sending a success result.

    """

    @wraps(func)
    def wrapped(event, context):

        # Set up logging and log the event.
        # Example event: https://docs.amazonaws.cn/en_us/lambda/latest/dg/services-codepipeline.html
        log.context = {"RequestId": context.aws_request_id}
        log("EVENT", json.dumps(event, indent=2))

        # Get the job data.
        job = event["CodePipeline.job"]

        # Process the job and then notify CodePipeline of its success or failure.
        try:
            func(event, context)
            log("SUCCESS")
            codepipeline_client.put_job_success_result(jobId=job["id"])
        except Exception as error:
            log("FAILURE", exception=error)
            codepipeline_client.put_job_failure_result(
                jobId=job["id"],
                failureDetails={
                    "type": "JobFailed",
                    "message": f"{error.__class__.__name__}: {error}",
                    "externalExecutionId": context.aws_request_id,
                },
            )

    return wrapped

@contextmanager
def create_zip_file(files):
    """
    Creates a temporary zip file on disk. The files parameter must be a
    dictionary of {filename: contents} which will be written to the zip
    file. The zip file path is yielded as the context value.

    """

    with tempfile.NamedTemporaryFile() as temp_file:
        with zipfile.ZipFile(temp_file.name, "w") as zip_file:
            for filename, contents in files.items():
                zip_file.writestr(filename, contents)
        yield temp_file.name

def get_artifact_s3_client(job):
    """
    Returns an S3 client with access to the CodePipeline artifact S3 bucket.

    """

    creds = job["data"]["artifactCredentials"]
    session = boto3.Session(
        aws_access_key_id=creds["accessKeyId"],
        aws_secret_access_key=creds["secretAccessKey"],
        aws_session_token=creds["sessionToken"],
    )
    return session.client("s3")

def get_cloudformation_template(cfn_client, stack_name):
    """
    Returns the template body of a CloudFormation stack.

    """

    response = cfn_client.get_template(StackName=stack_name)
    return response["TemplateBody"]

def get_input_artifact_location(job):
    """
    Returns the S3 location of the input artifact.

    """

    input_artifact = job["data"]["inputArtifacts"][0]
    input_location = input_artifact["location"]["s3Location"]
    input_bucket = input_location["bucketName"]
    input_key = input_location["objectKey"]
    return (input_bucket, input_key)

def get_output_artifact_location(job):
    """
    Returns the expected S3 destination location of the output artifact.
    The Lambda function needs to place an output artifact there.

    """

    output_artifact = job["data"]["outputArtifacts"][0]
    output_location = output_artifact["location"]["s3Location"]
    output_bucket = output_location["bucketName"]
    output_key = output_location["objectKey"]
    return (output_bucket, output_key)

def get_session(role_arn, session_name, duration_seconds=900):
    """
    Returns a boto3 session for the specified role.

    """

    response = sts_client.assume_role(
        RoleArn=role_arn,
        RoleSessionName=session_name,
        DurationSeconds=duration_seconds,
    )
    creds = response["Credentials"]
    return boto3.Session(
        aws_access_key_id=creds["AccessKeyId"],
        aws_secret_access_key=creds["SecretAccessKey"],
        aws_session_token=creds["SessionToken"],
    )

def get_user_parameters(job):
    """
    Returns the user parameters that were defined in CodePipeline.

    """

    return json.loads(
        job["data"]["actionConfiguration"]["configuration"]["UserParameters"]
    )

def log(title, message="", exception=None):
    """
    Logs a message, which will show up in CloudWatch Logs.

    """

    parts = [str(title)]
    for key, value in log.context.items():
        parts.append(key)
        parts.append(value)
    if message != "":
        parts.append(str(message))
    value = " ".join(parts)
    if exception:
        value += "\n"
        value += "\n".join(TracebackException.from_exception(exception).format())
    print(value.replace("\n", "\r"))

log.context = {}


import numpy as np
import pickle
import sys

from typing import List, Tuple
from pathlib import Path
from argparse import ArgumentParser
from matplotlib import pyplot as plt

from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score
from scipy.cluster.hierarchy import linkage, dendrogram

import logging
from loguru import logger

logger.remove()  # Remove the default logger
logger.add(sys.stdout, level="INFO")  # Add a console logger

def load_embeddings(file: Path) -> Tuple[List[Path], np.ndarray]:
    embeddings = pickle.loads(file.read_bytes())
    files, vectors = zip(*list(embeddings.items()))
    return files, vectors

def save_dendrogram(data: np.ndarray, dendrogram_file: Path, linkage_type: str):
    linkage_matrix = linkage(data, method=linkage_type)
    plt.figure(figsize=(12, 6))
    plt.title(f"Dendrogram ({linkage_type} linkage)")
    dendrogram(linkage_matrix, orientation='top')
    plt.savefig(dendrogram_file)
    plt.close()

if __name__ == "__main__":
    parser = ArgumentParser()
    parser.add_argument('embeddings_file', type=Path)
    parser.add_argument('--output-dir', type=Path, required=True, default='data/dendrograms/')
    args = parser.parse_args()

    logger.info("Loading embeddings...")
    _, vectors = load_embeddings(file=args.embeddings_file)

    dendrogram_linkages = ['ward', 'complete', 'centroid', 'median']

    logger.info("Saving Dendrograms for Different Linkage Methods...")

    for linkage_type in dendrogram_linkages:
        logger.info(f"Saving dendrogram for linkage: {linkage_type}")

        dendrogram_file = args.output_dir / f"dendrogram_{linkage_type}.png"
        save_dendrogram(vectors, dendrogram_file, linkage_type)

    logger.info("Dendrograms saved for different linkage methods.")


import collections
import signal
import sys
import time
import wave
import keras
import audio_utility as au
from array import array
from struct import pack

import pyaudio
from pydub import AudioSegment
from pydub.playback import play
import webrtcvad

import librosa
import numpy as np

FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000
CHUNK_DURATION_MS = 30  # supports 10, 20 and 30 (ms)
PADDING_DURATION_MS = 1000  # 1 sec jugement
CHUNK_SIZE = int(RATE * CHUNK_DURATION_MS / 1000)  # chunk to read
CHUNK_BYTES = CHUNK_SIZE * 2  # 16bit = 2 bytes, PCM
NUM_PADDING_CHUNKS = int(PADDING_DURATION_MS / CHUNK_DURATION_MS)
# NUM_WINDOW_CHUNKS = int(240 / CHUNK_DURATION_MS)
NUM_WINDOW_CHUNKS = int(400 / CHUNK_DURATION_MS)  # 400 ms/ 30ms  ge
NUM_WINDOW_CHUNKS_END = NUM_WINDOW_CHUNKS * 2

START_OFFSET = int(NUM_WINDOW_CHUNKS * CHUNK_DURATION_MS * 0.5 * RATE)

vad = webrtcvad.Vad(1)

pa = pyaudio.PyAudio()
stream = pa.open(
    format=FORMAT,
    channels=CHANNELS,
    rate=RATE,
    input=True,
    start=False,
    # input_device_index=2,
    frames_per_buffer=CHUNK_SIZE,
)

got_a_sentence = False
leave = False

# initialize inference
feature_extractor = au.SpeechFeatures()
wanted_words = [
    "_silence_",
    "_unknown_",
    "backward",
    "forward",
    "go",
    "left",
    "right",
    "stop",
]
# import keras model
model = keras.models.load_model(
    "models/vgg_19_model_mfcc_49x40_left_right_forward_backward_stop_go.hdf5"
)
model.summary()

def inference(test_audio):
    y, sr = librosa.load(test_audio, sr=16000)
    # fix the length of test audio to 1s or 16000 samples
    y = librosa.util.fix_length(y, size=16000)
    # normalize the test audio into [-1. 1]
    # y = np.clip(y, -1.0, 1.0)

    # extract the features
    audio_feature = feature_extractor.mfcc(y, fs=16000)
    audio_feature = audio_feature.flatten()
    audio_feature = np.expand_dims(audio_feature, axis=0)
    # inference
    prediction = model.predict(audio_feature)
    prediction = np.argmax(prediction)
    print(prediction, wanted_words[int(prediction)])

def handle_int(sig, chunk):
    global leave, got_a_sentence
    leave = True
    got_a_sentence = True

def record_to_file(path, data, sample_width):
    "Records from the microphone and outputs the resulting data to 'path'"
    # sample_width, data = record()
    data = pack("<" + ("h" * len(data)), *data)
    wf = wave.open(path, "wb")
    wf.setnchannels(1)
    wf.setsampwidth(sample_width)
    wf.setframerate(RATE)
    wf.writeframes(data)
    wf.close()

def normalize(snd_data):
    "Average the volume out"
    MAXIMUM = 16384  # 16384
    times = float(MAXIMUM) / max(abs(i) for i in snd_data)
    r = array("h")
    for i in snd_data:
        r.append(int(i * times))
    return r

signal.signal(signal.SIGINT, handle_int)

while not leave:
    ring_buffer = collections.deque(maxlen=NUM_PADDING_CHUNKS)
    triggered = False
    voiced_frames = []
    ring_buffer_flags = [0] * NUM_WINDOW_CHUNKS
    ring_buffer_index = 0

    ring_buffer_flags_end = [0] * NUM_WINDOW_CHUNKS_END
    ring_buffer_index_end = 0
    buffer_in = ""
    # WangS
    raw_data = array("h")
    index = 0
    start_point = 0
    StartTime = time.time()
    stream.start_stream()

    while not got_a_sentence and not leave:
        chunk = stream.read(CHUNK_SIZE)
        # add WangS
        raw_data.extend(array("h", chunk))
        index += CHUNK_SIZE
        TimeUse = time.time() - StartTime

        active = vad.is_speech(chunk, RATE)

        # sys.stdout.write('1' if active else '_')
        ring_buffer_flags[ring_buffer_index] = 1 if active else 0
        ring_buffer_index += 1
        ring_buffer_index %= NUM_WINDOW_CHUNKS

        ring_buffer_flags_end[ring_buffer_index_end] = 1 if active else 0
        ring_buffer_index_end += 1
        ring_buffer_index_end %= NUM_WINDOW_CHUNKS_END

        # start point detection
        if not triggered:
            ring_buffer.append(chunk)
            num_voiced = sum(ring_buffer_flags)
            if num_voiced > 0.8 * NUM_WINDOW_CHUNKS:
                # sys.stdout.write(' Open ')
                triggered = True
                start_point = index - CHUNK_SIZE * 20  # start point
                # voiced_frames.extend(ring_buffer)
                ring_buffer.clear()
        # end point detection
        else:
            # voiced_frames.append(chunk)
            ring_buffer.append(chunk)
            num_unvoiced = NUM_WINDOW_CHUNKS_END - sum(ring_buffer_flags_end)
            if num_unvoiced > 0.90 * NUM_WINDOW_CHUNKS_END or TimeUse > 10:
                triggered = False
                got_a_sentence = True

        sys.stdout.flush()

    sys.stdout.write("\n")

    stream.stop_stream()
    got_a_sentence = False

    # write to file
    raw_data.reverse()
    for index in range(start_point):
        raw_data.pop()
    raw_data.reverse()
    raw_data = normalize(raw_data)
    print("recorded")
    start = time.time()
    record_to_file("recording_.wav", raw_data, 2)
    print(f"time to save audio: {time.time() - start}")
    # leave = True
    start = time.time()
    inference("recording_.wav")
    print(f"time inference: {time.time() - start}")
    start = time.time()
    song = AudioSegment.from_wav("recording_.wav")
    play(song)
    print(f"time to play audio: {time.time() - start}")

stream.close()


from nltk_utils import tokenize, stem, bag_of_words
from Classes.ChatDataset import ChatDataset
from Classes.Model import NeuralNet
import numpy as np
import json
import re
import yaml
import torch
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader

def main():

    def load_json_data(filepath):
        with open(filepath) as f:
            intentsData = json.load(f)
        return intentsData

    def extract_allwords_tags_xy(intentsData):
        allWords = []
        tags = []
        xy = []
        for intent in intentsData['intents']:
            tag = intent['tag']
            tags.append(tag)
            for pattern in intent['patterns']:
                w = tokenize(pattern)
                allWords.extend(w)
                xy.append((w, tag))
        allWords = sorted(set([stem(word) for word in allWords if re.search('[a-zA-Z]', word)]))
        tags = sorted(set(tags))

        return allWords, tags, xy

    def get_XY_training_data(xy, allWords, tags):
        x_train, y_train = [], []
        for (pattern_sentence, tag) in xy:
            bag = bag_of_words(pattern_sentence, allWords)
            x_train.append(bag)
            label = tags.index(tag)
            y_train.append(label)
        return np.array(x_train), np.array(y_train)

    def get_hyper_params(tags, X_train, hyperPath):

        with open(hyperPath) as f:
            params = yaml.load(f, Loader=yaml.FullLoader)

        batch_size = params['batch_size']
        hidden_size = params['hidden_size']
        output_size = len(tags)
        input_size = len(X_train[0])
        learning_rate = params['learning_rate']
        num_epochs = params['num_epochs']
        MODEL_FILE_PATH = params['MODEL_FILE_PATH']

        return batch_size, hidden_size, output_size, input_size, learning_rate, num_epochs, MODEL_FILE_PATH

    def train_model(X_train, Y_train, batch_size, hidden_size, output_size, input_size, learning_rate, num_epochs):

        dataset = ChatDataset(X_train, Y_train)
        train_loader = DataLoader(dataset=dataset, batch_size=batch_size, shuffle=True, num_workers=2)
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
        model = NeuralNet(input_size, hidden_size, output_size).to(device)

        # loss and optimser
        criterion = nn.CrossEntropyLoss()
        optimiser = torch.optim.Adam(model.parameters(), lr=learning_rate)

        for epoch in range(num_epochs):
            for (words, labels) in train_loader:
                words = words.to(device)
                labels = labels.to(device)

                output = model(words)
                loss = criterion(output, labels.long())

                optimiser.zero_grad()
                loss.backward()
                optimiser.step()

            if (epoch +1) % 100 == 0:
                print(f'Epoch: {epoch+1}/{num_epochs}')
                print(f'Loss: {loss.item()}:.4f') # type: ignore

        print(f'Final Loss: {loss.item()}:.4f') # type: ignore

        dataModel = {
            "model_state": model.state_dict(),
            "input_size": input_size,
            "hidden_size": hidden_size,
            "output_size": output_size,
            "all_words": allWords,
            "tags": tags
        }

        return dataModel

    # load data
    paramsPath = r'src\params.yml'
    #intents = load_json_data(r'data\training_data\train.json')
    intents = load_json_data(r'data\training_data\data_full_response_data_transformed.json')
    allWords, tags, xy = extract_allwords_tags_xy(intents)
    X_train, Y_train = get_XY_training_data(xy, allWords, tags)

    # Hyperparameters
    batch_size, hidden_size, output_size, input_size, learning_rate, num_epochs, MODEL_FILE_PATH = get_hyper_params(tags, X_train, paramsPath)

    # Train Model
    dataModel = train_model(X_train, Y_train, batch_size, hidden_size, output_size, input_size, learning_rate, num_epochs)
    torch.save(dataModel, MODEL_FILE_PATH)
    print(f'Model saved to {MODEL_FILE_PATH}')

if __name__ == '__main__':
    main()


# Import Module
import os
import re
from nltk import word_tokenize
import pandas as pd

# Read text file
def create_text(file_path):
    file_object = open(file_path, 'r')

    return file_object.read()

# Create word token of text
def create_word_token(file_text):
    word = re.sub('[^a-z]',' ', file_text.lower())
    tokenize_word = word_tokenize(word)

    return tokenize_word

# Remove exclude word by using exclude word dictionary
def remove_exclude_word_by_file(tokenize_word, exclude_word):
    clean_word = list()

    for word in tokenize_word:
        if word not in exclude_word:
            clean_word.append(word)

    return clean_word

# Read file path
file_path = "Raw_Data/"

# Read files from the path
file_list = os.listdir(file_path)

# Read exclude word
exclude_word = pd.read_csv("exclude-words.txt")

# Create dictionary
word_dict = dict()

for index, file_name in enumerate(file_list):
    # Check file is text
    if file_name.endswith(".txt"):
        file_text = create_text(os.getcwd()+"/"+file_path+file_name)
        tokenize_word = create_word_token(file_text)
        clean_word = remove_exclude_word_by_file(tokenize_word, exclude_word)

        for word in clean_word:
            if word in word_dict.keys():
                if word_dict[word][-1] != index+1:
                    word_dict[word].append(index+1)
            else:
                word_dict[word] = [index+1]

# Sort dictionary
word_dict = dict(sorted(word_dict.items()))

#Create file
with open("index.txt", "w") as output_file:
    output_file.write("Word : Page Numbers"+"\n")
    output_file.write("-------------------"+"\n")
    for word in word_dict:
        output_file.write(word+" : "+','.join(map(str,word_dict[word]))+"\n")
output_file.close()


#!/usr/bin/env python3
# vim: syntax=python ts=4 et sw=4 sts=4:

# Common supporting classes and calculations.

import datetime
from wilks import wilks

PercentageTable = [
    [100.00, 97.80, 95.50, 93.90, 92.20, 90.70, 89.20, 87.80, 86.30], # 1 rep
    [95.50,  93.90, 92.20, 90.70, 89.20, 87.80, 86.30, 85.00, 83.70], # 2 reps
    [92.20,  90.70, 89.20, 87.80, 86.30, 85.00, 83.70, 82.40, 81.10], # 3 reps
    [89.20,  87.80, 86.30, 85.00, 83.70, 82.40, 81.10, 79.90, 78.60], # 4 reps
    [86.30,  85.00, 83.70, 82.40, 81.10, 79.90, 78.60, 77.40, 76.20], # 5 reps
    [83.70,  82.40, 81.10, 79.90, 78.60, 77.40, 76.20, 75.10, 73.90], # 6 reps
    [81.10,  79.90, 78.60, 77.40, 76.20, 75.10, 73.90, 72.30, 70.70], # 7 reps
    [78.60,  77.40, 76.20, 75.10, 73.90, 72.30, 70.70, 69.40, 68.00], # 8 reps
    [76.20,  75.10, 73.90, 72.30, 70.70, 69.40, 68.00, 66.70, 65.30], # 9 reps
    [73.90,  72.30, 70.70, 69.40, 68.00, 66.70, 65.30, 64.00, 62.60], # 10 reps
    [70.70,  69.40, 68.00, 66.70, 65.30, 64.00, 62.60, 61.30, 59.90], # 11 reps
    [68.00,  66.70, 65.30, 64.00, 62.60, 61.30, 59.90, 58.60, 00.00], # 12 reps
]

# Not used, but kept around for future error checking.
def percentage_tabular(reps, rpe):
    # Insufficient reps to accurately predict RPE or E1RM.
    if reps > 12 or reps < 1:
        return 0.0

    if rpe == 10.0: return PercentageTable[reps - 1][0]
    if rpe == 9.5:  return PercentageTable[reps - 1][1]
    if rpe == 9.0:  return PercentageTable[reps - 1][2]
    if rpe == 8.5:  return PercentageTable[reps - 1][3]
    if rpe == 8.0:  return PercentageTable[reps - 1][4]
    if rpe == 7.5:  return PercentageTable[reps - 1][5]
    if rpe == 7.0:  return PercentageTable[reps - 1][6]
    if rpe == 6.5:  return PercentageTable[reps - 1][7]
    if rpe == 6.0:  return PercentageTable[reps - 1][8]
    return 0.0

# This is the above chart expressed as a piecewise function.
# This enables using a larger set of real numbers for RPEs, like 8.75.
def percentage(reps, rpe):
    # No prediction if failure occurred, or if RPE is unreasonably low.
    if reps < 1 or rpe < 4:
        return 0

    # Handle the obvious case early to avoid error margins.
    if reps == 1 and rpe == 10:
        return 100

    # x is defined such that 1@10 = 0, 1@9 = 1, 1@8 = 2, etc.
    # By definition of RPE, then also:
    #  2@10 = 1@9 = 1
    #  3@10 = 2@9 = 1@8 = 2
    # And so on. That pattern gives the equation below.
    x = (10 - rpe) + (reps - 1)

    # The logic breaks down for super-high numbers,
    # and it's too hard to extrapolate an E1RM from super-high-rep sets anyway.
    if x >= 16:
        return 0

    intersection = 2.92

    # The highest values follow a quadratic.
    # Parameters were resolved via GNUPlot and match extremely closely.
    if x <= intersection:
        a = 0.347619
        b = -4.60714
        c = 99.9667
        return a*x*x + b*x + c

    # Otherwise it's just a line, since Tuchscherer just guessed.
    m = -2.64249
    b = 97.0955
    return m*x + b

def calc_weight(e1rm, reps, rpe):
    # weight / percentage(reps, rpe) * 100 = e1rm
    # weight = e1rm / 100 * percentage(reps, rpe);
    return e1rm / 100 * percentage(reps, rpe)

def calc_e1rm(weight, reps, rpe):
    if rpe == 0:
        return 0
    return weight / percentage(reps, rpe) * 100

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

class Set:
    def __init__(self, weight, reps, rpe=0, failure=False):
        self.weight = float(weight)
        self.reps = int(reps)
        self.rpe = float(rpe)
        self.failure = bool(failure)

        if self.reps < 0:
            error("Negative reps")
        if self.reps == 0 and not self.failure:
            error("Invalid set: no reps done and no failure.")

    def e1rm(self):
        factor = percentage(self.reps, self.rpe)

        # Use the Tuchscherer chart.
        if factor > 0:
            return self.weight / factor * 100

        # If RPEs are missing or the chart is inadequate, don't mislead.
        return 0.0

    # For cases that the RPE chart doesn't cover, we have the Epley formula.
    def epley(self):
        if self.reps == 0:
            return 0.0

        # Use RPE to include any reps not done.
        reps = self.reps
        if self.rpe:
            reps += 10 - self.rpe

        if reps == 1:
            return self.weight
        return self.weight + ((self.weight * reps) / 30)

    # Compared to the specified E1RM, how much fatigue did this set demonstrate?
    # Numbers returned are in units of "fatigue percents".
    def fatigue(self, best_e1rm):
        set_e1rm = self.e1rm()
        if set_e1rm == 0 or best_e1rm == 0:
            return 0
        return max(0, (1 - (set_e1rm / best_e1rm)) * 100)

class Lift:
    def __init__(self, name):
        self.name = name
        self.sets = []

    def addsets(self, slist):
        self.sets += slist

    # Get a list of non-warmup, actual training sets.
    def get_worksets(self):
        # Lifts that track RPE track them for every set.
        highrpe = list(filter(lambda x: x.rpe >= 6.0, self.sets))
        if len(highrpe) > 0:
            return highrpe

        # If this is one of the earlier lifts that didn't track RPE,
        # just take some of the heaviest sets of what's present.
        topweight = max([0] + list(map(lambda x: x.weight, self.sets)))
        cutoff = topweight * 0.70
        return filter(lambda x: x.weight >= cutoff, self.sets)

    # TODO: Should trust higher RPEs more.
    def e1rm(self):
        return max([0] + list(map(lambda x: x.e1rm(), self.get_worksets())))

    def epley(self):
        return max([0] + list(map(lambda x: x.epley(), self.get_worksets())))

    def volume(self):
        return sum(map(lambda x: x.reps, self.get_worksets()))

    def tonnage(self):
        return sum(map(lambda x: x.weight * x.reps, self.get_worksets()))

    def fatigue(self):
        best_e1rm = self.e1rm()
        if best_e1rm == 0:
            return 0
        # Compare to the most recent set that had an e1rm.
        for i in range(len(self.sets), 0, -1):
            e1rm = self.sets[i-1].e1rm()
            if e1rm == 0:
                continue
            return self.sets[i-1].fatigue(best_e1rm)
        return 0

class TrainingSession:
    def __init__(self, year, month, day):
        self.date = datetime.date(year, month, day)
        self.bodyweight = 0.0
        self.lifts = []

    def setbodyweight(self, bodyweight):
        self.bodyweight = bodyweight

    def addlift(self, l):
        self.lifts.append(l)

    def e1rm(self, matchfn):
        lifts = filter(matchfn, self.lifts)
        return max([0] + list(map(Lift.e1rm, lifts)))

    def epley(self, matchfn):
        lifts = filter(matchfn, self.lifts)
        return max([0] + list(map(Lift.epley, lifts)))

    def volume(self, matchfn):
        lifts = filter(matchfn, self.lifts)
        return sum(x.volume() for x in lifts)

    def tonnage(self, matchfn):
        lifts = filter(matchfn, self.lifts)
        return sum(x.tonnage() for x in lifts)

    def fatigue(self, matchfn):
        lifts = filter(matchfn, self.lifts)
        return sum(x.fatigue() for x in lifts)

    def epley_wilks(self, matchfn):
        lifts = filter(matchfn, self.lifts)
        def liftwilks(lift):
            return wilks(True, self.bodyweight/2.20462262, lift.epley()/2.20462262)
        return max([0] + list(map(liftwilks, lifts)))

# Handles the case of multiple TrainingSessions on the same day,
# but really just exists so that the code between daily/weekly
# uses the same types and the same interface.
class DailyIterator:
    def __init__(self, sessions):
        self.sessions = sessions

    def __iter__(self):
        self.idx = 0
        return self

    def __sameday(self, a, b):
        return a.toordinal() == b.toordinal()

    def __next__(self):
        if self.idx >= len(self.sessions):
            raise StopIteration

        startdate = self.sessions[self.idx].date
        acc = []
        for i in range(self.idx, len(self.sessions)):
            if self.__sameday(startdate, self.sessions[i].date):
                acc.append(self.sessions[i])
            else:
                break

        self.idx += len(acc)
        return acc

class WeeklyIterator:
    def __init__(self, sessions):
        self.sessions = sessions

    def __iter__(self):
        self.idx = 0
        return self

    # Whether the two given dates are in the same training week.
    # A training week is Sunday through Saturday (inclusive).
    def __sameweek(self, a, b):
        # Canonicalize each date according to the last Sunday.
        # isoweekday() gives 1 for Monday, 7 for Sunday.
        # So in terms of mapping how much to subtract:
        #  isoweekday -> subtract_amount
        #  [1,2,3,4,5,6,7] -> [1,2,3,4,5,6,0]
        week_a = a.toordinal() - (a.isoweekday() % 7)
        week_b = b.toordinal() - (b.isoweekday() % 7)
        return week_a == week_b

    def __next__(self):
        if self.idx >= len(self.sessions):
            raise StopIteration

        # Generate a list of sessions from here until Saturday (inclusive).
        # In terms of weekday(), Saturday is a return value of 6.
        startdate = self.sessions[self.idx].date
        acc = []

        for i in range(self.idx, len(self.sessions)):
            if self.__sameweek(startdate, self.sessions[i].date):
                acc.append(self.sessions[i])
            else:
                break

        self.idx += len(acc)
        return acc

# Return a single date as representative of the list of dates.
# For choosing a date on which to mark weekly volume, etc.
def canonical_date(sessionlist):
    return sessionlist[-1].date


#!/usr/bin/env python
#
"""
Test the various functions in the `deliver` module
"""
# system imports
#

# 3rd party imports
#
import factory
import pytest

# Project imports
#
from ..deliver import (
    apply_message_filter_rules,
    deliver_message,
    deliver_message_locally,
)
from ..models import EmailAccount, MessageFilterRule

pytestmark = pytest.mark.django_db

####################################################################
#
def assert_email_equal(msg1, msg2, ignore_headers=False):
    """
    Because we can not directly compare a Message and EmailMessage object
    we need to compare their parts. Since an EmailMessage is a sub-class of
    Message it will have all the same methods necessary for comparison.
    """
    # Compare all headers, unless we are ignoring them.
    #
    if ignore_headers is False:
        assert len(msg1.items()) == len(msg2.items())
        for header, value in msg1.items():
            value = value.replace("\n", "")
            assert msg2[header].replace("\n", "") == value

    # If we are ignoring only some headers, then skip those.
    #
    if isinstance(ignore_headers, list):
        ignore_headers = [x.lower() for x in ignore_headers]
        for header, value in msg1.items():
            if header.lower() in ignore_headers:
                continue
            assert msg2[header] != value

    assert msg1.is_multipart() == msg2.is_multipart()

    # If not multipart, the payload should be the same.
    #
    if not msg1.is_multipart():
        assert msg1.get_payload() == msg2.get_payload()

    # Otherwise, compare each part.
    #
    parts1 = msg1.get_payload()
    parts2 = msg2.get_payload()
    assert len(parts1) == len(parts2)

    for part1, part2 in zip(parts1, parts2):
        assert part1.get_payload() == part2.get_payload()

####################################################################
#
def test_apply_message_filter_rules(
    email_account_factory,
    message_filter_rule_factory,
    email_factory,
):
    ea = email_account_factory()
    ea.save()
    msg = email_factory()
    folder = "test"
    mfr = message_filter_rule_factory(
        email_account=ea,
        header=MessageFilterRule.FROM,
        pattern=msg["from"],
        destination=folder,
    )
    mfr.save()

    deliver_to = apply_message_filter_rules(ea, msg)
    assert deliver_to == [folder]

    # Make a new email, since the from is guaranteed to be different this will
    # NOT atch our rule.
    #
    msg = email_factory()
    deliver_to = apply_message_filter_rules(ea, msg)
    assert len(deliver_to) == 0

####################################################################
#
def test_deliver_message_locally(
    email_account_factory, message_filter_rule_factory, email_factory
):
    ea = email_account_factory()
    ea.save()
    msg = email_factory()

    deliver_message_locally(ea, msg)

    # The message should have been delivered to the inbox since there are no
    # mail filter rules. And it should be the only message in the mailbox.
    #
    mh = ea.MH()
    folder = mh.get_folder("inbox")
    stored_msg = folder.get(1)
    assert_email_equal(msg, stored_msg)

    # Now create a mfr and make sure the message is delivered to the proper
    # folder.
    #
    msg = email_factory()
    folder_name = "test"
    folder = mh.add_folder(folder_name)
    mfr = message_filter_rule_factory(
        email_account=ea,
        header=MessageFilterRule.FROM,
        pattern=msg["from"],
        destination=folder_name,
    )
    mfr.save()
    deliver_message_locally(ea, msg)
    stored_msg = folder.get(1)
    assert_email_equal(msg, stored_msg)

####################################################################
#
def test_deliver_alias(email_account_factory, email_factory):
    ea_1 = email_account_factory(account_type=EmailAccount.ALIAS)
    ea_1.save()
    ea_2 = email_account_factory()
    ea_2.save()
    ea_1.alias_for.add(ea_2)

    # Messages being delivered to ea1 will be delivered to ea2.
    #
    msg = email_factory()
    deliver_message(ea_1, msg)

    # The message should have been delivered to the inbox of ea_2.
    #
    mh = ea_2.MH()
    folder = mh.get_folder("inbox")
    stored_msg = folder.get(1)
    assert_email_equal(msg, stored_msg)

    # Create another level of aliasing.
    ea_3 = email_account_factory()
    ea_3.save()
    ea_2.alias_for.add(ea_3)
    ea_2.account_type = EmailAccount.ALIAS
    ea_2.save()

    # message sent to ea_1 will be delivered to ea_3
    #
    msg = email_factory()
    deliver_message(ea_1, msg)
    mh = ea_3.MH()
    folder = mh.get_folder("inbox")
    stored_msg = folder.get(1)
    assert_email_equal(msg, stored_msg)

####################################################################
#
def test_deliver_to_multiple_aliases(email_account_factory, email_factory):
    ea_1 = email_account_factory(account_type=EmailAccount.ALIAS)
    ea_1.save()
    ea_2 = email_account_factory()
    ea_2.save()
    ea_3 = email_account_factory()
    ea_3.save()

    ea_1.alias_for.add(ea_2)
    ea_1.alias_for.add(ea_3)

    msg = email_factory()
    deliver_message(ea_1, msg)

    mh_2 = ea_2.MH()
    folder = mh_2.get_folder("inbox")
    stored_msg = folder.get(1)
    assert_email_equal(msg, stored_msg)

    mh_3 = ea_3.MH()
    folder = mh_3.get_folder("inbox")
    stored_msg = folder.get(1)
    assert_email_equal(msg, stored_msg)

####################################################################
#
def test_email_account_alias_depth(
    email_account_factory, email_factory, caplog
):
    """
    we only let an alias go three deep. if we try to alias more than that
    it will be delivered at a higher level. also a warning will be logged.
    """
    # Make a list of email accounts, aliasing them to the next account.
    email_accounts = []
    prev_ea = None
    for i in range(EmailAccount.MAX_ALIAS_DEPTH + 2):
        ea = email_account_factory(account_type=EmailAccount.ALIAS)
        ea.save()
        email_accounts.append(ea)

        if prev_ea:
            prev_ea.alias_for.add(ea)
        prev_ea = ea

    # The message should be delivered to the max alias depth email
    # account. Also a message should have been logged about this.
    #
    msg = email_factory()
    deliver_message(email_accounts[0], msg)

    assert "Deliver recursion too deep for message" in caplog.text

    ea = email_accounts[EmailAccount.MAX_ALIAS_DEPTH]
    mh = ea.MH()
    folder = mh.get_folder("inbox")
    stored_msg = folder.get(1)
    assert_email_equal(msg, stored_msg)

####################################################################
#
def test_resent_forwarding(email_account_factory, email_factory, smtp):
    """
    Test forwarding of the message by having some headers re-written, the
    subject modified but the message otherwise sent on as it is.
    """
    ea_1 = email_account_factory(
        account_type=EmailAccount.FORWARDING,
        forward_style=EmailAccount.FORWARD_RESEND,
        forward_to=factory.Faker("email"),
    )
    ea_1.save()

    msg = email_factory()
    original_to = msg["To"]
    original_from = msg["From"]
    original_subj = msg["Subject"]

    deliver_message(ea_1, msg)

    # The message should have been delivered to our smtp mock using the
    # `send_message` call.
    #
    send_message = smtp.return_value.send_message
    assert send_message.call_count == 1
    assert send_message.call_args.kwargs == {
        "from_addr": ea_1.email_address,
        "to_addrs": [ea_1.forward_to],
    }

    sent_message = send_message.call_args.args[0]
    assert sent_message["Original-From"] == original_from
    assert sent_message["Original-Recipient"] == ea_1.email_address
    assert sent_message["Resent-From"] == ea_1.email_address
    assert sent_message["Resent-To"] == ea_1.forward_to
    assert sent_message["From"] == ea_1.email_address
    assert sent_message["To"] == original_to
    assert sent_message["Subject"] == f"Fwd: {original_subj}"

    assert_email_equal(msg, sent_message, ignore_headers=True)

####################################################################
#
def test_encapsulate_forwarding(email_account_factory, email_factory, smtp):
    """
    Test forwarding of the message by having the original message attached
    as an rfc822 attachment, the original content text being in the new
    message.
    """
    ea_1 = email_account_factory(
        account_type=EmailAccount.FORWARDING,
        forward_style=EmailAccount.FORWARD_ENCAPSULTE,
        forward_to=factory.Faker("email"),
    )
    ea_1.save()

    msg = email_factory()
    original_from = msg["From"]
    original_subj = msg["Subject"]

    deliver_message(ea_1, msg)

    # NOTE: in the models object we create a smtp_client. On the smtp_client
    #       the only thing we care about is that the `send_message` method was
    #       called with the appropriate values.
    #
    send_message = smtp.return_value.send_message
    assert send_message.call_count == 1
    assert send_message.call_args.kwargs == {
        "from_addr": ea_1.email_address,
        "to_addrs": [ea_1.forward_to],
    }

    sent_message = send_message.call_args.args[0]
    assert sent_message["Original-From"] == original_from
    assert sent_message["Original-Recipient"] == ea_1.email_address
    assert sent_message["Resent-From"] == ea_1.email_address
    assert sent_message["Resent-To"] == ea_1.forward_to
    assert sent_message["From"] == ea_1.email_address
    assert sent_message["To"] == ea_1.forward_to
    assert sent_message["Subject"] == f"Fwd: {original_subj}"

    # Look for the first message/rfc822 attachement. That should be our
    # forwarded message.
    #
    for attachment in sent_message.iter_attachments():
        if attachment.get_content_type() == "message/rfc822":
            print(attachment.get_payload(decode=True))
            assert attachment.get_payload(decode=True) == msg.as_bytes()

####################################################################
#
def test_deactivated_forward(email_account_factory, email_factory):
    """
    Deactivated email accounts can receive email, can alias email, but can
    not forward email. The account that tries to forward the email has it
    delivered locally.
    """
    ea_1 = email_account_factory(
        account_type=EmailAccount.FORWARDING,
        forward_to=factory.Faker("email"),
        deactivated=True,
    )
    ea_1.save()

    msg = email_factory()

    # Since this account is forwarding, but it is deactivated the message will
    # be locally delivered.
    #
    deliver_message(ea_1, msg)
    mh = ea_1.MH()
    folder = mh.get_folder("inbox")
    stored_msg = folder.get(1)
    assert_email_equal(msg, stored_msg)


from typing import Callable

from numpy import ndarray

from gym_jadx.ui.Button import Button
from gym_jadx.util.MatrixUtils import MatrixUtils

class Checkbox(Button):
    ARRAY_CLICKED = MatrixUtils.get_numpy_array_of_image('chk_clicked.png')
    ARRAY_UNCLICKED = MatrixUtils.get_numpy_array_of_image('chk_unclicked.png')

    def __init__(self,
                 relative_coordinates: ndarray,
                 reward: int,
                 on_click_listener: Callable[[Button], None] = lambda b: None):
        """
        A :class:`Button` with checkbox appearance

        :param relative_coordinates: Coordinates of the button relative to its parent Drawable
        :param reward: The amount of reward this button generates when clicked for the first time
        :param on_click_listener: Function which is called when the button is clicked
        """
        super().__init__(Checkbox.ARRAY_UNCLICKED,
                         relative_coordinates,
                         Checkbox.ARRAY_CLICKED,
                         reward,
                         on_click_listener,
                         False)


from decimal import Decimal
from django.test import TestCase
from django.utils import timezone

from ..game import Game
from ..purchase import Purchase
from ....review.models import Review

from ....user.utils.mock_user import create_mock_user

TWOPLACES = Decimal(10) ** -2

orig_value = {
    'name': 'game_0',
    'description': 'foo',
    'url': 'https://localhost:7999/',
    'price': 0
}
new_value = {
    'name': 'game_1',
    'description': 'bar',
    'url': 'https://localhost:7998/',
    'price': 0.01
}

class GameTestCase(TestCase):
    def setUp(self):
        """Set up some variables used in some tests."""
        # Create object without reviews
        self.no_grade = Game.objects.create(
            name='no_grade',
            url='https://localhost:8000/',
            price=0,
        )
        # Create some mock users
        self.user_0 = create_mock_user()
        self.user_1 = create_mock_user(1)
        # Create object with reviews
        self.with_grade = Game.objects.create(
            name='with_grade',
            url='https://localhost:8001/',
            price=0,
        )
        Purchase.objects.create(
            created_by=self.user_1.profile,
            game=self.with_grade,
            purchased_at=timezone.now(),
            price=10,
        )
        Purchase.objects.create(
            created_by=self.user_0.profile,
            game=self.with_grade,
            purchased_at=timezone.now(),
            price=10,
        )
        # Create mock review
        Review.objects.create(
            game=self.with_grade,
            created_by=self.user_0.profile,
            grade=5,
        )

    def test_games_can_be_created(self):
        """Create a game and assert."""
        game = Game.objects.create(
            name=orig_value['name'],
            url=orig_value['url'],
            price=orig_value['price'],
            description=orig_value['description'],
        )
        self.assertIsInstance(game, Game)
        self.assertEqual(game.__str__(), game.name)

    def test_games_can_be_updated(self):
        """Create a game, update fields, refresh from db and assert."""
        # create the instance with initial values
        game_0 = Game.objects.create(
            name=orig_value['name'],
            url=orig_value['url'],
            price=orig_value['price'],
            description=orig_value['description'],
        )
        # update the values and save
        game_0.name = new_value['name']
        game_0.url = new_value['url']
        game_0.price = new_value['price']
        game_0.description = new_value['description']
        game_0.save()
        # Refresh the instance with the one from database
        game_0.refresh_from_db()
        # Assert each field
        self.assertEqual(game_0.__str__(), new_value['name'])
        self.assertEqual(game_0.url, new_value['url'])
        self.assertEqual(game_0.price, Decimal(new_value['price']).quantize(TWOPLACES))
        self.assertEqual(game_0.description, new_value['description'])

    def test_games_can_have_grade(self):
        """Games that have grade can be identified"""
        self.with_grade.refresh_from_db()
        self.assertEqual(self.no_grade.grade, None, msg='Grade should not have value.')
        self.assertEqual(self.with_grade.grade, 5, msg='Grade should have value.')

    def test_games_grade_is_average(self):
        """Games that have grade, will have average"""
        # Create another review
        Review.objects.create(
            game=self.with_grade,
            created_by=self.user_1.profile,
            grade=3,
        )
        # Get data again
        self.assertEqual(self.with_grade.grade, 4, msg='Grade is average.')


#!/usr/bin/env python
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2017
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program.  If not, see [http://www.gnu.org/licenses/].
"""This module contains the Promise class."""

import logging
from threading import Event

logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())

class Promise(object):
    """A simple Promise implementation for the run_async decorator."""

    def __init__(self, pooled_function, args, kwargs):
        self.pooled_function = pooled_function
        self.args = args
        self.kwargs = kwargs
        self.done = Event()
        self._result = None
        self._exception = None

    def run(self):
        try:
            self._result = self.pooled_function(*self.args, **self.kwargs)

        except Exception as exc:
            logger.exception('An uncaught error was raised while running the promise')
            self._exception = exc

        finally:
            self.done.set()

    def __call__(self):
        self.run()

    def result(self, timeout=None):
        self.done.wait(timeout=timeout)
        if self._exception is not None:
            raise self._exception  # pylint: disable=raising-bad-type
        return self._result

    @property
    def exception(self):
        return self._exception