from typing import Any, List, Optional, Tuple, TypedDict, Union

from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser
from django.contrib.contenttypes.models import ContentType
from django.db.models import Case, IntegerField, Q, QuerySet, Value, When

from baserow.core.handler import CoreHandler
from baserow.core.mixins import TrashableModelMixin
from baserow.core.models import Group, GroupUser
from baserow.core.object_scopes import CoreObjectScopeType
from baserow.core.registries import object_scope_type_registry, subject_type_registry
from baserow.core.types import ScopeObject, Subject
from baserow_enterprise.exceptions import ScopeNotExist, SubjectNotExist
from baserow_enterprise.models import RoleAssignment
from baserow_enterprise.role.models import Role
from baserow_enterprise.signals import (
    role_assignment_created,
    role_assignment_deleted,
    role_assignment_updated,
)
from baserow_enterprise.teams.models import Team, TeamSubject

from .constants import (
    NO_ACCESS_ROLE_UID,
    NO_ROLE_LOW_PRIORITY_ROLE_UID,
    ROLE_ASSIGNABLE_OBJECT_MAP,
    SUBJECT_PRIORITY,
)

User = get_user_model()

class RoleAssignmentDict(TypedDict):
    scope: Any
    scope_id: int
    scope_type: ContentType
    subject: Any
    subject_id: int
    subject_type: ContentType
    role: Role

class RoleAssignmentHandler:
    def _get_role_assignments_for_valid_subjects_qs(self) -> QuerySet:
        """
        Constructs base queryset for role_assignments in order to filter out any
        role assignment related to a trashed subject.
        """

        id_filters = Q()
        for subject_type in subject_type_registry.get_all():
            if issubclass(subject_type.model_class, TrashableModelMixin):
                id_filters.add(
                    ~Q(
                        subject_id__in=subject_type.model_class.trash.all().values_list(
                            "id", flat=True
                        ),
                        subject_type=subject_type.get_content_type(),
                    ),
                    Q.AND,
                )

        return RoleAssignment.objects.filter(id_filters)

    @classmethod
    def _get_role_caches(cls):
        if not getattr(cls, "_init", False):
            cls._init = True
            cls._role_cache_by_uid = {}
            cls._role_cache_by_id = {}
            for role in Role.objects.prefetch_related("operations").all():
                cls._role_cache_by_uid[role.uid] = role
                cls._role_cache_by_id[role.id] = role

        return cls._role_cache_by_uid, cls._role_cache_by_id

    def get_role_by_uid(self, role_uid: str, use_fallback=False) -> Role:
        """
        Returns the role for the given uid.
        If `role_uid` isn't found, we fall back to `role_fallback`.

        :param role_uid: The uid we want the role for.
        :param use_fallback: If true and the role_uid is not found, we fallback to
           the NO_ACCESS role.
        :return: A role.
        """

        # Translate MEMBER to builder for compatibility with basic "role" name.
        if role_uid == "MEMBER":
            role_uid = "BUILDER"

        try:
            if role_uid not in self._get_role_caches()[0]:
                raise Role.DoesNotExist()

            return self._get_role_caches()[0][role_uid]
        except Role.DoesNotExist:
            if use_fallback:
                return self.get_role_by_uid(NO_ACCESS_ROLE_UID)
            else:
                raise

    def get_role_by_id(self, role_id: int) -> Role:
        """
        Returns the role for the given id.

        :param role_id: The id we want the role for.
        :return: A role.
        """

        if role_id not in self._get_role_caches()[1]:
            raise Role.DoesNotExist()

        return self._get_role_caches()[1][role_id]

    def get_current_role_assignment(
        self,
        subject: Union[AbstractUser, Team],
        group: Group,
        scope: Optional[Any] = None,
    ) -> Union[RoleAssignment, None]:
        """
        Returns the current assigned role for the given Group/Subject/Scope.

        :param subject: The subject we want the role for.
        :param group: The group in which you want the user or team role.
        :param scope: An optional scope on which the role applies.
        :return: The current `RoleAssignment` or `None` if no role is defined for the
            given parameters.
        """

        if scope is None:
            scope = group

        content_types = ContentType.objects.get_for_models(scope, subject)

        # If we are assigning a role to a group, we store the role uid in
        # the `.permissions` property of the `GroupUser` object instead to stay
        # compatible with other permission manager. This make it easy to switch from
        # one permission manager to another without losing nor duplicating information
        if (
            isinstance(scope, Group)
            and scope.id == group.id
            and isinstance(subject, User)
        ):
            try:
                group_user = group.get_group_user(subject)
                role = self.get_role_by_uid(group_user.permissions, use_fallback=True)
                # We need to fake a RoleAssignment instance here to keep the same
                # return interface
                return RoleAssignment(
                    subject=subject,
                    subject_id=subject.id,
                    subject_type=content_types[subject],
                    role=role,
                    group=group,
                    scope=scope,
                    scope_type=content_types[scope],
                )
            except GroupUser.DoesNotExist:
                return None

        try:
            role_assignment = (
                self._get_role_assignments_for_valid_subjects_qs()
                .select_related("role")
                .get(
                    scope_id=scope.id,
                    scope_type=content_types[scope],
                    group=group,
                    subject_id=subject.id,
                    subject_type=content_types[subject],
                )
            )

            return role_assignment
        except RoleAssignment.DoesNotExist:
            return None

    def get_roles_per_scope(
        self, group: Group, actor: AbstractUser, include_trash=False
    ) -> List[Tuple[Any, List[Role]]]:
        """
        Returns the RoleAssignments for the given actor in the given group. The roles
        are ordered by position of the role scope in the object hierarchy: the highest
        parent is before the lowest.

        :param group: The group the RoleAssignments belong to.
        :param actor: The actor for whom we want the RoleAssignments for.
        :param include_trash: If true then also checks even if given group has been
            trashed instead of raising a DoesNotExist exception.
        :return: A list of tuple containing the scope and the role ordered by scope.
            The higher a scope is high in the object hierarchy, the higher the tuple in
            the list.
        """

        actor_subject_type = subject_type_registry.get_by_model(actor)

        content_types = ContentType.objects.get_for_models(
            *[s.model_class for s in subject_type_registry.get_all()], Group
        )

        subjects_q = Q(
            subject_type=content_types[actor_subject_type.model_class],
            subject_id=actor.id,
        )

        # Add team roles
        user_teams_qs = TeamSubject.objects.filter(
            subject_type=content_types[actor_subject_type.model_class],
            subject_id=actor.id,
        )

        user_teams_ids = user_teams_qs.values_list("team_id", flat=True)

        subjects_q |= Q(
            subject_type=content_types[Team],
            subject_id__in=user_teams_ids,
        )

        scope_cases = [
            When(
                scope_type=ContentType.objects.get_for_model(scope_type.model_class),
                then=Value(scope_type.level),
            )
            for scope_type in [
                object_scope_type_registry.get(name)
                for name in ROLE_ASSIGNABLE_OBJECT_MAP
            ]
            if scope_type.type != CoreObjectScopeType.type
        ]

        role_priority_cases = [
            When(
                subject_type=content_types[subject_type.model_class],
                then=Value(order),
            )
            for order, subject_type in enumerate(
                [
                    subject_type_registry.get(subject_name)
                    for subject_name in SUBJECT_PRIORITY
                ]
            )
        ]

        role_assignments = (
            RoleAssignment.objects.filter(
                group=group,
            )
            .filter(subjects_q, ~Q(role__uid=NO_ROLE_LOW_PRIORITY_ROLE_UID))
            .annotate(
                scope_type_order=Case(
                    *scope_cases,
                    default=Value(0),
                    output_field=IntegerField(),
                ),
                role_priority=Case(
                    *role_priority_cases,
                    default=Value(0),
                    output_field=IntegerField(),
                ),
            )
            .order_by(
                "scope_type_order", "scope_id", "role_priority", "subject_id", "id"
            )
            .select_related("subject_type")
        )

        group_scope_param = (group.id, content_types[Group].id)
        # we are using a tuple of (scope.id, content_type.id) to prevent the query
        # automatically done when accessing the property from the role assignments
        # to query them all at once later
        roles_by_scope = {group_scope_param: []}
        priorities_by_scope = {}

        for role_assignment in role_assignments:
            scope_param = (role_assignment.scope_id, role_assignment.scope_type_id)
            role = self.get_role_by_id(role_assignment.role_id)
            priority = role_assignment.role_priority

            # We don't use defaultdict here to be sure we have the right key order
            if scope_param not in roles_by_scope:
                roles_by_scope[scope_param] = []

            existing_priority = priorities_by_scope.setdefault(scope_param, priority)
            if priority < existing_priority:
                roles_by_scope[scope_param] = [role]
            elif existing_priority == priority:
                roles_by_scope[scope_param].append(role)

        # Get the group level role by reading the GroupUser permissions property for
        # User actors.
        if isinstance(actor, User):

            # We want to get the group user even if the group is trashed as we still
            # want to support checking permissions on a trashed scope (the group).
            group_user = group.get_group_user(actor, include_trash=include_trash)

            group_level_role = self.get_role_by_uid(
                group_user.permissions,
                use_fallback=True,
            )
            if group_level_role.uid == NO_ROLE_LOW_PRIORITY_ROLE_UID:
                # Low priority role -> Use team role or NO_ACCESS if no team role
                if not roles_by_scope.get(group_scope_param):
                    roles_by_scope[group_scope_param] = [
                        self.get_role_by_uid(NO_ACCESS_ROLE_UID)
                    ]
            else:
                # Otherwise user role wins
                roles_by_scope[group_scope_param] = [group_level_role]

        roles_by_scope = [
            (self.get_scope(*key), value) for (key, value) in roles_by_scope.items()
        ]

        return roles_by_scope

    def get_computed_roles(
        self, group: Group, actor: AbstractUser, context: Any, include_trash=False
    ) -> List[Role]:
        """
        Returns the computed roles for the given actor on the given context.

        :param group: The group in which we want the roles.
        :param actor: The actor for whom we want the roles.
        :param context: The context on which we want to now the role.
        :param include_trash: If true then also checks even if given group has been
            trashed instead of raising a DoesNotExist exception.
        :return: A list of roles that applies on this context.
        """

        roles_by_scopes = self.get_roles_per_scope(
            group, actor, include_trash=include_trash
        )
        most_precise_roles = [
            RoleAssignmentHandler().get_role_by_uid(NO_ACCESS_ROLE_UID)
        ]

        for (scope, roles) in roles_by_scopes:
            if object_scope_type_registry.scope_includes_context(scope, context):
                # Check if this scope includes the context. As the role assignments
                # are sorted, the new scope is more precise than the previous one.
                # So we keep this new role.
                most_precise_roles = roles
            elif object_scope_type_registry.scope_includes_context(
                context, scope
            ) and any([r.uid != NO_ACCESS_ROLE_UID for r in roles]):
                # Here the user has a permission on a scope that is a child of the
                # context, then we grant the user permission on all read operations
                # for all parents of that scope and hence this context should be
                # readable.
                # For example, if you have a "BUILDER" role on only a table scope,
                # and the context here is the parent database of this table the
                # user should be able to read this database object so they can
                # actually have access to lower down.
                most_precise_roles.append(self.get_role_by_uid("VIEWER"))

        return most_precise_roles

    def assign_role(
        self,
        subject,
        group,
        role=None,
        scope=None,
    ) -> Optional[RoleAssignment]:
        """
        Assign a role to a subject in the context of the given group over a specified
        scope.

        :param subject: The subject targeted by the role.
        :param group: The group in which we want to assign the role.
        :param role: The role we want to assign. If the role is `None` then we remove
            the current role of the subject in the group for the given scope.
        :param scope: An optional scope on which the role applies. If no scope is given
            the group is used as scope.
        :return: The created RoleAssignment if role is not `None` else `None`.
        """

        if scope is None:
            scope = group

        if role is None:
            # Early return, we are removing the current role.
            self.remove_role(subject, group, scope=scope)
            return

        subject_type = subject_type_registry.get_by_model(subject)
        if not subject_type.is_in_group(subject.id, group):
            raise SubjectNotExist()

        if not object_scope_type_registry.scope_includes_context(group, scope):
            raise ScopeNotExist()

        content_types = ContentType.objects.get_for_models(scope, subject)

        # Group level permissions are not stored as RoleAssignment records
        if RoleAssignmentHandler.is_group_level_assignment(group, scope, subject):
            group_user = group.get_group_user(subject)
            new_permissions = "MEMBER" if role.uid == "BUILDER" else role.uid
            CoreHandler().force_update_group_user(
                None, group_user, permissions=new_permissions
            )

            # We need to fake a RoleAssignment instance here to keep the same
            # return interface
            return RoleAssignment(
                subject=subject,
                subject_id=subject.id,
                subject_type=content_types[subject],
                role=role,
                group=group,
                scope=scope,
                scope_type=content_types[scope],
            )

        role_assignment, created = RoleAssignment.objects.update_or_create(
            subject_id=subject.id,
            subject_type=content_types[subject],
            group=group,
            scope_id=scope.id,
            scope_type=content_types[scope],
            defaults={"role": role},
        )

        if created:
            role_assignment_created.send(
                self, subject=subject, group=group, scope=scope, role=role
            )
        else:
            role_assignment_updated.send(
                self, subject=subject, group=group, scope=scope, role=role
            )

        return role_assignment

    def remove_role(self, subject: Union[AbstractUser, Team], group: Group, scope=None):
        """
        Remove the role of a subject in the context of the given group over a specified
        scope.

        :param subject: The subject for whom we want to remove the role for.
        :param group: The group in which we want to remove the role.
        :param scope: An optional scope on which the existing role applied.
            If no scope is given the group is used as scope.
        """

        if scope is None:
            scope = group

        if RoleAssignmentHandler.is_group_level_assignment(group, scope, subject):
            group_user = group.get_group_user(subject)
            new_permissions = NO_ACCESS_ROLE_UID
            CoreHandler().force_update_group_user(
                None, group_user, permissions=new_permissions
            )
            return

        content_types = ContentType.objects.get_for_models(scope, subject)

        RoleAssignment.objects.filter(
            subject_id=subject.id,
            subject_type=content_types[subject],
            group=group,
            scope_id=scope.id,
            scope_type=content_types[scope],
        ).delete()
        role_assignment_deleted.send(self, subject=subject, group=group, scope=scope)

    def get_subject(self, subject_id: int, subject_type: str):
        """
        Helper method that returns the actual subject object given the subject_id and
        the subject type.

        :param subject_id: The subject id.
        :param subject_type: The subject type.
        """

        content_type = subject_type_registry.get(subject_type).get_content_type()
        return content_type.get_object_for_this_type(id=subject_id)

    def get_scope(self, scope_id: int, content_type_id: int) -> Any:
        """
        Helper method that returns the actual scope object given the scope ID and
        the scope type.

        :param scope_id: The scope id.
        :param content_type_id: The content_type id
        """

        content_type = ContentType.objects.get_for_id(content_type_id)
        return content_type.get_object_for_this_type(id=scope_id)

    def assign_role_batch(
        self,
        user: AbstractUser,
        group: Group,
        new_role_assignments: List[RoleAssignmentDict],
    ):
        """
        TODO: this function is orphaned until we have implemented it properly

        Creates role assignments in batch, this should be used if many role assignments
        are created at once, to be more efficient.

        :return:
        """

        return [
            self.assign_role(
                role_assignment["subject"],
                group,
                role=role_assignment["role"],
                scope=role_assignment["scope"],
            )
            for role_assignment in new_role_assignments
        ]

    def get_role_assignments(self, group: Group, scope=None):
        """
        Helper method that returns all role assignments given a scope and group.

        :param group: The group that the scope belongs to
        :param scope: The scope used for filtering role assignments
        """

        if isinstance(scope, Group) and scope.id == group.id:
            group_users = GroupUser.objects.filter(group=group)

            role_assignments = []

            for group_user in group_users:
                role_uid = group_user.permissions
                role = self.get_role_by_uid(role_uid, use_fallback=True)
                subject = group_user.user

                # TODO we probably shouldn't do this in a loop (performance)
                content_types = ContentType.objects.get_for_models(scope, subject)
                # We need to fake a RoleAssignment instance here to keep the same
                # return interface
                role_assignments.append(
                    RoleAssignment(
                        subject=subject,
                        subject_id=subject.id,
                        subject_type=content_types[subject],
                        role=role,
                        group=group,
                        scope=scope,
                        scope_type=content_types[scope],
                    )
                )
            return role_assignments
        else:
            qs = self._get_role_assignments_for_valid_subjects_qs()
            role_assignments = qs.filter(
                group=group,
                scope_id=scope.id,
                scope_type=ContentType.objects.get_for_model(scope),
            )
            return list(role_assignments)

    @classmethod
    def is_group_level_assignment(
        cls, group: Group, scope: ScopeObject, subject: Subject
    ):
        return scope == group and scope.id == group.id and isinstance(subject, User)


from typing import List

import torch
import torchvision

from ffcv.fields import IntField, RGBImageField
from ffcv.fields.decoders import IntDecoder, SimpleRGBImageDecoder
from ffcv.fields.rgb_image import CenterCropRGBImageDecoder, \
    RandomResizedCropRGBImageDecoder
from ffcv.loader import Loader, OrderOption
from ffcv.pipeline.operation import Operation
from ffcv.transforms import RandomResizedCrop, RandomHorizontalFlip, Cutout, \
    RandomTranslate, Convert, ToDevice, ToTensor, ToTorchImage, NormalizeImage
from ffcv.transforms.common import Squeeze
from ffcv.writer import DatasetWriter

def save_data_for_beton(dataset, root='../data'):
    if dataset == 'cifar10':
        trainset = torchvision.datasets.CIFAR10(root=root, train=True, download=True)
        testset = torchvision.datasets.CIFAR10(root=root, train=False, download=True)

    if dataset == 'cifar100':
        trainset = torchvision.datasets.CIFAR100(root=root, train=True, download=True)
        testset = torchvision.datasets.CIFAR100(root=root, train=False, download=True)

    if dataset == 'svhn':
        trainset = torchvision.datasets.SVHN(root=root, split='train', download=True)
        testset = torchvision.datasets.SVHN(root=root, split='test', download=True)

    if dataset == 'tiny':
        trainset = torchvision.datasets.ImageFolder(root + '/tiny-imagenet-200/train')
        testset = torchvision.datasets.ImageFolder(root + '/tiny-imagenet-200/val')

    if dataset == 'imagenet':
        trainset = torchvision.datasets.ImageFolder('imagenet_train_path')
        testset = torchvision.datasets.ImageFolder('imagenet_test_path')

        # for large dataset
        datasets = {
            'train': trainset,
            'test': testset
        }
        for (name, ds) in datasets.items():

            writer = DatasetWriter(f'imagenet_path/{dataset}_{name}.beton', {
                'image': RGBImageField(write_mode='jpg',
                                       max_resolution=256,
                                       compress_probability=0.5,
                                       jpeg_quality=90),
                'label': IntField(),
            }, num_workers=16)
            writer.from_indexed_dataset(ds, chunksize=100)

    else:
        # for small dataset
        datasets = {
            'train': trainset,
            'test': testset
        }
        for (name, ds) in datasets.items():
            writer = DatasetWriter(f'{root}/../ffcv_data/{dataset}/{dataset}_{name}.beton', {
                'image': RGBImageField(),
                'label': IntField(),},
                num_workers=16)
            writer.from_indexed_dataset(ds)

def get_fast_dataloader(dataset, train_batch_size, test_batch_size, num_workers=20, dist=True, shuffle=False):

    gpu = f'cuda:{torch.cuda.current_device()}'
    decoder = None

    if dataset == 'cifar10':
        mean = torch.tensor([0.4914, 0.4822, 0.4465])*255
        img_size = 32
    if dataset == 'cifar100':
        mean = torch.tensor([0.5071, 0.4867, 0.4408])*255
        img_size = 32
    if dataset == 'svhn':
        mean = torch.tensor([0.43090966, 0.4302428, 0.44634357])*255
        img_size = 32
    if dataset == 'tiny':
        mean = torch.tensor([0.48024578664982126, 0.44807218089384643, 0.3975477478649648])*255
        img_size = 64

    if dataset == 'imagenet':
        # fix size
        init_size = 160
        orgin_size = 256
        test_size = 224

        decoder = RandomResizedCropRGBImageDecoder((init_size, init_size))

        paths = {
            'train': 'imagenet_train_path',
            'test': 'imagenet_test_path'
        }
        # for large dataset
        loaders = {}
        for name in ['train', 'test']:
            if name == 'train':
                image_pipeline: List[Operation] = [decoder,
                                                   RandomHorizontalFlip()]
            else:
                image_pipeline: List[Operation] = [CenterCropRGBImageDecoder((test_size, test_size), test_size/orgin_size)]

            label_pipeline: List[Operation] = [IntDecoder(), ToTensor(), Squeeze(), ToDevice_modified(torch.device(gpu), non_blocking=True)]

            image_pipeline.extend([
                ToTensor(),
                ToDevice_modified(torch.device(gpu), non_blocking=True),
                ToTorchImage(),
                Normalize_and_Convert(torch.float16, True)
            ])
            if shuffle:
                order = OrderOption.RANDOM
            else:
                order = OrderOption.RANDOM if name == 'train' else OrderOption.SEQUENTIAL

            loaders[name] = Loader(paths[name], batch_size=train_batch_size if name == 'train' else test_batch_size,
                                   num_workers=num_workers, order=order, drop_last=(name == 'train'), os_cache=True,
                                   distributed=dist, pipelines={'image': image_pipeline, 'label': label_pipeline},
                                   seed = 0)
    else:
        # for small dataset
        paths = {
            'train': f'../ffcv_data/{dataset}/{dataset}_train.beton',
            'test': f'../ffcv_data/{dataset}/{dataset}_test.beton'
        }

        loaders = {}
        for name in ['train', 'test']:
            image_pipeline: List[Operation] = [SimpleRGBImageDecoder()]
            label_pipeline: List[Operation] = [IntDecoder(), ToTensor(), ToDevice_modified(torch.device(gpu)), Squeeze()]
            if name == 'train':
                image_pipeline.extend([
                    RandomHorizontalFlip(),
                    RandomTranslate(padding=int(img_size / 8.), fill=tuple(map(int, mean))),
                ])
            image_pipeline.extend([
                ToTensor(),
                ToDevice_modified(torch.device(gpu), non_blocking=True),
                ToTorchImage(),
                Normalize_and_Convert(torch.float16, True)
            ])

            order = OrderOption.RANDOM if name == 'train' else OrderOption.SEQUENTIAL

            loaders[name] = Loader(paths[name], batch_size=train_batch_size if name == 'train' else test_batch_size,
                                num_workers=num_workers, order=order, drop_last=(name == 'train'), os_cache=True,
                                   pipelines={'image': image_pipeline, 'label': label_pipeline})

    return loaders['train'], loaders['test'], decoder

from typing import Callable, Optional, Tuple
from dataclasses import replace
from ffcv.pipeline.state import State
from ffcv.pipeline.allocation_query import AllocationQuery

class Normalize_and_Convert(Operation):
    def __init__(self, target_dtype, target_norm_bool):
        super().__init__()
        self.target_dtype = target_dtype
        self.target_norm_bool = target_norm_bool

    def generate_code(self) -> Callable:
        def convert(inp, dst):
            if self.target_norm_bool:
                inp = inp / 255.0
            return inp.type(self.target_dtype)

        convert.is_parallel = True

        return convert

    def declare_state_and_memory(self, previous_state: State) -> Tuple[State, Optional[AllocationQuery]]:
        return replace(previous_state, dtype=self.target_dtype), None

from ffcv.transforms import ToDevice
class ToDevice_modified(ToDevice):
    def __init__(self, device, non_blocking=True):
        super(ToDevice_modified, self).__init__(device, non_blocking)

    def generate_code(self):
        def to_device(inp, dst):
            if len(inp.shape) == 4:
                if inp.is_contiguous(memory_format=torch.channels_last):
                    dst = dst.reshape(inp.shape[0], inp.shape[2], inp.shape[3], inp.shape[1])
                    dst = dst.permute(0, 3, 1, 2)

            if len(inp.shape) == 0:
                inp = inp.unsqueeze(0)

            dst = dst[:inp.shape[0]]
            dst.copy_(inp, non_blocking=self.non_blocking)
            return dst

        return to_device


import discord
from discord.ext import commands
import datetime
import humanize
from classes import checks
import typing
from classes import CustomBotClass

class AltFinder(commands.Cog):

    def __init__(self, bot: CustomBotClass.CustomBot):
        self.bot = bot

    @commands.command()
    @commands.has_permissions(kick_members=True)
    @commands.guild_only()
    async def alts(self, ctx, dur: typing.Optional[str]=None, size: int = 10):
        if dur:
            if not dur.lower().endswith("d"):
                return await ctx.send("The duration must be days like `7d`")
        alts = []

        paginator = commands.Paginator(prefix="```yaml", suffix="```", max_size=1000)
        counter = 0
        if dur:
            for member in ctx.guild.members:
                delta = datetime.timedelta(days=int(dur[:-1]))
                if (datetime.datetime.now() - member.created_at) < delta:
                    if counter > size:
                        break
                    alts.append(member)
                    counter += 1
            alts.sort(reverse=True, key=checks.created_at)
            for alt in alts:
                paginator.add_line(f"{alts.index(alt)+1}) {alt} Created at {humanize.naturaldate(alt.created_at.date())} ({humanize.precisedelta(datetime.datetime.now() - alt.created_at)})\n")
        if not dur:
            all_membrs = ctx.guild.members
            all_membrs.sort(reverse=True, key=checks.created_at)
            new_all_membrs = all_membrs[:size]
            for alt in new_all_membrs:
                paginator.add_line(
                    f"{alts.index(alt)+1}) {alt} Created at {humanize.naturaldate(alt.created_at.date())} ({humanize.precisedelta(datetime.datetime.now() - alt.created_at)})\n")
        for page in paginator.pages:
            title = f"Accounts less than {humanize.precisedelta(delta)} old" if dur else "Newest accounts"
            embed=discord.Embed(title=title, description=page, color=self.bot.color)
            await ctx.send(embed=embed)

def setup(bot):
    bot.add_cog(AltFinder(bot))


# Write a function named "flatten" that flattens a nested list.
from stacknqueue import *

def flatten(lst):
    stk = CreateStack()
    Push([lst], stk)
    flat = []
    while IsEmptyStack(stk) == False:
        top = Pop(stk)
        print(top)
        if type(top) == list:
            # can also append one by one in a reversed loop
            for i in top[::-1]:
                #print(stk)
                Push(i, stk)
        else:
                flat.append(top)
    return flat

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

CENG111/Python/Exercises/Stack Queue Advanced Iteration Advanced Recursion Exercies/flatten.py


from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.shortcuts import render, get_object_or_404, redirect
from django.utils.text import slugify

from . models import (
	Category,
	SubCategory,
	Prod,
	ProdMedia,
	RequestProd,
	)

from . forms import (
	CreateCategoryForm,
	CreateSubCategoryForm,
	CreateProdForm,
	CreateProdMediaForm,
	)
"""

"""

# def categoryProds(param=None):
# 	if param

def index(request):
	template_name = './main/index.html'
	specials = Prod.objects.filter(special=True)
	subCategories = SubCategory.objects.all()
	hotDeals = Prod.objects.filter(hotDeal=True)
	newArrivals = Prod.objects.all().order_by('-pk')[:8]
	topSellings = Prod.objects.all()[:20]
	prods = Prod.objects.all()[:12]
	context = {
		'subCategories':subCategories,
		'hotDeals':hotDeals,
		'specials':specials,
		'prods':prods,
		'newArrivals':newArrivals,
		'topSellings':topSellings,
		}
	return render(request, template_name, context)

def shop(request, subCategorySlug):
	template_name = './main/shop.html'
	category = request.GET.get('category')
	cat = False
	if category:
		#category = get_object_or_404(Category, name=name)
		prods = Prod.objects.filter(subCategory__category__name=category)
		cat = True
	else:
		subCategory = get_object_or_404(SubCategory, slug=subCategorySlug)
		prods = subCategory.prod_set.all().order_by('-pk')
	# subCategories = subCategory.category.subcategory_set.exclude(slug=subCategorySlug)
	hotDeals = Prod.objects.filter(hotDeal=True)
	context = {'prods':prods, 'hotDeals':hotDeals, 'cat':cat}
	return render(request, template_name, context)

@login_required
def prods(request):
	template_name = './main/prods.html'
	prods = Prod.objects.all().order_by('-pk')[:20]
	search = request.GET.get('subCategory')
	subCategories = SubCategory.objects.all()
	if search:
		subCategory = get_object_or_404(SubCategory, slug=search)
		prods = Prod.objects.filter(subCategory=subCategory)
	context = {'prods':prods, 'subCategories':subCategories}
	return render(request, template_name, context)

def prodDetail(request, prodSlug):
	template_name = './main/prodDetail.html'
	prod = get_object_or_404(Prod, slug=prodSlug)
	relatedProds = prod.subCategory.prod_set.all()
	context = {'prod':prod, 'relatedProds':relatedProds}
	return render(request, template_name, context)

def search(request):
	template_name = './main/search.html'
	param = request.GET.get('search')
	noResult = False
	send = False
	prods = Prod.objects.all()
	pop = False
	filterSet = []
	if param:
		#Giving preferences to names first

		filterSet.extend(prods.filter(
			Q(name__icontains=param)
			).distinct()
			)
		filterSet.extend(prods.filter(
			Q(keywords__icontains=param)|
			Q(subCategory__name__icontains=param)|
			Q(subCategory__category__name__icontains=param)
			).distinct()
			)

	if len(filterSet) == 0:
		noResult = False
		pop = True

	if request.method == "POST":
		prodName = request.POST.get('product')
		phoneNumber = request.POST.get('phoneNumber')
		requestProd = RequestProd(name=prodName)
		if phoneNumber:
			requestProd.phoneNumber = int(phoneNumber)
		requestProd.save()
		noResult = False
		send = True

	context = {'prods':filterSet, 'noResult':noResult, 'send':send, 'pop':pop}
	return render(request, template_name, context)
"""
Category section
"""
#Will display together with Subcategories
@login_required
def categories(request):
	if request.user.is_superuser:
		template_name = './categories.html'
		categories = Category.objects.all()
		context = {'categories':categories}
		return render(request, template_name, context)
	else:
		return redirect('product:noPerm')

@login_required
def createCategory(request):
	if request.user.is_superuser:
		template_name = './form/createCategory.html'
		if request.method == "POST":
			form = CreateCategoryForm(request.POST)
			if form.is_valid():
				newForm = form.save(commit=False)
				newForm.slug = slugify(newForm.name)
				newForm.save()
				return redirect("product:categories")
		else:
			form = CreateCategoryForm()

		context = {"form":form}
		return render(request, template_name, context)
	else:
		return redirect('product:noPerm')

@login_required
def updateCategory(request, categorySlug):
	if request.user.is_superuser:
		template_name = './form/updateCategory.html'
		category = get_object_or_404(Category, slug=categorySlug)
		if request.method == "POST":
			form = CreateCategoryForm(request.POST, request.FILES, instance=category)
			if form.is_valid():
				newForm = form.save()
				newForm.slug = slugify(newForm.name)
				newForm.save()
				return redirect('product:categories')
		else:
			form = CreateCategoryForm(instance=category)
		context = {'form':form}
		return render(request, template_name, context)
	else:
		return redirect('product:noPerm')

@login_required
def deleteCategory(request, categorySlug):
	if request.user.is_superuser:
		category = get_object_or_404(Category, slug=categorySlug)
		category.delete()
		return redirect('product:categories')
	else:
		return redirect('product:noPerm')

"""
Subcategory section
"""
@login_required

@login_required
def createSubCategory(request):
	if request.user.is_superuser:
		template_name = './form/createSubCategory.html'
		if request.method == "POST":
			form = CreateSubCategoryForm(request.POST, request.FILES)
			if form.is_valid():
				newForm = form.save(commit=False)
				newForm.slug = slugify(newForm.name)
				newForm.save()
				return redirect('product:categories')
		else:
			form = CreateSubCategoryForm()
		context = {"form":form}
		return render(request, template_name, context)
	else:
		return redirect('product:noPerm')

@login_required
def updateSubCategory(request, subCategorySlug):
	if request.user.is_superuser:
		template_name = './form/updateSubCategory.html'
		subCategory = get_object_or_404(Subcategory, slug=subCategorySlug)
		if request.method == "POST":
			form = CreateSubCategoryForm(request.POST, request.FILES, instance=subCategory)
			if form.is_valid():
				newForm = form.save(commit=False)
				newForm.slug = slugify(newForm.name)
				newForm.save()
				return redirect('product:categories')
		else:
			form = CreateSubCategoryForm(instance=subCategory)
		context = {'form':form}
		return render(request, template_name, context)
	else:
		return redirect('product:noPerm')

@login_required
def deleteSubCategory(request, subCategorySlug):
	if request.user.is_superuser:
		subCategory = get_object_or_404(Subcategory, slug=subCategorySlug)
		subCategory.delete()
		return redirect('product:categories')
	else:
		return redirect("product:noPerm")

"""
Product section
"""

@login_required
def createProd(request):
	if request.user.is_superuser:
		template_name = './form/createProd.html'
		success = False
		if request.method == "POST":
			form = CreateProdForm(request.POST)
			pic1 = request.FILES.get('pic1', None)
			pic2 = request.FILES.get('pic2', None)
			pic3 = request.FILES.get('pic3', None)
			if form.is_valid():
				newForm = form.save(commit=False)
				last = Prod.objects.last()
				slug = "{0} {1}".format(newForm.name, last.id)
				newForm.slug = slugify(slug)
				try:
					origPrice = form.cleaned_data['origPrice']
					price = form.cleaned_data['price']
					newForm.discount = (origPrice - price)/origPrice *100
				except:
					None
				newForm.save()
				if pic1:
					media1 = ProdMedia(prod=newForm, pic=pic1)
					media1.save()

				if pic2:
					media2 = ProdMedia(prod=newForm, pic=pic2)
					media2.save()

				if pic3:
					media3 = ProdMedia(prod=newForm, pic=pic3)
					media3.save()
				success = True
		else:
			form = CreateProdForm()

		context = {"form":form, 'success':success}
		return render(request, template_name, context)
	else:
		return redirect('product:noPerm')

@login_required
def updateProd(request, prodSlug):
	if request.user.is_superuser:
		template_name = './form/updateProd.html'
		prod = get_object_or_404(Prod, slug=prodSlug)
		success = False
		if request.method == "POST":
			form = CreateProdForm(request.POST, instance=prod)
			pic1 = request.FILES.get('pic1', None)
			pic2 = request.FILES.get('pic2', None)
			pic3 = request.FILES.get('pic3', None)
			if form.is_valid():
				newForm = form.save(commit=False)
				last = Prod.objects.last()
				slug = "{0} {1}".format(newForm.name, last.id)
				newForm.slug = slugify(slug)
				try:
					origPrice = form.cleaned_data['origPrice']
					price = form.cleaned_data['price']
					newForm.discount = (origPrice - price)/origPrice *100
				except:
					None
				newForm.save()
				if pic1:
					try:
						media1 = ProdMedia.objects.get(pk=1)
						media1.pic = pic1
					except:
						media1 = ProdMedia(prod=newForm, pic=pic1)
					media1.save()

				if pic2:
					try:
						media2 = ProdMedia.objects.get(pk=2)
						media2.pic = pic2
					except:
						media2 = ProdMedia(prod=newForm, pic=pic2)
					media2.save()
				if pic3:
					try:
						media3 = ProdMedia.objects.get(pk=3)
						media3.pic = pic3
					except:
						media3 = ProdMedia(prod=newForm, pic=pic3)
					media3.save()
				success = True
		else:
			form = CreateProdForm(instance=prod)

		context = {"form":form, 'success':success}
		return render(request, template_name, context)
	else:
		return redirect('product:noPerm')

@login_required
def deleteProd(request, prodSlug):
	if request.user.is_superuser:
		prod = get_object_or_404(Prod, slug=prodSlug)
		prod.delete()
		return redirect('product:prods')
	else:
		return redirect('product:noPerm')
"""
Prduct Media section
Does not have update if you want just delete the file and add another
"""

@login_required
def createProdMedia(request):
	if request.user.is_superuser:
		template_name = './form/createProdMediaCategory.html'
		if request.method == "POST":
			form = CreateProdMediaForm(request.FILES)
			if form.is_valid():
				form.save()
		else:
			form = CreateProdMediaForm()

		context = {"form":form}
		return render(request, template_name, context)
	else:
		return redirect('product:noPerm')

@login_required
def deleteProdMedia(request, prodMediaSlug):
	if request.user.is_superuser:
		prodMedia = get_object_or_404(ProdMedia, slug=prodMediaSlug)
		prodMedia.delete()
		return redirect('product:products')
	else:
		return redirect('product:noPerm')

def noPerm(request):
	template_name = './errors/noPerm.html'
	return render(request, template_name)

@login_required
def requestProd(request):
	template_name = './main/requestProd.html'
	requestProds = RequestProd.objects.all()

	if request.method == "POST":
		requestProdId = int(request.POST.get('id'))
		requestP = get_object_or_404(RequestProd, pk=requestProdId)
		requestP.delete()

	context= {'requestProds':requestProds}
	return render(request, template_name, context)


from collections import deque

n = int(input())

# 화면 이모티콘, 클립보드 이모티콘 배열
dist = [ [-1] * (n+1) for _ in range(n+1) ]

q = deque()
q.append((1,0))
dist[1][0] = 0
while q:
    s, c = q.popleft()
    # 1. 화면 클립보드에 복사
    if dist[s][s] == -1:
        dist[s][s] = dist[s][c] + 1
        q.append((s,s))
    # 2. 클립보드를 화면에 복사
    if s + c <= n and dist[s+c][c] == -1:
        dist[s+c][c] = dist[s][c] + 1
        q.append((s+c,c))
    # 3. 화면 내용 하나 빼기
    if s - 1 >= 0 and dist[s-1][c] == -1:
        dist[s-1][c] = dist[s][c] + 1
        q.append((s-1,c))

answer = -1

for i in range(n+1):
    if dist[n][i] != -1:
        if answer == -1 or answer > dist[n][i]:
            answer = dist[n][i]
print(answer)


class nó:
    def __init__(self, value):
        self.valor = value
        self.esq = None
        self.dir = None
    def print_posorder(self):
        if(self.esq is not None):
            self.esq.print_posorder()
        if(self.dir is not None):
            self.dir.print_posorder()
        print(self.valor, end='')

def find_tree(preoder, inorder):
    raiz = nó(preoder[0])
    inorder_esq, inorder_dir = inorder.split(preoder[0])
    preoder_esq = preoder[1:len(inorder_esq)+1]
    preoder_dir = preoder[len(inorder_esq)+1:]
    if(len(preoder_esq)>0):
        raiz.esq = find_tree(preoder_esq, inorder_esq)
    if(len(preoder_dir)>0):
        raiz.dir = find_tree( preoder_dir, inorder_dir)
    return raiz

n_testes = int(input())
for i in range(n_testes):
    num_nos, preorder, inorder = input().split()

    arvre = find_tree(preorder, inorder)
    arvre.print_posorder()
    print("")


#with out expection handling
n = int(input('Enter a number to validate division by zero'))
div = 100/n
print('result is ',div)

d=int(input('Enter a number to validate zero division'))
try:
    a=100/d
    print(a)
except:
    print('Exception : Enter a positive number')
else:
    print('No exception')

d=input('Enter a number to validate zero division')
try:
    a=100/d
    print(a)
except Exception as e:
    print('Enter a number to validate zero division')
    print('Exception occured ',e.trace())
else:
    print('No exception')

d = int(input('Enter a number to validate division by zero'))
try:
    a=10/d
    print(a)
except ArithmeticError:
    print("This statement is raising an exception")
else:
    print("No exception proceed")

print ('after the exception')
#Except with no exception

try:
    a=10/'a'
    print(a)
except Exception as e:
    print("Exception : ",e)
else:
    print("Proceed no exception")

#Declaring multiple exception
try:
    #a=10/0
    a=10/'raghu'
    print(a)
#except ArithmeticError,NameError: - 3.6 does not support
except ZeroDivisionError:
    print("ZeroDivisionError")
except ArithmeticError:
    print("ArithmeticError")
except:

    print("Generic Error")
else:
    print("Successfully Done")
#Finally Block

try:
    #a=10/0;
    a=10/2;
    print(a)
except ZeroDivisionError:
    print(ZeroDivisionError)
finally:
    print("Finally block is always called")
a=2
print('value of a ',a)
try:
   a=10/0;
   a=10/2;
   print(a)
except ZeroDivisionError:
   print(ZeroDivisionError)
finally:
    #print(a)
    b=29/(a+2)
    print("Finally block is always called and the result is: ",b)

#Raise an exception

try:
    a=10
    print(a)
    raise NameError("Hello")
except NameError as e:
    print("An exception occured :",e)

#Custom exception
class ErrorInCode(Exception):
    def __init__(self,data):
     self.data = data
    def __str__(self):
        return repr('Error Code ' +str(self.data))
try:
    raise ErrorInCode(2000)
except ErrorInCode as ae:
#except ErrorInCode:
    print("Received error :",ErrorInCode)
    print("Received error :",ae)

class Student(object):
	def __init__(self, name, age, twitter_url=None, google_plus=None, youtube_channel=None):
		self.name = name
		self.age = age
		self.twitter_url = twitter_url
		self.google_plus = google_plus
 #       self.youtube_channel = youtube_channel

	def __str__(self):
		# Override to print a readable string presentation of your object
		# below is a dynamic way of doing this without explicity constructing the string manually
		return ', '.join(['{key}={value}'.format(key=key, value=self.__dict__.get(key)) for key in self.__dict__])

student = Student(name='Jone', age=23, twitter_url='http://twitter.com/jone')
print(student)

#class InvalidAge(object):
class InvalidAge(Exception):
    def __init__(self,data):
     self.data = data

    def __str__(self):
        #print('over riding str')
        #return repr('Invalid Age ' +str(self.data))
        return 'Invalid age '
    '''
    def __repr__(self):
        print('overriding repr')
    '''
age = int(input ('Enter your age'))
if (age >= 18):
    print('you are eligible to vote')
else:
    print('you are not eligible to vote')
    raise InvalidAge(age)

class InvalidMarks(Exception):
    def __init__(self,data):
     self.data = data
    def __str__(self):
        return repr('Invalid marks ' +str(self.data))

marks=int(input('Enter your marks '))
if(marks<0 or marks>100):
    print('Marks is invalid ')
    raise  InvalidMarks(marks)
else:
    print('Marks is valid')

class InsufficientBal(Exception):
    def __init__(self,actno,amt):
        self.actno = actno
        self.amt = amt
    def __str__(self):
        return repr('Insufficient balance ' +str(self.amt))

class Account():
    def __init__(self,actno,name,mobile,email,idproof):
        self.actno = actno
        self.actno=actno
        self.mobile = mobile
        self.email = email
        self.idproof = idproof
        self.balance = 0

    def deposit(self,actno,amt):
        self.balance = self.balance + amt
        return self.balance

    def withdraw(self,actno,amt):
        if (amt > self.balance):
            raise InsufficientBal(actno,amt)
        else:
            self.balance = self.balance - amt
        return self.balance

myact = Account(101,'raghu',9845547471,'prasadraghuks@gmail.com','adhar')
bal = myact.deposit(101,30000)
try:
    bal = myact.withdraw(101,35000)
except Exception as e:
    print('exception ',e)

print('after initial deposit',bal)

# REPR
#https://www.journaldev.com/22460/python-str-repr-functions

class Person:
    name = ""
    age = 0

    def __init__(self, personName, personAge):
        self.name = personName
        self.age = personAge

p = Person('Pankaj', 34)

print(p.__str__())
print(p.__repr__())

class Person:
    name = ""
    age = 0

    def __init__(self, personName, personAge):
        self.name = personName
        self.age = personAge

    def __repr__(self):
        return '{name:'+self.name+', age:'+str(self.age)+ '}'

    '''
    def __str__(self):
        return 'Person(name='+self.name+', age='+str(self.age)+ ')'
    '''

p = Person('Pankaj', 34)

# __str__() example
print(p)
print(p.__str__())

s = str(p)
print(s)

# __repr__() example
print(p.__repr__())
print(type(p.__repr__()))
print(repr(p))

x = object()

print(dir(x))

'''
class calculator
add(n1,n2)
sub(n1,n2)
mul
div

write expection class to hangle folloing scenarios
if (n1 <0) then raise InvaidData
if (n1  or n2 is a charecter then raise InvalidDataFormat)
'''

#Calculator
n1= int (input ("Enter the value of number one"))
n2= int (input("Enter the value of number two"))

class Calculator():
    Add=0
    Sub=0
    Div=0
    Multi=0

try:
    Add=n1 + n2
    Sub=n1 - n2
    Div=n1/n2
    Multi=n1*n2

except (n1<0):
        print("Invalid data")
except (type(n1)==char or type(n2)==char):
        print ("Invalid data")

else:
    print ("Successfully done")
    print ("Addition is",Add)
    print ("Subtraction is",Sub)
    print ("Division is",Div)
    print ("Multiplication is",Multi)

class InvalidDataException(Exception):
    def __init__(self,data):
        self.data = data

    def __str__(self):
        return 'Invalid Data '

class Calculator():
    def add(self,n1,n2):
        if (n1 < 0 ):
            raise InvalidDataException(n1)


'''
Created on 2021年5月6日

@author: 40215
'''
from flask import Flask
from .extensions import db, api, cors, csrf
from pyadmin.admin import bp_admin, bp_general
from dotenv import load_dotenv

def create_app():
    load_dotenv(verbose=True)
    app = Flask(__name__.split('.')[0])
    # 加载配置
    app.config.from_object('pyadmin.config.DevelopmentConfig')

    register_extensions(app)
    register_blueprints(app)
    return app

def register_extensions(app):
    """ Register Flask extensions. """
    db.init_app(app)
    api.init_app(app)
    cors.init_app(app)      # 跨域配置
    csrf.init_app(app)      # 跨域攻击

def register_blueprints(app):
    """ Register Flask BluePrints """
    app.register_blueprint(bp_admin)
    app.register_blueprint(bp_general)


import os
import torch as th
import numpy as np
from .. import configs
import torch
import torch.nn as nn
from torch.autograd import Variable
from .miner import miner
import functools as ft
import itertools as it
import pytest
import torch.nn.functional as F
import rich
c = rich.get_console()

def fn_ptriplet_kernel(repA: th.Tensor, repP: th.Tensor, repN: th.Tensor,
                       *, metric: str, margin: float):
    '''
    <functional> the core computation for spc-2 triplet loss.
    '''
    if metric == 'C':
        dap = 1 - F.cosine_similarity(repA, repP, dim=-1)
        dan = 1 - F.cosine_similarity(repA, repN, dim=-1)
        loss = (dap - dan + margin).relu().mean()
    elif metric in ('E', 'N'):
        #dap = F.pairwise_distance(repA, repP, p=2)
        #dan = F.pairwise_distance(repA, repN, p=2)
        #loss = (dap - dan + margin).relu().mean()
        loss = F.triplet_margin_loss(repA, repP, repN, margin=margin)
    else:
        raise ValueError(f'Illegal metric type {metric}!')
    return loss

def fn_ptriplet(repres: th.Tensor, labels: th.Tensor,
                *, metric: str, minermethod: str, p_switch: float = -1.0, xa: bool = False):
    '''
    Variant of triplet loss that accetps [cls=1,cls=1,cls=2,cls=2] batch.
    This corresponds to the SPC-2 setting in the ICML20 paper.

    metrics: C = cosine, E = euclidean, N = normalization + euclidean
    '''
    # Determine the margin for the specific metric
    if metric in ('C', 'N'):
        margin = configs.triplet.margin_cosine
        repres = F.normalize(repres, p=2, dim=-1)
    elif metric in ('E',):
        margin = configs.triplet.margin_euclidean
    # Sample the triplets
    anc, pos, neg = miner(repres, labels, method=minermethod,
                          metric=metric, margin=margin, p_switch=p_switch)
    if xa:
        return fn_ptriplet_kernel(repres[anc, :].detach(), repres[pos, :],
                                  repres[neg, :], metric=metric, margin=margin)
    loss = fn_ptriplet_kernel(repres[anc, :], repres[pos, :], repres[neg, :],
                              metric=metric, margin=margin)
    return loss

class ptriplet(th.nn.Module):
    _datasetspec = 'SPC-2'
    _minermethod = 'spc2-random'
    _xa = False

    def __call__(self, *args, **kwargs):
        if hasattr(self, '_minermethod'):
            return ft.partial(fn_ptriplet,
                              metric=self._metric,
                              minermethod=self._minermethod,
                              xa=self._xa)(*args, **kwargs)
        else:
            return ft.partial(fn_ptriplet,
                              metric=self._metric,
                              xa=self._xa)(*args, **kwargs)

    def determine_metric(self):
        return self._metric

    def datasetspec(self):
        return self._datasetspec

    def raw(self, repA, repP, repN, *, override_margin: float = None):
        if self._metric in ('C', 'N'):
            margin = configs.triplet.margin_cosine
        elif self._metric in ('E',):
            margin = configs.triplet.margin_euclidean
        if override_margin is not None:
            margin = override_margin
        loss = fn_ptriplet_kernel(repA, repP, repN,
                                  metric=self._metric, margin=margin)
        return loss

class ptripletC(ptriplet):
    _metric = 'C'

class ptripletE(ptriplet):
    _metric = 'E'

class ptripletN(ptriplet):
    _metric = 'N'

class ptripxaN(ptriplet):
    _metric = 'N'
    _xa = True

class pmtriplet(ptriplet):
    _minermethod = 'spc2-semihard'

class pmtripletC(pmtriplet):
    _metric = 'C'

class pmtripletE(pmtriplet):
    _metric = 'E'

class pmtripletN(pmtriplet):
    _metric = 'N'

class phtriplet(ptriplet):
    _minermethod = 'spc2-hard'

class phtripletC(phtriplet):
    _metric = 'C'

class phtripletE(phtriplet):
    _metric = 'E'

class phtripletN(phtriplet):
    _metric = 'N'

class pstriplet(ptriplet):
    _minermethod = 'spc2-softhard'

class pstripletC(pstriplet):
    _metric = 'C'

class pstripletE(pstriplet):
    _metric = 'E'

class pstripletN(pstriplet):
    _metric = 'N'

class pdtriplet(ptriplet):
    _minermethod = 'spc2-distance'

class pdtripletC(pdtriplet):
    _metric = 'C'

class pdtripletE(pdtriplet):
    _metric = 'E'

class pdtripletN(pdtriplet):
    _metric = 'N'

class pDtripletN(pdtripletN):
    def __call__(self, *args, **kwargs):
        return ft.partial(fn_ptriplet, metric=self._metric,
                          minermethod=self._minermethod,
                          p_switch=0.15)(*args, **kwargs)

@pytest.mark.parametrize('metric, minermethod', it.product(('C', 'E', 'N'),
                                                           ('spc2-random', 'spc2-distance', 'spc2-hard', 'spc2-softhard', 'spc2-semihard')))
def test_fn_ptriplet(metric: str, minermethod: str):
    output, labels = th.rand(10, 32, requires_grad=True), th.randint(3, (10,))
    loss = fn_ptriplet(output, labels, metric=metric, minermethod=minermethod)
    loss.backward()

@pytest.mark.parametrize('func', (ptripletN, ptripletE, ptripletC,
                                  pmtripletN, pmtripletE, pmtripletC,
                                  pstripletN, pstripletE, pstripletC,
                                  pdtripletN, pdtripletE, pdtripletC,
                                  phtripletN, phtripletE, phtripletC))
def test_ptriplet(func: object):
    output, labels = th.rand(10, 32, requires_grad=True), th.randint(3, (10,))
    loss = func()(output, labels)
    loss.backward()


import tkinter
from src.colorchooser import ColorChooser

class ColorWheel():

        def __init__(
            self,
            params: dict,
            color_table: dict = None,
        ):

            self.params = params

            if color_table is None:
                self.color_table = {
                    "red": "#ff0000",
                    "green": "#00ff00",
                    "blue": "#0000ff",
                    "pink": "#d7449a",
                    "white": "#ffffff",
                    "black": "#000000",
                }
            else:
                self.color_table = color_table

        ####### WINDOW METHODS #######

        def _create_window(self):
            self.root = tkinter.Tk()

            self.W_max = self.root.winfo_screenwidth()
            self.H_max = self.root.winfo_screenheight()

            self.W_button = self.params["W_button"]
            self.H_button = self.params["H_button"]

            self.root.geometry(
                f'{self.W_max}x{self.H_max}'
            )

        ####### MAIN RECT METHODS #######

        def _display_color(self):
            self.root.title("ColorWheel")

            self.canvas = tkinter.Canvas(master=self.root)

            self.display_rect = self.canvas.create_rectangle(
                0, 0, self.W_max - self.W_button, self.H_max,
                outline='#000000',   # only first display color
                fill='#000000',      # only first display color
            )

            self.canvas.pack(fill=tkinter.BOTH, expand=1)

        ####### CUSTOM COLOR ENTRY METHODS #######

        def _create_entry(self):

            entry_label = tkinter.StringVar()
            entry_label.set("Color")
            self.entry_var = tkinter.StringVar()
            self.entry = tkinter.Entry(
                self.root,
                textvariable=self.entry_var,
                font=(
                    self.params["font_name"],
                    self.params["font_size"],
                    self.params["font_type"],
                ),
            )
            self.entry.pack()

            entry_button_label = tkinter.StringVar()
            entry_button_label.set("Change")
            self.entry_button = tkinter.Button(
                self.root,
                textvariable=entry_button_label,
                command=self.__entry_cmd_change_color,
            )
            self.entry_button.pack()

            self.entry.place(
                x=self.W_max - self.params["x_entry_offset"],
                y=self.H_max - self.H_button + self.params["y_entry_offset"],
            )
            self.entry_button.place(
                x=self.W_max - self.params["x_entry_button_offset"],
                y=self.H_max - self.H_button + self.params["y_entry_button_offset"],
            )

        @classmethod
        def __is_valid_rgb(cls, rgb_str: str):
            if len(rgb_str) != 7:
                return False

            try:
                return (  # this first check isn't needed
                    (rgb_str[0] == '#') and \
                    (int(rgb_str[1:3], 16) >= 0 and int(rgb_str[1:3], 16) < 256) and \
                    (int(rgb_str[3:5], 16) >= 0 and int(rgb_str[3:5], 16) < 256) and \
                    (int(rgb_str[5:], 16) >= 0 and int(rgb_str[5:], 16) < 256)
                )
            except (ValueError, IndexError):
                return False

        def __entry_cmd_change_color(self):
            new_color_str = self.entry_var.get()

            if len(new_color_str) != 0 and new_color_str[0] != '#':
                new_color_str = f'#{new_color_str}'

            if not ColorWheel.__is_valid_rgb(new_color_str):
                print("Invalid RGB color; please, try again")
            else:
                self.canvas.itemconfig(
                    self.display_rect,
                    fill=new_color_str,
                    outline=new_color_str,
                )

            self.entry_var.set('')

        ####### COLOR BUTTONS METHODS #######

        def _create_buttons(self):

            for i, (k, v) in enumerate(self.color_table.items()):
                button_label = tkinter.StringVar()
                button_label.set(k.capitalize())
                button = tkinter.Button(
                    self.root,
                    textvariable=button_label,
                    command=self.__button_cmd_color_change(v),
                )
                button.pack()
                button.place(
                    x=i * self.params["x_button_offset"],
                    y=self.H_max - self.H_button + self.params["y_button_offset"],
                )

            # Creating color chooser
            button_label_chooser = tkinter.StringVar()
            button_label_chooser.set("Choose Color")
            button_chooser = tkinter.Button(
                self.root,
                textvariable=button_label_chooser,
                command=self.__button_cmd_color_chooser,
            )
            button_chooser.pack()
            button_chooser.place(
                x=(i + 1) * self.params["x_button_offset"],
                y=self.H_max - self.H_button + self.params["y_button_offset"],
            )

        def __button_cmd_color_change(self, rgb_str: str):
            canvas = self.canvas
            display_rect = self.display_rect

            def __generic_color_change():
                canvas.itemconfig(
                    display_rect,
                    fill=rgb_str,
                    outline=rgb_str,
                )
            return __generic_color_change

        def __button_cmd_color_chooser(self):
            from tkinter.colorchooser import askcolor

            selected_color = askcolor(title="Choose Color")[-1]
            self.canvas.itemconfig(
                self.display_rect,
                fill=selected_color,
                outline=selected_color,
            )

        ####### MAIN FUNC #######

        def run(self):
            self._create_window()
            self._display_color()
            self._create_entry()
            self._create_buttons()
            self.root.mainloop()


'''
Eliminate consecutive duplicates of list elements.
    If a list contains repeated elements they should be replaced with a
	single copy of the element. The order of the elements should not be
	changed.

Example:
* (compress '(a a a a b c c a a d e e e e))
(A B C A D E)
'''

#taking input of list elements at a single time seperating by space and splitting each by split() method
demo_list = input('enter elements seperated by space: ').split(' ')
new_list = list()   #creating new list

def removeConsecutiveDuplicates(demo_list):
	no_consecutive_dupliates_list = list(demo_list[0])        #appending first element to new_list

	for item in demo_list:               #iterating through all elements of demo_list
		if no_consecutive_dupliates_list[-1] != item:         #Checking if lastly added element to new_list is identical to to iterating item
			no_consecutive_dupliates_list.append(item)        #if not same then appending to new_list. Here we're just eliminating the consecutive duplicates

	return no_consecutive_dupliates_list

no_repeatative_dupliates_list = removeConsecutiveDuplicates(demo_list)

#printing both lists
print(f'list before: {demo_list}')
print(f'list after removing repeatative duplicates: {no_repeatative_dupliates_list}')


# -*- coding: utf-8 -*-
# Imports: {{{
import codecs
import glob
import logging
import os
import sys
from platform import system

logging.basicConfig()
logger = logging.getLogger(name=__name__)

try:
    from setuptools import setup
except ImportError:
    from distutils.core import setup

    find_packages = None
else:
    from setuptools import find_packages

try:
    import sphinx
except ImportError:
    cmd_class = {}
else:
    from sphinx.setup_command import BuildDoc

    cmd_class = {"build_sphinx": BuildDoc}

if find_packages is not None:
    packages = find_packages()
else:
    packages=["src/winreadline"]

# for distutils setuptools compatabilit.
# TODO: add zip_safe=False
# }}}

# Metadata: {{{
# Name of the package for release purposes.  This is the name which labels
# the tarballs and RPMs made by distutils, so it's best to lowercase it.
name = "pyreadline"

version = "2.1"

description = "A python implmementation of GNU readline."

ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
README = os.path.join(ROOT_PATH, "", "README.rst")

with codecs.open(README, encoding="utf-8") as f:
    long_description = "\n" + f.read()

keywords = ["readline", "windows", "pyreadline"]
platforms = ["Windows XP/2000/NT", "Windows 95/98/ME", "Windows 10"]
# url = "https://github.com/pyreadline/pyreadline"
# download_url = "https://pypi.python.org/pypi/pyreadline"

license = "BSD"

authors = {
    # "Jorgen": ("Jorgen Stenarson", "jorgen.stenarson@kroywen.se"),
    # "Gary": ("Gary Bishop", ""),
    # "Jack": ("Jack Trainor", ""),
}

setup(
    name=name,
    version=version,
    description=description,
    long_description=long_description,
        long_description_content_type="text/restructuredtext",
        # python_requires=REQUIRES_PYTHON,
    # author=authors["Jorgen"][0],
    # author_email=authors["Jorgen"][1],
    # maintainer=authors["Jorgen"][0],
    # maintainer_email=authors["Jorgen"][1],
    src_root="src/winreadline",
    license=license,
    # where did we define classifiers?
    classifiers=[
        # Trove classifiers
        # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
        "Development Status :: 5 - Production/Stable",
        "Environment :: Console",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: BSD License",
        "Natural Language :: English",
        "Operating System :: Microsoft :: Windows",
        "Operating System :: Microsoft :: Windows :: Windows 10",
        "Programming Language :: Python",
        # "Programming Language :: Python :: 2",
        # "Programming Language :: Python :: 2.6",
        # "Programming Language :: Python :: 2.7",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.2",
        "Programming Language :: Python :: 3.3",
        "Programming Language :: Python :: 3.4",
        "Programming Language :: Python :: 3.5",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: Implementation :: CPython",
    ],
    # url=url,
    # check that this exists in setuptools
    # download_url=download_url,
    platforms=platforms,
    keywords=keywords,
    packages=packages,
    py_modules=["readline"],
    data_files=[("docs", glob.glob("docs/*")),],
    cmdclass=cmd_class,
    python_requires=">=2.6.0",
    requires=["setuptools", "pywin32", "wheel"],
    # whats the difference between requires, install_requires, setup_requires again?
    # i dont even understand what error this raised but let's leave this
    # commented out
    # setup_requires=["pkg_resources", "pipenv"],
    # They actually really don't but hey
    # install_requires=REQUIRED,
    tests_require=["pytest"],
        test_suite="test",
        include_package_data=True,
    extras_require={"docs": ["sphinx"], "test": ["pytest"]},
        package_data={
            # If any package contains *.txt or *.rst files, include them:
            "": ["*.txt", "*.rst"],
        },
        # # $ setup.py publish support.
        # cmdclass={"upload": UploadCommand},
        # # project home page, if any
        # project_urls={
        #     "Bug Tracker": "https://www.github.com/farisachugthai/dynamic_ipython/issues",
        #     "Documentation": "https://farisachugthai.github.io/dynamic_ipython",
        #     "Source Code": "https://www.github.com/farisachugthai/dynamic_ipython",
        # }
)

# Vim: set fdm=marker:


import os
import os.path as osp
import random

import scipy.io as sio

list_file = './img_list_all_with_id.txt'
#pairs_mat_file = './lfw_pairs_zyf.mat'

fn_probe = 'idcard_bjxj_test_ident_probe.txt'
fn_gallery = 'idcard_bjxj_test_ident_gallery.txt'

def load_image_list(list_file):
    fp = open(list_file, 'r')

    img_list = []
    id_list = []

    for line in fp:
        line=line.strip()
        if not line:
            continue

        line_split = line.split()

        img_name = line_split[0]
        img_id = int(line_split[1])

        img_list.append(img_name)
        id_list.append(img_id)

    fp.close()

    return (img_list, id_list)

def main():
    img_list, id_list = load_image_list(list_file)

    num_imgs = len(id_list)

    fp_probe = open(fn_probe, 'w')
    fp_gallery = open(fn_gallery, 'w')

    last_id = 0
    cls_cnt = 0
    has_idcard = 0

    for i in range(num_imgs):
        if 'card' in img_list[i].split()[-1]:
            fp_gallery.write('%s %d %d\n' % (img_list[i], i, id_list[i]) )
            has_idcard = 1
        elif id_list[i]!=last_id:
            has_idcard = 0

        if id_list[i]==last_id:
            cls_cnt += 1
        else:
            base_idx = i - cls_cnt

            if cls_cnt>1 and has_idcard:
                for j in range(cls_cnt):
                    if 'card' not in img_list[base_idx+j].split()[-1]:
                        fp_probe.write('%s %d %d\n' % (img_list[base_idx+j], base_idx+j, id_list[base_idx+j]) )

            cls_cnt = 1
            last_id = id_list[i]

    fp_gallery.close()
    fp_probe.close()

if __name__=='__main__':
    main()


import pickle
import numpy as np, pandas as pd
from flask import Flask, render_template, request
import regex as re
from sklearn.feature_extraction.text import TfidfVectorizer
import en_core_web_md
nlp = en_core_web_md.load()

app = Flask(__name__)
# pickle.dump(recommend, open('model.pkl','wb'))
model = pickle.load(open('../Deployment/model/model_rfw2v.pkl','rb'))

train = pd.read_csv('../datasets/final combined file/troll_data.csv')
# list_sequences_train = train["content"]
# max_features = 22000
# tokenizer = Tokenizer(num_words=max_features)
# train = tokenizer.fit_on_texts(list(list_sequences_train))

def preprocess_text(sen):
    # Remove punctuations and numbers
    sentence = re.sub('[^a-zA-Z]', ' ', sen)
    # Single character removal
    sentence = re.sub(r"\s+[a-zA-Z]\s+", ' ', sentence)
    # Removing multiple spaces
    sentence = re.sub(r'\s+', ' ', sentence)
    return sentence

def get_vec(x):
  doc = nlp(x)
  return doc.vector

@app.route('/')
def Home():
    return render_template('index.html')

@app.route('/predict', methods=['POST'])
def predict():
        comment = [x for x in request.form.values()]
        comment = [preprocess_text(comment[0])]
        comment = pd.DataFrame(comment)
        comment = comment[0].apply(lambda x: get_vec(x))
        XX = comment.to_numpy()
        XX = XX.reshape(-1,1)
        XX = np.concatenate(np.concatenate(XX,axis = 0),axis = 0).reshape(-1,300)
        data=XX
        prediction = model.predict(data)
        return render_template('index.html', predict = prediction)

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


from gemynd.api import Telegram
from gemynd import Config

config = Config('config.json')
telapi = Telegram(config)
messages, id = telapi.getNewMessages()
for msg in messages:
    msg.text = "Message in chat_id %d : '%s'" % (msg.chat_id, msg.text)
    telapi.sendMessage(msg)
telapi.commitNewMessages(id)
telapi.close()


import re
import collections

class LexerError(Exception):
    pass

Token = collections.namedtuple('Token', ['type', 'data'])

class Lexer:
    ALPHA = b'abcdefghijklmnopqrstuvwxyz'
    NUM = b'0123456789'
    SYMB = b" !&|?();[],_+-*/%^=<>:@{}`'~#"

    def __init__(self, src):
        self.cache = []
        self.idx = 0
        self.src = src
        self._preprocess()

    def preprocessed_source(self):
        return self.src

    def has_token(self):
        # Newlines only seperate tokens, just ignore.
        while self._hasc() and self._peekc() == b'\n':
            self.idx += 1
        return bool(self.cache or self._hasc())

    def peek_token(self, ahead=0):
        while len(self.cache) <= ahead:
            self.cache.append(self.get_token(ignore_cache=True))
        return self.cache[ahead]

    def get_token(self, *args, ignore_cache=False):
        if self.cache and not ignore_cache:
            return self.cache.pop(0)

        # Newlines only seperate tokens, just ignore.
        while self._hasc() and self._peekc() == b'\n':
            self.idx += 1

        if not self._hasc():
            raise LexerError('expected character, found EOF')

        c = self._getc()
        if c.lower() in self.ALPHA + self.SYMB:
            return Token('symb', c.decode('utf-8'))

        if c == b'$':
            c = self._getc()
            if c.lower() not in self.ALPHA + self.SYMB + b'$':
                raise LexerError("expected alphanumeric or symbol after '$'")
            return Token('symb', "$" + c.decode('utf-8'))

        if c in b'"\\':
            data = self._getc() if c == b'\\' else self._tok_str()
            return Token('lit', repr(data.decode('utf-8')))

        if c in self.NUM or (c == b'.' and self._peekc() in self.NUM):
            self.idx -= 1  # Push back '.' on character stream.
            return Token('lit', self._tok_num())

        if c == b'.':
            return self._tok_dot()

        raise LexerError(
            'unexpected character while parsing tokens: {:x}'.format(c[0]))

    def _tok_dot(self):
        if self.idx >= len(self.src):
            raise LexerError("expected character after '.', found EOF")

        c = self._getc()
        if c == b'"':
            return Token('lit', repr(list(self._tok_str())))

        return Token('symb', (b'.' + c).decode('utf-8'))

    def _tok_str(self):
        s = b''

        while self._hasc():
            c = self._getc()
            if c == b'"':
                break

            # Handle escape sequences.
            if c == b'\\' and self._hasc() and self._peekc() in b'"\\':
                s += self._getc()
            else:
                s += c

        return s

    def _tok_num(self):
        n = b''

        # Leading zeroes are seperate tokens (in a golf language a leading zero
        # is never useful):
        if self._peekc() == b'0':
            n += self._getc()
            if self._hasc() and self._peekc() in b'.':
                n += self._getc()
        else:
            while self._hasc() and self._peekc() in b'.' + self.NUM:
                if self._peekc() == b'.' and n.count(b'.') != 0:
                    break

                n += self._getc()

        if n.endswith(b'.') and self._hasc() and self._peekc() not in b' \n':
            self.idx -= 1

        return n.decode('utf-8')

    def _hasc(self):
        return self.idx < len(self.src)

    def _peekc(self):
        return self.src[self.idx:self.idx+1]

    def _getc(self):
        self.idx += 1
        return self.src[self.idx-1:self.idx]

    def _preprocess(self):
        # Finite state machine.
        binstring = False
        string = False

        # Meta command results.
        end_meta = None

        lines = [b'']
        while self._hasc():
            c = self._getc()

            # Don't normalize anything in binary strings.
            if binstring:
                lines[-1] += c

                if c == b'\\':
                    lines[-1] += self._getc()
                elif c == b'"':
                    binstring = False

            # Normalize newline.
            elif c in b'\r\n':
                if string:
                    lines[-1] += b'\n'
                else:
                    lines.append(b'')

                # Greedily read \r\n.
                if c == b'\r' and self._peekc() == b'\n':
                    self.idx += 1

            # Handle string state.
            elif string:
                lines[-1] += c

                if c == b'\\' and self._peekc() == b'"':
                    lines[-1] += self._getc()
                elif c == b'"':
                    string = False

            # The default state.
            else:
                # Comments.
                if c == b';' and (not lines[-1] or lines[-1][-1] in b' \t'):
                    # Read until newline.
                    comment = b''
                    while self._hasc():
                        c = self._getc()

                        # Greedily read \r\n, and break if found.
                        if c == b'\r' and self._peekc() == b'\n':
                            self.idx += 1
                        if c in b'\r\n':
                            lines.append(b'')
                            break

                        comment += c

                    # Meta-command.
                    if comment.startswith(b'#'):
                        meta = comment[1:].strip()
                        if meta == b'end' and end_meta is None:
                            end_meta = len(lines) - 1

                # Regular characters.
                else:
                    lines[-1] += c

                    if c == b'"':
                        string = True
                    elif c == b'.' and self._peekc() == b'"':
                        lines[-1] += self._getc()
                        binstring = True
                    elif c == b'\\':
                        if self._hasc():
                            c = self._getc()

                            # Greedily read \r\n.
                            if c == b'\r' and self._peekc() == b'\n':
                                self.idx += 1

                            lines[-1] += b'\n' if c in b'\r\n' else c

        # Handle the end metacommand.
        if end_meta is not None:
            lines = lines[:end_meta]

        self.src = self._preprocess_whitespace(lines)
        self.idx = 0

    def _preprocess_whitespace(self, lines):
        # Strip all trailing whitespace and an even amount of spaces from the
        # beginning.
        lines = [re.sub(b'^((  )|\t)*', b'', line.rstrip()) for line in lines]

        # Remove empty lines.
        lines = [line for line in lines if line.strip()]

        # Concatenate lines, unless a line ends in a number or period and the
        # next line begins in a number (the only time a newline is necessary).
        linenr = 0
        while linenr + 1 < len(lines):
            if not (lines[linenr][-1] in b'.0123456789' and
                    lines[linenr + 1][:1].isdigit()):
                lines[linenr] += lines.pop(linenr + 1)
            else:
                linenr += 1

        return b'\n'.join(lines)


import numpy as np
import csv
from obspy import UTCDateTime, read, Trace, Stream
import subprocess
import time
import sys

# //////////////////////////////// Parametros //////////////////////////////////
tipoArchivo = sys.argv[1] #1:RC 2:EE
# /////////////////////////////////////////////////////////////////////////////

# ///////////////////////////////// Archivos //////////////////////////////////
archivoConfiguracionMseed = '/home/rsa/configuracion/configuracion_mseed.csv'
archivoNombresArchivosRC = '/home/rsa/tmp/NombreArchivoRegistroContinuo.tmp'
archivoDatosConfiguracion = '/home/rsa/configuracion/DatosConfiguracion.txt'
archivoNombresArchivosEE = '/home/rsa/tmp/NombreArchivoEventoExtraido.tmp'

if tipoArchivo=='1':
    #Archivos registro continuo
    ficheroConfiguracion = open(archivoDatosConfiguracion)
    ficheroNombresArchivos = open(archivoNombresArchivosRC)
    lineasFicheroConfiguracion = ficheroConfiguracion.readlines()
    lineasFicheroNombresArchivos = ficheroNombresArchivos.readlines()
    nombreArchvioRegistroContinuo = lineasFicheroNombresArchivos[1].rstrip('\n')
    archivo_binario = lineasFicheroConfiguracion[2].rstrip('\n') + nombreArchvioRegistroContinuo
    print('Convirtiendo el archivo: %s' %archivo_binario)
elif tipoArchivo=='2':
    #Archivos eventos extraidos
    ficheroNombresArchivos = open(archivoNombresArchivosEE)
    lineasFicheroNombresArchivos = ficheroNombresArchivos.readlines()
    archivo_binario = lineasFicheroNombresArchivos[0]
    print('Convirtiendo el archivo: %s' %archivo_binario)

# /////////////////////////////////////////////////////////////////////////////

def parametros_():
#################################################################
#Método de Extracción de datos de conficuración de la estacion
#Desde el archivo configuracion.csv que debe estar presente en el mismo directorio del ejecutable.

        estaciones_=[]
        with open(archivoConfiguracionMseed,newline='') as f:
            datos=csv.reader(f,delimiter=';',quotechar=';')
            for r in datos:
                estaciones_.append(r)
        nombre_canal_total_=estaciones_[1][1]
        nombre_canal=estaciones_[1][2]
        tipo_canal_=estaciones_[1][3]
        n_canales_=estaciones_[1][4]
        hab_canal=estaciones_[1][5]
        componente_canal=estaciones_[1][6]
        grafico_=estaciones_[1][7]
        hab_plt=estaciones_[1][8]
        gan_plt=estaciones_[1][9]
        ganancia=estaciones_[1][10]
        diez_plt=estaciones_[1][11]
        bits_=estaciones_[1][12]
        calidad_=estaciones_[1][13]
        ubicacion_=estaciones_[1][14]
        tipo_canal=estaciones_[1][15]
        red_=estaciones_[1][16]
        muestreo_=estaciones_[1][17]
        longitud_=estaciones_[1][18]
        latitud_=estaciones_[1][19]
        altura_=estaciones_[1][20]
        ruido_=int(estaciones_[1][21])
        numero_est=int(estaciones_[1][0])
        filtro_=estaciones_[1][22]
        reserva_1=estaciones_[1][23]
        reserva_2=estaciones_[1][24]

        return(nombre_canal_total_, #Canal 0  'NOMBRE'
               nombre_canal,        #Canal 1  'CODIGO'
               tipo_canal_,         #Canal 2  'SENSOR'
               n_canales_,          #Canal 3  'CANALES'
               hab_canal,           #Canal 4  'HAB_CANAL'
               componente_canal,    #Canal 5  'COMPONENTE'
               grafico_,            #Canal 6  'HAB_GRAFICO'
               hab_plt,             #Canal 7  'HAB_PLT'
               gan_plt,             #Canal 8  'GAN_PLT'
               ganancia,            #Canal 9  'GANANCIA'
               diez_plt,            #Canal 10 'DIEZ_PLT'
               bits_,               #Canal 11 'FACTOR_MUL'
               longitud_,           #Canal 12 'LONGITUD'
               latitud_,            #Canal 13 'LATITUD'
               altura_,             #Canal 14 'ALTITUD'
               ruido_,              #Canal 15 'RUIDO'
               calidad_,            #Canal 16 'CALIDAD'
               ubicacion_,          #Canal 17 'UBICACIÓN'
               tipo_canal,          #Canal 18 'CANAL'
               red_,                #Canal 19 'RED'
               muestreo_,           #Canal 20 'MUESTREO'
               numero_est,          #Canal 21 'N° ESTACION'
               filtro_,             #Canal 22 'FILTRO'
               reserva_1,           #Canal 22 'Reserva 1'
               reserva_2)           #Canal 22 'Reserva 2'

def obtenerTraza(nombreCanal,num_canal, data, anio, mes, dia, horas, minutos, segundos, microsegundos, segundos_faltantes=None):

    # Define todas las caracteristicas de la traza
    parametros=parametros_()
    nombreRed=parametros[19]
    nombreEstacion=parametros[1]
    tipoEstacion=parametros[2]
    localizacion=parametros[17]
    nCanal=parametros[18]
    fsample=int(parametros[20])
    calidad=parametros[16]
    if fsample>80:
        nombreCanal='E'
    else:
        nombreCanal='S'
    if tipoEstacion=='SISMICO':
        nombreCanal=nombreCanal+'L'
    else:
        nombreCanal=nombreCanal+'N'
    num_canal=num_canal-3*(int((num_canal-1)/3))
    nombreCanal=nombreCanal+nCanal[num_canal-1:num_canal]
    stats = {'network': nombreRed, 'station': nombreEstacion, 'location': localizacion,
             'channel': nombreCanal, 'npts': len(data), 'sampling_rate': fsample,
             'mseed': {'dataquality': calidad}}
    # Establece el tiempo
    stats['starttime'] = UTCDateTime(anio, mes, dia, horas, minutos, segundos, microsegundos)

    # Crea la traza con los datos y las características
    if segundos_faltantes is not None:

        segundo_inicio = (horas*3600)+(minutos*60)+segundos
        muestras_por_segundo = int(fsample)
        lista_ceros = np.zeros(muestras_por_segundo, dtype=np.int32)
        npts_completo = len(data) + int(len(segundos_faltantes) * muestras_por_segundo)
        data_completo = np.zeros(npts_completo, dtype=np.int32)
        data_completo = data.copy()
        stats['npts'] = npts_completo
        for segundo_faltante in segundos_faltantes:
            tiempo_muestra_faltante = int(segundo_faltante-segundo_inicio)
            indice_muestra_faltante = tiempo_muestra_faltante * muestras_por_segundo
            data_completo = np.insert(data_completo, indice_muestra_faltante, lista_ceros)

        traza = Trace(data=data_completo, header=stats)

    else:

        traza = Trace(data=data, header=stats)

    return traza

def lectura_archivo(archivo):
    datos = [[], [], []]
    contador = 0
    segundo_anterior = None
    segundos_faltantes = []

    with open(archivo, "rb") as f:
        while True:
            tramaDatos = np.fromfile(f, np.int8, 2506)
            if len(tramaDatos) != 2506:
                break

            hora = tramaDatos[2503]
            minuto = tramaDatos[2504]
            segundo = tramaDatos[2505]
            n_segundo = hora * 3600 + minuto * 60 + segundo

            if segundo_anterior is not None:
                if n_segundo != segundo_anterior + 1:
                    segundos_faltantes.extend(range(segundo_anterior + 1, n_segundo))
                elif n_segundo > segundo_anterior + 1:
                    # Si hay un salto mayor, se llenan los segundos faltantes intermedios
                    segundos_faltantes.extend(range(segundo_anterior + 1, n_segundo))

            segundo_anterior = n_segundo

            for j in range(0, 3):
                for i in range(0, 250):
                    dato_1 = tramaDatos[i * 10 + j * 3 + 1]
                    dato_2 = tramaDatos[i * 10 + j * 3 + 2]
                    dato_3 = tramaDatos[i * 10 + j * 3 + 3]
                    xValue = ((dato_1 << 12) & 0xFF000) + ((dato_2 << 4) & 0xFF0) + ((dato_3 >> 4) & 0xF)
                    if (xValue >= 0x80000):
                        xValue = xValue & 0x7FFFF
                        xValue = -1 * (((~xValue) + 1) & 0x7FFFF)
                    datos[j].append(int(xValue))

            contador += 1
            if contador == 864:
                contador = 0

    datos_np = np.asarray(datos)

    if segundos_faltantes:
        print("Segundos faltantes:", segundos_faltantes)

    return datos_np, segundos_faltantes if segundos_faltantes else None

def verificacion_archivo(archivo):
    f = open(archivo, "rb")
    tramaDatos = np.fromfile(f, np.int8, 2506)
    hora = tramaDatos[2503]
    minuto = tramaDatos[2504]
    segundo = tramaDatos[2505]
    n_segundo=hora*3600+minuto*60+segundo
    anio=tramaDatos[2500]
    anio_s= str(anio)
    mes=tramaDatos[2501]
    mes_s=str(mes)
    if(mes<10):
        mes_s='0'+mes_s
    dia=tramaDatos[2502]
    dia_s=str(dia)
    if(dia<10):
        dia_s='0'+dia_s
    hora_s=str(hora)
    if(hora<10):
        hora_s='0'+hora_s
    minuto_s=str(minuto)
    if(minuto<10):
        minuto_s='0'+minuto_s
    segundo_s=str(segundo)
    if(segundo<10):
        segundo_s='0'+segundo_s
    fecha_=(anio,mes,dia,hora,minuto,segundo,n_segundo),(anio_s,mes_s,dia_s,hora_s,minuto_s,segundo_s)
    f.close
    return(fecha_)

def nombre_mseed(tipoArchivo,nombre_,fecha_):
    anio_s=fecha_[1][0]
    mes_s=fecha_[1][1]
    dia_s=fecha_[1][2]
    hora_s=fecha_[1][3]
    minuto_s=fecha_[1][4]
    segundo_s=fecha_[1][5]
    fecha_string=anio_s+mes_s+dia_s
    hora_string=hora_s+minuto_s+segundo_s
    if tipoArchivo=='1':
        #Archivos registro continuo
        fileName = '/home/rsa/resultados/mseed/'+nombre_+fecha_string+"_"+hora_string+".mseed"
    elif tipoArchivo=='2':
        #Archivos eventos extraidos
        fileName = '/home/rsa/resultados/eventos-extraidos/'+nombre_+fecha_string+"_"+hora_string+".mseed"
    return fileName

def conversion_mseed_digital(fileName,fecha_,data_np,segundos_faltantes):
    # Nombre del archivo en funcion del tiempo de inicio
    anio=fecha_[0][0]
    mes=fecha_[0][1]
    dia=fecha_[0][2]
    horas=fecha_[0][3]
    minutos=fecha_[0][4]
    segundos=fecha_[0][5]
    parametros=parametros_()
    nombre_=parametros[2]

    #fileName=self.directorio_registros+fileName

    # Una vez que se tiene los datos, llama al metodo para obtener la traza
    # Todos los parametros que recibe se detallan en el metodo (mas abajo)
    trazaCH1 = obtenerTraza(nombre_,1, data_np[0],(2000 + anio), mes, dia, horas, minutos, segundos, 0, segundos_faltantes)
    trazaCH2 = obtenerTraza(nombre_,2, data_np[1],(2000 + anio), mes, dia, horas, minutos, segundos, 0, segundos_faltantes)
    trazaCH3 = obtenerTraza(nombre_,3, data_np[2],(2000 + anio), mes, dia, horas, minutos, segundos, 0, segundos_faltantes)
    # Crea un objeto Stream con la traza
    #stData = Stream(traces=[trazaCH1])
    # Si se desea varias trazas, esto seria para cuando se tiene 3 canales
    stData = Stream(traces=[trazaCH1, trazaCH2, trazaCH3])

    stData.write(fileName, format = 'MSEED', encoding = 'STEIM1', reclen = 512)

parametros=parametros_()
nombre=parametros[1]
fecha_=verificacion_archivo(archivo_binario)
nombre_= parametros[1]+'_20'
n_mseed=nombre_mseed(tipoArchivo,nombre_,fecha_)
datos_np, segundos_faltantes = lectura_archivo(archivo_binario)
conversion_mseed_digital(n_mseed,fecha_,datos_np,segundos_faltantes)

print('Se ha creado el archivo: %s' %n_mseed)

# Sube los archivos convertidos a Drive
if tipoArchivo=='1':
    subprocess.run(["python3", "/home/rsa/ejecutables/SubirArchivoDrive.py", "3", n_mseed])
    time.sleep(5)
    subprocess.run(["python3", "/home/rsa/ejecutables/SubirArchivoDrive.py", "1", archivo_binario])
elif tipoArchivo=='2':
    subprocess.run(["python3", "/home/rsa/ejecutables/SubirArchivoDrive.py", "2", n_mseed])