from collections import defaultdict
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, DefaultDict, Dict, Iterable, List, Set

import datahub.emitter.mce_builder as builder
from datahub.ingestion.api.workunit import MetadataWorkUnit
from datahub.ingestion.source.sagemaker_processors.common import SagemakerSourceReport
from datahub.ingestion.source.sagemaker_processors.jobs import JobDirection, ModelJob
from datahub.ingestion.source.sagemaker_processors.lineage import LineageInfo
from datahub.metadata.com.linkedin.pegasus2avro.metadata.snapshot import (
    MLModelDeploymentSnapshot,
    MLModelGroupSnapshot,
    MLModelSnapshot,
)
from datahub.metadata.com.linkedin.pegasus2avro.mxe import MetadataChangeEvent
from datahub.metadata.schema_classes import (
    DeploymentStatusClass,
    MLModelDeploymentPropertiesClass,
    MLModelGroupPropertiesClass,
    MLModelPropertiesClass,
    OwnerClass,
    OwnershipClass,
    OwnershipTypeClass,
)

ENDPOINT_STATUS_MAP: Dict[str, str] = {
    "OutOfService": DeploymentStatusClass.OUT_OF_SERVICE,
    "Creating": DeploymentStatusClass.CREATING,
    "Updating": DeploymentStatusClass.UPDATING,
    "SystemUpdating": DeploymentStatusClass.UPDATING,
    "RollingBack": DeploymentStatusClass.ROLLING_BACK,
    "InService": DeploymentStatusClass.IN_SERVICE,
    "Deleting": DeploymentStatusClass.DELETING,
    "Failed": DeploymentStatusClass.FAILED,
    "Unknown": DeploymentStatusClass.UNKNOWN,
}

@dataclass
class ModelProcessor:
    sagemaker_client: Any
    env: str
    report: SagemakerSourceReport
    lineage: LineageInfo

    # map from model image file path to jobs referencing the model
    model_image_to_jobs: DefaultDict[str, Set[ModelJob]] = field(
        default_factory=lambda: defaultdict(set)
    )

    # map from model name to jobs referencing the model
    model_name_to_jobs: DefaultDict[str, Set[ModelJob]] = field(
        default_factory=lambda: defaultdict(set)
    )

    # map from model uri to model name
    model_uri_to_name: Dict[str, str] = field(default_factory=dict)
    # map from model image path to model name
    model_image_to_name: Dict[str, str] = field(default_factory=dict)

    def get_all_models(self) -> List[Dict[str, Any]]:
        """
        List all models in SageMaker.
        """

        models = []

        # see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sagemaker.html#SageMaker.Client.list_models
        paginator = self.sagemaker_client.get_paginator("list_models")
        for page in paginator.paginate():
            models += page["Models"]

        return models

    def get_model_details(self, model_name: str) -> Dict[str, Any]:
        """
        Get details of a model.
        """

        # see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sagemaker.html#SageMaker.Client.describe_model
        return self.sagemaker_client.describe_model(ModelName=model_name)

    def get_all_groups(self) -> List[Dict[str, Any]]:
        """
        List all model groups in SageMaker.
        """
        groups = []

        # see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sagemaker.html#SageMaker.Client.list_model_package_groups
        paginator = self.sagemaker_client.get_paginator("list_model_package_groups")
        for page in paginator.paginate():
            groups += page["ModelPackageGroupSummaryList"]

        return groups

    def get_group_details(self, group_name: str) -> Dict[str, Any]:
        """
        Get details of a model group.
        """

        # see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sagemaker.html#SageMaker.Client.describe_model_package_group
        return self.sagemaker_client.describe_model_package_group(
            ModelPackageGroupName=group_name
        )

    def get_all_endpoints(self) -> List[Dict[str, Any]]:

        endpoints = []

        # see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sagemaker.html#SageMaker.Client.list_endpoints
        paginator = self.sagemaker_client.get_paginator("list_endpoints")

        for page in paginator.paginate():
            endpoints += page["Endpoints"]

        return endpoints

    def get_endpoint_details(self, endpoint_name: str) -> Dict[str, Any]:

        # see https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sagemaker.html#SageMaker.Client.describe_endpoint
        return self.sagemaker_client.describe_endpoint(EndpointName=endpoint_name)

    def get_endpoint_status(
        self, endpoint_name: str, endpoint_arn: str, sagemaker_status: str
    ) -> str:
        endpoint_status = ENDPOINT_STATUS_MAP.get(sagemaker_status)

        if endpoint_status is None:

            self.report.report_warning(
                endpoint_arn,
                f"Unknown status for {endpoint_name} ({endpoint_arn}): {sagemaker_status}",
            )

            endpoint_status = DeploymentStatusClass.UNKNOWN

        return endpoint_status

    def get_endpoint_wu(self, endpoint_details: Dict[str, Any]) -> MetadataWorkUnit:
        """a
        Get a workunit for an endpoint.
        """

        # params to remove since we extract them
        redundant_fields = {"EndpointName", "CreationTime"}

        endpoint_snapshot = MLModelDeploymentSnapshot(
            urn=builder.make_ml_model_deployment_urn(
                "sagemaker", endpoint_details["EndpointName"], self.env
            ),
            aspects=[
                MLModelDeploymentPropertiesClass(
                    createdAt=int(
                        endpoint_details.get("CreationTime", datetime.now()).timestamp()
                        * 1000
                    ),
                    status=self.get_endpoint_status(
                        endpoint_details["EndpointArn"],
                        endpoint_details["EndpointName"],
                        endpoint_details.get("EndpointStatus", "Unknown"),
                    ),
                    customProperties={
                        key: str(value)
                        for key, value in endpoint_details.items()
                        if key not in redundant_fields
                    },
                )
            ],
        )

        # make the MCE and workunit
        mce = MetadataChangeEvent(proposedSnapshot=endpoint_snapshot)

        return MetadataWorkUnit(
            id=f'{endpoint_details["EndpointName"]}',
            mce=mce,
        )

    def get_model_wu(
        self, model_details: Dict[str, Any], endpoint_arn_to_name: Dict[str, str]
    ) -> MetadataWorkUnit:
        """
        Get a workunit for a model.
        """

        # params to remove since we extract them
        redundant_fields = {"ModelName", "CreationTime"}

        model_image = model_details.get("PrimaryContainer", {}).get("Image")
        model_uri = model_details.get("PrimaryContainer", {}).get("ModelDataUrl")

        model_endpoints = set()

        # get endpoints and groups by model image
        if model_image is not None:
            model_endpoints |= self.lineage.model_image_endpoints[model_image]
            self.model_image_to_name[model_image] = model_details["ModelName"]

        # get endpoints and groups by model uri
        if model_uri is not None:
            model_endpoints |= self.lineage.model_uri_endpoints[model_uri]
            self.model_uri_to_name[model_uri] = model_details["ModelName"]

        # sort endpoints and groups for consistency
        model_endpoints_sorted = sorted(
            [x for x in model_endpoints if x in endpoint_arn_to_name]
        )

        model_training_jobs: Set[str] = set()
        model_downstream_jobs: Set[str] = set()

        # extract model data URLs for matching with jobs
        model_data_urls = []

        for model_container in model_details.get("Containers", []):
            model_data_url = model_container.get("ModelDataUrl")

            if model_data_url is not None:
                model_data_urls.append(model_data_url)
        model_data_url = model_details.get("PrimaryContainer", {}).get("ModelDataUrl")
        if model_data_url is not None:
            model_data_urls.append(model_data_url)

        for model_data_url in model_data_urls:

            data_url_matched_jobs = self.model_image_to_jobs.get(model_data_url, set())
            # extend set of training jobs
            model_training_jobs = model_training_jobs.union(
                {
                    job.job_urn
                    for job in data_url_matched_jobs
                    if job.job_direction == JobDirection.TRAINING
                }
            )
            # extend set of downstream jobs
            model_downstream_jobs = model_downstream_jobs.union(
                {
                    job.job_urn
                    for job in data_url_matched_jobs
                    if job.job_direction == JobDirection.DOWNSTREAM
                }
            )

        # get jobs referencing the model by name
        name_matched_jobs = self.model_name_to_jobs.get(
            model_details["ModelName"], set()
        )
        # extend set of training jobs
        model_training_jobs = model_training_jobs.union(
            {
                job.job_urn
                for job in name_matched_jobs
                if job.job_direction == JobDirection.TRAINING
            }
        )
        # extend set of downstream jobs
        model_downstream_jobs = model_downstream_jobs.union(
            {
                job.job_urn
                for job in name_matched_jobs
                if job.job_direction == JobDirection.DOWNSTREAM
            }
        )

        model_snapshot = MLModelSnapshot(
            urn=builder.make_ml_model_urn(
                "sagemaker", model_details["ModelName"], self.env
            ),
            aspects=[
                MLModelPropertiesClass(
                    date=int(
                        model_details.get("CreationTime", datetime.now()).timestamp()
                        * 1000
                    ),
                    deployments=[
                        builder.make_ml_model_deployment_urn(
                            "sagemaker", endpoint_name, self.env
                        )
                        for endpoint_name in model_endpoints_sorted
                    ],
                    customProperties={
                        key: str(value)
                        for key, value in model_details.items()
                        if key not in redundant_fields
                    },
                    trainingJobs=sorted(list(model_training_jobs)),
                    downstreamJobs=sorted(list(model_downstream_jobs)),
                )
            ],
        )

        # make the MCE and workunit
        mce = MetadataChangeEvent(proposedSnapshot=model_snapshot)

        return MetadataWorkUnit(
            id=f'{model_details["ModelName"]}',
            mce=mce,
        )

    def get_group_wu(self, group_details: Dict[str, Any]) -> MetadataWorkUnit:
        """
        Get a workunit for a model group.
        """

        # params to remove since we extract them
        redundant_fields = {"ModelPackageGroupName", "CreationTime"}

        group_arn = group_details["ModelPackageGroupArn"]

        group_model_names = set()

        if group_arn in self.lineage.group_model_uris:
            model_uris = self.lineage.group_model_uris[group_arn]
            group_model_names |= {
                self.model_uri_to_name[x]
                for x in model_uris
                if x in self.model_uri_to_name
            }

        if group_arn in self.lineage.group_model_images:
            model_images = self.lineage.group_model_images[group_arn]
            group_model_names |= {
                self.model_image_to_name[x]
                for x in model_images
                if x in self.model_uri_to_name
            }

        owners = []

        if group_details.get("CreatedBy", {}).get("UserProfileName") is not None:
            owners.append(
                OwnerClass(
                    owner=group_details["CreatedBy"]["UserProfileName"],
                    type=OwnershipTypeClass.DATAOWNER,
                )
            )

        group_snapshot = MLModelGroupSnapshot(
            urn=builder.make_ml_model_group_urn(
                "sagemaker", group_details["ModelPackageGroupName"], self.env
            ),
            aspects=[
                MLModelGroupPropertiesClass(
                    createdAt=int(
                        group_details.get("CreationTime", datetime.now()).timestamp()
                        * 1000
                    ),
                    description=group_details.get("ModelPackageGroupDescription"),
                    customProperties={
                        key: str(value)
                        for key, value in group_details.items()
                        if key not in redundant_fields
                    },
                    models=sorted(
                        [
                            builder.make_ml_model_urn("sagemaker", model_name, self.env)
                            for model_name in group_model_names
                        ]
                    ),
                ),
                OwnershipClass(owners),
            ],
        )

        # make the MCE and workunit
        mce = MetadataChangeEvent(proposedSnapshot=group_snapshot)

        return MetadataWorkUnit(id=f'{group_details["ModelPackageGroupName"]}', mce=mce)

    def get_workunits(self) -> Iterable[MetadataWorkUnit]:

        endpoints = self.get_all_endpoints()
        # sort endpoints for consistency
        endpoints = sorted(endpoints, key=lambda x: x["EndpointArn"])

        endpoint_arn_to_name = {}

        # ingest endpoints first since we need to know the endpoint ARN -> name mapping
        for endpoint in endpoints:

            endpoint_details = self.get_endpoint_details(endpoint["EndpointName"])

            endpoint_arn_to_name[endpoint["EndpointArn"]] = endpoint_details[
                "EndpointName"
            ]

            self.report.report_endpoint_scanned()
            wu = self.get_endpoint_wu(endpoint_details)
            self.report.report_workunit(wu)
            yield wu

        models = self.get_all_models()
        # sort models for consistency
        models = sorted(models, key=lambda x: x["ModelArn"])

        for model in models:

            model_details = self.get_model_details(model["ModelName"])

            self.report.report_model_scanned()
            wu = self.get_model_wu(model_details, endpoint_arn_to_name)
            self.report.report_workunit(wu)
            yield wu

        groups = self.get_all_groups()
        # sort groups for consistency
        groups = sorted(groups, key=lambda x: x["ModelPackageGroupName"])

        # ingest endpoints first since we need to know the endpoint ARN -> name mapping
        for group in groups:

            group_details = self.get_group_details(group["ModelPackageGroupName"])

            self.report.report_group_scanned()
            wu = self.get_group_wu(group_details)
            self.report.report_workunit(wu)
            yield wu


"""wanplus_auto_test URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url, include
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.views.generic.base import RedirectView
from .views import logout_view, login_view, create_superuser
from django.contrib import admin

urlpatterns = [
    url(r'^login/$', login_view),
    url(r'^logout/$', logout_view),
    url(r'^superuser/$', create_superuser),
    url(r'^dashboard/', include('dashboard.urls')),
    url(r'^project/', include('project.urls')),
    url(r'^api/', include('api.urls')),
    url(r'^admin/', admin.site.urls),
    url(r'^$', RedirectView.as_view(url='/dashboard/')),
    url(r'^setting/', include('setting.urls')),
    url(r'^task/', include('task.urls'))
]

urlpatterns += staticfiles_urlpatterns()


from cryptography.fernet import Fernet

print("Hello Colin")
ques_1 = input("What is the password: ")
if ques_1 == "Soccer10":
    print("Welcome!")
    eng_file = open("English Grade", "w")
    ques_2 = input("How many grades would you like to enter: ")
    for num in ques_2:
        grade = input("Enter the grades: ")
        eng_file.write(grade)
        eng_file.close()

# eng_file = open("English Grade", "r")
# line = eng_file.read()
# line.split(", ")
# total = sum([int(num) for num in line.split(", ")])
# avg = total / int(ques_2)
# print(avg)

key = Fernet.generate_key()
with open("key", "wb") as key_file:
    key_file.write(key)

def load_key():
    return open("key", "rb").read()

fernet = Fernet(key)
with open("English Grade", "rb") as file:
    original = file.read()
encrypted = fernet.encrypt(original)
with open("English Grade", "wb") as encrypted_file:
    encrypted_file.write(encrypted)


from django.conf.urls import url, include
from . import views

urlpatterns = [
    url(r'^api/', include(([
        url(r'^$', views.NewsList.as_view(), name='list'),
        url(r'^(?P<pk>[0-9]+)/$', views.NewsDetail.as_view(), name='detail'),
        url(r'^(?P<pk>[0-9]+)/status/$', views.delete_status_news, name='delete_status'),
        url(r'^(?P<pk>[0-9]+)/data/$', views.delete_data_news, name='delete_data'),
    ], 'api'), namespace='api')),
]


"""This file contains helper python functions used in the Snakefile.

"""

from pathlib import Path

def get_samples(fastqdir):
    """Given a path `fastqdir` returns a dictionary `samples`, such that
    `samples[sample_name][1]` (or `2`) is a list of files containing
    R1 or R2 respectively.

    """

    if not Path(fastqdir).is_dir():
        raise Exception(f"""{fastqdir} does not exist""")

    files = Path(fastqdir).glob('**/*_R1_*.fastq.gz')
    samples = dict()

    for f in files:
        sample = f.name.split("_")[0]

        if sample not in samples:
            samples[sample] = {'1': [], '2': []}

        R1 = str(f)
        R2 = str(f).replace("_R1_", "_R2_")

        samples[sample]['1'].append(R1)
        samples[sample]['2'].append(R2)

    if not samples:
        raise Exception("Could not find any samples")

    return samples

def get_mode(samples):
    # check if read 2 exists for all files.  If at least one
    # R1 has no associated R2 switch to single end mode
    for sample in samples:
        for R2 in samples[sample]["2"]:
            if not Path(R2).is_file():
                return "single"
    return "paired"

def single_or_paired_input(wildcards, mode):
    """Selects between either a single or paired input based on the
mode"""

    sample = wildcards.sample
    R1, R2 = [f"""trimmed/{mode}/{sample}_R1.fastq""",
              f"""trimmed/{mode}/{sample}_R2.fastq"""]

    if mode == "single":
        return [R1]
    elif mode == "paired":
        return [R1, R2]


from furl import furl
import pendulum

from share.provider import OAIHarvester

class PMCHarvester(OAIHarvester):
    def do_harvest(self, start_date: pendulum.Pendulum, end_date: pendulum.Pendulum) -> list:
        url = furl(self.url)
        url.args['verb'] = 'ListRecords'
        url.args['metadataPrefix'] = 'pmc_fm'

        if self.time_granularity:
            url.args['from'] = start_date.format('YYYY-MM-DDT00:00:00', formatter='alternative') + 'Z'
            url.args['until'] = end_date.format('YYYY-MM-DDT00:00:00', formatter='alternative') + 'Z'
        else:
            url.args['from'] = start_date.date().isoformat()
            url.args['until'] = end_date.date().isoformat()

        return self.fetch_records(url)


import cv2
from keras.models import load_model
import numpy as np

face_cascade = cv2.CascadeClassifier(
    "C:/Summer Training/Face Recognition/haarcascade_frontalface_default.xml"
)
import h5py

f = h5py.File("C:/Summer Training/Face Recognition/livenessvgg.h5", "r+")
data_p = f.attrs["training_config"]
data_p = data_p.decode().replace("learning_rate", "lr").encode()
f.attrs["training_config"] = data_p
f.close()

model = load_model("C:/Summer Training/Face Recognition/livenessvgg.h5")

def face_extractor(img):
    # Function detects faces and returns the cropped face
    # If no face detected, it returns the input image

    # gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(img, 1.3, 5)

    if faces is ():
        return None

    # Crop all faces found
    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 255), 2)
        cropped_face = img[y : y + h, x : x + w]

    return cropped_face

from keras.preprocessing import image
from PIL import Image

video_capture = cv2.VideoCapture(0)
while True:
    _, frame = video_capture.read()
    # canvas = detect(gray, frame)
    # image, face =face_detector(frame)

    face = face_extractor(frame)
    if type(face) is np.ndarray:
        face = cv2.resize(face, (224, 224))
        im = Image.fromarray(face, "RGB")

        img_array = np.array(im)
        # Our keras model used a 4D tensor, (images x height x width x channel)

        img_array = np.expand_dims(img_array, axis=0)
        pred = model.predict(img_array)
        print(pred)
        if pred[0][0] > 0.7:
            image = "Fake"
            cv2.putText(
                frame, image, (50, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2
            )
        if pred[0][1] > 0.7:
            image = "Real"
            cv2.putText(
                frame, image, (50, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2
            )
    else:
        cv2.putText(
            frame, "Wait", (50, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2
        )

    cv2.imshow("Vide", frame)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break
video_capture.release()
cv2.destroyAllWindows()


"""
连接 redis-cli -h 主机 -p 端口
切换数据库 select num

string :
增 set/mset/append key value
删 del key
改 set key
查 get/mget key

list :
增 lpush/rpush key value 或 linsert key before/after value new-value
删 lrem key count value
改 lset key index value
查 lrange key index0 index1

set:
增 sadd key value
删 srem key value
查 smembers key

zset:
增 zadd key score value
删 zrem key value
查 zrange key index0 index1

hash:
增/改 hset/hmset obj key value
删 hdel obj key
查 hget/hmget obj key 或 hkeys key / hvals key

键:
查找键： keys pattern
判断键是否存在： exists key
查看值的类型： type key
删除键值对： del key1

"""

import redis
import pickle

class AA(object):
    name = "meng"

redis_cli = redis.StrictRedis(host="192.168.49.154", port=6379, db=0)
redis_cli.lpush("test", pickle.dumps(AA))
vv = pickle.loads(redis_cli.rpop("test"))
print(vv.name)


from django.shortcuts import render, redirect
from django.core.mail import send_mail
from django.contrib import messages
from django.views.generic import ListView, DetailView
from django.views.generic.base import View

from .forms import ContactForm
from .models import *

def index(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            mail = send_mail(
                form.cleaned_data['number'],
                form.cleaned_data['content'],
                'qurol.django99@gmail.com',
                ['qurol.abdujalilov99@gmail.com'],
                fail_silently=True)
            if mail:
                messages.success(request, 'Письмо отправлено!')
                return redirect('home')
            else:
                messages.error(request, 'Ошибка отправки')
        else:
            messages.error(request, 'Ошибка валидации')
    else:
        form = ContactForm()

    about = AboutUs.objects.all()
    catalogs = CatalogInfo.objects.all()
    consulting = Consulting.objects.all()
    return render(request, 'pharmshop/index.html', {'about': about, 'catalogs': catalogs, 'consulting': consulting, "form": form})

def about(request):
    about_ = AboutUs.objects.all()
    categories = Category.objects.all()
    return render(request, 'pharmshop/about.html', {'about_': about_, 'categories': categories})

def properties(request):
    medicines = Product.objects.filter(category=2)
    medical_devices = Product.objects.filter(category=1)
    return render(request, 'pharmshop/properties.html', {'medicines': medicines, 'medical_devices': medical_devices})

class ProductDetailView(View):
    def get(self, request, slug):
        product = Product.objects.get(slug=slug)
        return render(request, 'pharmshop/product_detail.html', {'product': product})

def services(request):
    return render(request, 'pharmshop/services.html')

def articles(request):
    articles = Article.objects.all()
    return render(request, 'pharmshop/articles.html', {'articles': articles})

class ArticleDetailView(View):
    def get(self, request, slug):
        article = Article.objects.get(slug=slug)
        return render(request, 'pharmshop/article_detail.html', {'article': article})

def videos(request):
    videos = Video.objects.all()
    return render(request, 'pharmshop/videos.html', {'videos': videos})

class VideoDetailView(View):
    def get(self, request, slug):
        video = Video.objects.get(slug=slug)
        videofile= video.video.url
        return render(request, 'pharmshop/video_detail.html', {'video_url': videofile, 'video': video})


# -*- coding: utf-8 -*-
"""
Created on Thu Jun  3 21:05:36 2021

@author: illusory
"""

import numpy as np
np.random.seed(None)

class MyGMM(object):
    def __init__(self, K=3):
        """
        高斯混合模型，用EM算法进行求解
        :param K: 超参数，分类类别

        涉及到的其它参数：
        :param N: 样本量
        :param D: 单个样本的维度
        :param alpha: 模型参数，高斯函数的系数，决定高斯函数的高度，维度（K）
        :param mu: 模型参数，高斯函数的均值，决定高斯函数的中型位置，维度（K,D）
        :param Sigma: 模型参数，高斯函数的方差矩阵，决定高斯函数的形状，维度（K,D,D）
        :param gamma: 模型隐变量，决定单个样本具体属于哪一个高斯分布，维度(N,K)
        """
        self.K = K
        self.params = {
            'alpha': None,
            'mu': None,
            'Sigma': None,
            'gamma': None
        }

        self.N = None
        self.D = None

    def __init_params(self):
        # alpha 需要满足和为1的约束条件
        alpha = np.random.rand(self.K)
        alpha = alpha / np.sum(alpha)
        mu = np.random.rand(self.K, self.D)
        Sigma = np.array([np.identity(self.D) for _ in range(self.K)])
        # 虽然gamma有约束条件，但是第一步E步时会对此重新赋值，所以可以随意初始化
        gamma = np.random.rand(self.N, self.K)

        self.params = {
            'alpha': alpha,
            'mu': mu,
            'Sigma': Sigma,
            'gamma': gamma
        }

    def _gaussian_function(self, y_j, mu_k, Sigma_k):
        '''
        计算高纬度高斯函数
        :param y_j: 第j个观测值
        :param mu_k: 第k个mu值
        :param Sigma_k: 第k个Sigma值
        :return:
        '''
        # 先取对数
        n_1 = self.D * np.log(2 * np.pi)
        # 计算数组行列式的符号和（自然）对数。
        _, n_2 = np.linalg.slogdet(Sigma_k)

        # 计算矩阵的（乘法）逆矩阵。
        n_3 = np.dot(np.dot((y_j - mu_k).T, np.linalg.inv(Sigma_k)), y_j - mu_k)

        # 返回是重新取指数抵消前面的取对数操作
        return np.exp(-0.5 * (n_1 + n_2 + n_3))

    def _E_step(self, y):
        alpha = self.params['alpha']
        mu = self.params['mu']
        Sigma = self.params['Sigma']

        for j in range(self.N):
            y_j = y[j]
            gamma_list = []
            for k in range(self.K):
                alpha_k = alpha[k]
                mu_k = mu[k]
                Sigma_k = Sigma[k]
                gamma_list.append(alpha_k * self._gaussian_function(y_j, mu_k, Sigma_k))

            # 对隐变量进行迭代跟新
            self.params['gamma'][j, :] = np.array([v / np.sum(gamma_list) for v in gamma_list])

    def _M_step(self, y):
        mu = self.params['mu']
        gamma = self.params['gamma']
        for k in range(self.K):
            mu_k = mu[k]
            gamma_k = gamma[:, k]
            gamma_k_j_list = []
            mu_k_part_list = []
            Sigma_k_part_list = []
            for j in range(self.N):
                y_j = y[j]
                gamma_k_j = gamma_k[j]
                gamma_k_j_list.append(gamma_k_j)

                # mu_k的分母的分母列表
                mu_k_part_list.append(gamma_k_j * y_j)

                # Sigma_k的分母列表
                Sigma_k_part_list.append(gamma_k_j * np.outer(y_j - mu_k, (y_j - mu_k).T))

            # 对模型参数进行迭代更新
            self.params['mu'][k] = np.sum(mu_k_part_list, axis=0) / np.sum(gamma_k_j_list)
            self.params['Sigma'][k] = np.sum(Sigma_k_part_list, axis=0) / np.sum(gamma_k_j_list)
            self.params['alpha'][k] = np.sum(gamma_k_j_list) / self.N

    def fit(self, y, max_iter=100):
        y = np.array(y)
        self.N, self.D = y.shape
        self.__init_params()

        for _ in range(max_iter):
            self._E_step(y)
            self._M_step(y)

def get_samples(n_ex=1000, n_classes=3, n_in=2, seed=None):
    # 生成100个样本，为了能够在二维平面上画出图线表示出来，每个样本的特征维度设置为2
    from sklearn.datasets.samples_generator import make_blobs
    from sklearn.model_selection import train_test_split
    y, _ = make_blobs(
        n_samples=n_ex, centers=n_classes, n_features=n_in, random_state=seed)
    return y

def run_my_model():
    from matplotlib import pyplot as plt
    my = MyGMM()
    y = get_samples()
    print(y)
    my.fit(y)
    max_index = np.argmax(my.params['gamma'], axis=1)
    #print(max_index)

    k1_list = []
    k2_list = []
    k3_list = []

    for y_i, index in zip(y, max_index):
        if index == 0:
            k1_list.append(y_i)
        elif index == 1:
            k2_list.append(y_i)
        else:
            k3_list.append(y_i)
    k1_list = np.array(k1_list)
    k2_list = np.array(k2_list)
    k3_list = np.array(k3_list)

    plt.scatter(k1_list[:, 0], k1_list[:, 1], c='red')
    plt.scatter(k2_list[:, 0], k2_list[:, 1], c='blue')
    plt.scatter(k3_list[:, 0], k3_list[:, 1], c='green')
    plt.show()

run_my_model()


# -*- coding: utf-8 -*-
import metadata.rule as rule

def check_record(records, result, event_type):

    item = dict()
    item['check_point'] = 'act_report_numbers'
    item['type'] = 'report_number'
    item['result'] = ''
    item['reason'] = {}
    item['data'] = {}

    if len(records) == 1:
        item['result'] = 'success'

    elif len(records) == 0:
        item['result'] = 'failure'
        item['reason']['number'] = 'query no data '
    else:
        item['result'] = 'failure'
        item['reason']['number'] = 'query data number was not 1'

    result['items'].append(item)
    return

def check_retry(records, result, event_type):

    item = dict()
    item['check_point'] = 'ip_retry_times'
    item['type'] = 'retry_times'
    item['result'] = ''
    item['reason'] = {}
    item['data'] = {}

    count = len(records)
    if count != 3:
        item['result'] = 'failure'
        item['reason'] = {'error': 'retry times set was 3, but was ' + str(count)}
    else:
        item['result'] = 'success'
        item['reason'] = {}

    result['items'].append(item)

def check(records, result, event_type):

    # retry case
    if event_type in ['cdn_if1_ip_retry_video', 'cdn_if1_ip_retry_channel']:
        check_retry(records, result, event_type)
        return

    check_record(records, result, event_type)
    for r in records:
        data_check(r, result, event_type)

def data_check(record, result, event_type):
    if 'if1' in event_type:
        if 'channel' in event_type:
            act = 'cdn_if1_c'
        else:
            act = 'cdn_if1_v'
    else:
        if 'channel' in event_type:
            act = 'cdn_if2_c'
        else:
            act = 'cdn_if2_v'

    item = dict()
    item['check_point'] = act
    item['type'] = 'field_check'
    item['result'] = ''
    item['reason'] = {}
    item['data'] = {}

    result['items'].append(item)

    item['data']['act'] = act
    item['data']['time'] = record['time2']

    tool = rule.CheckTool(act, event_type)
    tool.check_service(record, item['reason'])
    rule.get_data(record, item['data'])

    if len(item['reason']) == 0:
        item['result'] = 'success'
    else:
        item['result'] = 'failure'

    item2 = dict()
    item2['check_point'] = act + '_report_time'
    item2['type'] = 'report_time'
    item2['result'] = 'success'
    item2['reason'] = {}
    item2['data'] = {}
    result['items'].append(item2)

if __name__ == "__main__":
    pass


# importing various libraries
import sys
from PyQt5.QtWidgets import QMainWindow, QDialog, QApplication, QPushButton, QVBoxLayout, QComboBox , QHBoxLayout,QFileDialog
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import random
import numpy as np

# main window
# which inherits QDialog
class DOS1(QDialog):

	# constructor
    def __init__(self, parent=None):
        super(DOS1, self).__init__(parent)

		# a figure instance to plot on
        self.figure = plt.figure()

		# this is the Canvas Widget that
		# displays the 'figure'it takes the
		# 'figure' instance as a parameter to __init__
        self.canvas = FigureCanvas(self.figure)

		# this is the Navigation widget
		# it takes the Canvas widget and a parent
        self.toolbar = NavigationToolbar(self.canvas, self)

        self.buttondata=QPushButton('Open data')

		# Just some button connected to 'plot' method
        self.button = QPushButton('Plot')

		# adding action to the button
        self.button.clicked.connect(self.plot)
        self.buttondata.clicked.connect(self.open_dialog_box)
        self.combox = QComboBox()
        self.comboy = QComboBox()
        self.datapath = "None"
        self.headlines = []

   		# creating a Vertical Box layout
        layout = QVBoxLayout()
		# adding tool bar to the layout
        layout.addWidget(self.toolbar)
		# adding canvas to the layout
        layout.addWidget(self.canvas)

		# adding push button to the layout
        horizlayout=QHBoxLayout()
        horizlayout.addWidget(self.buttondata)
        horizlayout.addWidget(self.combox)
        horizlayout.addWidget(self.comboy)

        layout.addLayout(horizlayout)
        layout.addWidget(self.button)
        # setting layout to the main window
        self.setLayout(layout)

    # action called by thte push button

    def open_dialog_box(self):
        filename = QFileDialog.getOpenFileName()
        path = filename[0]
        directad = path.split('/')[:-1]
        fname=path.split('/')[-1]

        basename=fname.split(".")[0]
        print(path)
        print("your data file is ", fname)

        f=open(path, "r")
        firstline=f.readline()
        headers=firstline.split()[1:]
        f.close()

        self.datapath = path
        list1=headers
        self.combox.addItems(list1)
        self.comboy.addItems(list1)
        for val in list1:
        	self.headlines.append(val)
        print(self.headlines)

    def plot(self):

        xstr = self.combox.currentText()
        ystr = self.comboy.currentText()

        xind = self.headlines.index(xstr)
        yind = self.headlines.index(ystr)
        data = np.loadtxt(self.datapath)
        # clearing old figure
        self.figure.clear()
# create an axis
        ax = self.figure.add_subplot(111)

        # plot data
        ax.set_xlim(min(data[:,xind]), 1.1*max(data[:,xind]))
        ax.set_ylim(min(data[:,yind]), 1.1*max(data[:,yind]))
        ax.set_xlabel(xstr, fontsize=14)
        ax.set_ylabel(ystr, fontsize=12)
        ax.plot(data[:,xind], data[:,yind], '-')
        plt.tight_layout()
        plt.savefig("test00.png",bbox_inches='tight', dpi=300)

		# refresh canvas
        self.canvas.draw()

# driver code
if __name__ == '__main__':

	# creating apyqt5 application
	app = QApplication(sys.argv)
	# creating a window object
	win1 = DOS1()
	# showing the window
	win1.show()
	# loop
	app.exec_()


#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Simulate the "Abbey of crime" environment.

Each episode is making a single action (doing nothing is an action) .
"""

# core modules
import random
import math
import json
import time
import datetime
import os
from pathlib import Path
from threading import Thread
import gzip
import shutil

# 3rd party modules
import gym
import numpy as np
from gym import spaces
from google.cloud import storage

import logging

# AbadIA2 dependencies
import requests

def get_chance(x):
    """Get probability that a banana will be sold at price x."""
    e = math.exp(1)
    return (1.0 + e) / (1. + math.exp(x + 1))

class AbadiaEnv2(gym.Env):
    """
    Define a Abadia2 environment.

    The environment defines which actions can be taken at which point and
    when the agent receives which reward.
    """

    def __init__(self):
        self.__version__ = "0.0.7"
        print("AbadiaEnv2 - Version {}".format(self.__version__))

        self.url    = "http://localhost:4477"
        self.server = "http://localhost"
        self.port   = "4477"
        self.num_episodes   = 100
        self.num_steps      = 1500
        self.gsBucket       = None

        self.gameName       = ""
        self.actionsName    = ""
        self.checkpointName = None
        self.modelName      = None
        self.valueModelName = None
        self.initValueModelName = None
        self.dump_path      = "games/now/"
        self.gameId = datetime.datetime.now().strftime('%y%m%d_%H%M%S_%f')
        self.checkpointSec  = 1
        self.storage_client = None
        self.eventsGame     = []
        self.eventsAction   = []
        self.totalReward    = 0.0
        self.verbose        = 0
        self.playing        = False

        # Define what the agent can do
        # 0 -> STEP FORWARD
        # 1 -> RIGHT
        # 2 -> LEFT
        # 3 -> DOWN
        # 4 -> GET

        self.action_space = spaces.Discrete(9)

        # json from the dump state of the episode

        self.json_dump = {}

        self.action_mode = 1

        self.actions_list_2 = ("abadIA/game/current/actions/UP",
                             "abadIA/game/current/actions/RIGHT",
                             "abadIA/game/current/actions/LEFT",
                             "abadIA/game/current/actions/DOWN",
                             "cmd/N",
                             "cmd/_"
                             )
        self.actions_list = ("N", "NE", "E", "SE", "S", "SW", "W", "NW", "NOP")

        self.obsequium = -1
        self.reward = 0
        self.porcentaje = -1
        self.haFracasado = False
        self.prevPantalla = -1
        self.rejilla = []
        self.prev_ob = dict()
        self.estaGuillermo= False
        self.room = np.zeros([20,20,3], np.int)

        self.curr_step = -1
        self.is_game_done = False

        self.Personajes = {
            "Guillermo":  {},
            "Adso":       {},
            "Abad":       {},
            "Malaquias":  {},
            "Berengario": {},
            "Severino":   {},
            "Jorge":      {},
            "Bernardo":   {}
        }

        self.listaPersonajes = ("Guillermo", "Adso", "Abad", "Malaquias", "Berengario",
            "Severino", "Jorge", "Bernardo")

        self.Visited = np.zeros([512, 512])

        # Observation is the position of Guillermo and the information of the room
        X = np.array([0, 256])
        Y = np.array([0, 256])
        O = np.array([0,   4])

        high = np.array([np.inf] * 15)  # useful range is -1 .. +1, but spikes can be higher
        self.observation_space = spaces.Box(-high, high)

        # Store what the agent tried
        self.curr_episode = -1
        self.action_episode_memory = []

        now = datetime.datetime.now()
        self._seed(time.mktime(now.timetuple()))
        logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', datefmt='%d-%m-%y %H:%M:%S',
                            level=logging.INFO)

        # helper to normalize paths to positions
        #   1
        # 2   0
        #   3

        self.path2Pos = {
            "0N": "LEFT:UP:UP",
            "1N": "UP:UP",
            "2N": "RIGHT:UP:UP",
            "3N": "RIGHT:RIGHT:UP:UP",

            "0NE": "UP:UP:LEFT:UP:UP",
            "1NE": "UP:UP:RIGHT:UP:UP",
            "2NE": "RIGHT:UP:UP:RIGHT:UP:UP",
            "3NE": "RIGHT:RIGHT:UP:UP:RIGHT:UP:UP",

            "0E": "UP:UP",
            "1E": "RIGHT:UP:UP",
            "2E": "RIGHT:RIGHT:UP:UP",
            "3E": "LEFT:UP:UP",

            "0SE": "UP:UP:RIGHT:UP:UP",
            "1SE": "RIGHT:UP:UP:RIGHT:UP:UP",
            "2SE": "RIGHT:RIGHT:UP:UP:RIGHT:UP:UP",
            "3SE": "UP:UP:LEFT:UP:UP",

            "0S": "RIGHT:UP:UP",
            "1S": "RIGHT:RIGHT:UP:UP",
            "2S": "LEFT:UP:UP",
            "3S": "UP:UP",

            "0SW": "RIGHT:UP:UP:RIGHT:UP:UP",
            "1SW": "RIGHT:RIGHT:UP:UP:RIGHT:UP:UP",
            "2SW": "UP:UP:LEFT:UP:UP",
            "3SW": "UP:UP:RIGHT:UP:UP",

            "0W": "RIGHT:RIGHT:UP:UP",
            "1W": "LEFT:UP:UP",
            "2W": "UP:UP",
            "3W": "RIGHT:UP:UP",

            "0NW": "LEFT:UP:UP:LEFT:UP:UP",
            "1NW": "UP:UP:LEFT:UP:UP",
            "2NW": "UP:UP:RIGHT:UP:UP",
            "3NW": "RIGHT:RIGHT:UP:UP:RIGHT:UP:UP"

        }

    def set_url(self):
        self.url = self.server + ":" + self.port

    def check2dict(self, line):

        pre = "core_"
        output = {}
        for line in line.split("\n"):
            # print(line)
            res = line.split("// ")

            if (len(res) == 2):
                value = res[0]
                key = res[1]
                if (value == ""):
                    pre = key.replace(" ", "_") + "_"
                else:
                    output[pre + key] = int(value)

            # print("value ({}) key ({})".format(value, pre + key))
        # print(json.dumps(output))
        # logging.info(output)
        return output

    # TODO JT refactoring and eliminate this function
    def sendReset(self):
        self.sendCmd(self.url, "abadIA/game/current/actions/SPACE", mode='POST')
        # sleep(1)
        self.sendCmd(self.url, "abadIA/game/current/actions/SPACE", mode='POST')
        return self.sendCmd(self.url, "abadIA/game", mode="POST")

    def sendCmd(self, url, command, type="json", mode="GET"):
        cmd = "{}/{}".format(url, command)
        try:
            if mode == "GET":
                r = requests.get(cmd)
            if mode == "POST":
                r = requests.post(cmd)

            if (type == "json"):
                headers = {'accept': 'application/json'}
            else:
                headers = {'accept': 'text/x.abadIA+plain'}
        except:
            logging.error("Vigasoco comm error")
            return None
        headers = {'accept': 'text/x.abadIA+plain'}

        cmdDump = "{}/abadIA/game/current".format(self.url)
        core = requests.get(cmdDump, headers=headers)
        # logging.info(core.text)
        core_dict = self.check2dict(core.text)

        headers = {'accept': 'application/json'}
        cmdDump = "{}/abadIA/game/current".format(url)
        r = requests.get(cmdDump, headers= headers)

        if (type == "json"):
            tmp = r.json()
            tmp['core'] = core_dict

            if r.status_code == 599:
                tmp['haFracasado'] = True
            return tmp
        else:
            return r.text

    def sendMultiCmd(self, path):
        logging.info("Path: %s Cmds: %s" % (path,  self.path2Pos[path]))
        cmds = self.path2Pos[path].split(":")
        for step in cmds:
            self.sendCmd(self.url, "abadIA/game/current/actions/{}".format(step), mode='POST')

        headers = {'accept': 'text/x.abadIA+plain'}
        cmdDump = "{}/abadIA/game/current".format(self.url)
        core = requests.get(cmdDump, headers=headers)
        # logging.info(core.text)
        core_dict = {"version": "v7"}
        core_dict = self.check2dict(core.text)

        headers = {'accept': 'application/json'}
        cmdDump = "{}/abadIA/game/current".format(self.url)
        r = requests.get(cmdDump, headers=headers)
        tmp = r.json()
        tmp['core'] =  core_dict
        if r.status_code == 599:
            tmp['haFracasado'] = True
        return tmp

    def step(self, action):
        """
        The agent takes a step in the environment.

        Parameters
        ----------
        action : int

        Returns
        -------
        ob, reward, episode_over, info : tuple
            ob (object) :
                an environment-specific object representing your observation of
                the environment.
            reward (float) :
                amount of reward achieved by the previous action. The scale
                varies between environments, but the goal is always to increase
                your total reward.
            episode_over (bool) :
                whether it's time to reset the environment again. Most (but not
                all) tasks are divided up into well-defined episodes, and done
                being True indicates the episode has terminated. (For example,
                perhaps the pole tipped too far, or you lost your last life.)
            info (dict) :
                 diagnostic information useful for debugging. It can sometimes
                 be useful for learning (for example, it might contain the raw
                 probabilities behind the environment's last state change).
                 However, official evaluations of your agent are not allowed to
                 use this for learning.
        """

        try:
            if (action >=8 ):
                ob = self.sendCmd(self.url, self.actions_list[action], mode="POST")
            else:
                ori = str(self.Personajes['Guillermo']['orientacion'])
                ob = self.sendMultiCmd(ori + self.actions_list[action])
        except Exception as e:
            logging.error("Communication Error: I cannot send the CMDs {}".format(e))
            logging.error("Check if the game engine is UP")
            self.game_is_done = True
            return self.prev_ob, 0, self.game_is_done, {}

        # print("ob -> {}".format(ob)) # ['obsequium']))

        # extracting all the values from the json
        # first personajes

        self._get_personajes_info(ob)

        self.obsequium    = int(ob['obsequium'])
        self.porcentaje   = int(ob['porcentaje'])
        self.bonus        = int(ob['bonus'])
        self.numPantalla  = int(ob['numPantalla'])
        self.dia          = int(ob['dia'])
        self.momentoDia   = int(ob['momentoDia'])
        self.haFracasado  = ob['haFracasado']
        self.rejilla      = ob['Rejilla']

        # print(self.rejilla)

        # we need to check is make sense finish it
        # if self.is_game_done or self.porcentaje == 100:
        #   raise RuntimeError("Episode is done")
        self.curr_step += 1
        self._take_action(action)

        ob['jugada'] = self.curr_step
        ob['gameId'] = self.gameId

        # reward = self._get_reward()

        reward = 0
        self.eventsAction = []
        # TODO JT we need to check, that pass to another room
        # not just stay all the time between rooms to get the reward

        if self.estaGuillermo:
            if (self.prevPantalla == -1):
                self.prevPantalla = int(ob['numPantalla'])
            else:
                if (self.prevPantalla != int(ob['numPantalla'])):
                    # reward += 0.03
                    # logging.info("----------")
                    # logging.info("reward by screen change !!!!! {} !=  {}".format(self.prevPantalla, int(ob['numPantalla'])))
                    # logging.info("Personajes: {}".format(self.Personajes))
                    # # logging.info("ob: {}".format(ob))
                    # logging.info("----------")
                    # self.add_event("NewRoom", "prev {} curr {}".format(self.prevPantalla, int(ob['numPantalla'])), 0.001)
                    self.prevPantalla = int(ob['numPantalla'])
                    self.save_game_checkpoint()

        # # If there is an obsequium change, it will be rewarded pos/neg
        # if len(self.prev_ob) > 0 and int(self.prev_ob['obsequium']) > 0:
            # # reward for incrementing the obsequium: > 0 +50 / < 0 -30
            # incr_obsequium = self.obsequium - int(self.prev_ob['obsequium'])
            # if incr_obsequium > 0:
                # reward += (50 * incr_obsequium) / 10000
                # self.add_event("IncrObsequium", "Obsequium {} Incr {}".format(self.prev_ob['obsequium'],incr_obsequium), (50 * incr_obsequium) / 10000)

            # if incr_obsequium < 0:
                # reward += (30 * incr_obsequium) / 10000
                # self.add_event("DecrObsequium", "Obsequium {} Decr {}".format(self.prev_ob['obsequium'], incr_obsequium),(30 * incr_obsequium) / 10000)

        # reward for incrementing the bonus: >0 +500
        # if len(self.prev_ob) > 0 and int(self.prev_ob['bonus']) > 0:
            # incr_bonus = self.bonus - int(self.prev_ob['bonus'])
            # if incr_bonus > 0:
                # reward += (500 * incr_bonus) / 10000
                # self.add_event("Bonus", "prev {} curr {}".format(self.bonus, int(self.prev_ob['bonus'])), (500 * incr_bonus) / 10000)

        # we check if Guillermo change his position. Positive reward if yes, negative if no
        # if action == 0:
        # if len(self.prev_ob) > 0 and len(self.prev_ob['Personajes']) > 0:
            # prev = self.dataPersonaje(self.prev_ob, "Guillermo")
            # curr = self.dataPersonaje(ob, "Guillermo")
            # if (prev['posX'] != curr['posX']) or (prev['posY'] != curr['posY']):
                # logging.info("se ha movido: {},{} -> {},{}".format(prev['posX'], prev['posY'],
                                                        # curr['posX'], curr['posY']))
                # reward += 0.001

        # TODO: check this self.eventsGame.extend(self.eventsAction)
        # if the game is over, we just finish the game and reward is -1000
        # if we completed the game, we finish and the reward is 5000
        # the percentage must be variable to help the AI to learn
        # with variable explanatory/explotation

        if (self.obsequium < 29):
            logging.info("GAME OVER by lack of Obsequium {}        ".format(self.obsequium))
            self.sendCmd(self.url, "/abadIA/game", mode='POST', type='raw')
            self.game_is_done = True
            self.haFracasado = True
            reward = -1

        if (self.haFracasado == True):
            logging.info("GAME OVER")
            self.sendCmd(self.url, "/abadIA/game", mode='POST', type='raw')
            self.game_is_done = True
            reward = -1

        if (self.porcentaje >= 90):
            self.game_is_done = True
            logging.info("FUCKING YEAH GAME ALMOST DONE")
            logging.info("FUCKING YEAH GAME ALMOST DONE")
            logging.info("FUCKING YEAH GAME ALMOST DONE")
            logging.info("FUCKING YEAH GAME ALMOST DONE")
            logging.info("FUCKING YEAH GAME ALMOST DONE")
            reward = 1

        # if no reward we penalized it
        # if reward == 0:
            # logging.info("***** No reward, penalizing it")
            # reward = -0.005

        # if self.obsequium > 0:
        #    reward = reward * float((self.obsequium / self.obsequium)*0.5)
        # if self.porcentaje > 0:
        #    reward = reward * float(((self.porcentaje * 0.5) / self.porcentaje)+1)

        if (self.wallMovs[action] == 1):
            logging.info("***** Invalid move against Wall, penalizing it")
            reward = -0.00901

        if (self.perMovs[action] == 1):
            logging.info("***** Invalid move against a Character, penalizing it")
            reward = -0.00902

        ###########################
        # New Experimental Reward #
        ###########################

        reward = float( ((self.porcentaje + 1) / 10000) * self.obsequium / 31)

        self.reward       = reward
        self.totalReward += reward
        ob['reward']      = reward
        ob['totalReward'] = self.totalReward
        logging.info("reward: {} tr: {} action: {} ".format(reward, self.totalReward, action))

        # adding more information for debugging: valid moves, vectors, predictions, etc.
        ob['valMovs']            = self.valMovs.tolist()
        ob['wallMovs']           = self.wallMovs.tolist()
        ob['perMovs']            = self.perMovs.tolist()
        ob['predictions']        = self.calculated_predictions
        ob['final']              = self.final_predictions
        ob['vector']             = self.vector_predictions
        ob['action_predictions'] = self.action_predictions
        ob['action_type']        = self.action_type

        # we make a copy for the current observation in order to calculate
        # the reward for the next state

        self.ob = ob
        self.prev_ob = ob

        # JT chequear si esto está bien, no parece que este devolviendo bien el estado siguiente!!!

        return ob, reward, self.game_is_done, {}

    def _get_personajes_info(self, ob):
        # print ("ob personajes -> {} ", ob['Personajes']['Personaje'][0])
        self.estaGuillermo = False
        for persona in self.listaPersonajes[:]:
            self.Personajes[persona] = {}
        for personaje in ob['Personajes']:
            if (len(personaje) == 1):
                break
            # persona = self.listaPersonajes[int(personaje['id'])]
            # datos = self.Personajes[persona]
            # for key, value in personaje.items():
                #if key != "id" or key != "fil":
                # datos[key] = value
            self.Personajes[personaje['nombre']] = personaje

            if int(personaje['id']) == 0:
                self.estaGuillermo = True

        return self.estaGuillermo

    # check is make sense do it for special state

    def normalizaVisited(self, x, y):
        bordes = []
        for X in range(x-1, x+2):
            for Y in range(y-1, y+2):
                if (self.Visited[X,Y] < 0):
                    bordes.append(1)
                else:
                    bordes.append(0)
        # print("bordes {}".format(bordes))
        return bordes

    def stateVector(self):
        x, y, ori    = self.personajeByName('Guillermo')
        ax, ay, aori = self.personajeByName('Adso')

        vector = np.append([x, y, ori, ax, ay, aori],self.normalizaVisited(x,y))
        # print("vector {}".format(vector))
        return vector.reshape(1,15)

    def _take_action(self, action):
        self.action_episode_memory[self.curr_episode].append(action)

        game_is_done = (self.obsequium <= 0)

        # remaining_steps = self.TOTAL_TIME_STEPS - self.curr_step
        # time_is_over = (remaining_steps <= 0)
        # throw_away = time_is_over and not self.is_banana_sold
        # if throw_away:
            # self.is_banana_sold = False # abuse this a bit
            # self.price = 0.0

    def _get_reward(self):
        """Reward is about how complete is the game"""
        if self.is_game_done:
            return self.price - 1
        else:
            return 0.0

    def reset(self):
        """
        Reset the state of the environment and returns an initial observation.

        Returns
        -------
        observation (object): the initial observation of the space.
        """
        self.gameId      = datetime.datetime.now().strftime('%y%m%d_%H%M%S_%f')
        self.gameName    = "abadia_game_{}.json".format(self.gameId)
        self.actionsName = "abadia_actions_{}.json".format(self.gameId)

        self.curr_episode += 1
        self.curr_step     = 1

        self.eventsGame   = []
        self.eventsAction = []
        self.totalReward  = 0.0
        self.predictions  = []

        self.action_episode_memory.append([])
        # self.is_game_done = False
        self.game_is_done = False

        logging.info('-----> RESET the GAME')
        ob = self.sendReset()
        logging.info('reset status') # {}'.format(ob))
        logging.info('-----> DONE')
        logging.info('-----> INIT dumps files: START ...')
        self.init_dumps_files()
        logging.info('-----> INIT dumps files: DONE')
        # time.sleep(5)
        if self._get_personajes_info(ob):
            logging.info('Esta Guillermo')
        return ob

    def render(self, mode='human', close=False):
        logging.info('state info: {}'.format(self))
        return

    def _get_state(self):
        """Get the observation."""
        # ob = [self.TOTAL_TIME_STEPS - self.curr_step]
        logging.info("--------> I wil got the initial state with Guillermo")
        tooboring = 0
        while True:
            ob = self.sendCmd(self.url, "/abadIA/current/game", mode='GET', type='json')
            # logging.info("{}".format(ob))
            tooboring += 1
            if self._get_personajes_info(ob):
                logging.info("getting the characters from Dump")
                break
            else:
                logging.info("getting the characters from ob") # :{}".format(ob))
                logging.info("Guillermo is not present yet, waiting")
                if tooboring % 10 == 0:
                    logging.info("Getting Boring ...")
                    if tooboring <= 10:
                        self.sendCmd(self.url, "start")
                    else:
                        self.sendCmd(self.url, "fin")
                    # self.sendCmd(self.url, "cmd/B")
                    # self.sendCmd(self.url, "cmd/A")
                    time.sleep(1)
                time.sleep(2)
        return ob

    def _seed(self, seed):
        random.seed(seed)
        np.random.seed

    # "planta": "0", "sonidos": ["0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"], "frases": [], "Personajes": {"Personaje": [{"id": "0", "nombre": "Guillermo", "posX": "137", "posY": "168", "altura": "0", "orientacion": "0", "objetos": "32"}, {"id": "1", "nombre": "Adso", "posX": "134", "posY": "168", "altura": "0", "orientacion": "1", "objetos": "32"}]}, "Objetos": {"ListaObjetos": []}
    def get_commons(self):
        commons = dict()
        commons.update({'timestamp': "{}".format(datetime.datetime.now()), 'numDia': int(self.ob['dia'])})
        commons.update({'momentoDia': int(self.ob['momentoDia']), 'obsequium': int(self.ob['obsequium'])})
        x = int(self.Personajes['Guillermo']['posX'])
        y = int(self.Personajes['Guillermo']['posY'])
        pantallaHex = "%1X%1X" % (x >> 4, y >> 4)
        commons.update({'numPantalla': int(self.ob['numPantalla']), 'pantallaHex': pantallaHex})
        commons.update({'planta': int(self.ob['planta']), 'guillermoPosX': x, 'guillermoPosY': y})
        commons.update({'bonus': int(self.ob['bonus']), 'porcentaje': int(self.ob['porcentaje'])})
        return commons

    def init_google_store_bucket(self):
        storage_client = storage.Client()
        self.google_storage_bucket = storage_client.get_bucket(self.gsBucket)

    def download_blob(self, source_blob_name, destination_file_name):
        blob = self.google_storage_bucket.blob(source_blob_name)
        directory = os.path.dirname(destination_file_name)
        if not os.path.exists(directory):
            os.makedirs(directory)
        blob.download_to_filename(destination_file_name)

        logging.info('Blob {} downloaded to {}.'.format(
            source_blob_name,
            destination_file_name))

    def upload_blob(self, source_file_name, destination_blob_name):
        """Uploads a file to the bucket."""
        blob = self.google_storage_bucket.blob(destination_blob_name)
        blob.upload_from_filename(source_file_name)

        logging.info('File {} uploaded to {}.'.format(
            source_file_name,
            destination_blob_name))

    def add_event(self, name, des, reward):
        data = {'name': name, 'des': des, 'reward': reward, 'totalReward': self.totalReward, 'version': 1}
        data.update(self.get_commons())

        self.eventsAction.append(data)
        logging.info("events {}".format(self.eventsAction))

    def save_game(self):
        self.fdGame.write("{}{}\"gameId\":\"{}\", \"totalSteps\":{}, \"obsequium\":{}, \"porcentaje\":{}, \"bonus\":{}, "
                          .format("[", "{", self.gameId, self.curr_step, self.obsequium, self.porcentaje, self.bonus))

        self.fdGame.write("\"totalReward\": \"{}\", "
                          .format("%.4f" % self.totalReward))

        self.fdGame.write("\"events\":{}"
                .format(json.dumps(self.eventsGame)))

        self.fdGame.write("{}\n".format("}]"))
        self.fdGame.flush()
        # self.fdGame.close()

        if (not self.fdActions.closed):
            logging.info("flushing and closing {} before exit".format(self.actionsName))
            self.fdActions.flush()
            self.fdActions.close()

        if (self.gsBucket != None):
            logging.info("Uploading Game: {} to GCP".format(self.dump_path + "/" + self.gameName))
            t = Thread(target=self.upload_blob, args=(self.dump_path + "/" + self.gameName,
                                                      self.dump_path + "/" + self.gameName))
            t.start()

            # compressing the file
            logging.info("Gziping ---> {}".format(self.dump_path + "/" + self.actionsName))
            with open(self.dump_path + "/" + self.actionsName, 'rb') as f_in, gzip.open(self.dump_path + "/" + self.actionsName + '.gz', 'wb') as f_out:
                shutil.copyfileobj(f_in, f_out)

            logging.info("Uploading Actions: {} to GCP".format(self.dump_path + "/" + self.actionsName + ".gz"))
            t = Thread(target=self.upload_blob, args=(self.dump_path + "/" + self.actionsName + ".gz",
                             self.dump_path + "/" + self.actionsName + ".gz"))
            t.start()
            logging.info("Deleting ---> {}".format(self.dump_path + "/" + self.actionsName))
            os.remove(self.dump_path + "/" + self.actionsName)

    def save_action(self, state, action, reward, nextstate):
        s1 = state.copy()
        s2 = nextstate.copy()

        string = "{}{}\"action\":{}\"state\":{},\"action\":{},\"reward\":{},\"nextstate\":{}{}{}\n".format("[", "{", "{", json.dumps(s1), action, reward, json.dumps(s2), "}", "}]")
        self.fdActions.write(string)
        self.fdActions.flush()

    def visited_snap_load(self):
        nameVisitedSnap = "snapshoots/current-visited"

        # for speed up the games if the visited  exist locally
        # we download an updated version just a 10% of the time

        if self.gsBucket != None and np.random.randint(10) <= 1 and not os.path.exists(nameVisitedSnap):
            logging.info("Downloading Visited from GCP")
            try:
                self.download_blob(nameVisitedSnap, nameVisitedSnap)
            except:
                logging.info("File {} not exist at bucket {}".format(nameVisitedSnap, self.gsBucket))

        if os.path.exists(nameVisitedSnap) and os.path.getsize(nameVisitedSnap) > 0:
            fvisitedsnap = open(nameVisitedSnap, "rb+")
            self.Visited = np.load(fvisitedsnap)
        else:
            fvisitedsnap = open(nameVisitedSnap, "wb+")
            self.Visited = np.zeros([512, 512])
            np.save(fvisitedsnap, self.Visited)
            fvisitedsnap.flush()
            fvisitedsnap.close()

            if (self.gsBucket != None):
                logging.info("Uploading to GCP")
                self.upload_blob(nameVisitedSnap, nameVisitedSnap)

    def visited_snap_save(self):
        nameVisitedSnap = "snapshoots/current-visited"

        fvisitedsnap = open(nameVisitedSnap, "wb+")
        np.save(fvisitedsnap, self.Visited)
        fvisitedsnap.flush()
        fvisitedsnap.close()

        if (self.gsBucket != None):
            logging.info("Uploading visited to GCP")
            t = Thread(target=self.upload_blob, args=(nameVisitedSnap, nameVisitedSnap))
            t.start()

    def reset_fin_partida(self):
        self.sendCmd(self.url, "abadIA/game/current/actions/SPACE", mode='POST')
        ob = self.sendCmd(self.url, "abadIA/game", mode="POST")

    def init_dumps_files(self):

        # check is directory exist, if not we will create it
        now = datetime.datetime.now()
        self.dump_path = now.strftime('games/%Y%m%d')
        path = Path(self.dump_path)
        path.mkdir(parents=True, exist_ok=True)

        # create the game and actions files
        self.fdGame    = open(self.dump_path + "/" + self.gameName, "w")
        self.fdActions = open(self.dump_path + "/" + self.actionsName, "w")

    def save_game_checkpoint(self):

        checkpoint = self.sendCmd(self.url, "/abadIA/game/current", mode='GET', type="raw")
        if (checkpoint is None):
            logging.error("I cannot save the checkpoint game file. Probably because I cannot connect with the game server ")
            return
        now = datetime.datetime.now()
        self.dump_path = now.strftime('games/%Y%m%d')
        path = Path(self.dump_path)
        path.mkdir(parents=True, exist_ok=True)

        # create the checkpoint file
        self.checkpointTmpName  = "abadia_checkpoint_{}_{}".format(self.gameId, self.checkpointSec)
        self.checkpointSec     += 1
        self.checkpointTmpName += "_{}_{}_{}_{}_{}.checkpoint".format(self.dia, self.momentoDia,
                                                self.numPantalla, self.obsequium, np.round(self.porcentaje,2))

        self.fdCheckpoint = open(self.dump_path + "/" + self.checkpointTmpName, "w")
        self.fdCheckpoint.write(checkpoint)
        self.fdCheckpoint.flush()

        if (self.gsBucket != None):
            logging.info("Uploading {} to GCP".format(self.dump_path + '/' + self.checkpointTmpName))
            t = Thread(target=self.upload_blob, args=(self.dump_path + '/' + self.checkpointTmpName,
                             self.dump_path + '/' + self.checkpointTmpName))
            t.start()
        # else:
            # logging.error("Not saving it to the local filesystem")

    def load_game_checkpoint(self, name):
        logging.info("voy a abrir el fichero ({})".format(name))

        if (self.gsBucket != None):
            logging.info("Downloading Checkpoint {} from GCP".format(name))
            try:
                self.download_blob(name, name)
                self.fdCheckpoint = open(name, "r")
                checkpoint = self.fdCheckpoint.read()
                requests.put(self.url+"/abadIA/game/current", data=checkpoint)
            except:
                logging.error("*** ErrorFile: {} not exist at bucket {}".format(name, self.gsBucket))
        else:
            logging.error("Not Loading {} from local filesystem.".format(name))

        time.sleep(2)
        return self._get_state()

    def personajeByName(self, name):
        # TODO JT: we need to check that there are values for this personaje
        if (name in self.Personajes) and ('posX' in self.Personajes[name]):
            return int(self.Personajes[name]['posX']), int(self.Personajes[name]['posY']), int(self.Personajes[name]['orientacion'])
        else:
            # logging.info("No hay {}: {}".format(name, self.Personajes))
            return 0, 0, 0

    def dataPersonaje(self, ob, name):
        notfound = {}
        for persona in ob['Personajes']:
            if (persona['nombre'] == name):
                return persona
        return notfound

    def pintaRejilla(self, width, height):
        w = int(width / 2)
        h = int(height / 2)
        yRejilla = 0
        xRejilla = 0

        # TODO: to display all the characters, now only Guillermo and Adso
        # pers = {}
        # for per in env.Personajes:
        #    datos = {'x': per['posX'], 'y': per['posY']}
        #   pers.update(per['id']:datos)
        #

        x, y, ori           = self.personajeByName('Guillermo')
        adsoX, adsoY, adsoO = self.personajeByName('Adso')
        abadX, abadY, abadO = self.personajeByName('Abad')

        logging.info("\x1b[HGuillermo {},{} Adso {},{} Abad {},{} Obsequium:{} Porcentaje:{} Reward:{} TR:{} V:{}".format(x, y, adsoX, adsoY,
                             abadX, abadY, self.obsequium, self.porcentaje, np.round(self.reward, 6), np.round(self.totalReward, 6), np.round(self.predictions, 4)))

        logging.info("+---+" + "-" * (w * 2) + "+" + "-" * 24 + "+" + "-" * 48 + "+")

        for yy in range(y - h, y + h):
            ss = "|%3d|" % yy
            for xx in range(x - w, x + w):
                if (xx == x and yy == y):
                    if ori == 0:
                        ss += ">"
                    if ori == 3:
                        ss += "V"
                    if ori == 1:
                        ss += "^"
                    if ori == 2:
                        ss += "<"
                else:
                    character = False
                    if (xx == adsoX and yy == adsoY):
                        ss += "a"
                        character = True
                    if (xx == abadX and yy == abadY):
                        ss += "A"
                        character = True

                    if not character:
                        if (self.Visited[xx, yy] == 0):
                            ss += "·"
                        else:
                            if (self.Visited[xx, yy] > 0):
                                ss += " "
                            else:
                                ss += "#"

            ss += "|"
            if yRejilla < 24:
                for xx in range(0, 24):
                    if (self.rejilla[yRejilla][xx] == 0):
                        ss += " "
                    else:
                        if (self.rejilla[yRejilla][xx] >= 16):
                            ss += "P"
                        else:
                            ss += "#"

            ss += "|"
            if yRejilla < 24:
                for xx in range(0, 24):
                    if (self.rejilla[yRejilla][xx] == 0):
                        ss += "  "
                    else:
                        ss += "{}".format(format(self.rejilla[yRejilla][xx], '2x'))
            yRejilla += 1
            ss += "|"
            logging.info(ss)

        logging.info("+" + "-" * (w * 2) + "+" + "-" * 24 + "+" + "-" * 48 + "+")


from django.shortcuts import render

# Create your views here.

def home(request):
    return render(request, 'home.html')

def result(request):
    text = request.GET['fulltext']
    wordlist = text.split()
    wordlength = len(wordlist)
    wordcount=[]

    for i in wordlist:
        wordcount.append(i+":"+str(wordlist.count(i)))

    wordresult=list(set(wordcount))

    # wordmatch= "\n".join(wordcount)

    return render(request, 'result.html', {
        'text': text,
        'wordlist': wordlist,
        'wordlength': wordlength,
        'wordcount' : wordcount,
        'wordresult' : wordresult,
    })


import math
from typing import List

def part1(lines: List[str]):
    time = int(lines[0])
    split = filter(lambda x: x != "x", lines[1].split(","))
    times = [int(x) for x in split]
    diff = 1_000_000
    for i in range(time, time + diff):
        for j in times:
            if i % j == 0:
                return (i - time) * j

def chinese_remainder(A: List[int], N: List[int]):
    """
    Given

    x === A1 (mod N1)
    x === A2 (mod N2)
    ...
    x === An (mod Nn)

    Args:
        n: List of moduluses
        a: List of residues / remainders

    https://crypto.stanford.edu/pbc/notes/numbertheory/crt.html
    """
    result = 0
    prod = math.prod(N)
    for a_i, n_i in zip(A, N):
        N_i = prod // n_i
        result += a_i * mul_inv(N_i, n_i) * N_i
    return result % prod

def mul_inv(a: int, n: int):
    """Find multiplicative inverse of a under n.

    Solve: ax === 1 (mod n)

    This assumes that gcd(a, n) == 1, i.e.
    that a and n are coprime.

    http://www-math.ucdenver.edu/~wcherowi/courses/m5410/exeucalg.html
    """
    n0 = n
    x0, x1 = 0, 1
    if n == 1:
        return 1
    while a > 1:
        q = a // n
        a, n = n, a % n
        x0, x1 = x1 - q * x0, x0
    if x1 < 0:
        x1 += n0
    return x1

def part2(lines: List[str]):
    split = lines[1].split(",")
    idx = []
    for i, num in enumerate(split):
        if num != "x":
            new_index = (-i) % int(num)
            idx.append([new_index, int(num)])
    A = [x[0] for x in idx]
    N = [x[1] for x in idx]
    return chinese_remainder(A, N)


from collections import namedtuple, deque

import numpy as np
import pickle
import random
from typing import List, Optional
from math import isclose

import events as e
from .model import LinearQNet, QTrainer
from .visualization import Visualization
from .callbacks import state_to_features

# This is only an example!
Transition = namedtuple('Transition', ('state', 'action', 'next_state', 'reward'))

# Hyper parameters -- DO modify
TRANSITION_HISTORY_SIZE = 1000  # keep only ... last transitions
ACTION_HISTORY_SIZE = 10  # number of last actions for loop detection

# TODO: get dynamically
NUMBER_OF_FEATURES = 21

# Events
LOOP_EVENT = "LOOP_EVENT"
MOVED_TOWARDS_COIN = "MOVED_TOWARDS_COIN"
MOVED_AWAY_FROM_COIN = "MOVED_AWAY_FROM_COIN"
SURVIVED_BOMB = "SURVIVED_BOMB"
MOVED_TOWARDS_BOMB = "MOVED_TOWARDS_BOMB"
MOVED_AWAY_FROM_BOMB = "MOVED_AWAY_FROM_BOMB"
USELESS_BOMB = "USELESS_BOMB"
USEFUL_BOMB = "USEFUL_BOMB"

def setup_training(self):
    """
    Initialise self for training purpose.

    This is called after `setup` in callbacks.py.

    :param self: This object is passed to all callbacks and you can set arbitrary values.
    """
    self.transitions = deque(maxlen=TRANSITION_HISTORY_SIZE)
    self.action_history = deque(maxlen=ACTION_HISTORY_SIZE)
    self.model = LinearQNet(NUMBER_OF_FEATURES, 256, 6)
    self.trainer = QTrainer(self.model, lr=0.001, gamma=0.9)
    self.rewards = []
    self.steps = []
    self.average_rewards = []
    self.average_steps = []

def game_events_occurred(self, old_game_state: dict, self_action: str, new_game_state: dict, events: List[str]):
    """
    Called once per step to allow intermediate rewards based on game events.

    When this method is called, self.events will contain a list of all game
    events relevant to your agent that occurred during the previous step. Consult
    settings.py to see what events are tracked. You can hand out rewards to your
    agent based on these events and your knowledge of the (new) game state.

    This is *one* of the places where you could update your agent.

    :param self: This object is passed to all callbacks and you can set arbitrary values.
    :param old_game_state: The state that was passed to the last call of `act`.
    :param self_action: The action that you took.
    :param new_game_state: The state the agent is in now.
    :param events: The events that occurred when going from  `old_game_state` to `new_game_state`
    """
    self.logger.debug(f'Encountered game event(s) {", ".join(map(repr, events))} in step {new_game_state["step"]}')

    # Idea: Add your own events to hand out rewards

    if old_game_state is None:
        return

    # Update model
    update_model(self, old_game_state, self_action, new_game_state, events)

def end_of_round(self, last_game_state: dict, last_action: str, events: List[str]):
    """
    Called at the end of each game or when the agent died to hand out final rewards.

    This is similar to reward_update. self.events will contain all events that
    occurred during your agent's final step.

    This is *one* of the places where you could update your agent.
    This is also a good place to store an agent that you updated.

    :param self: The same object that is passed to all of your callbacks.
    """
    self.logger.debug(f'Encountered event(s) {", ".join(map(repr, events))} in final step')

    # Update model
    update_model(self, last_game_state, last_action, None, events)

    if len(self.transitions) > TRANSITION_HISTORY_SIZE:
        mini_sample = random.sample(self.transitions, TRANSITION_HISTORY_SIZE)
    else:
        mini_sample = self.transitions

    states, actions, next_states, rewards = zip(*mini_sample)
    self.trainer.train_step(states, actions, next_states, rewards)

    # Calculate total rewards
    round_transitions = np.array(self.transitions, dtype=object)[-last_game_state["step"]:]
    _, _, _, rewards = zip(*round_transitions)
    total_reward = np.sum(rewards)

    # Append statistics
    self.rewards.append(total_reward)
    self.steps.append(last_game_state['step'])

    # Calculate average statistics
    self.average_rewards.append(np.sum(self.rewards) / len(self.rewards))
    self.average_steps.append(np.sum(self.steps) / len(self.steps))

    # Plot training statistics after last round
    if "n_rounds" in last_game_state and last_game_state["round"] == last_game_state["n_rounds"]:
        Visualization.show_statistic("Reward", last_game_state["round"], self.rewards, self.average_rewards)
        Visualization.show_statistic("Steps", last_game_state["round"], self.steps, self.average_steps)

    # Reset action history
    self.action_history = deque(maxlen=ACTION_HISTORY_SIZE)
    #self.transitions = deque(maxlen=TRANSITION_HISTORY_SIZE)

    # Store the model
    with open("my-saved-model.pt", "wb") as file:
        pickle.dump(self.model, file)

def update_model(self, old_game_state: dict, action: str, new_game_state: Optional[dict], events: List[str]):
    # Convert state to features
    old_state_features = state_to_features(old_game_state)
    new_state_features = np.zeros(NUMBER_OF_FEATURES) if new_game_state is None else state_to_features(new_game_state)

    # Add auxiliary events
    if new_game_state is not None:
        add_auxiliary_events(self, events, old_state_features, new_state_features, action)

    # Calculate reward
    reward = reward_from_events(self, events)

    # Map action
    mapped_action = map_action(action)

    # Add transition to memory
    transition = Transition(old_state_features, mapped_action, new_state_features, reward)
    self.transitions.append(transition)

    # Update model
    self.trainer.train_step(old_state_features, mapped_action, new_state_features, reward)

def add_auxiliary_events(
    self,
    events: List[str],
    old_state_features: List[int],
    new_state_features: List[int],
    action: Optional[str]
):
    if e.BOMB_EXPLODED not in events:
        old_bomb_distance = old_state_features[4]
        new_bomb_distance = new_state_features[4]

        if isclose(old_bomb_distance - new_bomb_distance, 1 / 20, abs_tol=0.01):
            events.append(MOVED_TOWARDS_BOMB)
        elif isclose(new_bomb_distance - old_bomb_distance, 1 / 20, abs_tol=0.01):
            events.append(MOVED_AWAY_FROM_BOMB)

    if e.BOMB_EXPLODED in events and e.KILLED_SELF not in events:
        events.append(SURVIVED_BOMB)

    if e.BOMB_DROPPED in events and old_state_features[20] == 0:
        events.append(USELESS_BOMB)

    if e.BOMB_DROPPED in events and old_state_features[20] == 1:
        events.append(USEFUL_BOMB)

    if action is not None and loop_detected(self, action):
        events.append(LOOP_EVENT)

    # Add coin event if no bomb event
    if new_state_features[4] == 0 and new_state_features[5] == 0:
        old_coin_distance = old_state_features[9]
        new_coin_distance = new_state_features[9]

        if isclose(old_coin_distance - new_coin_distance, 1 / 20, abs_tol=0.01):
            events.append(MOVED_TOWARDS_COIN)
        elif isclose(new_coin_distance - old_coin_distance, 1 / 20, abs_tol=0.01):
            events.append(MOVED_AWAY_FROM_COIN)

def reward_from_events(self, events: List[str]) -> int:
    """
    *This is not a required function, but an idea to structure your code.*

    Here you can modify the rewards your agent get so as to en/discourage
    certain behavior.
    """
    game_rewards = {
        e.COIN_COLLECTED: 10,
        # e.KILLED_OPPONENT: 5,
        e.KILLED_SELF: -20,
        # e.GOT_KILLED: -10,
        # e.OPPONENT_ELIMINATED: 1,
        e.WAITED: -0.2,
        e.BOMB_DROPPED: -2,
        # e.BOMB_EXPLODED: 0,
        e.CRATE_DESTROYED: 3,
        e.COIN_FOUND: 0.5,
        e.INVALID_ACTION: -5,
        e.MOVED_UP: -0.1,
        e.MOVED_DOWN: -0.1,
        e.MOVED_LEFT: -0.1,
        e.MOVED_RIGHT: -0.1,
        # e.SURVIVED_ROUND: 10,
        LOOP_EVENT: -2,
        MOVED_TOWARDS_COIN: 1.5,
        MOVED_AWAY_FROM_COIN: -1.5,
        SURVIVED_BOMB: 1.8,
        MOVED_AWAY_FROM_BOMB: 2.5,
        MOVED_TOWARDS_BOMB: -2.5,
        USELESS_BOMB: -5,
        USEFUL_BOMB: 3
    }

    reward_sum = 0

    for event in events:
        if event in game_rewards:
            reward_sum += game_rewards[event]

    # print(reward_sum, events)

    self.logger.info(f"Awarded {reward_sum} for events {', '.join(events)}")
    return reward_sum

def map_action(self_action: str) -> List[int]:
    if self_action == "UP":
        return [1, 0, 0, 0, 0, 0]
    elif self_action == "RIGHT":
        return [0, 1, 0, 0, 0, 0]
    elif self_action == "DOWN":
        return [0, 0, 1, 0, 0, 0]
    elif self_action == "LEFT":
        return [0, 0, 0, 1, 0, 0]
    elif self_action == "WAIT":
        return [0, 0, 0, 0, 1, 0]
    else:  # BOMB
        return [0, 0, 0, 0, 0, 1]

def loop_detected(self, action: str) -> bool:
    # Append action to queue
    self.action_history.append(action)

    if len(self.action_history) <= 3:
        return False

    return self.action_history[-1] == self.action_history[-3] and self.action_history[-1] != \
        self.action_history[-2] and self.action_history[-2] == self.action_history[-4]


# MIT License

# Copyright (c) 2021 TRUMPF Werkzeugmaschinen GmbH + Co. KG

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
import datetime

def get_application_uri(hostname, applicationName):
    return f"urn:{hostname}:freeopcua:{applicationName}"

def gen_certificates(privateKeyFullPath, certificateFullPath, hostname, applicationName):

    # Generate the key
    key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=2048,
    )

    privateKeyBytes = key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.NoEncryption(),
        )

    # Write our key to disk for safe keeping
    if (privateKeyFullPath):
        with open(privateKeyFullPath, "wb") as f:
            f.write(privateKeyBytes)

    # Various details about who we are. For a self-signed certificate the
    # subject and issuer are always the same.
    # Did not set country, state and locality
    # https://cryptography.io/en/latest/x509/reference.html
    # https://cryptography.io/en/latest/x509/reference.html#general-name-classes
    # https://cryptography.io/en/latest/x509/reference.html#x-509-extensions
    theName = f"{applicationName}@{hostname}"
    serialNumber = x509.random_serial_number()
    subject = issuer = x509.Name([
        x509.NameAttribute(NameOID.LOCALITY_NAME, applicationName),
        x509.NameAttribute(NameOID.ORGANIZATION_NAME, f"{applicationName}_Organization"),
        x509.NameAttribute(NameOID.COMMON_NAME, theName),
       ])

    # Create early, so that ski.digest can be used in the certificate builder
    ski = x509.SubjectKeyIdentifier.from_public_key(key.public_key())

    cert = (
        x509.CertificateBuilder()
        .subject_name(subject)
        .issuer_name(issuer)
        .public_key(key.public_key())
        .serial_number(serialNumber)
        # Start validity period from yesterday
        .not_valid_before(datetime.datetime.today() - datetime.timedelta(days=1))
        # Our certificate will be valid for 10 years
        .not_valid_after(datetime.datetime.utcnow() + (datetime.timedelta(days=365)*10))
        # -------------------------------------------------------------------------------------------------
        # If an extension is marked as critical (critical True), it can not be ignored by an application.
        # The application must recognise and process the extension.
        # -------------------------------------------------------------------------------------------------
        .add_extension(
            # The subject key identifier extension provides a means of identifying
            # certificates that contain a particular public key.
            ski, critical=False)
        .add_extension(
            # The authority key identifier extension provides a means of
            # identifying the public key corresponding to the private key used to sign a certificate.
            x509.AuthorityKeyIdentifier(ski.digest, [x509.DirectoryName(issuer)], serialNumber), critical=False)
        # Subject alternative name is an X.509 extension that provides a list of general name instances
        # that provide a set of identities for which the certificate is valid.
        .add_extension(
            x509.SubjectAlternativeName([
                # URI must be first entry of SubjectAlternativeName. Must exactly match the client.application_uri
                x509.UniformResourceIdentifier(get_application_uri(hostname, applicationName)),
                x509.DNSName(hostname)
                ]), critical=False)
        # The key usage extension defines the purpose of the key contained in the certificate.
        .add_extension(
            # Basic constraints is an X.509 extension type that defines whether a given certificate is
            # allowed to sign additional certificates and what path length restrictions may exist.
            x509.BasicConstraints(ca=False, path_length=None), critical=True)
        .add_extension(
            x509.KeyUsage(
                digital_signature=True, content_commitment=True, key_encipherment=True,
                data_encipherment=True, key_agreement=False, key_cert_sign=True, crl_sign=False,
                encipher_only=False, decipher_only=False), critical=True)
        .add_extension(
            # This extension indicates one or more purposes for which the certified public key may be used,
            # in addition to or in place of the basic purposes indicated in the key usage extension.
            x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH, x509.OID_CLIENT_AUTH]), critical=True)
        # Sign our certificate with our private key
        .sign(key, algorithm=hashes.SHA256()))

    certificateBytes = cert.public_bytes(serialization.Encoding.DER)

    if (certificateFullPath):
        with open(certificateFullPath, "wb") as f:
            f.write(certificateBytes)

    return (privateKeyBytes, certificateBytes)


# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
from PIL import Image
from io import BytesIO
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline
from scrapy.utils.misc import md5sum

from tools.mysql import Mysql
import time

from tutorial.tools.DB import DB

class TutorialPipeline(object):
    def __init__(self):
        pass

    def process_item(self, item, spider):
        sql = 'SELECT * FROM illusts WHERE pixiv_id = "%s"'
        value = {
            'pixiv_id': item['pixiv_id']
        }
        db = DB()
        count = db.select(sql, value)
        if count > 0:
            raise DropItem(item['pixiv_id'])
        else:
            return item

# class DownloadImagePipeline(ImagesPipeline):
#     def item_completed(self, results, item, info):
#         image_paths = [x['path'] for ok, x in results if ok]
#         if not image_paths:
#             raise DropItem("Item contains no images")
#         item['image_paths'] = image_paths['path']
#         self.saveMysql(item)
#         return item

class Save(object):
    def __init__(self):
        pass

    def process_item(self, item, spider):
        if item['mode'] == 'daily':
            illust_mode = 1
        else:
            illust_mode = 0
        date = time.strftime('%Y-%m-%d')
        value = {
            'date': date,
            'mode': illust_mode,
            'path': item['images'][0]['path'],
            'pixiv_id': item['pixiv_id'],
            'title': item['title'],
            'total_score': item['total_score'],
            'author': item['author'],
            'image_urls': item['image_urls'],
            'rank': item['rank'],
            'author_id': item['author_id']
        }
        sql = "INSERT INTO illusts(pixiv_id, title, total_score, author, image_urls, date, rank, author_id, path, mode)  VALUES (%(pixiv_id)s, %(title)s, %(total_score)s, %(author)s, %(image_urls)s, %(DATE)s, %(rank)s, %(author_id)s, %(path)s, %(MODE)s)"
        db = Mysql()
        db.action(sql, value)

class myImagePipelines(ImagesPipeline):
    def convert_image(self, image, size=None):
        buf = BytesIO()
        image.save(buf, image.format)
        return image, buf


import sqlite3
import logging

logger = logging.getLogger()

db_file = 'db.sqlite'

class ManageTodoDB:

    def connect_db(self):
        try:
            db = sqlite3.connect(db_file)
            logger.info("Connected to DB: %s", db_file)
            return db
        except sqlite3.Error as e:
            logger.error('Error connecting to DB: %s', e)

    # Create tables
    def create_db_struct(self):
        sql = '''
            CREATE TABLE IF NOT EXISTS tasks (
                task_id INTEGER PRIMARY KEY AUTOINCREMENT,
                task_name VARCHAR(250) NOT NULL,
                task_description VARCHAR(1000) NOT NULL,
                task_assignee INTEGER NOT NULL,
                task_start_date DATE, task_end_date DATE,
                FOREIGN KEY (task_assignee) REFERENCES users(user_id)
            );

            CREATE TABLE IF NOT EXISTS users (
                user_id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_name VARCHAR(50) NOT NULL UNIQUE
            );
              '''
        c = self.connect_db().cursor()
        try:
            c.executescript(sql)
            logger.info("DB structure was created!")
        except sqlite3.Error as e:
            logger.error("Error creating DB: %s", e)
            return e

    # Add new user
    def add_user(self, username):
        sql = '''
            INSERT INTO users (user_name) VALUES("{:s}")
        '''.format(username)
        c = self.connect_db().cursor()
        try:
            c.executescript(sql)
            logger.info("Successfully added user %s", username)
            return True
        except sqlite3.IntegrityError as e:
            logger.error("Error adding user %s. Message: %s", username, e)
            return False

    # Add new task
    def add_task(self, name, description, assignee, start_date, end_date):

        user_id = self.__get_user_id(assignee)
        if not user_id:
            return 404

        sql = '''
            INSERT INTO tasks (task_name, task_description, task_assignee, task_start_date, task_end_date)
            VALUES("{:s}", "{:s}", {:d}, "{:s}", "{:s}")
        '''.format(name, description, user_id, start_date, end_date)

        c = self.connect_db().cursor()
        try:
            c.executescript(sql)
            logger.info("Successfully added task: %s", name)
            return 201

        except sqlite3.IntegrityError as e:
            logger.error("DB integrity error: %s", e)
            return e

    # Helper  method to user id by name
    def __get_user_id(self, user_name):

        sql = '''
            SELECT user_id FROM users WHERE user_name="{:s}"
        '''.format(user_name)

        c = self.connect_db().cursor()
        user_id = c.execute(sql).fetchone()
        if user_id is None:
            return False

        return user_id[0]

    # Remove all tables
    def recreate_db(self):
        sql = '''
            DROP TABLE IF EXISTS tasks;
            DROP TABLE IF EXISTS users;
        '''
        c = self.connect_db().cursor()

        c.executescript(sql)

        logger.info("Deleted all tables")
        self.create_db_struct()

    # Get all tasks in DB
    def get_all_tasks(self):
        sql = '''
            SELECT task_name, task_description, task_start_date, task_end_date, user_name FROM tasks, users
            WHERE task_assignee = user_id;
        '''

        conn = self.connect_db()

        c = conn.cursor()
        c.execute(sql)

        tasks = c.fetchall()
        return tasks

    def get_all_users(self):
        sql = '''
            SELECT * FROM users;
        '''

        conn = self.connect_db()

        c = conn.cursor()
        c.execute(sql)

        users = c.fetchall()

        return users


from django import forms
from django.forms import ModelForm
from .models import Alumno, Participante, ParticipantesEvent, PagosAlumno

#Se requiere modificar este form
class AlumnoForm(ModelForm):
	class Meta:
		model = Alumno
		fields = [
			'RUT',
			'Nombre',
			'Genero',
			'Nacimiento',
			'Profesion',
			'DirPersonal',
			'DirLaboral',
			'Email',
			'Ntelefono',
			]

		labels = {
			'RUT' :'RUT',
			'Nombre' : 'Nombre',
			'Genero' : 'Genero',
			'Nacimiento' : 'Fecha Nacimiento',
			'Profesion' : 'Profesion',
			'DirPersonal' : 'Direccion Personal',
			'DirLaboral' : 'Direccion Laboral',
			'Email' : 'E-mail',
			'Ntelefono' : 'Telefono',
		}

		widgets = {
			'RUT' : forms.TextInput(attrs={'class' : 'forms-control','placeholder': 'Con Punto & Guion'}),
			'Nombre' : forms.TextInput(attrs={'class' : 'forms-control','placeholder': 'Primer Nombre & Apellidos'}),
			'Genero' : forms.Select(attrs={'class' : 'forms-control'}),
			'Nacimiento' : forms.SelectDateWidget(years=range(1950,2101)),
			'Profesion' : forms.TextInput(attrs={'class' : 'forms-control'}),
			'DirPersonal' : forms.TextInput(attrs={'class' : 'forms-control'}),
			'DirLaboral' : forms.TextInput(attrs={'class' : 'forms-control'}),
			'Email' : forms.EmailInput(),
			'Ntelefono' : forms.TextInput(attrs={'class' : 'forms-control'}),
		}

class PagosForm(ModelForm):
	class Meta:
		model = PagosAlumno
		fields= [
    		'id_Alumno',
    		'RUT',
    		'Nombre',
    		'Local',
    		'ClasePagada',
    		'Num_Clases_Pagadas',
    		'Mes',
    		'Anno',
    		'IngresoAlumno',
    		'MetodoPago',
    		'Grupal',
		]

		labels= {
			'id_Alumno':'ID',
    		'RUT':'RUT',
    		'Nombre':'Nombre',
    		'Local':'Local',
    		'ClasePagada':'Clase Pagada',
    		'Num_Clases_Pagadas':'N°Clases Pagadas',
    		'Mes':'Mes',
    		'Anno':'Año',
    		'IngresoAlumno':'Ingreso',
    		'MetodoPago':'Metodo Pago',
    		'Grupal':'Clase Grupal',
		}

		widgets={
			'Local':forms.Select(attrs={'class' : 'forms-control'}),
    		'Mes':forms.Select(attrs={'class' : 'forms-control'}),
    		'Grupal':forms.RadioSelect(attrs={'class' : 'forms-control'}),
		}

class ParticipanteForm(ModelForm):
	class Meta:
		model = Participante
		fields = [
			    'Nombre',
    			'Clase_Perteneciente',
				'Code_Clase',
   				'Local',
    			'Dia',
    			'Horario_Inicio',
    			'Horario_Termino',
			]

		labels = {
			'Nombre':'Nombre',
    		'Clase_Perteneciente':'Clase',
			'Code_Clase':'ID Clase',
   			'Local':'Local',
    		'Dia':'Dia',
    		'Horario_Inicio':'Inicio',
    		'Horario_Termino':'Termino',
		}

		widgets = {
			'Nombre' : forms.TextInput(attrs={'class' : 'forms-control','placeholder': 'Primer Nombre & Apellidos'}),
			'Local':forms.Select(attrs={'class' : 'forms-control'}),
    		'Dia':forms.Select(attrs={'class' : 'forms-control'}),
		}

class ParticipanteEventForm(ModelForm):
	class Meta:
		model = ParticipantesEvent
		fields= [
			'ID_Event',
			'EventInscrito',
    		'NombreParticipante',
    		'Escena',
		]

		labels= {
			'EventInscrito' : 'Evento Inscrito',
    		'NombreParticipante' : 'Nombre Participante',
    		'Escena' : 'Escena participante',
		}

		widgets={
			'NombreParticipante' : forms.TextInput(attrs={'class' : 'forms-control','placeholder': 'Primer Nombre & Apellidos'}),
		}

Proyecto -As You Wish (All Version)/ProyectosUNAB (Final Version)/AsYouWish_Serv/Base_Alumno/forms.py