from copy import deepcopy
from datetime import datetime

from babel.dates import format_date
from discord import Colour, Embed
from figure_hook.extension_class import ReleaseFeed

from .abcs import PublishFactory

embed_templates = {
    "en": {
        "maker": "Manufacturer",
        "series": "Series",
        "price": "Price",
        "release_date": "Release Date",
        "sculptors": "Sculptors",
        "paintworks": "Paintworks",
        "date_format": "MMM, yyyy",
        "size": "Size",
        "scale": "Scale",
        "new_release": "New Release",
        "re_release": "Rerelease"
    },
    "ja": {
        "maker": "メーカー",
        "series": "作品名",
        "price": "価格",
        "release_date": "発売時期",
        "sculptors": "原型制作",
        "paintworks": "彩色",
        "date_format": "yyyy年 MMM",
        "size": "サイズ",
        "scale": "スケール",
        "new_release": "新リリース",
        "re_release": "新リリース（再販）"
    },
    "zh-TW": {
        "maker": "製造商",
        "series": "作品名稱",
        "price": "價格",
        "release_date": "發售日期",
        "sculptors": "原型製作",
        "paintworks": "色彩",
        "date_format": "yyyy年 MMM",
        "size": "尺寸",
        "scale": "比例",
        "new_release": "新商品",
        "re_release": "新商品(再販)"
    },
}

locale_mapping = {
    "en": "en",
    "ja": "ja",
    "zh-TW": "zh"
}

class NewReleaseEmbed(Embed):
    _is_nsfw: bool

    def __init__(self, **kwargs):
        kwargs.setdefault("colour", Colour.red())
        super().__init__(**kwargs)
        self._is_nsfw = kwargs.get("is_nsfw", False)

    @property
    def is_nsfw(self):
        return self._is_nsfw

    def copy(self):
        return deepcopy(super().copy())

    def localized_with(self, lang: str):
        """lang: en, ja, zh-TW"""
        embed: Embed = self.copy()
        embed_locale = embed_templates[lang]

        if embed.author:
            key = str(embed.author.name)
            author_name = embed_locale.get(key)
            embed.set_author(
                name=author_name,
                icon_url=embed.author.icon_url
            )

        for f in embed._fields:
            key = f["name"]
            f["name"] = embed_locale.get(key, key)

            if key == "release_date":
                locale = locale_mapping.get(lang, "en")
                date_format = embed_locale["date_format"]
                if f["value"]:
                    release_date = datetime.strptime(
                        f["value"], "%Y-%m-%d").date()
                    f["value"] = str(format_date(
                        release_date, date_format, locale=locale)
                    )

        return embed

    def add_field(self, *, name, value, inline):
        if not value:
            return self
        return super().add_field(name=name, value=value, inline=inline)

class DiscordEmbedFactory(PublishFactory):
    @staticmethod
    def create_new_release(release_feed: ReleaseFeed):
        embed = NewReleaseEmbed(
            title=release_feed.name,
            type="rich",
            url=release_feed.url,
            is_nsfw=release_feed.is_adult
        )

        author = "re_release" if release_feed.rerelease else "new_release"

        embed.set_image(
            url=release_feed.media_image
        ).set_author(
            name=author,
            # Icons made by Pixel perfect from www.flaticon.com
            icon_url="https://image.flaticon.com/icons/png/32/879/879833.png"  # type: ignore
        ).add_field(
            name="maker", value=release_feed.maker, inline=False
        ).add_field(
            name="series", value=release_feed.series, inline=False
        )

        if release_feed.thumbnail:
            embed.set_thumbnail(url=release_feed.thumbnail)

        if release_feed.size:
            embed.add_field(
                name="size", value=f"{release_feed.size} mm", inline=True
            )

        # if scale:
        #     embed.add_field(
        #         name="scale", value=f"1/{scale}", inline=True
        #     )

        embed.add_field(
            name="release_date", value=release_feed.release_date, inline=True
        )

        if release_feed.price:
            embed.add_field(
                name="price", value=f"JPY {release_feed.price:,}", inline=True
            )

        return embed

    @staticmethod
    def create_new_hook_notification(msg: str):
        title = f":hook: {msg} :hook:"
        embed = Embed(title=title, colour=Colour(0x00B5FF))

        return embed


import logging
import os
from time import sleep

import requests

from git_syncer.models import Runnable

log = logging.getLogger(__name__)

MAX_RETRIES = 5
RETRY_DELAY = 5

# Note: This is just an example! Never keep secrets in the code, even if it's a private repository.
# If you want to use this, you can use local secrets file.
telegram_bot_token = "ABC123"
chat_id = "123456789"

def _notify_boot_on_telegram():
    log.info("Notifying successful boot")
    url = f"https://api.telegram.org/bot{telegram_bot_token}/sendMessage"
    device_name = os.uname().nodename
    data = {
        "chat_id": chat_id,
        "parse_mode": "Markdown",
        "text": f"Successfully booted *{device_name}*!",
    }

    def send_message():
        response = requests.post(url, data=data, timeout=5)
        response.raise_for_status()
        return response

    for _ in range(MAX_RETRIES):
        try:
            return send_message()
        except Exception as e:
            log.warning(f"Failed to notify boot: {e}")
            sleep(RETRY_DELAY)

class NotifyBoot(Runnable):
    @property
    def verbose_name(self) -> str:
        return "Notify boot"

    @property
    def run_on_boot(self) -> bool:
        return True

    def run(self) -> str:
        response = _notify_boot_on_telegram()
        return response.text


from channels.consumer import AsyncConsumer

#an Mqtt client for the consumers
class MqttConsumer(AsyncConsumer):
    # asynchrows when the websocket is opened
    async def connect(self):

        #join mqtt group
        await self.channel_layer.group_add(
            'mqtt',
            self.channel_name
        )

        # Receive message from mqtt group and send to websocket which is subscribing to the group
        await self.channel_layer.send(
            'mqtt',
            {
                'type': 'device_connected',
                'topic': f"chat/{self.room_name}",
                'group': 'mqtt',

            }
        )

        await self.accept()

    # Receive message from mqtt group and send to websocket
    async def chat_subscription(self, event):
        message = event['message']
        payload = message['payload']
        topic = message['topic']
        group = message['group']
        print(f"{topic} {payload} {group}")

        # Send message to WebSocket
        await self.send(text_data=json.dumps({
            'type': 'chat_message',
            'message': payload,
            'payload': event['payload'],
            'topic': event['topic']
        }))

    # Receive message from websocket
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        topic = text_data_json['topic']
        payload = text_data_json['payload']
        group = text_data_json['group']
        print(f"{topic} {message} {group}")

        #send message to mqtt group
        await self.channel_layer.send(
            'mqtt',
            {
                'type': 'mqtt_publish',
                'publish': {
                    'topic': f"chat/{self.room_name}_out",
                    'payload': message,
                    'qos': 0,
                    'retain': False,
                    'group': 'mqtt',
                }
            }
        )

    # asynchrows when the websocket is closed
    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            'mqttgroup',
            self.channel_name
        )


import json
import os

import boto3
from aws_lambda_powertools import Logger
from botocore.exceptions import ClientError

logger = Logger()

def send_sqs_message(event):
    try:
        msg = json.dumps(event)
        sqs_client = boto3.client('sqs')
        sqs_queue_url = os.getenv("SQS_QUEUE_URL")

        logger.info(f"Sending message to queue")
        response = sqs_client.send_message(QueueUrl=sqs_queue_url,
                                           MessageBody=msg)
    except ClientError as e:
        logger.error(e)
        return None
    logger.info(f"Message has been sent with success")
    return response


from nltk.corpus import stopwords
import string, re
from collections import Counter
import wordcloud
import seaborn as sns
import regex as re
import numpy as np  # linear algebra

import matplotlib.pyplot as plt
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split

import os

"""
refer: https://www.kaggle.com/serkanpeldek/text-classification-with-embedding-conv1d
采取的预处理：
    小写
    过滤标点符号
    过滤非字母字符
    限制文本长度
    过滤停用词
    过滤短词(<=2)
    过滤低频词(<=2)
    ...
"""

review_dataset_path = "../raw data/review_polarity/txt_sentoken"
# print(os.listdir(review_dataset_path))

# Positive and negative reviews folder paths
pos_review_folder_path = review_dataset_path + "/" + "pos"
neg_review_folder_path = review_dataset_path + "/" + "neg"

def load_text_from_textfile(path):
    file = open(path, "r")
    review = file.read()
    file.close()
    return review

def load_review_from_textfile(path):
    return load_text_from_textfile(path)

def get_data_target(folder_path, file_names, review_type):
    data = list()
    target = list()
    for file_name in file_names:
        full_path = folder_path + "/" + file_name
        review = load_review_from_textfile(path=full_path)
        data.append(review)
        target.append(review_type)
    return data, target

# text processing
class MakeString:
    def process(self, text):
        return str(text)

class ReplaceBy:
    def __init__(self, replace_by):
        # replace_by is a tuple contains pairs of replace and by characters.
        self.replace_by = replace_by

    def process(self, text):
        for replace, by in self.replace_by:
            text = text.replace(replace, by)
        return text

class LowerText:
    def process(self, text):
        return text.lower()

class ReduceTextLength:
    def __init__(self, limited_text_length):
        self.limited_text_length = limited_text_length
    def process(self, text):
        return text[:self.limited_text_length]

# word vector processing
class VectorizeText:
    def __init__(self):
        pass
    def process(self, text):
        return text.split()

class FilterPunctuation:

    def __init__(self):
        print("Punctuation Filter created...")
    def process(self, words_vector):
        reg_exp_filter_rule=re.compile("[%s]"%re.escape(string.punctuation))
        words_vector=[reg_exp_filter_rule.sub("", word) for word in words_vector]
        return words_vector

class FilterNonalpha:
    def __init__(self):
        print("Nonalpha Filter created...")
    def process(self, words_vector):
        words_vector=[word for word in words_vector if word.isalpha()]
        return words_vector

class FilterStopWord:
    def __init__(self, language):
        self.language=language
        print("Stopwords Filter created...")
    def process(self, words_vector):
        stop_words=set(stopwords.words(self.language))
        words_vector=[word for word in words_vector if not word in stop_words]
        return words_vector

class FilterShortWord:
    def __init__(self, min_length):
        self.min_length=min_length
        print("Short Words Filter created...")
    def process(self, words_vector):
        words_vector=[word for word in words_vector if len(word)>=self.min_length]
        return words_vector

# text processing
class TextProcessor:
    def __init__(self, processor_list):
        self.processor_list = processor_list
    def process(self, text):
        for processor in self.processor_list:
            text = processor.process(text)
        return text

class VocabularyHelper:
    def __init__(self, textProcessor):
        self.textProcessor=textProcessor
        self.vocabulary=Counter()
    def update(self, text):
        words_vector=self.textProcessor.process(text=text)
        self.vocabulary.update(words_vector)
    def get_vocabulary(self):
        return self.vocabulary

if __name__ == "__main__":
    # Positive and negative file names
    pos_review_file_names = os.listdir(pos_review_folder_path)
    neg_review_file_names = os.listdir(neg_review_folder_path)

    print(pos_review_file_names[0])
    pos_data, pos_target = get_data_target(folder_path=pos_review_folder_path,
                                           file_names=pos_review_file_names,
                                           review_type="positive")
    neg_data, neg_target = get_data_target(folder_path=neg_review_folder_path,
                                           file_names=neg_review_file_names,
                                           review_type="negative")

    print("正样本数量：", len(pos_data))
    print("负样本数量：", len(neg_data))
    data = pos_data + neg_data
    target_ = pos_target + neg_target
    print("总共数据：", len(data))
    # 标签转为数字，正1负0
    le = LabelEncoder()
    le.fit(target_)
    target = le.transform(target_)
    print(data[0])
    X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2, stratify=target, random_state=24)

    print("训练数据数：", len(X_train))
    print("训练标签数：", len(y_train))
    print("测试样本数：", len(X_test))
    print("测试标签数", len(y_test))

    fig, axarr = plt.subplots(nrows=1, ncols=2, figsize=(8, 4), sharey=True)
    axarr[0].set_title("Number of samples in train")
    sns.countplot(x=y_train, ax=axarr[0])
    axarr[1].set_title("Number of samples in test")
    sns.countplot(x=y_test, ax=axarr[1])
    plt.show()

    text_len = np.vectorize(len) # 向量化函数
    text_lengths = text_len(X_train) # [6975 4351 3120 ... 1869 4961 3808]

    mean_review_length = int(text_lengths.mean())
    print("平均评论长度:", mean_review_length)
    print("最小评论长度:", text_lengths.min())
    print("最大评论长度:", text_lengths.max())

    # 绘制文本长度的分布
    sns.distplot(a=text_lengths)

    # str()
    makeString = MakeString()

    # 过滤标点符号
    replace_by = [(".", " "), ("?", " "), (",", " "), ("!", " "), (":", " "), (";", " ")]
    replaceBy = ReplaceBy(replace_by=replace_by)

    # 小写
    lowerText = LowerText()

    # 限制文本长度
    FACTOR = 8
    reduceTextLength = ReduceTextLength(limited_text_length=mean_review_length * FACTOR)

    # 以空格分割
    vectorizeText = VectorizeText()

    # 过滤标点符号
    filterPunctuation = FilterPunctuation()
    # 过滤非字母字符
    filterNonalpha = FilterNonalpha()

    # 过滤停用词
    filterStopWord = FilterStopWord(language="english")

    # 过滤短词
    min_length = 2
    filterShortWord = FilterShortWord(min_length=min_length)

    # 预处理列表
    processor_list_1 = [makeString,
                        replaceBy,
                        lowerText,
                        reduceTextLength,
                        vectorizeText,
                        filterPunctuation,
                        filterNonalpha,
                        filterStopWord,
                        filterShortWord]

    # 文本处理器
    textProcessor1 = TextProcessor(processor_list=processor_list_1)

    # 随机看一个训练样本
    random_number = np.random.randint(0, len(X_train))
    print("Original Review:\n", X_train[random_number][:500])
    print("=" * 100)
    print("Processed Review:\n", textProcessor1.process(text=X_train[random_number][:500]))

    # 建立词汇表
    vocabularyHelper = VocabularyHelper(textProcessor=textProcessor1)
    for text in X_train:
        vocabularyHelper.update(text)
    vocabulary = vocabularyHelper.get_vocabulary()
    print("词汇表长度:", len(vocabulary))
    #  Counter({'film': 7098, 'movie': 4432, 'one': 4429, 'like': 2842,...})

    # 看一下频率最高的前10个词和最低的10个词
    n = 10
    print("{} most frequented words in vocabulary:{}".format(n, vocabulary.most_common(n)))

    print("{} least frequented words in vocabulary:{}".format(n, vocabulary.most_common()[:-n - 1:-1]))

    # 词云
    vocabulary_list = " ".join([key for key, _ in vocabulary.most_common()])
    plt.figure(figsize=(15, 35))
    wordcloud_image = wordcloud.WordCloud(width=1000, height=1000,
                                          background_color='white',
                                          # stopwords = stopwords,
                                          min_font_size=10).generate(vocabulary_list)

    plt.xticks([])
    plt.yticks([])
    plt.imshow(wordcloud_image)

    #过滤低频词
    min_occurence = 2
    vocabulary = Counter({key: value for key, value in vocabulary.items() if value > min_occurence})

    print("{} least frequented words in vocabulary:{}".format(n, vocabulary.most_common()[:-n - 1:-1]))

    print("Length of vocabulary after removing words occurenced less than {} times:{}".format(min_occurence,
                                                                                len(vocabulary)))

    # 过滤不在词典的
    class FilterNotInVocabulary:
        def __init__(self, vocabulary):
            self.vocabulary = vocabulary

        def process(self, words_vector):
            words_vector = [word for word in words_vector if word in self.vocabulary]
            return words_vector

    # 连起来
    class JoinWithSpace:
        def __init__(self):
            pass

        def process(self, words_vector):
            return " ".join(words_vector)

    filterNotInVocabulary = FilterNotInVocabulary(vocabulary=vocabulary)
    joinWithSpace = JoinWithSpace()
    processor_list_2 = [makeString,
                        replaceBy,
                        lowerText,
                        reduceTextLength,
                        vectorizeText,
                        filterPunctuation,
                        filterNonalpha,
                        filterStopWord,
                        filterShortWord,
                        filterNotInVocabulary,
                        joinWithSpace
                        ]
    textProcessor2 = TextProcessor(processor_list=processor_list_2)

    review = X_train[np.random.randint(0, len(X_train))]
    print("Original Text:\n", review[:500])
    processed_review = textProcessor2.process(review[:500])
    print("=" * 100)
    print("Processed Text:\n", processed_review)

    for i,j in enumerate(data):
        data[i] = textProcessor1.process(data[i])
        data[i] = textProcessor2.process(data[i])

    X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2, stratify=target, random_state=24)

    print("Dataset splited into train and test parts...")
    print("train data length  :", len(X_train))
    print("train target length:", len(y_train))
    print()
    print("test data length  :", len(X_test))
    print("test target length:", len(y_test))
    print(X_test[0])

    # """去除符号"""
    # re_punct = r"[\[\]\{\}\:\;\'\"\,\<\.\>\/\?\\\|\`\!\@\#\$\%\^\&\*\(\)\-\_\=\+]"
    # for i,j in enumerate(X_train):
    #     X_train[i] = re.sub(re_punct, "", j)
    #     X_train[i] = X_train[i].replace('\n', '')
    # for i,j in enumerate(X_test):
    #     X_test[i] = re.sub(re_punct, "", j)
    #     X_test[i] = X_test[i].replace('\n', '')

    # import random
    #
    # X = list(zip(X_train,y_train))
    # Y = list(zip(X_test,y_test))
    #
    # print(Y)
    # random.shuffle(X)
    # print(Y)
    # random.shuffle(Y)
    #
    # X_train = [i for i,j in X]
    # y_train = [j for i,j in X]
    # X_test = [i for i,j in Y]
    # y_test = [j for i,j in Y]

    # 字典中的key值即为csv中列名
    dataframe = pd.DataFrame({'a_name': y_train[:1400], 'b_name': X_train[:1400]})

    # 将DataFrame存储为csv,index表示是否显示行名，default=True
    dataframe.to_csv("../base/data/movie/train.tsv", index=False, sep='\t', header=False)

    dataframe = pd.DataFrame({'a_name': y_train[1400:], 'b_name': X_train[1400:]})

    # 将DataFrame存储为csv,index表示是否显示行名，default=True
    dataframe.to_csv("../base/data/movie/dev.tsv", index=False, sep='\t', header=False)

    dataframe = pd.DataFrame({'a_name': y_test, 'b_name': X_test})

    # 将DataFrame存储为csv,index表示是否显示行名，default=True
    dataframe.to_csv("../base/data/movie/test.tsv", index=False, sep='\t', header=False)


"""********************************************************************"""
"""                                                                    """
"""   [EnterRaffle] EnterRaffleTask.py                                 """
"""                                                                    """
"""   Author: seith <seith@synezia.com>                                """
"""                                                                    """
"""   Created: 10/09/2021 00:21:21                                     """
"""   Updated: 11/10/2021 00:46:37                                     """
"""                                                                    """
"""   Synezia Soft. (c) 2021                                           """
"""                                                                    """
"""********************************************************************"""

import random
import time

from requests import ConnectionError
from json.decoder import JSONDecodeError

from services.captcha import CaptchaHandler
from services.mail import MailController
from utilities import *

if "darwin" not in platform.system().lower():
    from helheim.exceptions import (
        HelheimException
    )

class EnterRaffleTask:

    def __init__(self, index, taskNumber, profile, raffle) -> None:

        """ Props """
        self.index: int = index + 1
        self.taskNumber: int = taskNumber
        self.profile: dict = profile
        self.raffle: dict = raffle

        """ Store """
        self.logIdentifier: str = "[{}/{} - {}]".format(self.index, self.taskNumber, self.profile["email"])
        self.state: str = "PENDING"
        self.success: bool = False
        self.retry: int = 0
        self.maxRetry: int = 10
        self.captchaToken: str = None

        """ Utilities """
        self.profile["Product"] = raffle["product"]

        """ Session """
        self.session, self.proxy = CreateCFSession()
        self.raffleId = self.raffle["metadata"]["entryUrl"].replace('https://raffle.bstn.com/', '')

        try:

            self.executeTask()
            self.proxy = ProxyManager().rotateProxy(self.session, self.proxy)

            if (self.profile['status'] == "PENDING"):
                self.profile['status'] = self.state

        except Exception as error:
            Logger.error(f"{self.logIdentifier} Exception has occured when running task!")
            Logger.error(str(error))

            self.profile['status'] = "FAILED"
            self.success = False

    def executeTask(self):

        Logger.log(f"{self.logIdentifier} Solving CloudFlare...")

        solveCloudFlareStatus: int = self.solveCloudflare()

        if (solveCloudFlareStatus == SUCCESS):
            self.retry = 0

            Logger.info(f"{self.logIdentifier} Successfully solved CloudFlare!")
            Logger.log(f"{self.logIdentifier} Submitting entry...")

            enterStatus = self.enterRaffle()

            if (enterStatus == SUCCESS):
                Logger.success(f"{self.logIdentifier} Successfully entered raffle!")

                if (self.raffle['AutoConfirmer']['status'] is True):
                    Logger.info(f"{self.logIdentifier} Launching AutoConfirmer! (Waiting ({self.raffle['AutoConfirmer']['delay']} s)")
                    time.sleep(self.raffle['AutoConfirmer']['delay'])

                    self.retry = 0
                    self.maxRetry = 30

                    autoconfirmFetch = self.AutoConfirm_FetchLink()

                    if (autoconfirmFetch == SUCCESS):
                        self.retry = 0
                        self.maxRetry = 7

                        Logger.info(f"{self.logIdentifier} Successfully fetched link to confirm your entry!")
                        confirmState = self.AutoConfirm_Confirm()

                        if (confirmState == SUCCESS):
                            Logger.success(f"{self.logIdentifier} Successfully AutoConfirmed Entry!")

                            self.profile['status'] = "CONFIRMED"
                            self.success = True

                        elif (confirmState == FAILED):
                            Logger.error(f"{self.logIdentifier} Failed to confirm entry maybe you have already confirmed entry.")

                            self.profile['status'] = "FAILED_AUTOCONFIRM"
                            self.success = True

                        else:
                            Logger.error(f"{self.logIdentifier} MaxRetryExceeded while confirming entry!")

                            self.profile['status'] = "FAILED_AUTOCONFIRM"
                            self.success = True

                    elif (autoconfirmFetch == FAILED):
                        self.profile['status'] = "FAILED_AUTOCONFIRM"
                        self.success = True
                    else:
                        self.profile['status'] = "FAILED_AUTOCONFIRM"
                        self.success = True
                else:
                    self.state = "SUCCESS"
                    self.success = True
            else:
                self.state = "FAILED"
                self.success = False

        else:
            self.state = "FAILED"
            self.success = False

    def solveCloudflare(self):
        """
            - Step [1]
                - Solve CloudFlare
                - Check if 200

            - Params: None

            - Returns:
                - 1: Successfully Solved CloudFlare
                - 0: Failed to SolveCloudflare (MaxRetryExceeded)
        """

        try:
            response = self.session.get(
                self.raffle["metadata"]["entryUrl"]
            )

            Logger.debug(f"{self.logIdentifier} Received {response.status_code} from BSTN [SolveCloudflare]")

            if response.status_code == 200:
                return SUCCESS
            else:
                self.retry += 1

                Logger.warning(
                    f"{self.logIdentifier} Failed to solve CloudFlare.. Rotating Session! ({self.retry}/{self.maxRetry})")

                self.proxy = ProxyManager().rotateProxy(self.session, self.proxy)

                if self.retry <= self.maxRetry:
                    return self.solveCloudflare()
                else:
                    return (FAILED)

        except ConnectionError as error:
            Logger.debug(f"{self.logIdentifier} ConnectionError while solving CloudFlare on BSTN: {str(error)}")

            self.retry += 1

            Logger.warning(
                f"{self.logIdentifier} Failed to solve CloudFlare.. Rotating Session! ({self.retry}/{self.maxRetry})")

            self.proxy = ProxyManager().rotateProxy(self.session, self.proxy)

            if (self.retry <= self.maxRetry):
                return self.solveCloudflare()
            else:
                return (FAILED)

        except Exception as error:
            Logger.debug(f"{self.logIdentifier} Error while solving CloudFlare on BSTN: {str(error)}")

            self.retry += 1

            Logger.warning(
                f"{self.logIdentifier} Failed to solve CloudFlare.. Rotating Session! ({self.retry}/{self.maxRetry})")

            self.proxy = ProxyManager().rotateProxy(self.session, self.proxy)

            if (self.retry <= self.maxRetry):
                return self.solveCloudflare()
            else:
                return (FAILED)

    def enterRaffle(self):

        if (self.captchaToken == None):
            Logger.log(f"{self.logIdentifier} Solving Captcha...")

            captcha = CaptchaHandler().handleRecaptcha(
                '6LemOsYUAAAAABGFj8B7eEvmFT1D1j8IbXJIdvNn',
                self.raffle["metadata"]["entryUrl"],
                pollingInterval=3
            )

            if (captcha['success']):
                self.captchaToken = captcha['code']
                Logger.info(f"{self.logIdentifier} Successfully solved Captcha!")
            else:
                self.retry += 1

                Logger.warning(f"{self.logIdentifier} Invalid Captcha! Solving another Captcha... ({self.retry}/3)")
                Logger.error(f"{self.logIdentifier} {captcha['error']}")

                if (self.retry <= 3):
                    return self.enterRaffle()
                else:
                    return (EXCEPTION)

        try:
            payload = {
                'additional': {
                    'instagram': self.profile["instagram"]
                },
                'title': 'female' if self.profile["gender"].lower() == "female" else 'male',
                'bDay': random.randint(1, 30),
                'bMonth': random.randint(1, 12),
                'email': self.profile["email"],
                'firstName': self.profile["first_name"],
                'lastName': self.profile["last_name"],
                'street': self.profile["street"],
                'streetno': self.profile["house_number"],
                'address2': self.profile["additional"],
                'zip': self.profile["zip"],
                'city': self.profile["city"],
                'country': self.profile["country"],
                'acceptedPrivacy': True,
                'newsletter': False,
                'recaptchaToken': self.captchaToken,
                'raffle': {'raffleId': self.raffleId, 'parentIndex': 0, 'option': self.profile["size"]},
                'issuerId': 'raffle.bstn.com'
            }

        except Exception as error:
            Logger.debug(f"{self.logIdentifier} Error happen when making Payload! ")
            Logger.debug(f"{self.logIdentifier} Error: {str(error)} ")
            Logger.error(f"{self.logIdentifier} Error while entering! {str(error)}")

            return (FAILED)

        try:
            response = self.session.post('https://raffle.bstn.com/api/register', json=payload)

            Logger.debug(f"{self.logIdentifier} Received {response.status_code} from BSTN [EnterRaffle]")
            Logger.debug(f"{self.logIdentifier} Received {response.text} from BSTN [EnterRaffle]")

            if (response.json()['message'] == "success"):
                return (SUCCESS)

            elif (response.json()['name'] == "GeneralError"):
                Logger.error(f"{self.logIdentifier} Error: {response.json()['message']}")

                self.retry += 1
                if (self.retry <= 3):
                    return self.enterRaffle()
                else:
                    return (EXCEPTION)
            else:
                return (FAILED)

        except JSONDecodeError:
            self.retry += 1

            Logger.warning(f"{self.logIdentifier} BSTN sent invalid response while submitting entry ({self.retry}/3)")

            if (self.retry <= 3):
                return self.enterRaffle()
            else:
                return (EXCEPTION)

        except HelheimException as error:
            Logger.debug(f"{self.logIdentifier} CloudFlare exception while submitting entry {str(error)}")

            self.retry += 1
            Logger.warning(f"{self.logIdentifier} Something went wrong with CloudFlare while submitting entry ({self.retry}/{self.maxRetry})")
            self.proxy = ProxyManager().rotateProxy(self.session, self.proxy)

            if (self.retry <= self.maxRetry):
                return self.enterRaffle()
            else:
                return (EXCEPTION)

        except ConnectionError as error:
            Logger.debug(f"{self.logIdentifier} ConnectionError while submitting entry {str(error)}")

            self.retry += 1
            Logger.warning(f"{self.logIdentifier} ConnectionError while submitting entry! ({self.retry}/{self.maxRetry})")
            self.proxy = ProxyManager().rotateProxy(self.session, self.proxy)

            if (self.retry <= self.maxRetry):
                return self.enterRaffle()
            else:
                return (EXCEPTION)

    def AutoConfirm_FetchLink(self):

        if (self.retry >= self.maxRetry):
            Logger.error(f"{self.logIdentifier} Failed to AutoConfirm (MaxRetryExceeded)")
            return (EXCEPTION)

        state = MailController().fetchMail("service@bstn.com", self.profile['email'], "Verify your email", False, "verify")

        if (state['status'] is True):

            if (state['link'] is None):

                if ("mail" in state):
                    Logger.error(f"{self.logIdentifier} Found email but doesn't contains a valid links to verify your entry!")
                    return (FAILED)

                self.retry += 1
                delay = self.raffle['AutoConfirmer']['delay']
                Logger.warning(f"{self.logIdentifier} AutoConfirm hasn't found email yet! Retrying in {delay}s. ({self.retry}/{self.maxRetry})")
                time.sleep(delay)
                return (self.AutoConfirm_FetchLink())

            else:
                self.confirmLink = state['link']
                return (SUCCESS)
        else:
            Logger.error(f"{self.logIdentifier} Error happen while trying to AutoConfirm! \"{state['message']}\"")
            return (FAILED)

    def AutoConfirm_Confirm(self):

        try:
            response = self.session.post(
                'https://raffle.bstn.com/api/verify',
                headers={
                    "referer": self.confirmLink
                },
                json={
                    "token": self.confirmLink.replace("https://raffle.bstn.com/verify/", "")
                }
            )

            Logger.debug(f"{self.logIdentifier} Received {response.status_code} from BSTN [ConfirmLink]")
            Logger.debug(f"{self.logIdentifier} Received {response.text} from BSTN [ConfirmLink]")

            if (response.status_code == 201):
                return (SUCCESS)
            else:
                return (FAILED)

        except HelheimException as error:
            Logger.debug(f"{self.logIdentifier} CloudFlare exception while confirming entry {str(error)}")

            self.retry += 1
            Logger.warning(f"{self.logIdentifier} Something went wrong with CloudFlare while confirming entry ({self.retry}/{self.maxRetry})")
            self.proxy = ProxyManager().rotateProxy(self.session, self.proxy)

            if (self.retry <= self.maxRetry):
                return self.AutoConfirm_Confirm()
            else:
                return (EXCEPTION)

        except ConnectionError as error:
            Logger.debug(f"{self.logIdentifier} ConnectionError while confirming entry {str(error)}")

            self.retry += 1
            Logger.warning(f"{self.logIdentifier} ConnectionError while confirming entry! ({self.retry}/{self.maxRetry})")
            self.proxy = ProxyManager().rotateProxy(self.session, self.proxy)

            if (self.retry <= self.maxRetry):
                return self.AutoConfirm_Confirm()
            else:
                return (EXCEPTION)


import json
import os
from datetime import datetime
from typing import Tuple

import torch
import torch.utils
import torch.utils.data
from torch import nn as nn

import evaluators.tensor_rank_metrics as trm
from common.evaluation import metrics as metrics
from common.evaluation.evaluators import SupervisedTrainEvaluator, SupervisedValidationEvaluator, TrainEvaluator, \
    Evaluator, ComposeEvaluator
from common.train import callbacks as callbacks
from common.train.callbacks import Callback
from common.train.fit_output import FitOutput
from common.train.trainer import Trainer
from common.train.trainers import SupervisedTrainer
from common.train.tuning import ConfigurableTrainerFitResult
from common.train.tuning.configurable_trainer_base import ConfigurableTrainerBase
from common.utils import module as module_utils
from datasets.tensor_completion_dataset import TensorCompletionDataset
from evaluators.tensor_factorization_rank_evaluator import TensorFactorizationCPRankEvaluator
from evaluators.tensor_metrics import ReconstructionErrorMetric, compute_reconstruction_error
from models.tensor_cp_factorization import TensorCPFactorization
from opt.group_rmsprop_optimizer import GroupRMSprop

class TensorCompletionConfigurableTrainer(ConfigurableTrainerBase):

    def initialize(self, params: dict, state: dict):
        super().initialize(params, state)

        now_utc_str = datetime.utcnow().strftime("%Y_%m_%d-%H_%M_%S")
        output_dir = params["output_dir"]
        experiment_name = params["experiment_name"]
        state["experiment_dir"] = os.path.join(output_dir, f"{experiment_name}_{now_utc_str}")
        os.makedirs(state["experiment_dir"])

        dataset = TensorCompletionDataset.load(params["dataset_path"])
        state["dataset"] = dataset

        train_indices = dataset.train_indices_order[:params["num_samples"]]
        train_dataset = torch.utils.data.Subset(dataset, train_indices)
        state["train_dataset"] = train_dataset

    def create_model(self, params: dict, state: dict) -> nn.Module:
        dataset = state["dataset"]
        return TensorCPFactorization(num_dim_per_mode=list(dataset.target_tensor.size()), order=len(dataset.target_tensor.size()),
                                     init_std=params["init_std"])

    def create_train_dataloader(self, params: dict, state: dict) -> torch.utils.data.DataLoader:
        train_dataset = state["train_dataset"]
        return torch.utils.data.DataLoader(train_dataset, batch_size=len(train_dataset), shuffle=False)

    def create_train_and_validation_evaluators(self, model: nn.Module, device, params: dict, state: dict) -> Tuple[TrainEvaluator, Evaluator]:
        train_metric_info_seq = [metrics.MetricInfo("mse_loss", metrics.MSELoss())]
        train_evaluator = SupervisedTrainEvaluator(train_metric_info_seq)

        dataset = state["dataset"]
        dataloader = torch.utils.data.DataLoader(dataset, batch_size=len(dataset), shuffle=False)

        reconstruction_error_metric_infos = [metrics.MetricInfo("reconstruction_error", ReconstructionErrorMetric(normalized=True))]
        reconstruction_evaluator = SupervisedValidationEvaluator(model, dataloader, reconstruction_error_metric_infos, device=device)

        val_evluators = [reconstruction_evaluator]
        if params["track_tensor_rank"]:
            val_evluators.append(TensorFactorizationCPRankEvaluator(model, tol=params["tensor_rank_tol"], device=device))

        return train_evaluator, ComposeEvaluator(val_evluators)

    def create_trainer_callback(self, model: nn.Module, params: dict, state: dict) -> Callback:
        additional_metadata = {
            "Number of model parameters": module_utils.get_number_of_parameters(model),
            "target_from_norm": torch.norm(state["dataset"].target_tensor, p="fro").item()
        }
        logging_callback = self.__class__.__create_logging_callback(params, state, additional_metadata=additional_metadata)

        callbacks_list = [logging_callback]

        if params["plot_metrics"]:
            callbacks_list.append(
                callbacks.MetricsPlotter(state["experiment_dir"], create_plots_interval=params["save_every_num_val"] * params["validate_every"]))

        if params["store_checkpoints"]:
            callbacks_list.append(
                callbacks.Checkpoint(state["experiment_dir"], save_interval=params["save_every_num_val"] * params["validate_every"], n_saved=1))

        train_loss_fn = lambda trainer: trainer.train_evaluator.get_tracked_values()["mse_loss"].current_value
        callbacks_list.append(callbacks.StopOnZeroTrainLoss(train_loss_fn=train_loss_fn, tol=params["stop_on_zero_loss_tol"], patience=2))
        callbacks_list.append(callbacks.TerminateOnNaN(verify_batches=False))

        return callbacks.ComposeCallback(callbacks_list)

    @staticmethod
    def __create_logging_callback(params, state, additional_metadata=None):
        if params["file_log"]:
            return callbacks.FileProgressLogger(state["experiment_dir"], experiment_name=params["experiment_name"],
                                                train_batch_log_interval=-1, epoch_log_interval=params["validate_every"],
                                                run_params=params, additional_metadata=additional_metadata)
        return callbacks.ConsoleProgressLogger(train_batch_log_interval=-1, epoch_log_interval=params["validate_every"], run_params=params,
                                               additional_metadata=additional_metadata)

    def create_trainer(self, model: nn.Module, train_evaluator: TrainEvaluator, val_evaluator: Evaluator,
                       callback: Callback, device, params: dict,
                       state: dict) -> Trainer:
        if params["use_adaptive_lr"]:
            optimizer = GroupRMSprop(model.parameters(), lr=params["lr"])
        else:
            optimizer = torch.optim.SGD(model.parameters(), lr=params["lr"])

        loss = nn.MSELoss()
        return SupervisedTrainer(model, optimizer, loss, train_evaluator=train_evaluator, val_evaluator=val_evaluator,
                                 callback=callback, device=device)

    def create_fit_result(self, trainer: Trainer, fit_output: FitOutput, params: dict,
                          state: dict) -> ConfigurableTrainerFitResult:
        dataset = state["dataset"]

        # Creates the "Memorizer" baseline predictions, that predict the given entries exactly and for the rest 0.
        train_indices = state["train_dataset"].indices
        memorizer_tensor = torch.zeros_like(dataset.target_tensor)
        train_indices_tensor = dataset.all_indices_tensor[train_indices]
        split_indices = [train_indices_tensor[:, i] for i in range(train_indices_tensor.size(1))]

        memorizer_tensor[split_indices] = dataset.target_tensor[split_indices]

        with torch.no_grad():
            model_tensor = trainer.model.compute_tensor()

        torch.save(model_tensor, os.path.join(state["experiment_dir"], "model_tensor.pt"))
        torch.save(memorizer_tensor, os.path.join(state["experiment_dir"], "memorizer_tensor.pt"))
        torch.save(dataset.target_tensor, os.path.join(state["experiment_dir"], "targets_tensor.pt"))

        additional_metadata = self.__create_tensor_rank_and_reconstruction_metrics(model_tensor, dataset.target_tensor,
                                                                                memorizer_tensor, params)
        with open(os.path.join(state["experiment_dir"], "tensor_rank_and_reconstruction_metrics.json"), "w") as f:
            json.dump(additional_metadata, f, indent=2)

        mse_loss_tracked_value = fit_output.train_tracked_values["mse_loss"]
        score = mse_loss_tracked_value.current_value if mse_loss_tracked_value.current_value is not None else -1
        score_epoch = mse_loss_tracked_value.epochs_with_values[-1] if len(mse_loss_tracked_value.epochs_with_values) > 0 else -1
        return ConfigurableTrainerFitResult(score, "mse_loss",
                                            score_epoch=score_epoch,
                                            additional_metadata=additional_metadata)

    def __create_tensor_rank_and_reconstruction_metrics(self, model_tensor, targets_tensor, memorizer_tensor, params):
        metrics = {
            "model_reconstruction_error": compute_reconstruction_error(model_tensor, targets_tensor, normalize=True),
            "memorizer_reconstruction_error": compute_reconstruction_error(memorizer_tensor, targets_tensor, normalize=True)
        }

        if params["compute_final_tensor_ranks"]:
            tol = params["tensor_rank_tol"]
            model_tensor_rank = trm.find_cp_rank(model_tensor, tol=tol)
            memorizer_tensor_rank = trm.find_cp_rank(memorizer_tensor, tol=tol)
            targets_tensor_rank = trm.find_cp_rank(targets_tensor, tol=tol)

            metrics.update({"model_tensor_rank": model_tensor_rank,
                            "memorizer_tensor_rank": memorizer_tensor_rank,
                            "targets_tensor_rank": targets_tensor_rank})

        return metrics


import os
import json
import numpy as np
from hand_eye_calibration.dual_quaternion import DualQuaternion

class ExtrinsicCalibration:
  def __init__(self, time_offset, pose_dual_quat):
    self.time_offset = time_offset
    self.pose_dq = pose_dual_quat

  def writeJson(self, out_file, switchConvention = False):
    pose = self.pose_dq.to_pose()
    if switchConvention:
      pose[3:6] *= -1.0; # convert to JPL
    calib = {
      'delay' : self.time_offset,
      'rotation' : { name : float(pose[i + 3]) for i, name in enumerate('ijkw') },
      'translation' : { name : float(pose[i]) for i, name in enumerate('xyz') }
    }
    with open(out_file, 'w') as f:
      json.dump(calib, f, indent = 3, sort_keys=True)

  @classmethod
  def fromJson(cls, in_file, switchConvention = False):
    with open(in_file, 'r') as f:
      data = json.load(f)

    p = [ float(data['translation'][name]) for name in 'xyz' ]

    q = np.array([ float(data['rotation'][name]) for name in 'ijkw' ])
    if switchConvention:
      q[:3] *= -1.0

    dq = DualQuaternion.from_pose_vector(np.hstack((p, q)))
    return ExtrinsicCalibration(float(data['delay']), dq)

  def __str__(self):
    return "[delta_time: %f, delta_pose: %s]" %(self.time_offset, str(self.pose_dq.to_pose()))

  def __mul__(self, other):
    if not isinstance(other, ExtrinsicCalibration):
        return NotImplemented
    return ExtrinsicCalibration(self.time_offset + other.time_offset, self.pose_dq * other.pose_dq)


from typing import List

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.axes import Axes
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

MAX_ROTATE_LABELS = 3
MAX_LABELS = 15
MAX_NR_CHARS = 15
STRING_LABEL_ROTATION = 45
NON_NEGATIVE_DECIMALS_AND_INTS = "^[0-9]+(?:\.[0]*|)$"
DATETIME_PATTERN = "^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$"
DATETIME_LABEL_PATTERN = "\d{2}-\d{2} \d{2}$"
TIME_REGEX = "\d{2}:\d{2}:\d{2}$"
TIME_FORMATTER = "%H:%M:%S"

def prepare_analysis_figure(master, x_name: str = "", y_name: str = "") -> FigureCanvasTkAgg:
    """
    creates a figure and sets the axis names
    :param master:      the master
    :param x_name:      the name of the x-axis
    :param y_name:      the name of the y-axis
    """
    figure = plt.Figure()
    figure.set_tight_layout(True)
    ax = figure.add_subplot(111)
    figure_canvas = FigureCanvasTkAgg(figure, master)
    # axis names
    ax.set_xlabel(x_name, fontsize=10)
    ax.set_ylabel(y_name, fontsize=10)
    return figure_canvas

# def prepare_columnformat(column: Series) -> Series:
#     if re.match(TIME_REGEX, str(column[0])):
#         return pandas.to_datetime(column, format=TIME_FORMATTER)
#     return column

def optimize_axes_labels(ax: Axes):
    """
    optimizes the axes labels:
    1) rotates string labels if there are too many, so they don't overlap
    2) converts labels of the time axis back to the time format
    :param ax:          the axes of the figure which labels are to optimize
    """
    _limit_label_length(ax)
    _optimize_nr_ticks(ax)
    _rotate_axes_labels(ax)

def _limit_label_length(ax: Axes):
    """
    limits the length of the labels to 10 characters
    :param ax:          the axes of the figure which labels are to optimize
    """
    if len(ax.get_xticklabels()[0].get_text()) > MAX_NR_CHARS:
        int_ticks = [str(x) for x in np.arange(1, len(ax.get_xticklabels()) + 1)]
        ax.set_xticklabels(int_ticks)
    if len(ax.get_yticklabels()[0].get_text()) > MAX_NR_CHARS:
        int_ticks = [str(x) for x in np.arange(1, len(ax.get_yticklabels()) + 1)]
        ax.set_yticklabels(int_ticks)

def _optimize_nr_ticks(ax: Axes):
    """
    optimizes the number of ticks on the axes
    :param ax:          the axes of the figure which labels are to optimize
    """
    # optimizes the number of ticks on the axes
    if len(ax.get_xticks()) > MAX_LABELS:
        ticks = ax.get_xticks()
        tick_labels = ax.get_xticklabels()
        step_size = len(ticks) // MAX_LABELS  # calculate the step size
        ticks = ticks[::step_size]  # create a list of ticks using the step size
        tick_labels = tick_labels[::step_size]  # create a list of tick labels using the step size
        ax.set_xticks(ticks)
        ax.set_xticklabels(tick_labels)
    labels = ax.get_yticklabels()
    labels = ax.get_yticks()
    if len(ax.get_yticks()) > MAX_LABELS:
        ticks = ax.get_yticks()
        tick_labels = ax.get_yticklabels()
        step_size = len(ticks) // MAX_LABELS  # calculate the step size
        ticks = ticks[::step_size]  # create a list of ticks using the step size
        tick_labels = tick_labels[::step_size]  # create a list of tick labels using the step size
        ax.set_yticks(ticks)
        ax.set_yticklabels(tick_labels)

# def _optimize_label_format(ax: Axes):
#     """
#     optimizes the formats of the columns in the dataframe:
#     1) converts datetime representations to datetime.time representation
#     :param ax:  the axes of the matplotlib diagram
#     """
#     first_x_label = ax.get_xticklabels()[0].get_text()
#     first_y_label = ax.get_yticklabels()[0].get_text()
#     if re.match(DATETIME_LABEL_PATTERN, first_x_label):
#         ax.xaxis.set_major_formatter(dates.DateFormatter(TIME_FORMATTER))
#     if re.match(DATETIME_LABEL_PATTERN, first_y_label):
#         ax.yaxis.set_major_formatter(dates.DateFormatter(TIME_FORMATTER))

def _rotate_axes_labels(ax: Axes):
    """
    rotates string labels if there are too many, so they don't overlap
    :param ax:          the axes of the figure which labels are to optimize
    """
    # rotates string labels if too many
    if len(ax.get_xticks()) > MAX_ROTATE_LABELS:
        ax.set_xticklabels(ax.get_xticklabels(), rotation=STRING_LABEL_ROTATION)

def _time_to_int(s: str) -> int:
    """
    converts a string in time format into an integer
    :param s:   the string in time format
    :return:    the integer
    """
    return int(''.join(s.split(':')))

def _int_to_time(i: int) -> str:
    """
    converts an integer back into time format
    :param i:   the integer in time format
    :return:    the string in time format
    """
    if i < 0:
        return ''
    time_str = '{}:{}:{}'.format(i // 10000, i % 10000 // 100, i % 100)
    return time_str

def time_column_to_int(time_column: List[str]) -> List[int]:
    """
    converts a column in time format into an integer column
    """
    return [_time_to_int(time) for time in time_column]

def int_column_to_time(int_column: List[int]) -> List[str]:
    """
    converts an integer column into a column in time format
    """
    return [_int_to_time(nr) for nr in int_column]


import datetime

from WolframAlphaFetch import WolframAlphaFetch
from DatabaseConnector import DatabaseConnector

import matplotlib.pyplot as plt
import matplotlib.ticker as plticker

class DataCreator:
    """class which will connect the data gathering from the API to the Firebase database through the firebase API"""
    def __init__(self, app_id):
        self.__waf = WolframAlphaFetch(app_id)
        self.__dbc = DatabaseConnector.getInstance()

    def addOneDate(self, date):
        """function to add exactly one temperature calculated from the Wolfram API to the Firebase database,
        as a tuple of date key and temperature value"""
        date = date.replace("/", "-")
        if self.__dbc.getValue(date) is None:
            """key already existing in the database"""
            print()
            value = self.__waf.getResponse(date)
            if value != -999:
                """error case in the Wolfram API"""
                return self.__dbc.addValue(date, str(value))
            else:
                print("Wolfram API key problem!")
        else:
            print("Key " + date + " already existing")

    def addMultipleDates(self, startDate, endDate):
        """function to add every value starting from the start date until the end date"""
        startDateObj = datetime.datetime.strptime(startDate, "%d/%m/%Y").date()
        endDateObj = datetime.datetime.strptime(endDate, "%d/%m/%Y").date()
        # valid parameters
        if (endDateObj - startDateObj).days >= 0:
            date = startDateObj
            # iterate through the dates
            while date <= endDateObj:
                self.addOneDate(str(date.strftime("%d/%m/%Y")))
                # print(date.strftime("%d/%m/%Y"))
                date += datetime.timedelta(days=1)

    def addUntilRecent(self):
        """function to start from the day before the current one and go backwards by adding days one by one, until the
        first day which is added in the database already"""
        today = datetime.datetime.today().date()
        yesterday = today - datetime.timedelta(days=1)
        while self.__dbc.getValue(yesterday.strftime("%d-%m-%Y")) is None:
            self.addOneDate(str(yesterday.strftime("%d-%m-%Y")))
            yesterday -= datetime.timedelta(days=1)

    def plotter(self, startDate, endDate):
        """function to plot from a given day each day until the last one, in celsius on the y axis"""
        x = []
        startDateObj = datetime.datetime.strptime(startDate, "%d/%m/%Y").date()
        endDateObj = datetime.datetime.strptime(endDate, "%d/%m/%Y").date()
        date = startDateObj
        while date <= endDateObj:
            x.append(date.strftime("%d-%m-%Y"))
            date += datetime.timedelta(days=1)

        y = []
        for i in x:
            val = self.__dbc.getValue(i)
            y.append(float(val))

        print(y)

        fig, ax = plt.subplots()
        ax.plot(x, y)

        plt.autoscale(enable=True, axis='x')

        loc = plticker.MultipleLocator(base=len(x) / 5.5)  # this locator puts ticks at regular intervals
        ax.xaxis.set_major_locator(loc)

        plt.xlabel("days")
        plt.ylabel("temperature (°C)")
        plt.title("from " + str(startDate) + " to " + str(endDate))
        plt.grid(True)

        plt.draw()
        plt.show()


from django.urls import path

from CTRS_course_project.reservation.views import create_reservation, \
    ReservationStep1View, ReservationStep2View, ReservationDetailsView, save_projection

urlpatterns = [
    path('start/', create_reservation, name='start reservation'),
    path('save/<int:pk>/', save_projection, name='save projection'),
    path('step1/', ReservationStep1View.as_view(), name='reservation step 1'),
    path('step2/', ReservationStep2View.as_view(), name='reservation step 2'),
    path('review/<int:pk>/', ReservationDetailsView.as_view(), name='reservation review'),
]


""" Functions to compute the ALO for lasso.

"""

import numpy as np
from scipy.linalg import cholesky, solve_triangular, solve

from ._helper_c import cholappend, choldelete

from ._helper_c import lasso_compute_alo as compute_alo_lasso

def compute_alo_lasso_reference(X, y, beta_hats):
    """ Compute ALO approximation of error for lasso.

    Parameters
    ----------
    X: the sensing matrix
    y: the observations
    beta_hats: A matrix [num_observations, num_alphas] of fits for a number
        of tuning along the path.

    Returns
    -------
    alo_values: The ALO mean-squared error for each tuning.
    """
    residuals = y[:, np.newaxis] - np.dot(X, beta_hats)

    alo_values = np.empty(beta_hats.shape[1])

    for i in range(beta_hats.shape[1]):
        E = np.abs(beta_hats[:, i]) > 1e-5
        h = compute_h_lasso(X, E)
        alo_values[i] = np.square(np.divide(residuals[:, i], (1 - h))).mean()

    return alo_values

def _compute_cholesky(X, index):
    S = np.dot(X[:, index].T, X[:, index])
    return cholesky(S, lower=True, overwrite_a=True, check_finite=False)

def _update_cholesky(X, L, index, index_new):
    index_added = set(index_new) - set(index)
    index_removed = set(index) - set(index_new)

    index = list(index)

    for i in index_removed:
        loc = index.index(i)
        del index[loc]
        L = choldelete(L, i)

    for i in index_added:
        L = cholappend(L, np.dot(X[:, index].T, X[:, i]), np.dot(X[:, i].T, X[:, i]))
        index.append(i)

    return L, index

def _compute_leverage_cholesky(X, L, index):
    W = X[:, index]
    return np.sum(solve_triangular(L, W.T, lower=True, check_finite=False) ** 2, axis=0)

def compute_alo_lasso_py(X: np.ndarray, y: np.ndarray, beta_hats: np.ndarray) -> np.ndarray:
    """Computes the ALO approximation of the error for the lasso estimator.

    See also `compute_alo_lasso` for a faster implementation in pure C++,
    and `compute_alo_lasso_reference` for a reference implementation in plain python.

    Parameters
    ----------
    X : np.ndarray
        Array of size ``n x p``, design matrix for the problem.
    y : np.ndarray
        Array of size ``n``, observations for the problem.
    beta_hats : np.ndarray
        Array of size ``p x num_alphas``, the fitted coefficients for each
        regularization parameter.

    Returns
    -------
    An array of size ``num_alphas``, containing the ALO approximation for
    the least square error for each regularization parameter.
    """
    residuals = y[:, np.newaxis] - np.dot(X, beta_hats)
    alo_values = np.empty(beta_hats.shape[1])

    cholesky_current = None
    active_index = None

    for i in range(beta_hats.shape[1]):
        E = np.abs(beta_hats[:, i]) > 1e-5
        num_active = np.sum(E)

        if num_active == 0:
            cholesky_current = None
            active_index = []
            alo_values[i] = np.mean(np.square(residuals[:, i]))
            continue

        if cholesky_current is None:
            current_index = np.flatnonzero(E)
            cholesky_current = _compute_cholesky(X, current_index)
        else:
            current_index = np.flatnonzero(E)
            cholesky_current, current_index = _update_cholesky(X, cholesky_current, active_index, current_index)

        active_index = current_index

        if num_active >= X.shape[0]:
            leverage = np.ones(X.shape[0], dtype=X.dtype)
        else:
            leverage = _compute_leverage_cholesky(X, cholesky_current, active_index)

        alo_values[i] = np.mean(np.square(residuals[:, i] / (1 - leverage)))

    return alo_values

def compute_h_lasso(X, E):
    """ Compute leverage for Lasso estimator.

    Computes the leverage for the Lasso estimator with the given
    equicorellation set

    Parameters
    ----------
    X: The design matrix.
    E: The equicorellation set.

    Returns
    -------
    h: a vector representing the leverage values for each observation
    """
    num_active = np.sum(E)

    if num_active == 0:
        return np.zeros(X.shape[0], dtype=X.dtype)
    elif num_active >= X.shape[0]:
        return np.ones(X.shape[0], dtype=X.dtype)

    W = X[:, E]
    S = np.dot(W.T, W)
    K = cholesky(S, lower=True, overwrite_a=True, check_finite=False)
    return np.sum(solve_triangular(K, W.T, lower=True, check_finite=False) ** 2, axis=0)

def compute_h_lasso_naive(X, E):
    """ Computes the leverage for the Lasso estimator using a naive method.

    Computes the leverage for the Lasso estimator with the given
    equicorellation set. See `compute_h_lasso` for a computationally
    efficient strategy to compute the leverage values.

    Parameters
    ----------
    X: The design matrix.
    E: The equicorellation set.

    Returns
    -------
    h: a vector representing the leverage values for each observation
    """
    W = X[:, E]
    S = np.dot(W.T, W)
    return np.diag(W.dot(solve(S, W.T, sym_pos=True)))


import random as rnd
from color_constant import colors
from enum import Enum

class RepaintGameState(Enum):
    NOT_PLAYING = 0
    PLAYING = 1
    WIN = 2

class Cell:
    def __init__(self, color_count):
        self._color = rnd.choice(list(colors.keys())[:color_count])
        self._is_painted = False
        self._neighbours = [None, None, None, None]

    @property
    def color(self) -> str:
        return self._color

    @color.setter
    def color(self, a):
        self._color = a

    @property
    def is_painted(self) -> bool:
        return self._is_painted

    @is_painted.setter
    def is_painted(self, a):
        self._is_painted = a

    @property
    def left(self):
        return self._neighbours[0]

    @left.setter
    def left(self, a):
        self._neighbours[0] = a

    @property
    def up(self):
        return self._neighbours[1]

    @up.setter
    def up(self, a):
        self._neighbours[1] = a

    @property
    def right(self):
        return self._neighbours[2]

    @right.setter
    def right(self, a):
        self._neighbours[2] = a

    @property
    def down(self):
        return self._neighbours[3]

    @down.setter
    def down(self, a):
        self._neighbours[3] = a

class RepaintGame:
    def __init__(self, row_count: int, col_count: int, color_count: int):
        self._first_cell = None
        self._row_count = row_count
        self._col_count = col_count
        self._color_count = color_count
        self._state = RepaintGameState.NOT_PLAYING
        self._turns = 0
        self.new_game()

    def new_game(self) -> None:
        self._first_cell = Cell(self.color_count)
        self._first_cell.is_painted = True
        curr_cell = None
        left_cell = None
        up_cell = None
        for i in range(self.row_count):
            for j in range(self.col_count):
                if j == 0:
                    if i == 0:
                        curr_cell = self._first_cell
                    else:
                        curr_cell = Cell(self.color_count)
                    up_cell = self._first_cell
                    for _ in range(i - 1):
                        up_cell = up_cell.down
                else:
                    if i > 0:
                        up_cell = up_cell.right
                    left_cell = curr_cell
                    curr_cell = Cell(self.color_count)
                if i != 0:
                    curr_cell.up = up_cell
                    up_cell.down = curr_cell
                if j != 0:
                    curr_cell.left = left_cell
                    left_cell.right = curr_cell
        repaint(self._first_cell.right, self._first_cell.color)
        repaint(self._first_cell.down, self._first_cell.color)
        last_cell = self._first_cell
        while last_cell.down is not None:
            last_cell = last_cell.down
        while last_cell.right is not None:
            last_cell = last_cell.right
        self.state = RepaintGameState.PLAYING

    @property
    def row_count(self) -> int:
        return self._row_count

    @property
    def col_count(self) -> int:
        return self._col_count

    @property
    def color_count(self) -> int:
        return self._color_count

    @property
    def first_cell(self) -> Cell:
        return self._first_cell

    @property
    def state(self) -> RepaintGameState:
        return self._state

    @state.setter
    def state(self, a):
        self._state = a

    @property
    def turns(self) -> int:
        return self._turns

    @turns.setter
    def turns(self, a):
        self._turns = a

    def __getitem__(self, indices: tuple) -> Cell:
        cell = self._first_cell
        for _ in range(indices[0]):
            cell = cell.down
        for _ in range(indices[1]):
            cell = cell.right
        return cell

    def print_field(self, cell):
        curr_cell = cell
        down_cell = cell.down
        for i in range(self.row_count):
            for j in range(self.col_count):
                print('{0} '.format(curr_cell.color), end='')
                curr_cell = curr_cell.right
            print()
            curr_cell = down_cell
            if i != self.row_count - 1:
                down_cell = down_cell.down

    def check_win(self, cell):
        if not cell.is_painted:
            return False
        curr_cell = cell
        up_cell = cell.up
        for i in range(self.row_count):
            for j in range(self.col_count):
                if not curr_cell.is_painted:
                    return False
                curr_cell = curr_cell.left
            curr_cell = up_cell
            if i != self.row_count - 1:
                up_cell = up_cell.up
        return True

    def left_mouse_click(self, color) -> None:
        if self.state == RepaintGameState.WIN:
            return
        repaint(self._first_cell, color)
        last_cell = self[self.row_count - 1, self.col_count - 1]
        if self.check_win(last_cell):
            self.state = RepaintGameState.WIN
        self._turns += 1

def repaint(cell, color):
    if cell is None:
        return
    if cell.is_painted and color != cell.color:
        cell.color = color
        repaint(cell.left, color)
        repaint(cell.up, color)
        repaint(cell.right, color)
        repaint(cell.down, color)
        return
    if not cell.is_painted and color == cell.color:
        cell.is_painted = True
        repaint(cell.left, color)
        repaint(cell.up, color)
        repaint(cell.right, color)
        repaint(cell.down, color)
        return


#coding=utf-8
#coding=utf-8
from django.http import HttpResponse,HttpResponseRedirect
from django.shortcuts import render_to_response

from common.format_helper import get_year,get_year_seq,month_to_standard,get_cur_year_month,get_cur_year, get_year_list, handle_year_seq
from common.common_data import month_axis,quarter_axis,type_list
from django.template import RequestContext
import simplejson
import datetime
from django.core.exceptions import ObjectDoesNotExist
from common.request_context import render_to_error_page
# from CarbonEmission.sys_switch import get_switch_value
from common_tools import get_time_stamp,change_unite,change_units_without_round,list_clear_and_extend
from common.validator import validate_report_date_old
from decimal import Decimal
import urllib
#对于判断是否是编辑页面还是添加页面，可以在模版中使用变量flag,1为编辑页面，0为添加页面.
class Action(object):
    fields_to_set = {
    }
    module_name = ''
    model = object

    list_to_redirect =  ''

    manage_to_render = ''
    list_to_render = ''
    detail_to_render = ''

    title_add = ''
    title_manage = ''

    #跳转页面路径前缀
    path_prefix = ''

    _module_name = None

    #钩子方法
    def hook_add(self,request,dict):
        pass

    def hook_update(self,request,objid,dict):
        pass

    def hook_list(self,requset):
        return self.model.objects.all()

    def hook_detail(self,request,obj,dict):
        pass

    def hook_delete(self,request,objid):
        obj = self.model.objects.get(id=objid)
        obj.delete()

    def __init__(self,path_prefix='',is_verify=False):
        if not self._module_name:
            self._module_name = self.model()._meta.module_name.__str__().lower()
        self.path_prefix = path_prefix

    def put_extra_object_list(self, request, dict):
        pass

    def object_list(self,request):
        dict = {}
        objs = self.hook_list(request)
        result_objs = []
        if objs:
            dict[self._module_name + 's'] = objs
        try:
            result_objs = objs.order_by('-create_time')
            obj_len = len(result_objs)
        except Exception:
            result_objs = objs
        dict[self._module_name + 's'] = result_objs

        self.put_extra_object_list(request, dict)

        return render_to_response('%s/%s' % (self.path_prefix,self.list_to_render),dict,context_instance=RequestContext(request))

    def object_add(self,request):
        dict = {'title':self.title_add,'flag':0}
        self.hook_add(request,dict)
        return render_to_response('%s/%s' %(self.path_prefix,self.manage_to_render),dict,context_instance=RequestContext(request))

    def object_update(self,request,objid):
        dict = {}
        obj = None
        if objid:
            obj = self.model.objects.get(id=objid)
            dict['title'] = self.title_manage
            dict['flag'] = 1
            dict[self._module_name] = obj
        self.hook_update(request,objid,dict)
        return render_to_response('%s/%s' % (self.path_prefix,self.manage_to_render),dict,context_instance=RequestContext(request))

    def object_detail(self,request,objid):
        dict = {}
        obj = None
        if objid:
            obj = self.model.objects.get(id=objid)
            dict['title'] = self.title_manage
            dict['flag'] = 1
            dict[self._module_name] = obj
        self.hook_detail(request,obj,dict)
        return render_to_response('%s/%s' % (self.path_prefix,self.detail_to_render),dict,context_instance=RequestContext(request))

    def object_delete(self,request,objid):
        self.hook_delete(request,objid)
        return HttpResponseRedirect('/%s/%s/' % (self.path_prefix,self.list_to_redirect))

    def object_manage(self,request):
        objid = None
        if request.method == 'POST':
            objid = request.POST.get("id")

        if objid and objid != '':
            obj = self.model.objects.get(id=objid)
            self.autowired(request,obj)
            self.wire_others(request,obj)
            obj.save(False,True)
        else:
            obj = self.model()
            self.autowired(request,obj)
            self.wire_others(request,obj)
            obj.save(True)

        return HttpResponseRedirect('/%s/%s/' % (self.path_prefix,self.list_to_redirect))

    def wire_properties(self,from_model_obj,to_model_obj):
        fields_set = type(to_model_obj)._meta.get_all_field_names()
        if fields_set:
            for field_name in fields_set:
                try:
                    val = getattr(from_model_obj,field_name)
                    setattr(to_model_obj,field_name,val)
                except Exception:
                    pass

    def autowired(self,request,obj):
        if not self.fields_to_set:
            self.fields_to_set = type(obj)._meta.get_all_field_names()

        if self.fields_to_set:
            val = None
            for field in self.fields_to_set:
                val = request.POST.get(field)
                if val:
                    setattr(obj,field,val)

    def wire_others(self,request,obj):
        pass

    def render_to_page(self,request,url):
        return render_to_response(url,{},context_instance=RequestContext(request))

    def render_dict_to_page(self,request,dict,url):
        return render_to_response(url,dict,context_instance=RequestContext(request))

    def render_jsondata_to_response(self,dict):
        return HttpResponse(simplejson.dumps(dict), content_type="application/json")

    def render_html_to_response(self,dict):
        return HttpResponse(simplejson.dumps(dict),content_type="text/html")

class ImportAction(Action):
    importor = None
    error_export_url = None

    def __init__(self,path_prefix='',is_verify=False,use_user_region=False):
        super(ImportAction,self).__init__(path_prefix,is_verify)
        self.use_user_region = use_user_region

    def object_import(self,request):
        pass

    def error_export(self,request):
        errors_to_export = request.session['errors_to_export']
        data = self.importor.export_data_to_excel(errors_to_export, True)
        file_name = self.importor.exported_file_name + '_%s.xls'%(get_time_stamp())
        response = HttpResponse(data,mimetype='application/vnd.ms-excel; charset=utf-8')
        response['Content-Disposition'] = 'attachment; filename=%s' %(urllib.quote(file_name.encode('utf-8')))
        #remove errros_to_export
        request.session['errors_to_export'] = None
        return response

    def template_export(self,request):
        data_to_export = self.importor.export_data_to_excel([])
        file_name = self.importor.exported_file_name + '导出模板.xls'

        response = HttpResponse(data_to_export,mimetype='application/vnd.ms-excel; charset=utf-8')
        #fixed by selwyn
        #IE导出文件乱码问题
        response['Content-Disposition'] = 'attachment; filename=%s' %(urllib.quote(file_name.encode('utf-8')))
        #response['Content-Disposition'] = 'attachment; filename=%s' %(file_name.encode('utf-8'))
        return response


import json

class Producer:

    def __init__(self, broker, topic):
        self.server = broker['server']
        self.sync = False
        self.topic = topic
        self.port = broker['port']
        self.flatten = False
        self.type = 'kafka'

class Workflow:
    def __init__(self, workflowFilename, instances, workflowName):
        self.workflowFilename = workflowFilename
        self.instances = instances
        self.workflowName = workflowName

class WorkflowConfig:
    def __init__(self, producers, workflows):
        self.producers = producers
        self.workflows = workflows

    def toJSON(self):
        config = self.__dict__
        data = config["producers"][0].__dict__
        data["broker.server"] = data.pop("server")
        data["broker.port"] = data.pop("port")
        return json.dumps(self, default=lambda o: o.__dict__,
            sort_keys=False, indent=1)


## ASIGNATURA : GESTIÓN DE INFORMACIÓN EN LA WEB
## PRÁCTICA MongoEngine
## GRUPO 10
## AUTORES: Victor Chamizo Rodriguez, Pablo García Hernandez, Fernando López Carrión, Irene Martín Berlanga y Sergio Martín Gómez

## Victor Chamizo Rodriguez, Pablo García Hernandez, Fernando López Carrión, Irene Martín Berlanga y Sergio Martín Gómez declaramos
## que esta solución es fruto exclusivamente de nuestro trabajo personal. No hemos sido ayudados por ninguna otra persona ni hemos
## obtenido la solución de fuentes externas, y tampoco hemos compartido nuestra solución con nadie. Declaramos además que no hemos
## realizado de manera deshonesta ninguna otra actividad que pueda mejorar nuestros resultados ni perjudicar los resultados de los demás.

from mongoengine import *
import datetime
import re

connect('giw_mongoengine')

class Producto(Document):
	codigoDeBarras = StringField(primary_key=True, regex="[0-9]{13}")
	nombre = StringField(required=True)
	categoriaPrincipal = IntField(required=True)
	categoriasSecundarias = ListField(IntField())

	def cumpleCondicionCategorias(self):
		tieneCategoriasSecundarias = len(self.categoriasSecundarias) > 0
		principalEstaEnPrimerLugar = True

		if tieneCategoriasSecundarias:
			principalEstaEnPrimerLugar = self.categoriaPrincipal == self.categoriasSecundarias[0]

		return not tieneCategoriasSecundarias or principalEstaEnPrimerLugar

	def sumarDigitosEnPosicionesPares(self):
		sumaDigitosEnPosicionesPares = 0

		for digito in self.codigoDeBarras[1::2]:
			sumaDigitosEnPosicionesPares += int(digito)

		return sumaDigitosEnPosicionesPares

	def sumarDigitosEnPosicionesImpares(self):
		sumaDigitosEnPosicionesImpares = 0

		for digito in self.codigoDeBarras[0:-1:2]:
			sumaDigitosEnPosicionesImpares += int(digito)

		return sumaDigitosEnPosicionesImpares

	def comprobarCodigoDeBarras(self):
		checksum = 3 * self.sumarDigitosEnPosicionesPares()
		checksum += self.sumarDigitosEnPosicionesImpares()

		checksum = 10 - (checksum % 10)

		if checksum == 10:
			checksum = 0

		return checksum == int(self.codigoDeBarras[-1:])

	def clean(self):
		cumpleCondicionDeCategorias = self.cumpleCondicionCategorias()
		estaBienFormadoElCodigoDeBarras = self.comprobarCodigoDeBarras()

		if not cumpleCondicionDeCategorias:
			raise ValidationError("El producto " + self.nombre + " no cumple la condición de categorias.")
		elif not estaBienFormadoElCodigoDeBarras:
			raise ValidationError("El codigo de barras del producto " + self.nombre + " no está bien formado.")

class LineaDePedido(EmbeddedDocument):
	cantidadDelProducto = IntField(required=True, min_value=1)
	precioDelProducto = FloatField(required=True, min_value=0)
	nombreDelProducto = StringField(required=True)
	precioTotalDeLaLinea = FloatField(required=True, min_value=0)
	producto = ReferenceField(Producto, required=True)

	def clean(self):
		nombresCoinciden = self.nombreDelProducto == self.producto.nombre
		precioCorrectamenteCalculado = self.precioTotalDeLaLinea == self.cantidadDelProducto * self.precioDelProducto

		if not nombresCoinciden:
			raise ValidationError("El nombre del producto no coincide en la línea" + self.producto.nombre + ".")
		elif not precioCorrectamenteCalculado:
			raise ValidationError("El precio de la linea " + self.nombreDelProducto + " no es correcto.")

class Pedido(Document):
	precio = FloatField(required=True, min_value=0)
	fecha = ComplexDateTimeField(required=True)
	lineasDelPedido = ListField(EmbeddedDocumentField(LineaDePedido), required=True)

	def clean(self):
		precioTotalLineas = 0

		for linea in self.lineasDelPedido:
			precioTotalLineas += linea.precioTotalDeLaLinea

		if self.precio != precioTotalLineas:
			raise ValidationError("El precio del pedido con precio " + str(self.precio) + " no coincide con el de sus líneas: " + str(precioTotalLineas))

class Usuario(Document):
	dni = StringField(primary_key=True, regex="[0-9]{7,8}-?[A-Z]{1}")
	nombre = StringField(required=True)
	primerApellido = StringField(required=True)
	segundoApellido = StringField()

	fechaDeNacimiento = StringField(required=True, regex="([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))")
	ultimosDiezAccesosAlSistema = ListField(ComplexDateTimeField)
	tarjetasDeCredito = ListField(StringField())
	pedidos = ListField(ReferenceField(Pedido, reverse_delete_rule=4))

	def clean(self):
		mapaRestosLetrasDni = {0 : "T", 1 : "R", 2 : "W", 3 : "A", 4 : "G", 5 : "M", 6 : "Y", 7 : "F", 8 : "P",
						   9 : "D", 10 : "X", 11 : "B", 12 : "N", 13 : "J", 14 : "Z", 15 : "S", 16 : "Q",
						   17 : "V", 18 : "H", 19 : "L", 20 : "C", 21 : "K", 22 : "E"}

		m = re.search('([0-9]{7,8})', self.dni)
		numerosDni = int(m.group(0))
		numerosDniMod23 = numerosDni % 23
		digitoDeControl = self.dni[-1]

		if digitoDeControl != mapaRestosLetrasDni[numerosDniMod23]:
			raise ValidationError("El dígito de control del dni " + self.dni + " no es correcto.")

class TarjetaDeCredito(Document):
	propietario = StringField(required=True)
	numero = StringField(primary_key=True, regex="[0-9]{16}")
	mesDeCaducidad = StringField(required=True, regex="^(0?[1-9]|1[012])$")
	añoDeCaducidad = StringField(required=True, regex="[1-9]{2}")
	codigoDeVerificacion = IntField(required=True, min_value=100, max_value=999)

def insertar():

	# ¿Hay que meter alguno mal para que salte ValidationError?
	producto1 = Producto(codigoDeBarras="0012345678905", nombre="PS4", categoriaPrincipal=1, categoriasSecundarias=[1, 2])
	producto2 = Producto(codigoDeBarras="9780201379624", nombre="Xbox", categoriaPrincipal=2)
	producto3 = Producto(codigoDeBarras="1234567890197", nombre="Nintendo Switch", categoriaPrincipal=5, categoriasSecundarias=[5, 4])
	producto4 = Producto(codigoDeBarras="1254567890195", nombre="Super Mario Odissey", categoriaPrincipal=8)

	linea1Pedido1Usuario1 = LineaDePedido(cantidadDelProducto=6, precioDelProducto=5.0, nombreDelProducto="PS4", precioTotalDeLaLinea=30.0, producto=producto1)
	linea2Pedido1Usuario1 = LineaDePedido(cantidadDelProducto=1, precioDelProducto=5.0, nombreDelProducto="Xbox", precioTotalDeLaLinea=5.0, producto=producto2)

	linea1Pedido2Usuario1 = LineaDePedido(cantidadDelProducto=7, precioDelProducto=5.0, nombreDelProducto="Nintendo Switch", precioTotalDeLaLinea=35.0, producto=producto3)
	linea2Pedido2Usuario1 = LineaDePedido(cantidadDelProducto=2, precioDelProducto=5.0, nombreDelProducto="Super Mario Odissey", precioTotalDeLaLinea=10.0, producto=producto4)

	linea1Pedido1Usuario2 = LineaDePedido(cantidadDelProducto=8, precioDelProducto=5.0, nombreDelProducto="PS4", precioTotalDeLaLinea=40.0, producto=producto1)
	linea2Pedido1Usuario2 = LineaDePedido(cantidadDelProducto=3, precioDelProducto=5.0, nombreDelProducto="Xbox", precioTotalDeLaLinea=15.0, producto=producto2)

	linea1Pedido2Usuario2 = LineaDePedido(cantidadDelProducto=5, precioDelProducto=5.0, nombreDelProducto="Nintendo Switch", precioTotalDeLaLinea=25.0, producto=producto3)
	linea2Pedido2Usuario2 = LineaDePedido(cantidadDelProducto=8, precioDelProducto=5.0, nombreDelProducto="Super Mario Odissey", precioTotalDeLaLinea=40.0, producto=producto4)

	lineasPedido1Usuario1 = [linea1Pedido1Usuario1, linea2Pedido1Usuario1]
	lineasPedido2Usuario1 = [linea1Pedido2Usuario1, linea2Pedido2Usuario1]

	lineasPedido1Usuario2 = [linea1Pedido1Usuario2, linea2Pedido1Usuario2]
	lineasPedido2Usuario2 = [linea1Pedido2Usuario2, linea2Pedido2Usuario2]

	pedido1Usuario1 = Pedido(precio=35.0, fecha=datetime.datetime.now(), lineasDelPedido=lineasPedido1Usuario1)
	pedido2Usuario1 = Pedido(precio=45.0, fecha=datetime.datetime.now(), lineasDelPedido=lineasPedido2Usuario1)

	pedido1Usuario2 = Pedido(precio=55.0, fecha=datetime.datetime.now(), lineasDelPedido=lineasPedido1Usuario2)
	pedido2Usuario2 = Pedido(precio=65.0, fecha=datetime.datetime.now(), lineasDelPedido=lineasPedido2Usuario2)

	tarjeta1Usuario1 = TarjetaDeCredito(propietario="Sergio", numero="1234567890123456", mesDeCaducidad="12", añoDeCaducidad="23", codigoDeVerificacion=123)
	tarjeta2Usuario1 = TarjetaDeCredito(propietario="Sergio", numero="2167013026479256", mesDeCaducidad="09", añoDeCaducidad="24", codigoDeVerificacion=456)

	tarjeta1Usuario2 = TarjetaDeCredito(propietario="Irene", numero="8901234561234567", mesDeCaducidad="01", añoDeCaducidad="25", codigoDeVerificacion=789)
	tarjeta2Usuario2 = TarjetaDeCredito(propietario="Irene", numero="6789012312345456", mesDeCaducidad="05", añoDeCaducidad="26", codigoDeVerificacion=327)

	usuario1 = Usuario(dni="12345678Z", nombre="Sergio", primerApellido="Martin", segundoApellido="Gomez", fechaDeNacimiento="1990-05-29", tarjetasDeCredito=[tarjeta1Usuario1.numero, tarjeta2Usuario1.numero], pedidos=[pedido1Usuario1, pedido2Usuario1])
	usuario2 = Usuario(dni="23456123X", nombre="Irene", primerApellido="Martin", fechaDeNacimiento="1992-01-28", tarjetasDeCredito=[tarjeta1Usuario2.numero, tarjeta2Usuario2.numero], pedidos=[pedido1Usuario2, pedido2Usuario2])

	producto1.save()
	producto2.save()
	producto3.save()
	producto4.save()

	pedido1Usuario1.save()
	pedido2Usuario1.save()

	pedido1Usuario2.save()
	pedido2Usuario2.save()

	tarjeta1Usuario1.save()
	tarjeta2Usuario1.save()

	tarjeta1Usuario2.save()
	tarjeta2Usuario2.save()

	usuario1.save()
	usuario2.save()

if __name__ == '__main__':
	insertar()


import torch
import yaml
import warnings

def save_experiment(config, output_dir, name, model=None):
    outfile = f"{output_dir}/{name}.yml"
    if model:
        config["weights_file"] = f"{output_dir}/{name}.pt"
        torch.save(model.state_dict(), f"{output_dir}/{name}.pt")
    with open(outfile, "w") as f:
        yaml.dump(config, f)
    return outfile

def load_experiment(config_path):
    with open(config_path, "r") as f:
        config = yaml.load(f)
    # Convert tuples back to slices
    for period in ['test_period', 'valid_period', 'train_period']:
        try:
            time_range = config['data_config'][period]
            time_range = slice(*time_range)
            config['data_config'][period] = time_range
        except KeyError:
            warnings.warn(f"Missing key in config: {period}. Skipping...")
            continue
    return config


#!/usr/bin/env python3
import os
from glob import glob

import astropy.units as u
import matplotlib.pyplot as plt
from astropy.table import Table
from astropy.visualization import ImageNormalize, MinMaxInterval, SqrtStretch
from matplotlib.patches import Ellipse
from spectral_cube import SpectralCube

def plot_comp(row, c="b"):
    ax = plt.gca()
    ax.plot(
        row["RA"], row["Dec"], marker="X", color=c, transform=ax.get_transform("world")
    )
    e = Ellipse(
        ((row["RA"] * u.deg).value, (row["Dec"] * u.deg).value),
        width=(row["Maj"] * u.arcsec).to(u.deg).value,
        height=(row["Min"] * u.arcsec).to(u.deg).value,
        angle=row["PA"] + 90,
        transform=ax.get_transform("world"),
        facecolor="none",
        edgecolor=c,
        linewidth=2,
    )
    ax.add_artist(e)

    ax.text(
        (row["RA"] * u.deg).value,
        (row["Dec"] * u.deg).value,
        row["Peak_flux"],
        transform=ax.get_transform("world"),
    )

def main(cutdir, source):
    cat = Table.read(
        "/home/athomson/athomson/projects/RACS/Catalogues/RACS-25asec-Mosaiced_Gaussians_Final_GalCut_v2020_11_15.fits"
    )
    cat_S = Table.read(
        "/home/athomson/athomson/projects/RACS/Catalogues/RACS-25asec-Mosaiced_Sources_Final_GalCut_v2020_11_15.fits"
    )
    cat.add_index("Source_ID")
    cat_S.add_index("Source_ID")
    sub = Table(cat.loc[source])
    cat_S.add_index("Source_ID")
    sub_S = Table(cat_S.loc[source])

    cutdir = os.path.abspath(cutdir)
    images = glob(f"{cutdir}/{source}/*.image.*.i.*.linmos.fits")

    cube = SpectralCube.read(images[0])
    mom0 = cube.mean(axis=0)

    fig = plt.figure()
    ax = plt.subplot(projection=mom0.wcs)
    norm = ImageNormalize(mom0.value, interval=MinMaxInterval(), stretch=SqrtStretch())
    im = ax.imshow(mom0.value, norm=norm)
    ax.plot(
        sub["RA"] * u.deg, sub["Dec"] * u.deg, "rX", transform=ax.get_transform("world")
    )
    ax.plot(
        sub_S["RA"] * u.deg,
        sub_S["Dec"] * u.deg,
        "bX",
        transform=ax.get_transform("world"),
    )
    ra = ax.coords["ra"]
    dec = ax.coords["dec"]
    ra.set_major_formatter("d.dd")
    dec.set_major_formatter("d.dd")
    fig.colorbar(im, label=f"Average flux density [{mom0.unit}]")
    for row in sub:
        plot_comp(row, c="w")
    plt.show()
    # plt.savefig('test.png')

def cli():
    import argparse

    descStr = """
    Check cutouts
    """
    parser = argparse.ArgumentParser(
        description=descStr, formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    parser.add_argument("cutdir", metavar="cutdir", type=str, help="Cutout dir")

    parser.add_argument("source", metavar="source", type=str, help="Source name.")

    args = parser.parse_args()
    main(args.cutdir, args.source)

if __name__ == "__main__":
    cli()


import cv2
import csv
import math
import random
import glob
import os

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.decomposition import PCA
from mpl_toolkits.mplot3d import Axes3D

prop_cycle = plt.rcParams['axes.prop_cycle']
colors = prop_cycle.by_key()['color']
SIZE = (640,480)

def getCSVData():
    dataSet = []
    with open("diabetes.csv") as csvfile:
        reader = csv.reader(csvfile)
        for row in reader:
            dataSet.append(row)
    dataSet = [list(map(float,i)) for i in dataSet]
    'dataset[0] = [-1.0, 6.0, 148.0, 72.0, 35.0, 0.0, 33.6, 0.627, 50.0]'
    return dataSet

def get_dataPoints(f):
    dataSet = getCSVData()
    df = pd.DataFrame(dataSet)
    df = np.asarray(df)
    df = df[:, 1:f+1]
    df = np.asarray(df)
    standardMatrix = get_standardMatrix(df)
    if f > 3:

        feature_3 = PCA(3)
        dataPoints = feature_3.fit_transform(standardMatrix)
        dataPoints = np.asarray(dataPoints).transpose()
        return dataPoints
    else:
        df =standardMatrix.transpose()
        return df

def plotData(x,y,z, k,name,f,refVec):
    name = "image_" + str(k) + "_" + str(name)
    fig = plt.figure()
    plt.clf()
    ax = fig.add_subplot(111, projection='3d')

    if f >= 3:
        mx = max(len(x[0]), len(y[0]), len(z[0]))
        for i in range(k):
            ax.scatter(x[i], y[i], z[i], c=colors[i], marker='x')
            ax.scatter(refVec[i][0],refVec[i][1],refVec[i][2],c=colors[i],marker='o')
    else:
        mx = max(len(x[0]), len(y[0]))
        for i in range(k - 1):
            mx1 = max(len(x[i + 1]), len(y[i + 1]))
            if mx < mx1:
                mx = mx1

        for i in range(k):
            ax.scatter(x[i], y[i], c=colors[i], marker='x')
            ax.scatter(refVec[i][0], refVec[i][1], c=colors[i], marker='o')
    plt.title("Purity="+str(round((mx/768),3)))
    plt.savefig(name)
    plt.close('all')
    CreateVideo(k,f)

def CreateVideo(k,f):
    name = "K_" + str(k) + "_F" + str(f) + ".avi"
    listPic = glob.glob('*.png')
    video = cv2.VideoWriter(name, cv2.VideoWriter_fourcc(*'DIVX'), 1, SIZE)

    for image in listPic:
        video.write(cv2.imread(image))

    cv2.destroyAllWindows()
    video.release()

"""Method to pick the first K points randomly and returns those points"""
def pickKPoints(k, dataLen,data):
    list_randomPoints = []
    random.seed(0)
    centroids = []
    for i in range(0,k):
        rand = random.randint(0,dataLen)
        list_randomPoints.append(rand)

    for i in list_randomPoints:
        centroids.append(get_points(data,i))

    return centroids

"""Helper method to return a Point in that Index"""
def get_points(data,index):
    'returns [x,y,z] point'
    if len(data) == 3:
        return [data[0][index],data[1][index],data[2][index]]
    else:
        return [data[0][index],data[1][index]]

"""Calculates and clusters the sets depending on the number of K"""
def myKMeans(k,f):
    data = get_dataPoints(f)
    x = []
    y = []
    z = []
    'centroids = [[x,y,z],[x,y,z]]'
    centroids = pickKPoints(k, len(data[0]),data)
    refVector = centroids.copy()
    Set_Points = {i: [] for i in range(len(centroids))}
    list_Dis = [None]*k
    j = 0
    if f >=3:
        while (True):
            j += 1
            for i in range(0, len(data[0])):
                """get the coordinates of the observation and put it in Set Points"""
                coord = get_points(data, i)
                found_clusterPoint = closet_point(centroids, coord)
                indexAt = centroids.index(found_clusterPoint)
                Set_Points[indexAt].append(coord)
            for num_k in range(k):
                x1,y1,z1 = zip(*Set_Points[num_k])
                x.append(x1)
                y.append(y1)
                z.append(z1)

                matrix  = Set_Points[num_k]
                matrix  = np.asarray(matrix)
                meanMatrix = get_mean(matrix)
                dis = ManhattanDist(centroids[num_k],meanMatrix)
                list_Dis[num_k] = dis
                centroids[num_k] = meanMatrix
                centroids = np.array(centroids).tolist()

            plotData(x, y, z, k,j,f,refVector)
            refVector = centroids.copy()
            x.clear()
            y.clear()
            z.clear()
            for key in Set_Points:
                Set_Points[key].clear()

            if check_done(list_Dis):
                break
            else:
                continue
    else:
        while (True):
            j += 1
            for i in range(0, len(data[0])):
                """get the coordinates of the observation and put it in Set Points"""
                coord = get_points(data, i)
                found_clusterPoint = closet_point(centroids, coord)
                indexAt = centroids.index(found_clusterPoint)
                Set_Points[indexAt].append(coord)
            for num_k in range(k):
                x1, y1= zip(*Set_Points[num_k])
                x.append(x1)
                y.append(y1)
                matrix = Set_Points[num_k]
                matrix = np.asarray(matrix)
                meanMatrix = get_mean(matrix)
                dis = ManhattanDist(centroids[num_k], meanMatrix)
                list_Dis[num_k] = dis
                centroids[num_k] = meanMatrix
                centroids = np.array(centroids).tolist()

            plotData(x, y, z,k,j, f, refVector)
            x.clear()
            y.clear()
            for key in Set_Points:
                Set_Points[key].clear()

            if check_done(list_Dis):
                break
            else:
                continue

    files = glob.glob('*.png')
    for f in files:
        os.remove(f)

"""Calculates the Manhattan Distance"""
def ManhattanDist(p1,p2):
    if len(p1)== 3:
        x0,x1 = p1[0],p2[0]
        y0,y1 = p1[1],p2[1]
        z0,z1 = p1[2],p2[2]

        return math.fabs(x0-x1) + math.fabs(y0-y1) + math.fabs(z0-z1)
    else:
        x0, x1 = p1[0], p2[0]
        y0, y1 = p1[1], p2[1]
        return math.fabs(x0 - x1) + math.fabs(y0 - y1)

"""Checks if the we should end the iterations"""
def check_done(change_dist):
    if float(sum(change_dist)) < 2**(-23):
        return True
    else:
        return False

def closet_point(centroids, A):
    minimum = 9999999
    point = centroids[0]
    for i in centroids:
        D = Euclidiandistance(i,A)
        if D < minimum:
            minimum = D
            point = i

    return point

def Euclidiandistance(A,B):
    """A = [x,y,z] B=[x,y,z]"""
    if len(A) == 3:
        x0,x1 = A[0],B[0]
        y0,y1 = A[1],B[1]
        z0,z1 = A[2],B[2]

        return math.sqrt((x0 - x1)**2 + (y0 - y1)**2 + (z0 - z1)**2)
    else:
        x0, x1 = A[0], B[0]
        y0, y1 = A[1], B[1]
        return math.sqrt((x0 - x1) ** 2 + (y0 - y1) ** 2)

def get_mean(matrix):
    return matrix.mean(axis=0)

def get_standardMatrix(matrix):
    '1x1600 mean'
    m = matrix.mean(axis=0)
    '1x1600 std'
    std = matrix.std(axis=0)

    'get standardized matrix'
    standMatrix = (matrix - m) / std

    return standMatrix

myKMeans(k=3,f=4)
myKMeans(k=4,f=7)
myKMeans(k=5,f=8)