import logging
from pathlib import Path

from more_itertools import pairwise

from docint.span import Span

# from more_itertools import pairwise
from docint.util import get_full_path, get_model_path, load_config
from docint.vision import Vision

# TODO: 1. Model save options locally, huggingface cloud
# TODO: 2 Save the results and verify the model is correct

def get_text_paras(docs):
    for page in [p for d in docs for p in d.pages]:
        text_paras = getattr(page, "text_paras", [])
        for idx, para in enumerate(text_paras):
            yield f"{page.doc.pdf_name}-{page.page_idx}-{idx}", para

def get_ner_tags(labels):
    ner_tags = []
    for (idx, label) in enumerate(labels):
        if label is None:
            ner_tags.append("O")
            continue

        stub = "OFF" if label == "officer" else "DEP"
        if idx == 0 or label != labels[idx - 1]:
            ner_tags.append(f"B-{stub}")
        else:
            ner_tags.append(f"I-{stub}")
    return ner_tags

##def check_datset(data_dict):
# num_examples = len(data_dict["id"])
# assert all(len(v) == num_examples for v in data_dict.values())

# zip_iter = zip(data_dict["texts"], data_dict["bboxes"], data_dict["ner_tags"])
# assert all(len(t) == len(b) == len(n) for (t, b, n) in zip_iter)

# max_val = MAX_IMAGE_HEIGHT
# for page_id, example in zip(data_dict["id"], data_dict["bboxes"]):
#     for idx, box in enumerate(example):
#         for coord_val in box:
#             assert (
#                 0 <= coord_val <= max_val
#             ), f"incorrect coord_val: {coord_val} {page_id} word: {idx}"

# assert all(0 <= c <= max_val for e in data_dict["bboxes"] for b in e for c in b)
# assert all(len(b) == 4 for e in data_dict["bboxes"] for b in e)
# assert all(i.size[0] <= i.size[1] == max_val for i in data_dict["pil_images"])

@Vision.factory(
    "learn_ner",
    requires="labels_dict",
    depends=[
        "transformers[torch]",
        "seqeval",
        "datasets",
    ],
    default_config={
        "num_folds": 3,
        "max_steps": 100,
        "warmup_ratio": 0.1,
        "publish_name": "",
        "conf_stub": "ner",
        "model_dir": ".model",
        "orig_model_name": "huggingface:distilbert-base-uncased",
        "save_model_name": "orgpedia:orgpedia-foundation/rajpol-dept-ner",
    },
)
class LearnNER:
    def __init__(
        self,
        num_folds,
        max_steps,
        warmup_ratio,
        publish_name,
        conf_stub,
        model_dir,
        orig_model_name,
        save_model_name,
    ):
        self.num_folds = num_folds
        self.max_steps = max_steps
        self.warmup_ratio = warmup_ratio
        self.publish_name = publish_name
        self.conf_stub = conf_stub
        self.ner_model_name = orig_model_name
        self.save_model_name = save_model_name

        self.conf_dir = Path("conf")
        self.model_dir = get_full_path(model_dir)

        from transformers import AutoTokenizer

        self.ner_model_dir = get_model_path(self.ner_model_name, self.model_dir)

        self.tokenizer = AutoTokenizer.from_pretrained(self.ner_model_dir)

        self.save_model_dir = get_model_path(self.save_model_name, self.model_dir)

        print(f"num_folds: {self.num_folds}")

        self.lgr = logging.getLogger(__name__)
        self.lgr.setLevel(logging.INFO)
        self.lgr.addHandler(logging.StreamHandler())

    def get_folds(self, num_examples):
        assert (
            num_examples >= self.num_folds and self.num_folds >= 1
        ), f"num_examples: {num_examples} folds: {self.num_folds}"
        assert isinstance(num_examples, int)

        if self.num_folds == 1:
            yield list(range(num_examples)), []
            return

        fold_size = num_examples / self.num_folds
        fold_idxs = [int(i * fold_size) for i in range(self.num_folds)] + [num_examples]

        for (start_idx, end_idx) in pairwise(fold_idxs):
            test_idxs = list(range(start_idx, end_idx))
            train_idxs = list(range(0, start_idx)) + list(range(end_idx, num_examples))
            yield train_idxs, test_idxs

    def add_para_spans(self, doc):
        doc_config = load_config(self.conf_dir, doc.pdf_name, self.conf_stub)

        for para_config in doc_config["page_configs"]:  # please correct t his
            if "ignore" in para_config:
                continue

            para = doc[para_config["page_idx"]].text_paras[para_config["para_idx"]]
            para.clear_labels()

            for (label, spans) in para_config.items():
                if label == "para_idx" or label == "page_idx":
                    continue

                if not spans or not spans[0]:
                    continue

                for (start, end) in spans:
                    span = Span(start=start, end=end)
                    para.add_label(span, label)
                    print(f"Adding {label}: {span}")

    # https://github.com/huggingface/notebooks/blob/main/examples/token_classification.ipynb
    def tokenize_and_align_labels(self, examples):
        tokenized_inputs = self.tokenizer(
            examples["tokens"], truncation=True, is_split_into_words=True
        )
        label_all_tokens = True
        labels = []
        for i, label in enumerate(examples["ner_tags"]):
            word_ids = tokenized_inputs.word_ids(batch_index=i)
            previous_word_idx = None
            label_ids = []
            for word_idx in word_ids:
                # Special tokens have a word id that is None.
                # We set the label to -100 so they are automatically
                # ignored in the loss function.
                if word_idx is None:
                    label_ids.append(-100)
                    # We set the label for the first token of each word.
                elif word_idx != previous_word_idx:
                    label_ids.append(label[word_idx])
                    # For the other tokens in a word, we set the label to
                    # either the current label or -100, depending on
                    # the label_all_tokens flag.
                else:
                    label_ids.append(label[word_idx] if label_all_tokens else -100)
                previous_word_idx = word_idx

            labels.append(label_ids)

        tokenized_inputs["labels"] = labels
        return tokenized_inputs

    def generate_dataset(self, docs):
        data_dict = {"id": [], "tokens": [], "ner_tags": []}
        class_labels = set()

        for (para_id, para) in get_text_paras(docs):
            data_dict["id"].append(para_id)

            tokens, labels = para.get_texts_labels(para)
            print(tokens)
            print(labels)

            data_dict["tokens"].append(tokens)

            ner_tags = get_ner_tags(labels)
            data_dict["ner_tags"].append(ner_tags)
            class_labels.update(ner_tags)

            assert len(data_dict["tokens"][-1]) == len(data_dict["ner_tags"][-1])

        sorted_class_labels = sorted(class_labels)  # + ["B-LOC", "I-LOC", "B-MISC", "I-MISC"]
        class_labels = sorted_class_labels

        from datasets import ClassLabel, Dataset, Features, Sequence, Value

        features = Features(
            {
                "id": Value("string"),
                "tokens": Sequence(Value("string")),
                "ner_tags": Sequence(ClassLabel(names=class_labels)),
            }
        )

        # dataset = Dataset.from_dict(mapping=data_dict, features)
        dataset = Dataset.from_dict(data_dict, features)

        print(sorted_class_labels)
        # dataset = dataset.cast_column("ner_tags", Sequence(ClassLabel(names=sorted_class_labels)))

        print("DATASET GENERATED")

        tokenized_dataset = dataset.map(self.tokenize_and_align_labels, batched=True)

        return tokenized_dataset, sorted_class_labels

    def run_cross_validation(self, dataset, class_labels):
        def compute_metrics(p):
            predictions, labels = p
            predictions = np.argmax(predictions, axis=2)

            # Remove ignored index (special tokens)
            true_predictions = [
                [class_labels[p] for (p, l) in zip(prediction, label) if l != -100]  # noqa
                for prediction, label in zip(predictions, labels)
            ]
            true_labels = [
                [class_labels[l] for (p, l) in zip(prediction, label) if l != -100]  # noqa
                for prediction, label in zip(predictions, labels)
            ]

            results = metric.compute(predictions=true_predictions, references=true_labels)
            if return_entity_level_metrics:
                # Unpack nested dictionaries
                final_results = {}
                for key, value in results.items():
                    if isinstance(value, dict):
                        for n, v in value.items():
                            final_results[f"{key}_{n}"] = v
                        else:
                            final_results[key] = value
                return final_results
            else:
                return {
                    "precision": results["overall_precision"],
                    "recall": results["overall_recall"],
                    "f1": results["overall_f1"],
                    "accuracy": results["overall_accuracy"],
                }

        import numpy as np
        import seqeval  # noqa
        from datasets import load_metric
        from transformers import (
            AutoModelForTokenClassification,
            DataCollatorForTokenClassification,
            Trainer,
            TrainingArguments,
        )

        model = AutoModelForTokenClassification.from_pretrained(
            self.ner_model_dir, num_labels=len(class_labels)
        )

        batch_size = 8

        id2label = {v: k for v, k in enumerate(class_labels)}
        label2id = {k: v for v, k in enumerate(class_labels)}
        return_entity_level_metrics = True  # CHANGE THIS

        args = TrainingArguments(
            self.save_model_name,
            evaluation_strategy="steps",
            learning_rate=2e-5,
            per_device_train_batch_size=batch_size,
            per_device_eval_batch_size=batch_size,
            num_train_epochs=5,  # change this
            logging_steps=10,  # change this from 1000
            report_to="wandb",
            weight_decay=0.01,
            push_to_hub=False,
        )

        data_collator = DataCollatorForTokenClassification(self.tokenizer)
        for fold_idx, (train_idxs, test_idxs) in enumerate(self.get_folds(len(dataset))):
            print(f"Test[{fold_idx}]: {test_idxs}")
            print(f"Train[{fold_idx}]: {train_idxs}")

            train_dataset = dataset.select(train_idxs)
            test_dataset = dataset.select(test_idxs)

            metric = load_metric("seqeval")

            model.config.id2label = id2label
            model.config.label2id = label2id

            trainer = Trainer(
                model,
                args,
                train_dataset=train_dataset,
                eval_dataset=test_dataset,
                data_collator=data_collator,
                tokenizer=self.tokenizer,
                compute_metrics=compute_metrics,
            )
            trainer.train()
            predictions, labels, metrics = trainer.predict(test_dataset)
            if self.num_folds > 1:
                predictions, labels, metrics = trainer.predict(test_dataset)
                predictions = np.argmax(predictions, axis=2)
                labeled_predictions = [  # noqa
                    [id2label[p] for (p, l) in zip(prediction, label) if l != -100]  # noqa E741
                    for prediction, label in zip(predictions, class_labels)
                ]
                # doc_labels = [class_labels[idx] for idx in test_idxs]
                # self.print_results(test_idxs, doc_labels, labeled_predictions)
            else:
                predictions, labels, metrics = trainer.predict(train_dataset)
                print(metrics)
                assert not test_idxs
                trainer.save_model(self.save_model_dir)
            print(f"DONE fold:{fold_idx}")

    def pipe(self, docs, **kwargs):
        self.lgr.info("> infer_layoutlm.pipe")
        print("INSIDE LEARN LAYOUT")
        docs = list(docs)

        for doc in docs:
            self.add_para_spans(doc)

        dataset, class_labels = self.generate_dataset(docs)  # noqa

        self.run_cross_validation(dataset, class_labels)

        return docs

"""
    def get_folds(self, num_examples):
        assert (
            num_examples >= self.num_folds and self.num_folds >= 1
        ), f"num_examples: {num_examples} folds: {self.num_folds}"
        assert isinstance(num_examples, int)

        if self.num_folds == 1:
            yield list(range(num_examples)), []
            return

        fold_size = num_examples / self.num_folds
        fold_idxs = [int(i * fold_size) for i in range(self.num_folds)] + [num_examples]

        for (start_idx, end_idx) in pairwise(fold_idxs):
            test_idxs = list(range(start_idx, end_idx))
            train_idxs = list(range(0, start_idx)) + list(range(end_idx, num_examples))
            yield train_idxs, test_idxs

    def print_results(self, test_idxs, actuals, predictions):
        for page_idx, page_actuals, page_predicts in zip(test_idxs, actuals, predictions):
            page_correct = len([(a, t) for (a, t) in zip(page_actuals, page_predicts)])
            print(f"*** {page_idx}: {page_correct} {len(page_actuals)}")

    def run_cross_validation(self, dataset, class_labels, ner_tags):
        import numpy as np
        from datasets import load_metric
        from torch.utils.data import DataLoader
        from transformers import LayoutLMv2ForTokenClassification, Trainer, TrainingArguments

        def compute_metrics(p):
            predictions, labels = p
            predictions = np.argmax(predictions, axis=2)
            # Remove ignored index (special tokens)
            true_predictions = [
                [id2label[p] for (p, l) in zip(prediction, label) if l != -100]  # noqa E741
                for prediction, label in zip(predictions, labels)
            ]
            true_labels = [
                [id2label[l] for (p, l) in zip(prediction, label) if l != -100]  # noqa E741
                for prediction, label in zip(predictions, labels)
            ]
            results = metric.compute(predictions=true_predictions, references=true_labels)
            if return_entity_level_metrics:
                # Unpack nested dictionaries
                final_results = {}
                for key, value in results.items():
                    if isinstance(value, dict):
                        for n, v in value.items():
                            final_results[f"{key}_{n}"] = v
                        else:
                            final_results[key] = value
                return final_results
            else:
                return {
                    "precision": results["overall_precision"],
                    "recall": results["overall_recall"],
                    "f1": results["overall_f1"],
                    "accuracy": results["overall_accuracy"],
                }

        def build_trainer(model, train, test):
            train_loader = DataLoader(train, batch_size=4, shuffle=True)
            test_loader = DataLoader(test, batch_size=2)

            model.config.id2label = id2label
            model.config.label2id = label2id

            class LayoutTrainer(Trainer):
                def get_train_dataloader(self):
                    return train_loader

                def get_test_dataloader(self, test_dataset):
                    return test_loader

            # Initialize our Trainer
            trainer = LayoutTrainer(
                model=model,
                args=args,
                compute_metrics=compute_metrics,
            )
            return trainer

        print(f"Cross Validaton: {self.num_folds}")

        args = TrainingArguments(
            output_dir=self.model_dir / "checkpoints",
            max_steps=self.max_steps,  # we train for a maximum of 1,000 batches #80
            warmup_ratio=self.warmup_ratio,  # we warmup a bit
            fp16=False,  # we use mixed precision (less memory consumption)
            push_to_hub=False,  # after training, we'd like to push our model to the hub
            # push_to_hub_model_id=self.publish_name,
        )

        id2label = {v: k for v, k in enumerate(class_labels)}
        label2id = {k: v for v, k in enumerate(class_labels)}

        for fold_idx, (train_idxs, test_idxs) in enumerate(self.get_folds(len(dataset))):
            print(f"Test[{fold_idx}]: {test_idxs}")
            print(f"Train[{fold_idx}]: {train_idxs}")

            train_dataset = dataset.select(train_idxs)
            test_dataset = dataset.select(test_idxs)

            # Metrics - used in compute_metrics
            metric = load_metric("seqeval")
            return_entity_level_metrics = True

            model_path = self.model_dir / Path(self.model_name).name
            pretrained = LayoutLMv2ForTokenClassification.from_pretrained
            if model_path.exists():
                print("MODEL PATH FOUND")
                model = pretrained(model_path, num_labels=len(class_labels))
            else:
                model = pretrained(
                    "microsoft/layoutlmv2-base-uncased", num_labels=len(class_labels)
                )

            trainer = build_trainer(model, train_dataset, test_dataset)

            trainer.train()
            if self.num_folds > 1:
                predictions, labels, metrics = trainer.predict(test_dataset)
                predictions = np.argmax(predictions, axis=2)
                labeled_predictions = [
                    [id2label[p] for (p, l) in zip(prediction, label) if l != -100]  # noqa E741
                    for prediction, label in zip(predictions, class_labels)
                ]
                doc_labels = [ner_tags[idx] for idx in test_idxs]
                self.print_results(test_idxs, doc_labels, labeled_predictions)
            else:
                predictions, labels, metrics = trainer.predict(train_dataset)
                print(metrics)
                assert not test_idxs
                trainer.save_model(self.model_dir)
            print(f"DONE fold:{fold_idx}")

def generate_dataset(learn_pages, model_dir, model_name, has_labels=True):
    class_labels = set()

    def get_ner_tags(page):
        ner_tags = ["O"] * len(page.words)
        if not has_labels:
            class_labels.update(ner_tags)
            return ner_tags

        lr_items = page.word_labels.items()
        label_region_iter = ((lab, r.words) for lab, rs in lr_items for r in rs)
        for (label, words) in label_region_iter:
            ner_tags[words[0].word_idx] = f"B-{label}".replace("_", "").upper()
            for w in words[1:]:
                ner_tags[w.word_idx] = f"I-{label}".replace("_", "").upper()

        class_labels.update(ner_tags)
        return ner_tags

    def get_bbox(page, w):
        box = page.get_image_shape(w.box, img_size=(None, MAX_IMAGE_HEIGHT))
        return [box.top.x, box.top.y, box.bot.x, box.bot.y]

    def preprocess_data(examples):
        images = examples["pil_images"]
        words = examples["texts"]
        boxes = examples["bboxes"]
        word_labels = examples["ner_tags"]

        encoded_inputs = processor(
            images,
            words,
            boxes=boxes,
            word_labels=word_labels,
            padding="max_length",
            truncation=True,
            # return_tensors="pt",
            # return_offsets_mapping=True, # TODO, how to add offsets_mapping to the Features
        )

        # close the images as they take a lot of memory
        for img in images:
            img.close()

        return encoded_inputs

    img_size = (None, MAX_IMAGE_HEIGHT)  # All heights have to be fixed
    data_dict = {"id": [], "texts": [], "bboxes": [], "ner_tags": [], "pil_images": []}
    for page in learn_pages:
        data_dict["id"].append(f"{page.doc.pdf_name}-{page.page_idx}")
        data_dict["texts"].append([w.text for w in page.words])
        data_dict["bboxes"].append([get_bbox(page, w) for w in page.words])
        data_dict["ner_tags"].append(get_ner_tags(page))
        data_dict["pil_images"].append(page.page_image.to_pil_image(img_size).convert("RGB"))

        # data_dict["pil_images"].append(get_wand_array(page.page_image))

    check_datset(data_dict)

    ner_tags = data_dict["ner_tags"]

    from datasets import Array2D, Array3D, ClassLabel, Dataset, Features, Sequence, Value
    from transformers import LayoutLMv2Processor

    hf_dataset = Dataset.from_dict(mapping=data_dict)

    sorted_class_labels = sorted(class_labels)
    hf_dataset = hf_dataset.cast_column("ner_tags", Sequence(ClassLabel(names=sorted_class_labels)))

    model_path = model_dir / Path(model_name).name

    if model_path.exists():
        print("MODEL PATH FOUND")
        processor = LayoutLMv2Processor.from_pretrained(
            model_path,
            revision="no_ocr",
            # return_offsets_mapping=True,
        )
    else:
        processor = LayoutLMv2Processor.from_pretrained(
            "microsoft/layoutlmv2-base-uncased",
            revision="no_ocr",
            # return_offsets_mapping=True,
        )

    features = Features(
        {
            "image": Array3D(dtype="int64", shape=(3, 224, 224)),
            "input_ids": Sequence(feature=Value(dtype="int64")),
            "attention_mask": Sequence(Value(dtype="int64")),
            "token_type_ids": Sequence(Value(dtype="int64")),
            "bbox": Array2D(dtype="int64", shape=(512, 4)),
            "labels": Sequence(ClassLabel(names=sorted_class_labels)),
        }
    )
    pt_dataset = hf_dataset.map(
        preprocess_data,
        batched=True,
        remove_columns=hf_dataset.column_names,
        features=features,
    )
    pt_dataset.set_format(type="torch")
    return pt_dataset, sorted_class_labels, ner_tags

"""

"""
from transformers import AutoTokenizer, DataCollatorForTokenClassification, AutoModelForTokenClassification, TrainingArguments, Trainer
tokenizer = AutoTokenizer.from_pretrained("distilbert-base-uncased")
data_collator = DataCollatorForTokenClassification(tokenizer=tokenizer)
model = AutoModelForTokenClassification.from_pretrained("distilbert-base-uncased", num_labels=len(dm.unique_entities), id2label=dm.id2label, label2id=dm.label2id)
"""


import datetime
import os
import re
import urllib
import sys
import math
import numpy as np
import pandas as pd
from scipy.stats import describe

# Visualization
import matplotlib.pyplot as plt
import matplotlib.cm as cmap

from wordcloud import WordCloud
import networkx as nx
from gensim.models import KeyedVectors

# Data files
SRC_ARTICLES = '../data/guardian-all/articles-standardized.csv'
SRC_AUTHORS = '../data/guardian-all/authors-standardized.csv'
SRC_COMMENTS = '../data/guardian-all/sorted_comments-standardized.csv'

def plot_history(history):
    plt.plot(history.history['acc'], 'b', label='Train Acc')
    plt.plot(history.history['loss'], 'r', label='Train Loss')
    plt.plot(history.history['val_acc'], 'b--', label='Val Acc')
    plt.plot(history.history['val_loss'], 'r--', label='Val Loss')
    plt.legend()

def plot_categories_pie(articles):
    regex = re.compile('https://www\.theguardian\.com/([^/]*)(/(.*)|$)')
    sections = [regex.match(x).group(1) for x in articles['article_url'] if regex.match(x)]
    mismatches = [x for x in articles['article_url'].unique() if not regex.match(x)]
    print(f'Not matching URLs: {"  ".join(mismatches)}')

    section_counts = pd.DataFrame(sections).groupby(0).apply(lambda x: len(x))
    section_counts = list(zip(section_counts.index, section_counts.values))
    section_counts = np.array(sorted(section_counts, reverse=True, key=lambda x: x[1]))

    fig, ax = plt.subplots(1, 1, figsize=(10, 10))
    ax.pie(section_counts[:, 1], labels=section_counts[:, 0], autopct='%1.1f%%',
           explode=[x == 'politics' for x in section_counts[:, 0]],shadow=True, startangle=90)
    ax.axis('equal')  # Equal aspect ratio ensures that pie is drawn as a circle.
    return section_counts

def plot_timestamps(article_id):
    datetimes = data[data['article_id'] == article_id]['timestamp']
    timestamps = [int(datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%SZ").timestamp()) for x in datetimes]
    plt.hist(timestamps)

def plot_feature_correlations(extracted_features_df, author_comments=0):
    labels = list(reversed(extracted_features_df.columns))

    fig, ax = plt.subplots(1, 1, figsize=(14, 12))
    cax = ax.matshow(extracted_features_df[extracted_features_df['author_comments'] > author_comments][labels].corr())
    cbar = fig.colorbar(cax)
    ax.set_xticklabels([''] + labels, rotation=45, ha='left')
    ax.set_yticklabels([''] + labels)
    ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
    ax.yaxis.set_major_locator(ticker.MultipleLocator(1))
    ax.set_title(rf'Correlations: Comment Features ($comments_{{author}} \geq {author_comments}$)', y=1.15)
    fig.savefig(f'correlations-{author_comments}.pdf')


#
#   MySlice version 2
#
#   Activity process service: manages events and requests
#
#   (c) 2016 Ciro Scognamiglio <ciro.scognamiglio@lip6.fr>
##
from multiprocessing import Process
import signal
import threading
from queue import Queue

import random

import myslice.db as db
import rethinkdb as r

from myslice.db import connect, changes, events
from myslice.db.activity import Event, EventStatus
from myslice.services.workers.events import run as manageEvents
import myslice.lib.log as logging

import zmq
import pickle
import json

logger = logging.getLogger()

def receive_signal(signum, stack):
    logger.info('Received signal %s', signum)
    raise SystemExit('Exiting')

def run():
    """

    """
    signal.signal(signal.SIGINT, receive_signal)
    signal.signal(signal.SIGTERM, receive_signal)
    signal.signal(signal.SIGHUP, receive_signal)

    qEvents = Queue()

    threads = []
    for y in range(1):
        t = threading.Thread(target=manageEvents, args=(qEvents,))
        t.daemon = True
        threads.append(t)
        t.start()

    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.setsockopt_string(zmq.SUBSCRIBE, 'activity')
    socket.connect("tcp://localhost:6002")
    logger.info("[activity] Collecting updates from ZMQ bus for activity")

    while True:
        logger.debug("[activity]Change in activity feed")

        topic, zmqmessage = socket.recv_multipart()
        activity = pickle.loads(zmqmessage)

        logger.debug("[activity]{0}: {1}".format(topic, activity))

        try:
            event = Event(activity['new_val'])
            logger.debug("[activity] Adding event %s to Events queue" % (event.id))
            qEvents.put(event)

            #for debbuging purposes

        except Exception as e:
            import traceback
            traceback.print_exc()
            logger.exception(e)
            if 'new_val' in activity and 'id' in activity['new_val']:
                logger.error("[activity] Problem with event: {}".format(activity['new_val']['id']))
            continue

    logger.critical("Service activity stopped")
    # waits for the thread to finish
    for x in threads:
        x.join()

if __name__ == '__main__':
    Process(target=run,).start()


# coding: utf-8

from django.core.cache import cache
from django.db import IntegrityError

class ProfilerData(object):
    """
    Encapsulates work with the profiling data.
    """
    def add(self, view_name, method, is_anon_call, is_cache_hit, sql_time, sql_count, view_execution_time):
        """Adds profiling data.

        :param str view_name: View name
        :param str method: HTTP method (GET, POST, etc.)
        :param bool is_anon_call: If True, it was an anonymous request
        :param bool is_cache_hit: If True, view response was retrieved from cache
        :param float sql_time: SQL queries execution time
        :param int sql_count: Number of SQL queries
        :param float view_execution_time: View execution time
        """
        from django.db.models import F
        from speedinfo.models import ViewProfiler

        try:
            vp, created = ViewProfiler.objects.get_or_create(view_name=view_name, method=method)
        except IntegrityError:
            # IntegrityError exception raised in case of concurrent access
            # to get_or_create method from another webserver worker process
            vp = ViewProfiler.objects.get(view_name=view_name, method=method)

        ViewProfiler.objects.filter(pk=vp.pk).update(
            anon_calls=F('anon_calls') + (is_anon_call and 1 or 0),
            cache_hits=F('cache_hits') + (is_cache_hit and 1 or 0),
            sql_total_time=F('sql_total_time') + sql_time,
            sql_total_count=F('sql_total_count') + sql_count,
            total_calls=F('total_calls') + 1,
            total_time=F('total_time') + view_execution_time
        )

    def reset(self):
        """Deletes all profiling data"""
        from speedinfo.models import ViewProfiler
        ViewProfiler.objects.all().delete()

class Profiler(object):
    """
    Profiler class to store its state and process the data.
    """
    PROFILER_STATE_CACHE_KEY = 'speedinfo.profiler.is_on'

    def __init__(self):
        self.data = ProfilerData()

    @property
    def is_on(self):
        """Returns state of the profiler.

        :return: state of the profiler
        :rtype: bool
        """
        return cache.get(self.PROFILER_STATE_CACHE_KEY, False)

    @is_on.setter
    def is_on(self, value):
        """Sets state of the profiler.

        :param bool value: State value
        """
        cache.set(self.PROFILER_STATE_CACHE_KEY, value, None)

{'F': 'django.db.models.F', 'ViewProfiler': 'speedinfo.models.ViewProfiler'}


import logging
import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
import setup_malcolm_paths

import unittest
from mock import MagicMock, ANY
import time

#module imports
from malcolm.compat import queue
from malcolm.core.task import Task
from malcolm.core.spawnable import Spawnable
from malcolm.core.response import Error, Return, Update, Delta
from malcolm.core.request import Request
from malcolm.core.methodmeta import MethodMeta
from malcolm.core.future import Future
from malcolm.core.vmeta import VMeta
from malcolm.core.attribute import Attribute
from malcolm.core import Process, Block, SyncFactory

#import logging
#logging.basicConfig(level=logging.DEBUG)

class TestWarning(Exception):
    pass

class TestTask(unittest.TestCase):

    def setUp(self):
        self.callback_result = 0
        self.callback_value = ''
        meta = VMeta("meta for unit tests")
        self.proc = MagicMock(q=queue.Queue())
        self.proc.create_queue = MagicMock(side_effect=queue.Queue)
        self.block = Block()
        self.block.set_parent(self.proc, "testBlock")
        self.attr = meta.make_attribute()
        self.attr.set_parent(self.block, "testAttr")
        self.attr2 = meta.make_attribute()
        self.attr2.set_parent(self.block, "testAttr2")
        self.method = MethodMeta("method for unit tests")
        self.method.set_parent(self.block, "testFunc")
        self.method2 = MethodMeta("method for unit tests")
        self.method2.set_parent(self.block, "testFunc")
        self.bad_called_back = False

    def test_init(self):
        t = Task("testTask", self.proc)
        self.assertIsInstance(t._logger, logging.Logger)
        self.assertIsInstance(t.q, queue.Queue)
        self.assertEqual(t.process, self.proc)

    def test_put_async(self):
        t = Task("testTask", self.proc)
        t.put_async(self.attr, "testValue")
        req = self.proc.q.get(timeout=0)
        self.assertIsInstance(req, Request)
        self.assertEqual(req.endpoint,
                         ['testBlock', 'testAttr', 'value'])
        self.assertEqual(len(t._futures), 1)

        d = {self.attr: "testValue", self.attr2: "testValue2"}
        t.put_async(d)
        self.proc.q.get(timeout=0)
        req2 = self.proc.q.get(timeout=0)
        self.assertEqual(self.proc.q.qsize(), 0)
        self.assertIsInstance(req2, Request)
        self.assertEqual(len(t._futures), 3)

    def test_put(self):
        # single attribute
        t = Task("testTask", self.proc)
        resp = Return(0, None, None)
        resp.set_value('testVal')
        # cheat and add the response before the blocking call to put
        t.q.put(resp)
        t.stop()
        t.put(self.attr, "testValue")
        self.assertEqual(len(t._futures), 0)
        self.assertEqual(self.proc.q.qsize(), 1)

    def test_post(self):
        t = Task("testTask", self.proc)
        resp1 = Return(0, None, None)
        resp1.set_value('testVal')
        resp2 = Error(1, None, None)
        # cheat and add the responses before the blocking call to put
        t.q.put(resp1)
        t.q.put(resp2)
        t.stop()
        t.post(self.method, {"a": "testParm"})
        self.assertRaises(ValueError, t.post, self.method, {"a": "testParm2"})
        self.assertEqual(len(t._futures), 0)
        self.assertEqual(self.proc.q.qsize(), 2)

    def test_wait_all(self):
        t = Task("testTask", self.proc)
        f1 = Future(t)
        f2 = Future(t)
        f3 = Future(t)
        f0 = Future(t)
        t._futures = {0: f0, 1: f1, 2: f2, 3: f3}
        f_wait1 = [f2, f0]
        self.assertRaises(queue.Empty, t.wait_all, f_wait1, 0)

        resp0 = Return(0, None, None)
        resp0.set_value('testVal')
        resp2 = Error(2, None, None)
        t.q.put(resp0)
        t.q.put(resp2)
        self.assertRaises(ValueError, t.wait_all, f_wait1, 0)
        self.assertEqual(t._futures, {1: f1, 3: f3})
        self.assertEqual(f0.done(), True)
        self.assertEqual(f1.done(), False)
        self.assertEqual(f2.done(), True)
        self.assertEqual(f3.done(), False)
        self.assertEqual(self.proc.q.qsize(), 0)

        resp3 = Delta(3, None, None)
        t.q.put(resp3)
        f_wait1 = [f3]
        self.assertRaises(ValueError, t.wait_all, f_wait1, 0.01)
        t.stop()
        self.assertRaises(StopIteration, t.wait_all, f_wait1, 0.01)

        resp1 = Return(1, None, None)
        resp1.set_value('testVal')
        t.q.put(resp1)
        self.assertRaises(queue.Empty, t.wait_all, f_wait1, 0.01)
        self.assertEqual(t._futures, {})

        t._futures = {0: f0, 1: f1, 2: f2}
        t.q.put(resp1)
        t.q.put(Spawnable.STOP)
        self.assertEqual(f1.result(), 'testVal')

    def test_wait_all_missing_futures(self):
        # unsolicited response
        t = Task("testTask", self.proc)
        f1 = Future(t)
        resp10 = Return(10, None, None)
        t.q.put(resp10)
        t.q.put(Spawnable.STOP)
        self.assertRaises(StopIteration, t.wait_all, f1, 0)

        # same future twice
        f2 = Future(t)
        t._futures = {1: f2}
        resp1 = Return(1, None, None)
        t.q.put(resp1)
        t.q.put(Spawnable.STOP)
        t.wait_all(f2,0)
        t.wait_all(f2,0)

    def _callback(self, value, a, b):
        self.callback_result = a+b
        self.callback_value = value

    def test_subscribe(self):
        t = Task("testTask", self.proc)
        resp = Update(0, None, None)
        resp.set_value('changedVal')
        t.q.put(resp)
        t.stop()

        new_id = t.subscribe(self.attr, self._callback, 3, 5)
        f1 = Future(t)
        t._futures = {1: f1}

        self.assertRaises(StopIteration, t.wait_all, f1, 0)
        self.assertEqual(self.callback_value, 'changedVal')
        self.assertEqual(self.callback_result, 8)
        t.unsubscribe(new_id)

    def test_callback_error(self):
        t = Task("testTask", self.proc)
        resp = Error(0, None, None)
        resp.set_message('error')
        t.q.put(resp)
        t.stop()

        t.subscribe(self.attr, self._callback, 3, 5)
        f1 = Future(t)
        t._futures = {1: f1}
        self.assertRaises(RuntimeError, t.wait_all, f1, 0)

    def test_callback_unexpected(self):
        t = Task("testTask", self.proc)
        resp = Delta(0, None, None)
        t.q.put(resp)
        t.stop()
        t.subscribe(self.attr, self._callback, 3, 5)
        f1 = Future(t)
        t._futures = {1: f1}
        self.assertRaises(ValueError, t.wait_all, f1, 0)

    def _bad_callback(self, value):
        self.bad_called_back = True
        raise TestWarning()

    def test_callback_crash(self):
        t = Task("testTask", self.proc)
        resp = Update(0, None, None)
        resp.set_value('changedVal')
        t.q.put(resp)
        t.stop()

        t.subscribe(self.attr, self._bad_callback)
        f1 = Future(t)
        t._futures = {1: f1}
        self.assertRaises(StopIteration, t.wait_all, f1, 0)
        self.assertEquals(self.bad_called_back, True)

    def test_sleep(self):
        t = Task("testTask", self.proc)
        start = time.time()
        t.sleep(0.05)
        end = time.time()
        self.assertAlmostEqual(end-start, 0.05, delta=0.005)

    def test_when_matches(self):
        t = Task("testTask", self.proc)

        f = t.when_matches(self.attr, "matchTest")

        # match (response goes to the subscription at id 1,
        # not the future at id 0)
        resp = Update(1, None, None)
        resp.set_value('matchTest')
        t.q.put(resp)
        t.stop()
        self.assertEqual(f[0].result(0),'matchTest')

    def test_not_when_matches(self):
        t = Task("testTask", self.proc)
        f = t.when_matches(self.attr, "matchTest")

        # match (response goes to the subscription at id 1,
        # not the future at id 0)
        resp = Update(1, None, None)
        resp.set_value('NOTmatchTest')
        t.q.put(resp)
        t.stop()

        # this will abort the task because f[0] never gets filled
        self.assertRaises(StopIteration, f[0].result)

    def test_start_default_raises(self):
        t = Task("t", self.proc)
        self.assertRaises(AssertionError, t.start)

    def test_clear_spawn_functions(self):
        t = Task("testTask", self.proc)
        f = MagicMock()
        t.define_spawn_function(None)
        self.assertEquals([(None, (), ANY)], t._spawn_functions)

    def test_clear_raises_if_running(self):
        proc = Process("proc", SyncFactory("sync"))
        t = Task("testTask", proc)
        import time
        def f():
            time.sleep(0.05)
        t.define_spawn_function(f)
        start = time.time()
        t.start()
        self.assertRaises(AssertionError, t.define_spawn_function, None)
        t.wait()
        end = time.time()
        self.assertAlmostEqual(end-start, 0.05, delta=0.005)
        t.define_spawn_function(None)

if __name__ == "__main__":
    unittest.main(verbosity=2)


from itertools import permutations
from random import random
import numpy as np
from math import e
import matplotlib.pyplot as plt
from copy import deepcopy

def logistica(u,beta):
    return 1/(1 + e**(-beta*u))

def tangenteHiperbolica(u,beta):
    return (1 - e**(-beta*u))/(1 + e**(-beta*u))

def camadaSimples(entrada_e_peso=[],entrada_e_peso_prod=[],limiarDeAtivacao =[],funcaoDeAtivacao=[]):#entradas e pesos e limiar

    pontencialDeAtv = []#potencial de ativação de cada neuronio
    saidas = []#saídas de cada neuronio g(u)/y
    #print("\nPasso 1 [u = Σ - θ]:")

    '''
    for indexEntrada,i in enumerate(entrada_e_peso_prod):
        #print("u"+str(indexEntrada+1)+" = ",end="")
        for indexCamada,j in enumerate(i):
            if indexCamada != len(i)-1:#se nao for o ultimo elemento nao dá \n
                #print("x"+str(indexCamada+1)+"*w("+str(indexCamada+1)+","+str(indexEntrada+1)+") + ",end="")
                continue
            #print("x"+str(indexCamada+1)+"*w("+str(indexCamada+1)+","+str(indexEntrada+1)+") - θ"+str(indexEntrada+1))#se for o ultimo elemento dá \n
    '''

    #print("\nPasso 2 [u = Σ - θ]:")
    for indexEntrada,i in enumerate(entrada_e_peso_prod):
        #print("u"+str(indexEntrada+1)+" = ",end="")
        for indexCamada,j in enumerate(i):
            if indexCamada != len(i)-1:#se nao for o ultimo elemento nao dá \n
                #print(str(entrada_e_peso[indexCamada][indexEntrada][0])+"*"+str(entrada_e_peso[indexCamada][indexEntrada][1])+" + ",end="")
                continue
            u = sum(i)-limiarDeAtivacao[indexEntrada]
            #print(str(entrada_e_peso[indexCamada][indexEntrada][0])+"*"+str(entrada_e_peso[indexCamada][indexEntrada][1]),
                  #"-",limiarDeAtivacao[indexEntrada],"=>",u)#se for o ultimo elemento dá \n
            pontencialDeAtv.append(u)

    k = 0
    #print("\nPasso 3 g(u):")
    for indicePotencial,potencial in enumerate(pontencialDeAtv):
        if funcaoDeAtivacao[indicePotencial] == 2:
            k = logistica(potencial,beta)
        elif funcaoDeAtivacao[indicePotencial] == 1:
            k = tangenteHiperbolica(potencial,beta)
        saidas.append(k)
        #print("g(u"+str(indicePotencial+1)+") =",k)
    return saidas

def camadasMultiplas(entrada_e_peso=[],limiarDeAtivacao =[],funcaoDeAtivacao=[],numeroCamadas=2,camadaAtual = 1,quantCamadaAnterior=2,pesosCamadas=[]):
    potencialDeAtvGlobal = []#lista que irá conter o potencial de ativação de todos neuronios
    pontencialDeAtv = []#potencial de ativação dos neuronios da camada atual que está sendo analisada
    saidasGlobal = []#saídas de todos neurônios g(u)/y
    global saidas
    saidas = []#saídas de cada neuronio da camada atual g(u)/y

    '''
    print("\nPasso 1 [u = Σ - θ]:")
    for indexEntrada in range(quantidadePorCamada[camadaAtual-1]):
        print("u"+str(indexEntrada+1)+" = ",end="")
        for indexCamada in range(quantCamadaAnterior):
            if indexCamada != quantCamadaAnterior-1:#se nao for o ultimo elemento nao dá \n
                print("x"+str(indexCamada+1)+"*w("+str(indexCamada+1)+","+str(indexEntrada+1)+") + ",end="")
                continue
            print("x"+str(indexCamada+1)+"*w("+str(indexCamada+1)+","+str(indexEntrada+1)+") - θ"+str(indexEntrada+1))#se for o ultimo elemento dá \n

    print("\nPasso 2 [u = Σ - θ]:")
    '''

    for indexEntrada in range(quantidadePorCamada[camadaAtual-1]):
        expressao = ""
        #print("u"+str(indexEntrada+1)+" = ",end="")
        for indexCamada in range(quantCamadaAnterior):
            if indexCamada != quantCamadaAnterior-1:#se nao for o ultimo elemento nao dá \n
                expressao += str(entrada_e_peso[indexCamada][indexEntrada][0])+"*"+str(entrada_e_peso[indexCamada][indexEntrada][1])+" + "
                #print(str(entrada_e_peso[indexCamada][indexEntrada][0])+"*"+str(entrada_e_peso[indexCamada][indexEntrada][1])+" + ",end="")
                continue

            expressao+= str(entrada_e_peso[indexCamada][indexEntrada][0])+"*"+str(entrada_e_peso[indexCamada][indexEntrada][1])+" - "+str(limiarDeAtivacao[indexEntrada])
            u = eval(expressao)
            #print(str(entrada_e_peso[indexCamada][indexEntrada][0])+"*"+str(entrada_e_peso[indexCamada][indexEntrada][1]),
                  #"-",limiarDeAtivacao[indexEntrada],"=>",u)#se for o ultimo elemento dá \n
            pontencialDeAtv.append(u)

    potencialDeAtvGlobal = deepcopy(pontencialDeAtv) #potencial de atv global recebe todos potenciais de ativação da camada 1

    k = 0
    #print("\nPasso 3 g(u):")
    for indicePotencial,potencial in enumerate(pontencialDeAtv):
        if funcaoDeAtivacao[indicePotencial] == 2:
            k = logistica(potencial,beta)
        elif funcaoDeAtivacao[indicePotencial] == 1:
            k = tangenteHiperbolica(potencial,beta)
        saidas.append(k)
        #print("x"+str(indicePotencial+1)+" = g(u"+str(indicePotencial+1)+") =",k)

    if camadaAtual==numeroCamadas:#caso tenha chegado na ultima camada
        return saidas

    saidasGlobal = deepcopy(saidas)
    auxLimiarDeAtivacao = deepcopy(limiarDeAtivacao[quantidadePorCamada[camadaAtual-1]:])#desconsidera os limiares já processados
    auxFuncaoDeAtivacao = deepcopy(funcaoDeAtivacao[quantidadePorCamada[camadaAtual-1]:])#desconsidera o tipo das funcoes de ativacao já processadas
    auxentrada_e_peso = []

    #print("\nCamada "+str(camadaAtual+1)+"\n")
    for i in range(len(saidas)):
        aux = []
        for j in range(quantidadePorCamada[camadaAtual]):#Quantidade de neurônios da enesima - camada
            aux.append((saidas[i],pesosCamadas[j]))
        auxentrada_e_peso.append(aux)#pega o peso randomico e entrada de cada neuronio da n- camada interna
    saidas = []#reseta a lista de saidas
    pontencialDeAtv = []#reseta a lista de potetencial de ativacao
    camadaAtual+=1
    #print(camadaAtual,numeroCamadas)
    if camadaAtual<=numeroCamadas:
        return camadasMultiplas(auxentrada_e_peso,auxLimiarDeAtivacao,auxFuncaoDeAtivacao,numeroCamadas,camadaAtual,quantidadePorCamada[camadaAtual-2],pesosCamadas[j:])

def valoresPA(a1,an,n=20):
    r = (an -a1)/(n-1)
    valores = []
    for i in range(1,n+1):
        valores.append(a1 + (i-1)*r)
    return valores

if  __name__ == '__main__':
    simplesOuMultipla = int(input("Entre com 1-[Algoritmo de Camada Simples] ou 2-[Algoritmo de Múltiplas Camadas]\n->"))
    entrada = int(input("Digite 1-[Gerar Gráfico da Função TangenteHiperbolica] ou 2-[Gerar Gráfico da Função Logística] \n->"))
    dominio = [float(input("Valor Inicial do Dominio: ")),float(input("Valor Final do Dominio: "))]
    beta = float(input("Digite o valor de beta: "))
    _pontosDeDiscretizacao = int(input("Quantidade de pontos de discretização: "))
    numeroDeConfiguracoes = 5#numero de configurações adotada
    entrada_e_peso = []
    numeroCamadas = 0
    quantidadePorCamada = []#quantidade de neurônio por camada <-> Usado no algoritmo de Múltiplas Camadas
    entrada_e_peso_prod = []#produto da entrada com o peso
    valoresDeEntrada = valoresPA(dominio[0],dominio[1],_pontosDeDiscretizacao)

    vezes = []#guardará o resultado de cada vez que foi rodado o script
    informacoes = []#guarda os pesos e limiar randomico adotado

    fig, axs1 = plt.subplots(nrows=2, ncols=2,figsize=(13, 6),subplot_kw=dict(projection="3d"))
    tipoFuncao = ""
    if entrada == 1:
        tipoFuncao = "Tangente Hiperbólica"
    elif entrada == 2:
        tipoFuncao = "Logística"

    if simplesOuMultipla == 1:
        for i in range(numeroDeConfiguracoes):
            w1 = random()#gera o peso w1 randomico para cada configuracao
            w2 = random()#gera o peso w2 randomico para cada configuracao
            limiarDeAtivacao = [random()] #limiar de ativação randomico para cada configuracao
            informacoes.append([w1,w2,limiarDeAtivacao[0]])
            #print(w1,w2,limiarDeAtivacao)

            eixo_x = []#valores do eixo x
            eixo_y = []#valores do eixo y
            eixo_z = []#valores do eixo z

            valoresP = list(permutations(valoresDeEntrada,2)) + [(i,i) for i in valoresDeEntrada]

            for x1,x2 in valoresP:
                entrada_e_peso.append([[x1,w1]])
                entrada_e_peso.append([[x2,w2]])

                for linha in entrada_e_peso: #Faz o produto da entrada com o peso para cada neuronio
                    entrada_e_peso_prod.append(np.prod(linha,axis=1))

                entrada_e_peso = np.array(entrada_e_peso)
                entrada_e_peso_prod = np.array(entrada_e_peso_prod).transpose()

                resultado = camadaSimples(entrada_e_peso,entrada_e_peso_prod,limiarDeAtivacao,funcaoDeAtivacao = [entrada,entrada])[0]

                eixo_x.append(x1)
                eixo_y.append(x2)
                eixo_z.append(resultado)

                entrada_e_peso = []
                entrada_e_peso_prod = []
            vezes.append([eixo_x,eixo_y,eixo_z])#guarda o resultado para cada configuração
    elif simplesOuMultipla == 2:
        numeroCamadas = int(input("Quantidade de camadas que o neurônio possui:\n->"))
        for i in range(numeroCamadas):
                quantidadePorCamada.append(int(input("Quantidade de neurônios da camada "+str(i+1)+":\n->")))
        for i in range(numeroDeConfiguracoes):
            pesosCamadas = []#vetor que guarda o peso randomico dos neuronios de cada camada
            limiarDeAtivacao = [] #limiar de ativação randomico para cada configuracao
            funcaoDeAtivacao = [] #Funcao de ativação para cada neurônio

            eixo_x = []#valores do eixo x
            eixo_y = []#valores do eixo y
            eixo_z = []#valores do eixo z

            for i in range(int(sum(quantidadePorCamada))):#percorre em todos neurônios para atribuir o limiar para cada um
                limiarDeAtivacao.append(random())#Limiar de ativacao randomico para cada neuronio
                funcaoDeAtivacao.append(entrada)#Funcao de ativacao vai ser a mesma para todos

            numeroDePesos = sum([quantidadePorCamada[i]*quantidadePorCamada[i+1]for i in range(len(quantidadePorCamada)-1)])#numero total de pesos das camadas internas

            for i in range(int(2*quantidadePorCamada[0]+numeroDePesos)):#numero de pesos da primeira camada + numero de pesos das camadas internas
                pesosCamadas.append(random())#peso randomico gerado para cada neuronio

            informacoes.append((pesosCamadas,limiarDeAtivacao))

            valoresP = list(permutations(valoresDeEntrada,2)) + [(i,i) for i in valoresDeEntrada]

            for x1,x2 in valoresP:
                contadorAux = 0
                for i in range(2):#sempre sera duas entradas nas questoes pedidas
                    aux = []
                    if i == 0:
                        entrada = x1
                    else:
                        entrada = x2
                    for j in range(quantidadePorCamada[0]):#Quantidade de neurônios da primeira camada
                        aux.append((entrada,pesosCamadas[contadorAux]))

                    contadorAux+=1
                    entrada_e_peso.append(aux)

                resultado = camadasMultiplas(entrada_e_peso,limiarDeAtivacao,funcaoDeAtivacao,numeroCamadas,quantCamadaAnterior=2,pesosCamadas=pesosCamadas[contadorAux:])[0]#quantCamadaAnterior = 2 pois sempre será duas entradas nos problemas que foram solicitados graficos
                eixo_x.append(x1)
                eixo_y.append(x2)
                eixo_z.append(resultado)
            vezes.append([eixo_x,eixo_y,eixo_z])#guarda o resultado para cada configuração

    cont = 0
    for i in range(2):
        for j in range(2):
            if simplesOuMultipla == 1:
                axs1[i,j].set_title('Gráfico com w1 = '+str(round(informacoes[cont][0],2))+', w2 = '+
                                    str(round(informacoes[cont][1],2))+
                  ', limiar(θ) = '+str(round(informacoes[cont][2],2)))
            elif simplesOuMultipla == 2:
                axs1[i,j].set_title('Feedforward - Múltiplas camadas')

            axs1[i, j].plot(vezes[cont][0],vezes[cont][1],vezes[cont][2],label = tipoFuncao)
            axs1[i,j].set_xlabel("x1")
            axs1[i,j].set_ylabel("x2")
            axs1[i,j].set_zlabel("g(u)")
            axs1[i,j].legend()
            cont+=1

    if simplesOuMultipla == 2:
        for i in range(len(informacoes)):
            print()
            print("Configuração",i+1)
            print("Pesos Adotados:",informacoes[i][0])
            print("Limiares Adotados:",informacoes[i][1])

    #ax = fig.add_subplot(projection='3d')
    #ax.set_title('Gráfico com w1 = '+str(round(w1,2))+', w2 = '+str(round(w2,2))+', limiar(θ) = '+str(round(limiarDeAtivacao[0],2)))

    fig2, axs2 = plt.subplots(subplot_kw=dict(projection="3d"))
    if simplesOuMultipla == 1:
        axs2.set_title('Gráfico com w1 = '+str(round(informacoes[4][0],2))+', w2 = '+
                  str(round(informacoes[4][1],2))+
                  ', limiar(θ) = '+str(round(informacoes[4][2],2)))
    elif simplesOuMultipla == 2:
                axs2.set_title('Feedforward - Múltiplas camadas')

    axs2.plot(eixo_x,eixo_y,eixo_z,label = tipoFuncao)

    axs2.set_xlabel("x1")
    axs2.set_ylabel("x2")
    axs2.set_zlabel("g(u)")
    axs2.legend()

    plt.show()


#!/usr/bin/python3

import pytest
from web3 import Web3

@pytest.fixture(scope="module")
def popularity_indices():
    return 0x0505050505

@pytest.fixture(scope="module")
def buyer(accounts):
    return accounts[1]

def test_commission_one_piece(simulacra, buyer, popularity_indices):
    assert not simulacra.artSoldOut()
    assert simulacra.totalSupply() == 0
    price = simulacra.getCurrentPrice()
    tx = simulacra.commissionPieces(popularity_indices, 1, {'from': buyer, 'value': price})
    assert simulacra.balance() > 0
    assert simulacra.balanceOf(buyer) == 1
    assert simulacra.totalSupply() == 1

def test_commission_multiple_piece(simulacra, buyer, popularity_indices):
    expected_supply = simulacra.totalSupply()
    remaining = simulacra.remainingAtCurrentPrice()
    while remaining:
        assert not simulacra.artSoldOut()
        price = simulacra.getCurrentPrice()
        amount = min(remaining, 56)  # Approximate limit amount with test block gas limit
        tx = simulacra.commissionPieces(popularity_indices, amount, {'from': buyer, 'value': price * amount})
        assert simulacra.balance() > 0
        assert simulacra.balanceOf(buyer) == expected_supply + amount
        assert simulacra.totalSupply() == expected_supply + amount
        expected_supply = simulacra.totalSupply()
        remaining = simulacra.remainingAtCurrentPrice()

    assert simulacra.artSoldOut()
    assert not simulacra.artWasRevealed()
    assert not simulacra.isInRefundMode()


from matplotlib import pyplot as plt
from sklearn.cluster import KMeans
from pg_db import acc_db as acc
import numpy as np
import pandas as pd
'''
connection = acc.exec_con()
cabecalho = ['nest_id','treatment','r_time', 'a_x', 'a_y', 'a_z']
df = pd.read_sql_query("select a_x, a_y, a_z from data_vibration_1 where nest_id = 'N15YCC2017' and treatment = 'T02' order by r_time", connection)
population = []
for rows in df.itertuples():
    population.append([rows.a_y,rows.a_x])
X = np.array(population)
'''
population = pd.read_csv('c:/BASE1/NNTW/norma_cluster.csv')
X = np.array(population)
kmeans = KMeans(n_clusters = 10, #numero de clusters
init = 'k-means++', n_init = 10, #algoritmo que define a posição dos clusters de maneira mais assertiva
max_iter = 300) #numero máximo de iterações
pred_y = kmeans.fit_predict(X)
plt.scatter(X[:,1], X[:,0], c = pred_y) #posicionamento dos eixos x e y
plt.xlim(min(X[:,1]),max(X[:,1])) #range do eixo x
plt.ylim(min(X[:,0]),max(X[:,0])) #range do eixo y
plt.grid() #função que desenha a grade no nosso gráfico
plt.scatter(kmeans.cluster_centers_[:,1],kmeans.cluster_centers_[:,0], s = 70, c = 'red') #posição de cada centroide no gráfico

print("KMeans - Scikit-Learn")
print("Labels")
print(kmeans.labels_)
print("Cluster centers:")
print(kmeans.cluster_centers_)

plt.show()


from setuptools import setup
# from sphinx.setup_command import BuildDoc
from os import path
#cmdclass = {'build_sphinx': BuildDoc}

# https://pypi.org/classifiers/

name = 'list_session_inhibitors'
keywords = 'inhibitors'
version = '0.9.8'
this_directory = path.abspath(path.dirname(__file__))
with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
    long_description = f.read()

setup(
    name=name,
    keywords=keywords,
    version=version,
    author='Tim Richardson',
    author_email='tim@growthpath.com.au',
    description='command line utility to list session power inhibitors for Linux Gnome desktop users',
    long_description=long_description,
    long_description_content_type='text/markdown',
    packages=['list_session_inhibitors'],
    python_requires='>=3.6',
    install_requires=['pydbus','PyGObject>=3.40','click'],
    setup_requires=['pytest-runner', ],
    entry_points={"console_scripts": ["inhibitors=list_session_inhibitors.inhibitors:main"]},
    tests_require=["pytest", ],
    classifiers=[
        'Development Status :: 4 - Beta',
        'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
        'Programming Language :: Python :: 3.8',
        'Programming Language :: Python :: 3.9',
        'Topic :: Office/Business',
    ],
    url='https://github.com/timrichardson/gnome_inhibit_list',
    license='LGPLv3',

    #cmdclass=cmdclass,
    # these are optional and override conf.py settings
    # command_options={
    #     'build_sphinx': {
    #         'project': ('setup.py', name),
    #         'version': ('setup.py', version),
    #         'release': ('setup.py', version),
    #         'source_dir': ('setup.py', 'docs')}},

)


#!/usr/bin/python3
"""This module defines the State class."""
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class State(Base):
    """Represents a state mapped to the states table."""

    __tablename__ = 'states'

    id = Column(Integer, primary_key=True)
    name = Column(String(128), nullable=False)


# Recently, a colleague needed to know how much light a distribution of salt aerosol would scatter into two detectors, one at 60° and one at 90°. We modeled a lognormal distribution of NaCl particles based on laboratory measurements and then tried to figure out how much light we’d see at various angles.

import PyMieScatt as ps  # import PyMieScatt and abbreviate as ps
# import standard plotting library and abbreviate as plt
import matplotlib.pyplot as plt
import numpy as np  # import numpy and abbreviate as np
# import a single function for integration using trapezoidal rule
from scipy.integrate import trapz

m = 1.536  # refractive index of NaCl
wavelength = 405  # replace with the laser wavelength (nm)

dp_g = 85  # geometric mean diameter - replace with your own (nm)
# geometric standard deviation - replace with your own (unitless)
sigma_g = 1.5
N = 1e5  # total number of particles - replace with your own (cm^-3)

B = ps.Mie_Lognormal(m, wavelength, sigma_g, dp_g, N,
                     returnDistribution=True)  # Calculate optical properties

S = ps.SF_SD(m, wavelength, B[7], B[8])

fig1 = plt.figure(figsize=(10.08, 6.08))
ax1 = fig1.add_subplot(1, 1, 1)

ax1.plot(S[0], S[1], 'b', ls='dashdot', lw=1, label="Parallel Polarization")
ax1.plot(S[0], S[2], 'r', ls='dashed', lw=1,
         label="Perpendicular Polarization")
ax1.plot(S[0], S[3], 'k', lw=1, label="Unpolarized")

x_label = ["0", r"$\mathregular{\frac{\pi}{4}}$", r"$\mathregular{\frac{\pi}{2}}$",
           r"$\mathregular{\frac{3\pi}{4}}$", r"$\mathregular{\pi}$"]
x_tick = [0, np.pi / 4, np.pi / 2, 3 * np.pi / 4, np.pi]
ax1.set_xticks(x_tick)
ax1.set_xticklabels(x_label, fontsize=14)
ax1.tick_params(which='both', direction='in')
ax1.set_xlabel("Scattering Angle ϴ", fontsize=16)
ax1.set_ylabel(r"Intensity ($\mathregular{|S|^2}$)", fontsize=16, labelpad=10)
handles, labels = ax1.get_legend_handles_labels()
fig1.legend(handles, labels, fontsize=14, ncol=3, loc=8)

fig1.suptitle("Scattering Intensity Functions", fontsize=18)

plt.tight_layout(rect=[0.01, 0.05, 0.915, 0.95])

# Highlight certain angles and compute integral
sixty = [0.96 < x < 1.13 for x in S[0]]
ninety = [1.48 < x < 1.67 for x in S[0]]
ax1.fill_between(S[0], 0, S[3], where=sixty, color='g', alpha=0.15)
ax1.fill_between(S[0], 0, S[3], where=ninety, color='g', alpha=0.15)
ax1.set_yscale('log')

int_sixty = trapz(S[3][110:130], S[0][110:130])
int_ninety = trapz(S[3][169:191], S[0][169:191])

# Annotate plot with integral results
ax1.annotate("Integrated value = {i:1.3f}".format(i=int_sixty),
             xy=(np.pi / 3, S[3][120]), xycoords='data',
             xytext=(np.pi / 6, 0.8), textcoords='data',
             arrowprops=dict(arrowstyle="->",
                             connectionstyle="arc3"),
             )
ax1.annotate("Integrated value = {i:1.3f}".format(i=int_ninety),
             xy=(np.pi / 2, S[3][180]), xycoords='data',
             xytext=(2 * np.pi / 5, 2), textcoords='data',
             arrowprops=dict(arrowstyle="->",
                             connectionstyle="arc3"),
             )
plt.show()


from requests import Request, Session
from core.constant import CRYPTOKEY, CRYPTOURL, CRYPTOURL2

import requests
import json
import sys
import re

class CryptoService:

    url = CRYPTOURL
    api = CRYPTOKEY
    url2 = CRYPTOURL2

    def listar2(self, command):
        ret = ''
        try:
            lst = command.split(' ')
            dst = 'USD'

            if(len(lst) < 2 or len(lst) > 2):
                ret = 'Subcomando inválido'
                return ret

            rsp = requests.get(self.url2.format(lst[1].upper(), dst, self.api), timeout = 45)
            jrsp = json.loads(rsp.text)

            print(rsp.text)
            print(jrsp)

            ret += 'Papel: ' + lst[1].upper() + '\n'
            ret += 'Preço: ' + jrsp['DISPLAY']['PRICE'] + '\n'
            ret += 'Abertura: ' + jrsp['DISPLAY']['OPEN24HOUR'] + '\n'
            ret += 'Mínima: ' + jrsp['DISPLAY']['LOW24HOUR'] + '\n'
            ret += 'Máxima: ' + jrsp['DISPLAY']['HIGH24HOUR'] + '\n'
            ret += 'Variação: ' + jrsp['DISPLAY']['CHANGEPCT24HOUR'] + '%\n'
            ret += 'Volume: ' + jrsp['DISPLAY']['VOLUME24HOUR'] + ' (24h)\n'
            ret += 'Mercado: ' + jrsp['DISPLAY']['LASTMARKET'] + '\n'

        except:
            type, value, traceback = sys.exc_info()
            print('Error: {0} {1} {2}', type, value, traceback)
            ret = 'Falha ao buscar dados'

        return ret

    def listar(self, command):
        ret = ''
        try:
            lst = command.split(' ')
            dst = 'USD'

            if(len(lst) < 2 or len(lst) > 2):
                ret = 'Subcomando inválido'
                return ret

            rsp = requests.get(self.url.format(lst[1].upper(), dst, self.api), timeout = 45)

            ret += 'Papel: ' + lst[1].upper() + '\n'
            ret += self.stripChars(rsp.text)

            #jrsp = json.loads(rsp.text)
            #if jrsp['Response'] == 'Success':
            #    ret += 'Preço: ' +
            #    ret += 'Minima 30 dias: ' +
            #    ret += 'Máxima 30 dias: ' +
            #print(jrsp)

            #ret += 'Preço: ' + jrsp['DISPLAY']['USD']['PRICE'] + '\n'
            #ret += 'Abertura: ' + jrsp['DISPLAY']['USD']['OPENDAY'] + '\n'
            #ret += 'Máxima: ' + jrsp['DISPLAY']['USD']['HIGHDAY'] + '\n'
            #ret += 'Mínima: ' + jrsp['DISPLAY']['USD']['LOWDAY'] + '\n'
            #ret += 'Volume: ' + jrsp['DISPLAY']['USD']['TOTALVOLUME24H'] + '\n'

            #ret = rsp.text
            #ret = lst[1] + ': ' + self.stripChars(rsp.text)

        except:
            type, value, traceback = sys.exc_info()
            print('Error: {0} {1} {2}', type, value, traceback)
            ret = 'Falha ao buscar dados'

        return ret

    #def obterMinimaMaxima(self, jrsp, tipo):
    #    preco = ''
    #    minima = ''
    #    maxima = ''#
    #
    #    for i=0 to len(jrsp[Data]):
    #        preco = jrsp[Data][i][]

    def processarComando(self, command):

        ret = self.listar2(command)
        return ret

    def stripChars(self, data):
        p = self.striphtml(data)
        p = p.replace('\n', '')
        p = p.replace(':', ' ')
        p = p.replace('"', '')
        p = p.strip(' ')
        p = p.strip('/')
        p = p.strip('{')
        p = p.strip('}')

        return p

    def striphtml(self, data):
        pdata = '<td' + data
        p = re.compile(r'<.*?>')
        st = p.sub(' ', pdata)
        st = st.replace('  ', '')
        st = st.replace(' ', ' ')
        st = st.replace('\n', ' ')
        st = st.replace('  ', ' ')
        st = st.strip('/')
        st = st.replace('<td', '')
        return st


"""
This module contains the functions for clustering.
"""

import logging as log

import numpy as np
from numba import njit

@njit
def get_density(distances, dc):
    """
    Returns the density of each date calculated by the distances and the dc value.
    """
    dist_cz = np.zeros(distances.shape[0])

    for i in range(distances.shape[0]):
        for j in range(i+1, distances.shape[0]):
            if distances[i, j] <= dc:
                dist_cz[i] += 1
                dist_cz[j] += 1
    return dist_cz

@njit
def get_maphd_index(distances, density, dc):
    """
    Returns for every datapoint the nearest data point with a higher density.
    """
    next_node = np.full(distances.shape[0], -1)

    for i in range(distances.shape[0]):
        for j in range(distances.shape[0]):
            if density[i] < density[j]:
                if next_node[i] == -1:
                    next_node[i] = j
                else:
                    if distances[i, next_node[i]] > distances[i, j]:
                        next_node[i] = j
            elif density[i] == density[j] and i < j:
                if next_node[i] == -1:
                    next_node[i] = j
                elif distances[i, next_node[i]] > distances[i, j] and distances[i, j] <= dc:
                    next_node[i] = j
    return next_node

@njit
def get_maphd(distances, next_nodes):
    """
    Returns the distance to the nearest data point with a higher density.
    """
    maphd = np.zeros(distances.shape[0])
    for i in range(distances.shape[0]):
        if next_nodes[i] == -1:
            maphd[i] = 1
        else:
            maphd[i] = distances[i, next_nodes[i]]

    return maphd

@njit
def clustering(next_nodes, cz):
    """
    Returns a list of the cluster center indices for every data point.
    """
    result = np.full(next_nodes.shape[0], -1)
    i = -1
    temp = []

    for cz_element in cz:
        result[cz_element] = cz_element

    for todo in result:
        i += 1
        if todo == -1:
            k = i
            while result[k] == -1:
                temp.append(k)
                k = next_nodes[k]
            cz_element = result[k]
            while len(temp) != 0:
                result[temp.pop()] = cz_element

    return result

def calculate_centers(df):
    """
    Returns the cluster centers.
    """
    cz = []
    while len(df[1]) != 0:
        if df[0, 0] >= df[0].max():
            cz.append(int(df[2, 0]))
            df = np.delete(arr=df, obj=0, axis=1)
        elif df[0, 0] >= df[0].mean():
            cz.append(int(df[2, 0]))
            df = np.delete(arr=df, obj=0, axis=1)
        else:
            break
    return cz

def get_centers(store):
    """
    Returns the cluster centers as a list.
    """
    log.info('Test dc: {store.dc}')
    log.info('...')

    # Calculate the density of the dates dependant on dc
    store.df['density'] = get_density(store.distances, store.dc)

    # maphd - Minimaler Abstand zu einem Punkt höherer Dichte (Delta im Paper)
    store.df['next_node'] = get_maphd_index(
        store.distances,
        store.df['density'].to_numpy(),
        store.dc
    )

    store.df['maphd'] = get_maphd(
        store.distances,
        store.df['next_node'].to_numpy()
    )

    temp_df = store.df.loc[:, ['density', 'maphd']].sort_values(
        'maphd', axis=0, ascending=False
    )
    temp_df['index'] = temp_df.index

    store.centers = np.array(calculate_centers(
        temp_df.to_numpy().T
    ))

    store.df['cluster_center'] = clustering(
        store.df['next_node'].to_numpy(),
        store.centers
    )

    return store.centers


import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn import Sequential, Linear, LeakyReLU, Dropout, LayerNorm, Identity, Sigmoid
from torch_geometric.nn import GCNConv, global_add_pool, Set2Set, GlobalAttention
from typing import Optional
import torch
from torch import Tensor
from torch_scatter import scatter_mean
from torch_geometric.nn.inits import zeros, ones
import utils

def zero_init_weights(m):
    if isinstance(m, nn.Linear):
        torch.nn.init.zeros_(m.weight)
        m.bias.data.fill_(0)

def gate_linear_init_weights(m):
    if isinstance(m, nn.Linear):
        torch.nn.init.zeros_(m.weight)
        m.bias.data.fill_(1)

class ResidualGraphConv(torch.nn.Module):
	def __init__(self, in_dim, heads):
		super().__init__()
		self.norm_conv = LayerNorm(in_dim)
		self.conv = GCNConv(in_dim, in_dim)

	def forward(self, x, edge_index):
		x = F.relu(x + self.conv(self.norm_conv(x), edge_index)) # not using edge attr
		return x

class ResidualSelfAttention(torch.nn.Module):
	def __init__(self, hidden_dim, heads, edge_dim, dropout=0., geometric=False, update_p=False, d_space=3, uniform_attention=False):
		super().__init__()
		self.norm_conv = LayerNorm(hidden_dim)
		self.edge_dim = edge_dim
		self.geometric = geometric
		self.d_space = d_space
		if edge_dim != None:
			self.norm_edge = LayerNorm(edge_dim)
		self.uniform_attention = uniform_attention
		self.conv = CovariantGraphAttention(hidden_dim, heads=heads, edge_dim=edge_dim, dropout=dropout, geometric=geometric, update_p=update_p, d_space=d_space, uniform_attention=self.uniform_attention)

	def forward(self, x, p, edge_index, edge_attr):
		x_normed = self.norm_conv(x)
		if self.geometric:
			in_feat = torch.cat([p, x_normed], dim=-1)
		else:
			in_feat = x_normed
		if self.edge_dim != None:
			m_x, p = self.conv(in_feat, edge_index, self.norm_edge(edge_attr))
			x = x + m_x # p = p + m_p, already
		else:
			m_x, p = self.conv(in_feat, edge_index)
			x = x + m_x # p = p + m_p, already
		# if self.geometric:
		# 	print('self_attn:\n', p) # __debug__
		return x, p

class ResidualCrossAttentionBlock(torch.nn.Module):
	def __init__(self, hidden_dim, heads, edge_dim, dropout=0., geometric=False, update_p=False, d_space=3, uniform_attention=False):
		super().__init__()
		self.norm_conv_source = LayerNorm(hidden_dim)
		self.norm_conv_out = LayerNorm(hidden_dim)
		self.geometric = geometric
		self.edge_dim = edge_dim
		if edge_dim != None:
			self.norm_edge = LayerNorm(edge_dim)
		self.uniform_attention = uniform_attention
		self.conv = CovariantGraphAttention(hidden_dim, heads=heads, edge_dim=edge_dim, dropout=dropout, geometric=geometric, update_p=update_p, d_space=d_space, uniform_attention=self.uniform_attention)

	def get_alpha(self):
		return self.conv._alpha

	def get_phi_message_norm(self):
		return self.conv._phi_message_norm

	def forward(self, x_source, p_source, x_out, p_out, cross_edge_index, cross_edge_attr):
		x_normed_source = self.norm_conv_source(x_source)
		x_normed_out = self.norm_conv_out(x_out)
		if self.geometric:
			in_feat = (torch.cat([p_source, x_normed_source], dim=-1), torch.cat([p_out, x_normed_out], dim=-1))
		else:
			in_feat = (x_normed_source, x_normed_out)
		if self.edge_dim != None:
			m_x_out, p_out = self.conv(in_feat, cross_edge_index, self.norm_edge(cross_edge_attr)) # not using edge attr
			x_out = x_out + m_x_out
		else:
			m_x_out, p_out = self.conv(in_feat, cross_edge_index) # not using edge attr
			x_out = x_out + m_x_out
		# if self.geometric:
		# 	print('cross_attn:\n', p_out) # __debug__
		return x_out, p_out

class ResidualFeedForward(torch.nn.Module):
	def __init__(self, hidden_dim, dropout=0.):
		super().__init__()
		self.norm_fc = LayerNorm(hidden_dim)
		self.fc = Sequential(Dropout(dropout), Linear(hidden_dim, hidden_dim), LeakyReLU(), Dropout(dropout), Linear(hidden_dim, hidden_dim))

	def forward(self, x):
		return x + self.fc(self.norm_fc(x))

class TransformerEncoderBlock(torch.nn.Module):
	def __init__(self, hidden_dim, heads, edge_dim, dropout=0., geometric=False, update_p=False, d_space=3, uniform_attention=False):
		super().__init__()
		self.self_attn = ResidualSelfAttention(hidden_dim, heads, edge_dim, dropout=dropout, geometric=geometric, update_p=update_p, d_space=d_space, uniform_attention=uniform_attention)
		self.feedforward = ResidualFeedForward(hidden_dim, dropout=dropout)
		self.edge_dim = edge_dim
		self.geometric = geometric
		self.d_space = d_space
		if self.edge_dim != None:
			self.edge_nn = Sequential(Dropout(dropout), LayerNorm(edge_dim + 2 * hidden_dim), Linear(edge_dim + 2 * hidden_dim, edge_dim), LeakyReLU(), Dropout(dropout), Linear(edge_dim, edge_dim))

	def forward(self, x, p, edge_index, edge_attr):
		x, p = self.self_attn(x, p, edge_index, edge_attr)
		x = self.feedforward(x)
		if self.edge_dim != None:
			x_i, x_j = x[edge_index[0]], x[edge_index[1]]
			edge_attr = edge_attr + self.edge_nn(torch.cat([edge_attr, x_i, x_j], dim=-1))
		return x, p, edge_attr

class TransformerDecoderBlock(torch.nn.Module):
	def __init__(self, hidden_dim, edge_dim, heads, dropout=0., geometric=False, update_p=False, d_space=3, uniform_attention=False):
		super().__init__()
		self.geometric = geometric
		self.self_attn = ResidualSelfAttention(hidden_dim, heads, edge_dim=None, dropout=dropout, geometric=geometric, update_p=update_p, d_space=d_space, uniform_attention=uniform_attention)
		self.cross_attn = ResidualCrossAttentionBlock(hidden_dim, heads, edge_dim, dropout=dropout, geometric=geometric, update_p=update_p, d_space=d_space, uniform_attention=uniform_attention)
		self.feedforward = ResidualFeedForward(hidden_dim, dropout=dropout)
		self.edge_dim = edge_dim
		if self.edge_dim != None:
			# self.self_edge_nn = Sequential(Dropout(dropout), LayerNorm(edge_dim + 2 * hidden_dim), Linear(edge_dim + 2 * hidden_dim, edge_dim), LeakyReLU(), Dropout(dropout), Linear(edge_dim, edge_dim))
			self.cross_edge_nn = Sequential(Dropout(dropout), LayerNorm(edge_dim + hidden_dim + hidden_dim), Linear(edge_dim + hidden_dim + hidden_dim, edge_dim), LeakyReLU(), Dropout(dropout), Linear(edge_dim, edge_dim))
			self.cross_edge_gate = Sequential(Dropout(dropout), Linear(edge_dim + hidden_dim + hidden_dim, hidden_dim), Sigmoid())
			self.cross_edge_gate.apply(gate_linear_init_weights) # w = 0, b = 1
		self.get_alpha = self.cross_attn.get_alpha
		self.get_phi_message_norm = self.cross_attn.get_phi_message_norm

	def forward(self, x_source, p_source, x_out, p_out, self_edge_index, self_edge_attr, cross_edge_index, cross_edge_attr):
		x_out, p_out = self.self_attn(x_out, p_out, self_edge_index, self_edge_attr)
		x_out, p_out = self.cross_attn(x_source, p_source, x_out, p_out, cross_edge_index, cross_edge_attr)
		x_out = self.feedforward(x_out)
		if self.edge_dim != None:
			x_i, x_j = x_source[cross_edge_index[0]], x_out[cross_edge_index[1]]
			pair_and_edge = torch.cat([cross_edge_attr, x_i, x_j], dim=-1)
			g = self.cross_edge_gate(pair_and_edge)
			cross_edge_attr = cross_edge_attr + g * self.cross_edge_nn(pair_and_edge)
			# x_i, x_j = x_out[self_edge_index[0]], x_out[self_edge_index[1]]
			# self_edge_attr = self_edge_attr + self.self_edge_nn(torch.cat([self_edge_attr, x_i, x_j], dim=-1))
		return x_out, p_out, cross_edge_attr

class GraphMLP(torch.nn.Module):
	def __init__(self, in_dim, hidden_dim, out_dim, dropout, normalize_input):
		super().__init__()
		if normalize_input:
			self.norm_input = LayerNorm(in_dim)
		else:
			self.norm_input = torch.nn.Identity(in_dim)
		self.linear1 = Linear(in_dim, hidden_dim)
		self.act1 = LeakyReLU()
		self.norm2 = LayerNorm(hidden_dim)
		self.dropout2 = Dropout(dropout)
		self.linear2 = Linear(hidden_dim, out_dim)
	def forward(self, x):
		x = self.linear1(x)
		x = self.act1(x)
		x = self.norm2(x)
		x = self.dropout2(x)
		x = self.linear2(x)
		return x

class TransformerEncoder(torch.nn.Module):
	def __init__(self, in_dim, hidden_dim, edge_dim=None, num_convs=6, heads=8, dropout=0., recycle=0, geometric=False, update_p=False, d_space=3, uniform_attention=False):
		super().__init__()
		self.num_convs = num_convs
		self.heads = heads
		self.recycle = recycle
		self.geometric = geometric
		self.uniform_attention = uniform_attention
		self.input_embedding = GraphMLP(in_dim, hidden_dim, hidden_dim, dropout, normalize_input=False)
		self.edge_dim = edge_dim
		self.d_space = d_space
		if edge_dim != None:
			self.edge_embedding = Sequential(Dropout(dropout), Linear(edge_dim, hidden_dim), LeakyReLU(), Dropout(dropout), Linear(hidden_dim, hidden_dim))
			edge_dim = hidden_dim
		self.encoder_blocks = nn.ModuleList([TransformerEncoderBlock(hidden_dim=hidden_dim, heads=heads, edge_dim=edge_dim, dropout=dropout, geometric=geometric, update_p=update_p, d_space=d_space, uniform_attention=uniform_attention) for i in range(self.num_convs)])

	def forward(self, x, edge_index, edge_attr, p=None):
		if self.geometric:
			assert p != None and p.shape[-1] == self.d_space, 'p should be a (-1, d_space) tensor'
		x = self.input_embedding(x)
		if self.edge_dim != None:
			edge_attr = self.edge_embedding(edge_attr)
		for _ in range(self.recycle + 1):
			for encoder_block in self.encoder_blocks:
				x, p, edge_attr = encoder_block(x, p, edge_index, edge_attr)
		if self.edge_dim:
			return x, p, edge_attr
		return x, p

class TransformerDecoder(torch.nn.Module):
	def __init__(self, in_dim, hidden_dim, edge_dim=None, num_convs=6, heads=8, dropout=0., geometric=False, update_p=False, d_space=3, uniform_attention=False):
		super().__init__()
		self.num_convs = num_convs
		self.output_embedding = GraphMLP(in_dim, hidden_dim, hidden_dim, dropout, normalize_input=True)
		self.edge_dim = edge_dim
		self.geometric = geometric
		self.update_p = update_p
		self.d_space = d_space
		self.uniform_attention = uniform_attention
		if edge_dim != None:
			self.edge_embedding = Sequential(Dropout(dropout), Linear(edge_dim, hidden_dim), LeakyReLU(), Dropout(dropout), Linear(hidden_dim, hidden_dim))
			edge_dim = hidden_dim
		self.decoder_blocks = nn.ModuleList([TransformerDecoderBlock(hidden_dim=hidden_dim, edge_dim=edge_dim, heads=heads, dropout=dropout, geometric=geometric, update_p=update_p, d_space=d_space, uniform_attention=uniform_attention) for i in range(self.num_convs)])

	def get_alpha(self):
		alphas = [block.get_alpha() for block in self.decoder_blocks]
		alpha = torch.stack(alphas, dim=1)
		return alpha # (|E|, L, H)

	def get_phi_message_norm(self):
		phi_message_norms = [block.get_phi_message_norm() for block in self.decoder_blocks]
		return torch.cat(phi_message_norms)

	def forward(self, x_source, x_out, self_edge_index, self_edge_attr, cross_edge_index, cross_edge_attr, p_source=None, p_out=None):
		self.y_intermediates = []
		if self.geometric:
			assert p_source != None and p_source.shape[-1] == self.d_space, 'p_source should be a (-1, d_space) tensor'
			assert p_out != None and p_out.shape[-1] == self.d_space, 'p_out should be a (-1, d_space) tensor'
		x_out = self.output_embedding(x_out)
		if self.edge_dim != None:
			cross_edge_attr = self.edge_embedding(cross_edge_attr)
		for decoder_block in self.decoder_blocks:
			# if self.geometric:
			# 	p_out = p_out.detach() # stop grad
			x_out, p_out, cross_edge_attr = decoder_block(x_source, p_source, x_out, p_out, self_edge_index, self_edge_attr, cross_edge_index, cross_edge_attr)
			# record intermediate predictions
			if self.geometric:
				y_pred = utils.format_prediction(x_out[:, :2], p_out)
				self.y_intermediates.append(y_pred) #(B*N, 5)
		if self.edge_dim:
			return x_out, p_out, cross_edge_attr
		return x_out, p_out

#################### Equivariant Graph Attention ####################

import math
from typing import Union, Tuple, Optional
from torch_geometric.typing import PairTensor, Adj, OptTensor

import torch
from torch import Tensor
import torch.nn.functional as F
from torch.nn import Linear
from torch_geometric.nn.conv import MessagePassing
from torch_geometric.utils import softmax

class CovariantGraphAttention(MessagePassing):
	def __init__(self, hidden_dim: int,
				 heads: int = 1, gate: bool = True,
				 dropout: float = 0., edge_dim: Optional[int] = None,
				 bias: bool = True, geometric=False, d_space=3, update_p=False, uniform_attention=False, **kwargs):
		kwargs.setdefault('aggr', 'add')
		super().__init__(node_dim=0, **kwargs)

		self.hidden_dim = hidden_dim
		self.heads = heads
		self.gate = gate
		self.dropout = dropout
		self.edge_dim = edge_dim
		self.geometric = geometric
		self.d_space = d_space
		self.update_p = update_p
		self._alpha = None
		self._phi_message_norm = None
		self.pi = 3.1415926
		self.uniform_attention = uniform_attention

		if self.geometric:
			self.geometric_encoder = Sequential(Linear(d_space, hidden_dim), LeakyReLU(), Dropout(dropout), Linear(hidden_dim, hidden_dim))
			self.geometric_decoder = Sequential(Linear(hidden_dim, hidden_dim), LeakyReLU(), Dropout(dropout), Linear(hidden_dim, d_space)) # consider tanh to keep norm of m_p[:, 1:] close to 1?

		self.lin_query = Linear(hidden_dim, hidden_dim, bias=False)
		self.lin_key = Linear(hidden_dim, hidden_dim, bias=False)
		self.lin_value = Linear(hidden_dim, hidden_dim, bias=False)

		if edge_dim is not None:
			self.lin_edge = Sequential(LayerNorm(edge_dim), Linear(edge_dim, heads, bias=False))
		else:
			self.lin_edge = self.register_parameter('lin_edge', None)
		if self.gate:
			self.gate_nn = Sequential(Dropout(dropout), Linear(2 * hidden_dim, hidden_dim), Sigmoid())
			if self.geometric:
				self.gate_nn_space = Sequential(Dropout(dropout), Linear(2 * hidden_dim, d_space), Sigmoid())

		self.reset_parameters()

	def reset_parameters(self):
		self.lin_key.reset_parameters()
		self.lin_query.reset_parameters()
		self.lin_value.reset_parameters()
		if self.edge_dim:
			self.lin_edge.reset_parameters()
		if self.geometric:
			self.geometric_decoder[-1].apply(zero_init_weights) # updates to 4-vectors are initialized to identity
		if self.gate:
			self.gate_nn.apply(gate_linear_init_weights) # w = 0, b = 1
			if self.geometric:
				self.gate_nn_space.apply(gate_linear_init_weights) # w = 0, b = 1

	def forward(self, x: Union[Tensor, PairTensor], edge_index: Adj,
				edge_attr: OptTensor = None):

		if isinstance(x, Tensor):
			in_feat: PairTensor = (x, x)
		else:
			in_feat = x
		if self.geometric:
			assert in_feat[1].shape[1] == in_feat[0].shape[1] == self.hidden_dim + self.d_space, 'Geometric mode requires x to be (N, d_space + hidden_dim, D)'

		# propagate_type: (x: PairTensor, edge_attr: OptTensor)
		m = self.propagate(edge_index, x=in_feat, edge_attr=edge_attr, size=None) # aggreagated messgaes
		m = m.contiguous().view(-1, self.hidden_dim) # (|E|, D)
		if self.geometric:
			x = in_feat[1][:, self.d_space:] # initial target feat
			p = in_feat[1][:, :self.d_space] # initial target feat
			m_x = m
			m_p = self.geometric_decoder(m)
		else:
			x = in_feat[1] # initial target feat
			p = None
			m_x = m
			m_p = None

		if self.gate:
			m_x = self.gate_nn(torch.cat([x, m_x], dim=-1)) * m_x
			if self.geometric:
				m_p = self.gate_nn_space(torch.cat([x, m_x], dim=-1)) * m_p

		if self.geometric and self.update_p:
			# bias the update towards identity
			m_p = self.normalize_phi_vec(m_p + torch.FloatTensor([0, 1, 0]).view(-1, 3).to(m_p.device), store_norm=True) # m_p = [deta, vec(dphi)]
			eta = p[:, 0] + m_p[:, 0]
			phi = self.rotate(p[:, 1:], m_p[:, 1:], inverse=False)
			p = torch.cat([eta.view(-1, 1), phi], dim=-1)
			# normalize again to prevent accumulation of numerical error
			p = self.normalize_phi_vec(p)
		return m_x, p

	def normalize_phi_vec(self, p, eps=1e-8, store_norm=False):
		phi_vec = p[:, 1:]
		phi_message_norm = phi_vec.norm(dim=-1, keepdim=True)
		if store_norm:
			self._phi_message_norm = phi_message_norm.view(-1)
		phi_vec = phi_vec / (phi_message_norm + eps)
		return torch.cat([p[:, 0].view(-1, 1), phi_vec], dim=-1)

	def to_angle(self, phi):
		# return phi in [-pi, pi]
		return (phi + self.pi).remainder(2*self.pi) - self.pi

	def rotation_from_vec(self, v):
		"""
		v = [c, s] # (B, 2)
		R = [[c, -s]
			 [s, c]]
		"""
		c = v[..., 0] # (B, )
		s = v[..., 1] # (B, )
		r = torch.stack([c, -s, s, c], dim=-1) # (B, 4)
		r = r.reshape(-1, 2, 2) # (B, 2, 2)
		return r

	def rotate(self, phi2, phi1, inverse=False):
		# phi : (B, 2)
		r = self.rotation_from_vec(phi1) # (B, 2, 2)
		if inverse:
			r = torch.transpose(r, -1, -2) # transpose to get the inverse (B, 2, 2)
		phi21 = torch.einsum('...ij, ...j', r, phi2) # rotate phi2 by -phi1
		return phi21

	def boost(self, p2, p1):
		# boost p2 into p1's frame
		# p = [eta, cos(phi), sin(phi)], (cos(phi), sin(phi)) is a unit vector representing the phi-angle
		eta21 = p2[..., 0] - p1[..., 0]
		phi1, phi2 = p1[..., 1:], p2[..., 1:]
		phi21 = self.rotate(phi2, phi1, inverse=True)
		p21 = torch.cat([eta21.view(-1, 1), phi21], dim=-1)
		return p21

	def message(self, x_i: Tensor, x_j: Tensor, edge_attr: OptTensor,
				index: Tensor, ptr: OptTensor,
				size_i: Optional[int]) -> Tensor:

		if self.geometric:
			p_i = x_i[:, :self.d_space] # (|E|, d_space)
			p_j = x_j[:, :self.d_space] # (|E|, d_space)
			x_i = x_i[:, self.d_space:] # (|E|, d_node)
			x_j = x_j[:, self.d_space:] # (|E|, d_node)
		query = self.lin_query(x_i).view(-1, self.heads, self.hidden_dim // self.heads)
		if self.geometric:
			# boost into i's frame
			relative_p = self.boost(p_j, p_i)
			relative_p = self.geometric_encoder(relative_p)
			key = self.lin_key(x_j + relative_p).view(-1, self.heads, self.hidden_dim // self.heads)
			value = self.lin_value(x_j + relative_p).view(-1, self.heads, self.hidden_dim // self.heads)
		else:
			key = self.lin_key(x_j).view(-1, self.heads, self.hidden_dim // self.heads)
			value = self.lin_value(x_j).view(-1, self.heads, self.hidden_dim // self.heads)

		edge_bias = 0
		if self.lin_edge is not None:
			assert edge_attr is not None
			edge_bias = self.lin_edge(edge_attr).view(-1, self.heads) # (|E|, H)
			# key = key + edge_attr
			# value = value + edge_attr
		if not self.uniform_attention:
			alpha = (query * key).sum(dim=-1) / math.sqrt(self.hidden_dim // self.heads) + edge_bias
		else:
			alpha = torch.zeros(query.shape[0], query.shape[1]).to(query.device)
		alpha = softmax(alpha, index, ptr, size_i)
		self._alpha = alpha

		m = value * alpha.view(-1, self.heads, 1) # invariant messages (|E|, H, D // H)
		return m

	def __repr__(self):
		return '{}({}, {}, heads={})'.format(self.__class__.__name__,
											 self.hidden_dim,
											 self.hidden_dim, self.heads)


import re
from typing import List, Optional, Tuple

import numpy as np

from hwinarion.dispatcher import ActionResult, ActProcessResult, BaseAction
from hwinarion.screen.pyautogui_wrapper import InterruptibleScreenInteractor

class MouseAction(BaseAction):
    def __init__(self):
        super().__init__("mouse")
        self.screen_interactor = InterruptibleScreenInteractor()
        self.screen_interactor.start()
        self.speed_mapping = {
            "very slow": InterruptibleScreenInteractor.SPEED_VERY_SLOW,
            "slow": InterruptibleScreenInteractor.SPEED_SLOW,
            None: InterruptibleScreenInteractor.SPEED_NORMAL,
            "fast": InterruptibleScreenInteractor.SPEED_FAST,
            "very fast": InterruptibleScreenInteractor.SPEED_VERY_FAST,
        }

    @property
    def recognized_words(self) -> List[str]:
        return [
            "move",
            "mouse",
            "left",
            "right",
            "up",
            "down",
            "very",
            "fast",
            "slow",
            "stop",
            "double",
            "triple",
            "middle",
            "click",
        ]  # pragma: no cover

    def parse_text(self, text: str) -> Optional[Tuple]:
        move_parse = re.fullmatch(
            r"move\s+mouse\s+(?P<direction>left|right|up|down)(\s+(?P<speed>(?:very\s+)?(?:fast|slow)))?",
            text,
            flags=re.IGNORECASE,
        )
        if move_parse:
            speed = move_parse["speed"].lower() if move_parse["speed"] else None
            return "move", move_parse["direction"].lower(), speed

        if re.fullmatch(r"stop\s+mouse", text, flags=re.IGNORECASE):
            return ("stop",)

        click_parse = re.fullmatch(
            r"(?P<n_clicks>single|double|triple)?\s*(?:(?P<button>left|right|middle)[- ])?mouse\s*click",
            text,
            flags=re.IGNORECASE,
        )
        if click_parse:
            button = click_parse["button"].lower() if click_parse["button"] else "left"
            if click_parse["n_clicks"] in (None, "single"):
                n_clicks = 1
            elif click_parse["n_clicks"] == "double":
                n_clicks = 2
            elif click_parse["n_clicks"] == "triple":
                n_clicks = 3
            else:
                raise ValueError(f"Unrecognized number of clicks: {click_parse['n_clicks']}")  # pragma: no cover
            return "click", button, n_clicks

        return None

    def act(self, text: str, *, get_recording_data: bool = False) -> ActionResult:
        if not self.enabled:
            return ActionResult(ActProcessResult.TEXT_NOT_PROCESSED)

        recording_data = {}

        parsed_text = self.parse_text(text)
        if parsed_text:
            action, *parameters = parsed_text
            recording_data["action"] = action
            recording_data["parameters"] = parameters
            if get_recording_data:
                recording_data["mouse_position"] = tuple(self.screen_interactor.get_mouse_position())
                recording_data["screen"] = np.asarray(self.screen_interactor.get_screenshot().tobytes())

            if action == "stop":
                self.screen_interactor.stop_moving()
                return ActionResult(ActProcessResult.TEXT_PROCESSED, recording_data)

            if action == "move":
                direction, speed = parameters
                speed = self.speed_mapping[speed]
                recording_data["speed"] = speed
                if direction == "left":
                    move_function = self.screen_interactor.move_left
                elif direction == "right":
                    move_function = self.screen_interactor.move_right
                elif direction == "down":
                    move_function = self.screen_interactor.move_down
                elif direction == "up":
                    move_function = self.screen_interactor.move_up
                else:
                    raise KeyError(f"Unrecognized direction: {direction}")  # pragma: no cover

                move_function(speed)
                return ActionResult(ActProcessResult.TEXT_PROCESSED, recording_data)

            if action == "click":
                button, n_clicks = parameters
                self.screen_interactor.click(button, n_clicks)
                return ActionResult(ActProcessResult.TEXT_PROCESSED, recording_data)

        return ActionResult(ActProcessResult.TEXT_NOT_PROCESSED)


# Authors: Chris Melville and Jake Martens
# Revised by Chris Melville

'''
    books.py
    Chris Melville & Jake Martens, September/October 2021

    For use in the "books" assignment at the beginning of Carleton's
    CS 257 Software Design class, Fall 2021.
'''

import booksdatasource
import argparse

'''
        All three of these functions use booksdatasource.py to create a list of books
        or authors given parameters from the command line and then print the results
'''
def print_matching_titles(title_to_check, database, sort_flag):
    if sort_flag:
        list_of_books = database.books(title_to_check, 'year')
    else:
        list_of_books = database.books(title_to_check)
    for book in list_of_books:
        print(book)

def print_matching_authors(author_to_check, database):
    list_of_authors = database.authors(author_to_check)
    for author in list_of_authors:
        print(author)

def print_books_between_years(start_year, end_year, database):
    list_of_books_between_years = database.books_between_years(start_year, end_year)
    for book in list_of_books_between_years:
        print(book)

'''
        Parses the command line to see which flags were raised, and then calls the
        print methods at the top of books.py to print the appropriate data given
        the parameters the user passed in
'''

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('filename', type=str, help='The csv file to search.')
    parser.add_argument('-t','--title',const='', type = str, nargs = '?',help = 'Title of a book')
    parser.add_argument('-y','--year', action='store_true', help = 'Use with --title to sort by publication year')
    parser.add_argument('-a','--author', const='', type = str, nargs = '?', help = 'Author of a book')
    parser.add_argument('-d','--date',type = str, nargs='*', help = "Years between which books were published, e.g. 1850 1967. Leave the second argument empty to include all years after the first date, or leave both blank for all books.")

    args = parser.parse_args()
    database = booksdatasource.BooksDataSource(args.filename)

    if args.author == None and args.date == None:
        print_matching_titles(args.title, database, args.year)

    elif args.title == None and args.author != None and args.date == None:
        print_matching_authors(args.author, database)

    elif args.title == None and args.author == None and args.date != None:
        if len(args.date) == 0:
            print_books_between_years(None,None,database)
        elif len(args.date) == 1:
            print_books_between_years(args.date[0], None, database)
        else:
            print_books_between_years(args.date[0], args.date[1], database)

    else:
        parser.print_help()

main()


# This file will hold the request framework
import requests
from requests.auth import HTTPBasicAuth

class Get_Frame:
    def __init__(self, url):
        self.url = url
        #self.token = token

    def __call__(self, url, token, params=''):
        print(url)
        print(token)
        headers = {"Accept": "application/json"}

        # Note API keys could be better documented in the UI, no date created or created by what user
        auth = HTTPBasicAuth(token, '')  # No password

        # weak check on params but remains flexible
        if params != '':
            response = requests.request("GET", url, headers=headers, auth=auth, params=params)

        else:
            response = requests.request("GET", url, headers=headers, auth=auth)

        #print(response.text)
        return response.json()


# -*- coding: utf-8 -*-
# @Time    : 2020/11/11 22:50
# @Author  : longrong.lang
# @FileName: conftest.py
# @Software: PyCharm
# @Cnblogs ：https://www.cnblogs.com/longronglang
import pytest

@pytest.fixture(scope='function')
def addcart(login):
    print("从详情页登录，将商品加入购物车")
    price="2099元"
    yield price
    print('添加购物车成功，累计计算中')


from adapters import inputs, outputs
from core import errors
from core.request import request_service
from core import request as core_request

class ServerInstance:
    ServerAction = inputs.ServerAction
    ServerStatus = outputs.ServerStatus

    def __init__(self, server):
        self.server = server

    def action(self, act: str):
        """
        :raises: Error
        """
        server = self.server
        params = inputs.ServerActionInput(
            instance_id=server.instance_id, instance_name=server.instance_name, action=act)

        try:
            r = request_service(server.service, method='server_action', params=params)
        except errors.APIException as exc:
            raise exc

    def status(self):
        """
        :raises: Error
        """
        try:
            status_code, status_text = core_request.server_status_code(server=self.server)
        except errors.APIException as exc:
            raise exc

        return status_code, status_text


from django.core.management.base import BaseCommand, CommandError

from lemonaid.serializers import PoolLoanSerializer
from lemonaid.models import UserProfile, PoolLoan, Pool

class Command(BaseCommand):
    help = 'Distributes the pool to the people'

    def handle(self, *args, **options):
        if UserProfile.objects.all().count() == 0:
            raise CommandError('UserProfiles does not exist')

        pools = Pool.objects.all()

        to_distribute = []
        for pool in pools:
            to_distribute = PoolLoan.objects.filter(interest=pool.interest_rate)
            distribute_amt = pool.amount / to_distribute.count()
            # for loan in to_distribute:
            #     to_distribute.profile

        serializer = PoolLoanSerializer(to_distribute, many=True)

        self.stdout.write(self.style.SUCCESS('to_distribute pool_loans = {}'.format(serializer.data)))