# -*- coding: utf-8 -*-
"""
Created on Sun Nov 29 17:05:07 2020

@author: Ganyu Wang

define style and content loss extractor here

"""
import numpy as np
import os
import PIL
import PIL.Image
import tensorflow as tf

from tensorflow import keras

from tensorflow.keras.layers import Dense, Dropout, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Conv2DTranspose
from tensorflow.keras.datasets import cifar10
from tensorflow.keras import layers
from tensorflow.keras.preprocessing.image import ImageDataGenerator

from Model import Transform_model
from Utility import load_image

#

"""
The way to use extractor is
input a image,
the extractor will outputs the outputs, of that layer.

Calling extractor will return embedding dictiona
{'content': content_dict,
 'style'  : style_dict}

content_dict = {content_name:value
                        for content_name, value
                        in zip(self.content_layers, content_outputs)}

style_dict = {style_name:value
              for style_name, value
              in zip(self.style_layers, style_outputs)}

the image input is a tf tensor, the shape is [1, width, height, 3]

style_targets = extractor(style_image)['style']
content_targets = extractor(content_image)['content']

"""

"""
    content_input: [Batch_size, 256, 256, 3]
"""

class Style_Content_Loss():

    import tensorflow as tf

    from tensorflow import keras

    def __init__(self, style_image_path):
        # content layer name
        self.content_layers = ['block5_conv2']
        self.num_content_layers = len(self.content_layers)
        # style layer
        self.style_layers = ['block1_conv1',
                        'block2_conv1',
                        'block3_conv1',
                        'block4_conv1',
                        'block5_conv1']
        self.num_style_layers = len(self.style_layers)
        # style image
        self.style_image = load_image(style_image_path, return_type='tensor')

        # style_weight, content weight.
        self.style_weight=1e-2
        self.content_weight=1e4

        self.extractor = StyleContentModel(style_layers, content_layers)

    # content input batch, the data from data generator, [batch, 256, 256, 3]
    def content_loss(self, content_input, transform_model_output):
        content_input_target = self.extractor(content_input)['content']  # a dict, content
        content_trans_target = self.extractor(transform_model_output)['content']
        content_loss = tf.add_n([tf.reduce_mean((content_trans_target[name]-content_input_target[name])**2, [1,2,3])
                                 for name in content_trans_target.keys()])
        content_loss /= self.num_content_layers     # divided by number of layers to standardlize the weight.
        return content_loss

    # style input is the image tf tensor (1, width, height, 3).
    def style_loss(self, style_input, transform_model_output):
        style_input_target = self.extractor(style_input)['style'] # a dict, {style_layer: tensor }
        style_trans_target = self.extractor(transform_model_output)['style']
        style_loss = tf.add_n([tf.reduce_mean((style_trans_target[name]-style_input_target[name])**2, [1,2])
                               for name in style_trans_target.keys()])
        style_loss /= self.num_style_layers
        return style_loss

    def style_content_loss(self, content_input, transform_model_output):
        total_loss = self.content_weight * self.content_loss(content_input, transform_model_output) \
                + self.style_weight * self.style_loss(self.style_image, transform_model_output)
        return total_loss

    class StyleContentModel(tf.keras.models.Model):
        def __init__(self, style_layers, content_layers):
            super(StyleContentModel, self).__init__()
            self.vgg =  self.vgg_layers(style_layers + content_layers)
            self.style_layers = style_layers
            self.content_layers = content_layers
            self.num_style_layers = len(style_layers)
            self.vgg.trainable = False

        # VGG layers.
        def vgg_layers(self, layer_names):
            """ Creates a vgg model that returns a list of intermediate output values."""
            # Load our model. Load pretrained VGG, trained on imagenet data
            vgg = tf.keras.applications.VGG19(include_top=False, weights='imagenet')
            vgg.trainable = False
            outputs = [vgg.get_layer(name).output for name in layer_names]
            model = tf.keras.Model([vgg.input], outputs)
            return model

        def gram_matrix(self, input_tensor):
            result = tf.linalg.einsum('bijc,bijd->bcd', input_tensor, input_tensor)
            input_shape = tf.shape(input_tensor)
            num_locations = tf.cast(input_shape[1]*input_shape[2], tf.float32)
            return result/(num_locations)

        def call(self, inputs):
            "Expects float input in [0,1]"
            inputs = inputs*255.0
            #preprocessed_input = tf.keras.applications.vgg19.preprocess_input(inputs) # problem here
            preprocessed_input = inputs
            # eliminated preprocess

            outputs = self.vgg(preprocessed_input)
            style_outputs, content_outputs = (outputs[:self.num_style_layers],
                                              outputs[self.num_style_layers:])

            style_outputs = [self.gram_matrix(style_output)
                             for style_output in style_outputs]

            content_dict = {content_name:value
                            for content_name, value
                            in zip(self.content_layers, content_outputs)}

            style_dict = {style_name:value
                          for style_name, value
                          in zip(self.style_layers, style_outputs)}

            return {'content':content_dict, 'style':style_dict}


def solution():
    n, m = map(int, input().split())

    see = set()
    listen = set()
    for i in range(n):
        see.add(input())
    for i in range(m):
        listen.add(input())
    ans = sorted(list(see & listen))
    print(len(ans))
    for name in ans:
    	print(name)
solution()


from dataclasses import dataclass, field
import numpy as np
import random
from tqdm import tqdm
import torch
from typing import List, Tuple

import gzip
import pickle

from data_utils.dataset import TokenizedDataset, SentenceDropDataset
from data_utils.sentence import Sentence
from data_utils.example import ExampleWithSentences

##random.sample vs random.choice

@dataclass
class FindCatSentence(Sentence):
    pass

@dataclass
class FindCatExample(ExampleWithSentences):
    target_tokens: List[int]
    positions: List[int]
    label: int = 0

def contains_subsequence_old(target, sequence):
    if len(target) == 0:
        return True

    if target[0] not in sequence:
        return False
    else:
        for i in range(len(sequence) - len(target) + 1):
            if sequence[i] == target[0]:
                subresult = contains_subsequence(target[1:], sequence[i + 1:])
                if subresult:
                    return True
        return False

def contains_subsequence(target, sequence):
    if len(target) == 0:
        return True
    remaining = sequence
    matched = 0
    for t in target:
        idx = 0
        while idx < len(remaining) and remaining[idx] != t:
            idx += 1
        if idx >= len(remaining):
            return False
        else:
            matched += 1
            if matched == len(target):
                return True
            remaining = remaining[idx + 1:]

RESERVED_TOKENS = 10
VOCAB_SIZE = 26
PAD = 0
CLS = 1
SEP = 2
MASK = 3
VOCAB = tuple(range(RESERVED_TOKENS, RESERVED_TOKENS + VOCAB_SIZE))

def neg_example_generation(target_tokens, vocab, exam_seq_len):
    retval = random.choices(vocab, k=exam_seq_len)
    while contains_subsequence(target_tokens, retval):
        retval = random.choices(vocab, k=exam_seq_len)
    return retval

class FindCatDataset(TokenizedDataset):
    def __init__(self, tokenizer_class="bert-base-uncased",
                 total_examples=1000, seqlen=(300,), vocab=VOCAB,
                 target_tokens='cat', prob=0.5,
                 top_position=None,
                 fixed_positions=None,
                 eval=False, multi_target=True, seed=42, data_file_name=None):
        super().__init__(tokenizer_class=tokenizer_class)
        random.seed(seed)

        self.prob = prob
        self.multi_target = multi_target
        self.seqlen = seqlen
        self.vocab = vocab
        self.target_tokens = [[ord(x) - ord('a') + RESERVED_TOKENS for x in y] for y in target_tokens.split('_')]
        self.fixed_positions = fixed_positions
        self.total_examples = total_examples
        self.top_position = top_position
        if data_file_name is None:
            self.data = self.data_generation()
        else:
            self.data = self.load_data_from_file(data_file_name=data_file_name)

    def _generate_example(self):
        target = int(random.random() < self.prob)
        target_tokens = random.choice(self.target_tokens)
        # print(target_tokens)
        ##=========
        exam_seq_len = np.random.choice(self.seqlen, 1)[0]
        ##=========
        # positions = []
        retval = neg_example_generation(target_tokens=target_tokens, exam_seq_len=exam_seq_len, vocab=self.vocab)
        # if target == 1:
        #     # if self.multi_target:
        #     #     retval = random.choices(self.vocab, k=exam_seq_len)
        #     if self.fixed_positions is not None:
        #         assert len(self.fixed_positions) == len(target_tokens)
        #         positions = self.fixed_positions
        #     else:
        #         if self.top_position is None:
        #             # positions = sorted(random.choices(list(range(exam_seq_len)), k=len(target_tokens)))
        #             positions = sorted(random.sample(list(range(exam_seq_len)), k=len(target_tokens)))
        #         else:
        #             top_len = self.top_position if self.top_position < exam_seq_len else exam_seq_len
        #             # positions = sorted(random.choices(list(range(top_len)), k=len(target_tokens)))
        #             positions = sorted(random.sample(list(range(top_len)), k=len(target_tokens)))
        #
        #     for p_i, p in enumerate(positions):
        #         retval[p] = target_tokens[p_i]

        positions = []
        if target == 1:
            if self.fixed_positions is not None:
                assert len(self.fixed_positions) == len(target_tokens)
                positions = self.fixed_positions
            else:
                if self.top_position is None:
                    # positions = sorted(random.choices(list(range(exam_seq_len)), k=len(target_tokens)))
                    positions = sorted(random.sample(list(range(exam_seq_len)), k=len(target_tokens)))
                else:
                    top_len = self.top_position if self.top_position < exam_seq_len else exam_seq_len
                    # positions = sorted(random.choices(list(range(top_len)), k=len(target_tokens)))
                    positions = sorted(random.sample(list(range(top_len)), k=len(target_tokens)))

            for p_i, p in enumerate(positions):
                retval[p] = target_tokens[p_i]

        # return FindCatExample(
        #     tokenized_sentences=[FindCatSentence(sentence_idx=s_i, token_ids=[s]) for s_i, s in enumerate(retval)],
        #     target_tokens=target_tokens, positions=positions, label=target)
        return FindCatExample(
            tokenized_sentences=[FindCatSentence(sentence_idx=s_i, token_ids=[s]) for s_i, s in enumerate(retval)],
            target_tokens=target_tokens, positions=positions, label=target)

    def __len__(self):
        return len(self.data)

    def __getitem__(self, key):
        return self.data[key]

    def data_generation(self):
        data = [self._generate_example() for _ in tqdm(range(self.total_examples))]
        return data

    def save_data_into_file(self, data_file_name):
        with gzip.open(data_file_name, 'wb') as fout:
            pickle.dump(self.data, fout)
        print('save {} records into {}'.format(len(self.data), data_file_name))

    def load_data_from_file(self, data_file_name):
        with gzip.open(data_file_name, 'rb') as fin:
            data = pickle.load(fin)
        print('load {} records from {}'.format(len(data), data_file_name))
        return data

def find_cat_collate_fn(examples):
    ex_lens = [3 + len(ex.target_tokens) + len(ex.tokenized_sentences) for ex in examples]
    max_ex_len = max(ex_lens)

    batched_input = np.full((len(examples), max_ex_len), -1, dtype=np.int64)
    batched_labels = np.zeros((len(examples),), dtype=np.int64)

    for ex_i, ex in enumerate(examples):
        # print(ex.target_tokens)
        batched_input[ex_i, :ex_lens[ex_i]] = [CLS] + ex.target_tokens + [SEP] + [s.token_ids[0] for s in
                                                                                ex.tokenized_sentences] + [SEP]
        batched_labels[ex_i] = ex.label

    retval = {
        'input': batched_input,
        'labels': batched_labels
    }
    retval = {k: torch.from_numpy(retval[k]) for k in retval}
    return retval

def find_cat_probe_collate_fn(examples):
    ex_lens = [3 + len(ex.target_tokens) + len(ex.tokenized_sentences) for ex in examples]
    max_ex_len = max(ex_lens)

    batched_input = np.full((len(examples), max_ex_len), -1, dtype=np.int64)
    batched_labels = np.zeros((len(examples),), dtype=np.int64)
    batched_seq_labels = np.zeros((len(examples), max_ex_len), dtype=np.int64)
    batched_seq_mask = np.ones((len(examples), max_ex_len), dtype=np.int64)

    for ex_i, ex in enumerate(examples):
        ##++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        assert ex.label == 1
        # if ex.label == 0:
        #     positions = sorted(random.choices(list(range(len(ex.tokenized_sentences))), k=len(ex.target_tokens)))
        #     for p_i, p in enumerate(positions):
        #         ex.tokenized_sentences[p].token_ids[0] = ex.target_tokens[p_i]
        #     ex.positions = positions
        #     ex.label = 1
        ##++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        batched_input[ex_i, :ex_lens[ex_i]] = [CLS] + ex.target_tokens + [SEP] + [s.token_ids[0] for s in
                                                                                ex.tokenized_sentences] + [SEP]

        batched_labels[ex_i] = ex.label
        ex_mask_len = 2 + len(ex.target_tokens)
        mask_position = [_ for _ in range(ex_mask_len)] + [_ for _ in range(ex_mask_len + len(ex.tokenized_sentences), max_ex_len)]

        target_position = [_ + ex_mask_len for _ in ex.positions]
        batched_seq_labels[ex_i, target_position] = 1
        assert batched_seq_labels[ex_i].sum() == len(ex.target_tokens)
        batched_seq_mask[ex_i, mask_position] = 0

    retval = {
        'input': batched_input,
        'labels': batched_labels,
        'seq_labels': batched_seq_labels,
        'seq_mask': batched_seq_mask
    }
    retval = {k: torch.from_numpy(retval[k]) for k in retval}
    return retval

def find_cat_validation_fn(ex):
    return (ex.label == 0) or contains_subsequence(ex.target_tokens, [s.token_ids[0] for s in ex.tokenized_sentences])

# if __name__ == "__main__":
#
#     # dataset = FindCatDataset(total_examples=10)
#     #
#     # examples = dataset.data
#     #
#     # print(len(examples))
#     # # for x in examples:
#     # #     print(len(x.tokenized_sentences))
#     #
#     cached_examples_file = 'test.pkl.gz'
#     # # with gzip.open(cached_examples_file, 'wb') as fout:
#     # #     pickle.dump(examples, fout)
#     # # print('save {} records into {}'.format(len(examples), cached_examples_file))
#     #
#     # dataset.save_data_into_file(data_file_name=cached_examples_file)
#
#     dataset = FindCatDataset(data_file_name=cached_examples_file)
#
#
#     # true_count = 0
#     # count = 20000
#     # for _ in tqdm(range(count)):
#     #     x = random.choices(dataset.vocab, k=300)
# #         y = contains_subsequence(target=dataset.target_tokens, sequence=x)
# #         if y:
# #             true_count = true_count + 1
# #         # while y:
# #         #     x = random.choices(dataset.vocab, k=300)
# #         #     y = contains_subsequence(target=dataset.target_tokens, sequence=x)
# #         #     true_count = true_count + 1
# #     print(true_count * 1.0/count)
# #
# #     # dataset.data_generation()
# #     # sdrop_dataset = SentenceDropDataset(dataset, sent_drop_prob=.1,
# #     #                                     example_validate_fn=lambda ex: find_cat_validation_fn(ex, dataset=dataset))
# #     #
# #     # from tqdm import tqdm
# #     # from torch.utils.data import DataLoader
# #     #
# #     # dataloader = DataLoader(sdrop_dataset, batch_size=32, collate_fn=find_cat_collate_fn)
# #     #
# #     # for batch in tqdm(dataloader):
#     #     pass


from django.db.models import Q
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated, BasePermission
from rest_framework.viewsets import ModelViewSet

from core.models import VotingSession, Position, Aspirant, Family, User
from core.serializers.ballot import VotingSessionSerializer, CreateVotingSessionSerializer, PositionSerializer, \
	CreateAspirantSerializer, AspirantSerializer
from core.serializers.user import UserSerializer
from core.utilities.api_response import SuccessResponse, FailureResponse
from core.utilities.utils import get_family, send_ws

class CanUseBallot(BasePermission):
	message = "You don't have a license for the ballot app"

	def has_permission(self, request, view):
		family = Family.objects.get(username=request.META.get("HTTP_FAMILY"))
		return family.can_use_ballot()

class VotingSessionAPI(ModelViewSet):
	queryset = VotingSession.objects.all()
	serializer_class = VotingSessionSerializer
	http_method_names = ("get", "post", "patch", "delete")
	permission_classes = (IsAuthenticated, CanUseBallot)

	def get_queryset(self):
		return VotingSession.objects.filter(family__user=self.request.user,
		                                    family__username__iexact=get_family(self.request))

	def get_serializer_context(self):
		data = super(VotingSessionAPI, self).get_serializer_context()
		data['family'] = Family.objects.get(username__iexact=get_family(self.request))
		return data

	@swagger_auto_schema(request_body=CreateVotingSessionSerializer,
	                     operation_summary="creates a voting session", tags=['ballot', ]
	                     )
	def create(self, request, *args, **kwargs):
		self.serializer_class = CreateVotingSessionSerializer
		return super(VotingSessionAPI, self).create(request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="retrieves a voting session", tags=['ballot', ]
	                     )
	def retrieve(self, request, *args, **kwargs):
		return super(VotingSessionAPI, self).retrieve(request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="retrieves a list of voting sessions", tags=['ballot', ]
	                     )
	def list(self, request, *args, **kwargs):
		return super(VotingSessionAPI, self).list(request, *args, **kwargs)

	@swagger_auto_schema(request_body=CreateVotingSessionSerializer,
	                     operation_summary="updates a voting session", tags=['ballot', ]
	                     )
	def partial_update(self, request, *args, **kwargs):
		self.serializer_class = CreateVotingSessionSerializer
		return super(VotingSessionAPI, self).partial_update(request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="deletes a voting session", tags=['ballot', ]
	                     )
	def destroy(self, request, *args, **kwargs):
		return super(VotingSessionAPI, self).destroy(request, *args, **kwargs)

class AspirantAPI(ModelViewSet):
	queryset = Aspirant.objects.all()
	serializer_class = AspirantSerializer
	http_method_names = ("post", "get", "delete")
	permission_classes = (IsAuthenticated, CanUseBallot)

	position_query = openapi.Parameter("position", in_=openapi.IN_QUERY, type=openapi.TYPE_INTEGER,
	                                   description="Position ID",
	                                   required=True)
	search_query = openapi.Parameter(name="search", in_=openapi.IN_QUERY, description="search aspirant",
	                                 type=openapi.TYPE_STRING)

	def get_queryset(self):
		return Aspirant.objects.filter(position__family__username__iexact=get_family(self.request),
		                               position__family__user=self.request.user)

	def get_serializer_context(self):
		data = super(AspirantAPI, self).get_serializer_context()
		data['family'] = Family.objects.get(username__iexact=get_family(self.request))
		return data

	def filter_queryset(self, queryset):
		position = self.request.query_params.get("position")
		search = self.request.query_params.get("search")
		if position:
			queryset = queryset.filter(position_id=position)
		if search:
			queryset = queryset.filter(Q(user__first_name__icontains=search) | Q(user__last_name__icontains=search)
			                           | Q(user__email__icontains=search))
		return queryset

	@swagger_auto_schema(operation_summary="views all aspirants in a voting session", tags=['ballot', ],
	                     manual_parameters=[search_query, position_query])
	def list(self, request, *args, **kwargs):
		return super(AspirantAPI, self).list(request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="views an aspirants in a voting session", tags=['ballot', ])
	def retrieve(self, request, *args, **kwargs):
		return super(AspirantAPI, self).retrieve(request, *args, **kwargs)

	@swagger_auto_schema(request_body=CreateAspirantSerializer,
	                     operation_summary="adds an aspirant", tags=['ballot', ]
	                     )
	def create(self, request, *args, **kwargs):
		self.serializer_class = CreateAspirantSerializer
		return super(AspirantAPI, self).create(request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="removes an aspirants from a voting session", tags=['ballot', ]
	                     )
	def destroy(self, request, *args, **kwargs):
		return super(AspirantAPI, self).destroy(self, request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="votes for an aspirant", tags=['ballot', ])
	@action(methods=["post", ], detail=True,
	        url_path="vote",
	        url_name="vote-aspirant")
	def vote(self, request, *args, **kwargs):
		aspirant = self.get_object()
		if not aspirant.session.can_vote():
			return FailureResponse(message="Voting session is inactive")
		if User.objects.filter(votes__user_id=request.user, aspirant__position=aspirant.position,
		                    aspirant__session=aspirant.session).exists():
			return FailureResponse(message="You have voted already")
		aspirant.votes.add(request.user)
		aspirant.save()
		data = AspirantSerializer(aspirant).data
		ws_payload = data
		ws_payload['family'] = aspirant.session.family_id
		ws_payload['sender'] = UserSerializer(request.user).data
		send_ws(action="vote", family=aspirant.session.family.username,payload=ws_payload,
		        socket_type="ballot", user=request.user)
		return SuccessResponse(message="Voted successfully", data=data)

class PositionAPI(ModelViewSet):
	queryset = Position.objects.all()
	serializer_class = PositionSerializer
	http_method_names = ("get", "post", "patch", "delete")
	permission_classes = (IsAuthenticated, CanUseBallot)

	search_query = openapi.Parameter(name="search", in_=openapi.IN_QUERY, description="search position",
	                                 type=openapi.TYPE_STRING)
	session_query = openapi.Parameter(name="session", in_=openapi.IN_QUERY, description="session query",
	                                  type=openapi.TYPE_NUMBER)

	def get_queryset(self):
		return Position.objects.filter(family__username__iexact=get_family(self.request),
		                               family__user=self.request.user)

	def get_serializer_context(self):
		data = super(PositionAPI, self).get_serializer_context()
		data['family'] = Family.objects.get(username__iexact=get_family(self.request))
		session = self.request.query_params.get("session")
		if session:
			data['session'] = VotingSession.objects.get(id=session)
		return data

	def filter_queryset(self, queryset):
		session = self.request.query_params.get("session")
		search = self.request.query_params.get("search")
		if search:
			queryset = queryset.filter(title__icontains=search)
		if session:
			queryset = Position.objects.filter(aspirant__session_id=session).distinct()
		return queryset

	@swagger_auto_schema(request_body=PositionSerializer,
	                     operation_summary="creates a position", tags=['ballot', ]
	                     )
	def create(self, request, *args, **kwargs):
		return super(PositionAPI, self).create(request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="retrieves a position", tags=['ballot', ]
	                     )
	def retrieve(self, request, *args, **kwargs):
		return super(PositionAPI, self).retrieve(request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="retrieves a list of positions", tags=['ballot', ],
	                     manual_parameters=[search_query, session_query]
	                     )
	def list(self, request, *args, **kwargs):
		return super(PositionAPI, self).list(request, *args, **kwargs)

	@swagger_auto_schema(request_body=PositionSerializer,
	                     operation_summary="updates a position", tags=['ballot', ]
	                     )
	def partial_update(self, request, *args, **kwargs):
		return super(PositionAPI, self).partial_update(request, *args, **kwargs)

	@swagger_auto_schema(operation_summary="deletes a position", tags=['ballot', ]
	                     )
	def destroy(self, request, *args, **kwargs):
		return super(PositionAPI, self).destroy(request, *args, **kwargs)


from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
import json

from common.json import ModelEncoder
from .models import AutomobileVO, Appointment, Technician

class AutomobileVOEncoder(ModelEncoder):
    model = AutomobileVO
    properties = [
        "vin",
        "sold",
        "id"
    ]

class TechnicianEncoder(ModelEncoder):
    model = Technician
    properties = [
        "id",
        "first_name",
        "last_name",
        "employee_id"
    ]

class AppointmentEncoder(ModelEncoder):
    model = Appointment
    properties = [
        "id",
        "date",
        "time",
        "reason",
        "status",
        "vin",
        "customer",
        "technician",
        "vip"
    ]
    encoders = {
        "technician": TechnicianEncoder(),
    }

    def get_extra_data(self, o):
        if isinstance(o.date, str) and isinstance(o.time, str):
            return {
                "date": o.date,
                "time": o.time,
            }
        else:
            return {
                "date": o.date.isoformat(),
                "time": o.time.isoformat(),
            }

@require_http_methods(["GET", "POST"])
def api_list_technicians(request):
    if request.method == "GET":
        technicians = Technician.objects.all()
        return JsonResponse(
            {"technicians": technicians},
            encoder=TechnicianEncoder,
        )
    else:
        content = json.loads(request.body)
        try:
            technician = Technician.objects.create(**content)
            return JsonResponse(
                technician,
                encoder=TechnicianEncoder,
                safe=False,
            )
        except Technician.DoesNotExist:
            return JsonResponse(
                {"message": "could not create the technician!!!"},
                status=400,
            )

@require_http_methods(["GET", "DELETE"])
def api_show_technician(request, pk):
    if request.method == "GET":
        try:
            technician = Technician.objects.get(id=pk)
            return JsonResponse(
                technician,
                encoder=TechnicianEncoder,
                safe=False,
            )
        except Technician.DoesNotExist:
            return JsonResponse(
                {"message": "could not retrieve the technician!!!"},
                status=400,
            )
    elif request.method == "DELETE":
        count, _ = Technician.objects.filter(id=pk).delete()
        return JsonResponse({"deleted": count > 0})

@require_http_methods(["GET", "POST"])
def api_list_appointments(request):
    if request.method == "GET":
        appointments = Appointment.objects.all()
        return JsonResponse(
            {"appointments": appointments},
            encoder=AppointmentEncoder,
        )
    else:
        content = json.loads(request.body)
        try:
            technician_id = content["technician"]
            technician = Technician.objects.get(employee_id=technician_id)
            content["technician"] = technician
        except Technician.DoesNotExist:
            return JsonResponse(
                {"message": "invalid technician!!!"},
                status=400,
            )
        appointment = Appointment.objects.create(**content)
        return JsonResponse(
            appointment,
            encoder=AppointmentEncoder,
            safe=False,
        )

@require_http_methods(["GET", "DELETE"])
def api_show_appointment(request, pk):
    if request.method == "GET":
        try:
            appointment = Appointment.objects.get(id=pk)
            return JsonResponse(
                appointment,
                encoder=AppointmentEncoder,
                safe=False
            )
        except Appointment.DoesNotExist:
            return JsonResponse(
                {"message": "couldn't create appointment!!!"},
                status=400,
            )
    elif request.method == "DELETE":
        try:
            model = Appointment.objects.get(id=pk)
            model.delete()
            return JsonResponse(
                model,
                encoder=AppointmentEncoder,
                safe=False,
                )
        except Appointment.DoesNotExist:
            return JsonResponse({"message": "doesn't exist!!!"})

@require_http_methods(["PUT"])
def api_finish_appointment(request, pk):
    appointment = Appointment.objects.get(id=pk)
    appointment.status = "finished"
    appointment.save()
    return JsonResponse(
        appointment,
        encoder=AppointmentEncoder,
        safe=False
    )

@require_http_methods(["PUT"])
def api_cancel_appointment(request, pk):
    appointment = Appointment.objects.get(id=pk)
    appointment.status = "canceled"
    appointment.save()
    return JsonResponse(
        appointment,
        encoder=AppointmentEncoder,
        safe=False
    )

@require_http_methods(["GET"])
def api_list_automobileVOs(request):
    if request.method == "GET":
        automobileVO = AutomobileVO.objects.all()
        return JsonResponse(
            {"AutomobileVOs": automobileVO},
            encoder=AutomobileVOEncoder,
            safe=False,
        )


import requests
from zipfile import ZipFile
import unicodedata
import os
import re

from process_cornell import create_training_files

def maybe_download_and_read_file(url, filename):
    """ Download and unzip training data

    Args:
        url: data url
        filename: zip filename

    Returns:
        Training data: an array containing text lines from the data
    """
    if not os.path.exists(filename):
        session = requests.Session()
        response = session.get(url, stream=True)

        CHUNK_SIZE = 32768
        with open(filename, "wb") as f:
            for chunk in response.iter_content(CHUNK_SIZE):
                if chunk:
                    f.write(chunk)

    zipf = ZipFile(filename)
    zipf.extractall()

    input_text_file, target_text_file, _ = create_training_files()

    with open(input_text_file, 'r') as f:
        input_lines = f.read()

    input_lines = input_lines.split('\n')[:-1]

    with open(target_text_file, 'r') as f:
        target_lines = f.read()

    target_lines = target_lines.split('\n')[:-1]

    return list(zip(input_lines, target_lines))

def unicode_to_ascii(s):
    return ''.join(
        c for c in unicodedata.normalize('NFD', s)
        if unicodedata.category(c) != 'Mn')

def normalize_string(s):
    s = unicode_to_ascii(s)
    s = re.sub(r'([!.?])', r' \1', s)
    s = re.sub(r'[^a-zA-Z.!?]+', r' ', s)
    s = re.sub(r'\s+', r' ', s)
    return s


import openai

root_path = 'C:\\OpenAI\\'
key_file_path = f'{root_path}SECRET_KEY.txt'
key_file = open(key_file_path, "r", encoding='utf-8')
key = key_file.read()
print(f'key={key}')
openai.api_key = key

while True:
    completion = openai.Completion.create(
      model="text-davinci-003",
      prompt=input("You: ")
    )
    print(completion.choices[0]['text'])


import json
import numba
from scipy.io.wavfile import read, write
import matplotlib.pyplot as plt
import argparse
def str2bool(v):
    if isinstance(v, bool):
       return v
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')
parser = argparse.ArgumentParser(description='Process wav file')
parser.add_argument('file', help='File to process')
parser.add_argument('--show', type=str2bool, default=False, nargs='?', const=True, help='show graph')
args = parser.parse_args()
if "." in args.file:
    baseName = ".".join(args.file.split(".")[:-1])
else:
    baseName = args.file

fSampl, data = read(args.file)

d = data[:,0]
#data = data[:1000000]

print("Freq is :{}".format(fSampl))

peaks_threshold = 600
secPerSample = 1 / fSampl
minDelay = 0.15
multiplier_threshold = 0.58
quick_avg_k = 0.001
long_avg_k = 0.0001
@numba.jit()
def avg(data, mk):
    d1 = []
    avg = 0
    for curVal in data:
        curVal = abs(curVal)
        avg += (curVal - avg) * mk
        d1.append(avg)
    return d1

@numba.jit()
def detectPeaks(d1):
    isPeak = []
    trend = 0
    isPeak.append(0)
    for i in range(1, len(d1)):
        av = d1[i]
        prev = d1[i-1]
        if av > prev and not trend:
            isPeak.append(10000)
        else:
            isPeak.append(0)

        trend = av > prev
    return isPeak

@numba.jit()
def analyze(data):
    data = [numba.float64(k[0]) for k in data]
    d1 = avg(data, quick_avg_k)
    d2 = avg(d1, long_avg_k)
    d3 = avg(d2, quick_avg_k)
    peaks = detectPeaks(d3)
    return d1, d3, peaks

d1, d2, peaks = analyze(data)

def showPlot():
    plt.figure()
    plt.plot(data)
    plt.plot(d1)
    plt.plot(d2)
    plt.plot(peaks)
    plt.show()

print("saving peaks")
f = open(baseName + ".txt", "w+")
time = 0
prev = 0
res = []
for k in peaks:
    time += secPerSample
    if k > 0:
        f.write("{}: {}\n".format(time, k))
        res.append(time)
open(baseName + ".json", "w+").write(json.dumps(res))

if args.show:
    showPlot()


from django.db import models
from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from treebeard.al_tree import AL_Node
from embed_video.fields import EmbedVideoField
from django.contrib.postgres.fields import ArrayField
# Create your models here.
class NewsRecord(models.Model):

    title = models.CharField(
        verbose_name=_("Title"),
        max_length=60, blank=False)

    description = models.TextField(
        verbose_name=_("Content"),
        blank=False)

    figure = models.ImageField(upload_to='uploads/%Y/%m/%d',
                               blank=True,
                               null=True,
                               verbose_name=_("Figure"))
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    class Meta:
        ordering = ['-updated_at','-created_at',]

class MagicNode(AL_Node):
    owner = models.ForeignKey(User, on_delete=models.SET_DEFAULT, default = 1)
    is_ready = models.BooleanField(default = False)
    updated_at = models.DateTimeField(auto_now = True)
    parent = models.ForeignKey('self',
                               related_name='children_set',
                               null=True,
                               db_index=True,on_delete=models.CASCADE)
    sib_order = models.PositiveIntegerField()
    desc = models.CharField(max_length=255)
    figure = models.ImageField(upload_to='uploads/%Y/%m/%d',
                               blank=True,
                               null=True,
                               verbose_name=_("Figure"))
    text = models.TextField(
            verbose_name=_("Text"),
            blank=True)

    next = models.CharField(max_length=255, null=True, blank=True)

    video = EmbedVideoField(null=True,blank=True)  # same like models.URLField(

    sites = ArrayField(
            models.TextField(blank=True),
            blank = True,
            null=True,
            size=5,

        )

    videos = ArrayField(
                models.TextField(blank=True),
                blank = True,
                null=True,
                size=5,

            )

    pre_nodes = ArrayField(
                models.TextField(blank=True),
                blank = True,
                null=True,
                size=5,

            )

    post_nodes = ArrayField(
                models.TextField(blank=True),
                blank = True,
                null=True,
                size=5,

            )

    friends = ArrayField(
                models.TextField(blank=True),
                blank = True,
                null=True,
                size=5,

            )

    def __str__(self):
        return self.desc

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    node_last_visited = models.ForeignKey(MagicNode,on_delete=models.CASCADE, default=1)
    visited_at = models.DateTimeField(auto_now=True)

class Interest(models.Model):
    user = models.ForeignKey(User,on_delete=models.CASCADE)
    topic = models.ForeignKey(MagicNode,on_delete=models.CASCADE)
    i_like_the_topic = models.BooleanField(default = False)
    i_like_the_content = models.BooleanField(default = False)
    i_am_an_expert = models.BooleanField(default = False)


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

T = int(input())
for i in range(T):
    N = int(input())
    Stu_list = map(int, input().split())

    score_dic = {}
    max_val = 0

    for score in Stu_list:
        if score not in score_dic:
            score_dic[score] = 1
        else:
            score_dic[score] += 1

    for key, val in score_dic.items():
        if val > max_val:
            max_val = val
            max_score = []
            max_score.append(key)
        elif val == max_val:
            max_score.append(key)
    max_score.sort()

    print(f'#{N} {max_score[-1]}')


# -*- encoding: utf-8 -*-
# Author: Oscar
# Create Time: 2021/8/4 20:32
# Project name: solve.py
# IDE: PyCharm
# File name: 3.py
# 程老师需要把下面表格中的数据进行处理，请按照下列要求完成程序。
#
# （1）输入对应的数字，生成下列表格
#
# 姓名  身高  体重
#  小本  43kg  1.48米
#  小辰  38kg 1.49米
# 输入格式：
#
# 请输入小本的身高和体重数字，用英文逗号隔开：43,1.48
#
# 请输入小辰的身高和体重数字，用英文逗号隔开：38,1.49
#
# （2）发现记录学生的表格出现了问题，体重和身高的数据填入相反，
# 现在需要把该csv文件中身高数据和体重数据对换。
import csv

ben = input('请输入小本的身高和体重数字，用英文逗号隔开：')
ceng = input('请输入小辰的身高和体重数字，用英文逗号隔开：')
l1 = [i for i in ben.split(',')]
l2 = [j for j in ceng.split(',')]
dict1 = [{"姓名": "小本", "身高": l1[1]+"米", "体重": l1[0]+"kg"},
         {"姓名": "小辰", "身高": l2[1]+"米", "体重": l2[0]+"kg"}]

with open('data1.csv', 'a+', encoding="utf-8") as fp:
    writer = csv.DictWriter(fp, ["姓名", "身高", "体重"])
    writer.writeheader()
    writer.writerows(dict1)


from itertools import groupby
def func(alist):
        def ctr_ele(el):
            if len(el)>1: return [len(el), el[0]]
            else: return el[0]
        return [ctr_ele(list(group)) for key, group in groupby(alist)]

n_list = [1,1,2,3,4,4,5, 1]
print("Original list:")
print(n_list)
print("\nList reflecting the modified run-length encoding from the said list:")
print(func(n_list))


import sys
import json
import time
import subprocess
import traceback
import asyncio
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QDialog, QTextEdit
from PyQt5.QtCore import pyqtSlot, QDate, Qt
from PyQt5.QtGui import QPixmap, QColor
from backend import Backend

class Ui_MainWindow(QMainWindow):
    def __init__(self):
        self.backend = Backend()
        super(Ui_MainWindow, self).__init__()
        self.setObjectName("Main window")
        self.resize(640, 480)
        self.setMinimumSize(QtCore.QSize(640, 480))
        self.setMaximumSize(QtCore.QSize(640, 480))
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 0, 621, 431))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.tabWidget = QtWidgets.QTabWidget(self.gridLayoutWidget)
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.gridLayoutWidget_2 = QtWidgets.QWidget(self.tab)
        self.gridLayoutWidget_2.setGeometry(QtCore.QRect(10, 10, 601, 71))
        self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget_2)
        self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.label = QtWidgets.QLabel(self.gridLayoutWidget_2)
        font = QtGui.QFont()
        font.setPointSize(14)
        self.label.setFont(font)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName("label")
        self.label.setWordWrap(True)
        self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
        self.gridLayoutWidget_3 = QtWidgets.QWidget(self.tab)
        self.gridLayoutWidget_3.setGeometry(QtCore.QRect(10, 90, 601, 181))
        self.gridLayoutWidget_3.setObjectName("gridLayoutWidget_3")
        self.gridLayout_3 = QtWidgets.QGridLayout(self.gridLayoutWidget_3)
        self.gridLayout_3.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.comboBox = QtWidgets.QComboBox(self.gridLayoutWidget_3)
        self.comboBox.setPlaceholderText("Select your date or one from listed event")
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.comboBox.sizePolicy().hasHeightForWidth())
        self.comboBox.setSizePolicy(sizePolicy)
        self.comboBox.setMinimumSize(QtCore.QSize(0, 0))
        self.comboBox.setCurrentText("")
        self.comboBox.setObjectName("comboBox")
        self.comboBox.setEnabled(True)
        self.gridLayout_3.addWidget(self.comboBox, 1, 0, 1, 1)
        self.label_2 = QtWidgets.QLabel(self.gridLayoutWidget_3)
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_2.setFont(font)
        self.label_2.setAlignment(QtCore.Qt.AlignCenter)
        self.label_2.setObjectName("label_2")
        self.gridLayout_3.addWidget(self.label_2, 0, 0, 1, 1)
        self.tabWidget.addTab(self.tab, "")
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.gridLayoutWidget_4 = QtWidgets.QWidget(self.tab_2)
        self.gridLayoutWidget_4.setGeometry(QtCore.QRect(10, 10, 601, 181))
        self.gridLayoutWidget_4.setObjectName("gridLayoutWidget_4")
        self.gridLayout_4 = QtWidgets.QGridLayout(self.gridLayoutWidget_4)
        self.gridLayout_4.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_4.setObjectName("gridLayout_4")
        self.label_3 = QtWidgets.QLabel(self.gridLayoutWidget_4)
        self.label_3.setAlignment(QtCore.Qt.AlignCenter)
        self.label_3.setObjectName("label_3")
        self.gridLayout_4.addWidget(self.label_3, 0, 0, 1, 1)
        self.gridLayoutWidget_5 = QtWidgets.QWidget(self.tab_2)
        self.gridLayoutWidget_5.setGeometry(QtCore.QRect(10, 200, 301, 191))
        self.gridLayoutWidget_5.setObjectName("gridLayoutWidget_5")
        self.gridLayout_5 = QtWidgets.QGridLayout(self.gridLayoutWidget_5)
        self.gridLayout_5.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_5.setObjectName("gridLayout_5")
        self.graphicsView = QtWidgets.QGraphicsView(self.gridLayoutWidget_5)
        self.graphicsView.setObjectName("graphicsView")
        self.graphicsView.setStyleSheet("border-style: none; background-color: transparent;")
        self.scene = QtWidgets.QGraphicsScene(self)
        self.scene.setBackgroundBrush(QtGui.QBrush(QtCore.Qt.transparent))
        self.graphicsView.setScene(self.scene)
        self.gridLayout_5.addWidget(self.graphicsView, 0, 0, 1, 1)
        self.gridLayoutWidget_6 = QtWidgets.QWidget(self.tab_2)
        self.gridLayoutWidget_6.setGeometry(QtCore.QRect(320, 200, 291, 191))
        self.gridLayoutWidget_6.setObjectName("gridLayoutWidget_6")
        self.gridLayout_6 = QtWidgets.QGridLayout(self.gridLayoutWidget_6)
        self.gridLayout_6.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_6.setObjectName("gridLayout_6")
        self.label_4 = QtWidgets.QLabel(self.gridLayoutWidget_6)
        self.label_4.setAlignment(QtCore.Qt.AlignCenter)
        self.label_4.setObjectName("label_4")
        self.gridLayout_6.addWidget(self.label_4, 0, 0, 1, 1)
        self.tabWidget.addTab(self.tab_2, "")
        self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
        self.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 640, 21))
        self.menubar.setObjectName("menubar")
        self.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)
        self.retranslateUi()
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(self)
        self.activateComboBox()
        self.createPopupInstance()

    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("MainWindow", "DayCounter-pyqt"))
        self.label.setText(_translate("MainWindow", "It\'s been x days since"))
        self.comboBox.setPlaceholderText(_translate("MainWindow", "Test"))
        self.label_2.setText(_translate("MainWindow", "Choose event (or select your date):"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Main window"))
        self.label_3.setFont(QtGui.QFont('Arial',20))
        self.label_3.setText(_translate("MainWindow", "Marcin Popko"))
        self.addAboutMe()
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "About me"))
        # Load the PNG image and create a QPixmap from it
        pixmap = QtGui.QPixmap("graphics/me.jpg")
        pixmap_item = QtWidgets.QGraphicsPixmapItem(pixmap)
        self.scene.addItem(pixmap_item)

    def addAboutMe(self):
        text = "Hello! I\'m From Bialystok, Poland I\'m interested in dancing, singing, coding \n crazy stuff (currently working as embedded dev. Feel free to e-mail me marcinpopko@outlook.com)"
        self.label_4.setFont(QtGui.QFont('Arial', 8))
        self.label_4.setTextFormat(QtCore.Qt.RichText)
        self.label_4.setOpenExternalLinks(True)
        self.label_4.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)
        self.label_4.setText(text)
        self.label_4.setWordWrap(True)

    def activateComboBox(self):
        self.comboBox.currentIndexChanged.connect(self.on_index_changed)
        self.comboBox.addItem("Your date - select from calendar")
        for i in self.backend.event_list:
            self.comboBox.addItem(i + " " + self.backend.get_event_date(i))
        self.comboBox.setCurrentIndex(1)

    @pyqtSlot(int)
    def on_index_changed(self,index):
        if index == 0:
            self.popup.show()
            self.comboBox.setEnabled(False)
        else:
            days, future = self.backend.get_days_from_event(self.backend.return_events_list()[index-1])
            if days == -1:
                self.label.setText( "Wrong date format of event " + self.backend.return_events_list()[index-1])
            else:
                if not future:
                    self.label.setText( "It\'s been " + str(days) + " days since " + self.backend.return_events_list()[index-1])
                else:
                    self.label.setText( "There are " + str(days) + " days from the date of " + self.backend.return_events_list()[index-1])

    '''
    Popup related stuff
    '''
    def createPopupInstance(self):
        self.popup = Ui_Form()
        self.popup.pushButton.clicked.connect(self.sendDateCloseWindow)
    def sendDateCloseWindow(self):
        selected_date = self.popup.calendarWidget.selectedDate()
        selected_date_str = selected_date.toString("dd.MM.yyyy")
        self.popup.close()
        days, future = self.backend.get_days_from_date(selected_date_str)
        if not future:
            self.label.setText( "It\'s been " + str(days) + " days since " + selected_date_str)
        else:
            self.label.setText( "There are " + str(days) + " days from the date of " + selected_date_str)
        self.comboBox.setEnabled(True)

class Ui_Form(QtWidgets.QWidget):
    def __init__(self):
        super(Ui_Form, self).__init__()
        self.setObjectName("self")
        self.resize(640, 480)
        self.setMinimumSize(QtCore.QSize(640, 480))
        self.setMaximumSize(QtCore.QSize(640, 480))
        self.setWindowFlag(Qt.WindowCloseButtonHint, False)
        self.gridLayoutWidget = QtWidgets.QWidget(self)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 10, 621, 401))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.calendarWidget = QtWidgets.QCalendarWidget(self.gridLayoutWidget)
        self.calendarWidget.setObjectName("calendarWidget")
        #self.calendarWidget.setMaximumDate(QDate.currentDate())
        self.gridLayout.addWidget(self.calendarWidget, 0, 0, 1, 1)
        self.gridLayoutWidget_2 = QtWidgets.QWidget(self)
        self.gridLayoutWidget_2.setGeometry(QtCore.QRect(10, 420, 621, 51))
        self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.gridLayoutWidget_2)
        self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.pushButton = QtWidgets.QPushButton(self.gridLayoutWidget_2)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout_2.addWidget(self.pushButton, 0, 0, 1, 1)

        self.retranslateUi()
        QtCore.QMetaObject.connectSlotsByName(self)

    def retranslateUi(self):
        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("Form", "Select date"))
        self.pushButton.setText(_translate("Form", "Accept date"))


"""
Entradas
Fecha de nacimiento-->int-->fecha
Salidas
Edad-->int-->edad
Signo zodiacal-->str-->signo
"""
from datetime import date
#Entrada
fecha=input("Digite su fecha de nacimiento en el formato dia/mes/año ")
(dia,mes,año)=fecha.split(" ")
dia=int(dia)
mes=int(mes)
año=int(año)

año_ac=date.today().year
mes_ac=date.today().month
dia_ac=date.today().day
#Caja negra
edad=año_ac-año
if mes<=mes_ac and dia<=dia_ac:
        edad=edad
elif mes<mes_ac:
    edad=edad
else:
    edad=edad-1

if dia>=22 and mes==11 or dia<=21 and mes==12:
    signo="sagitario"
elif dia>=22 and mes==12 or dia<=20 and mes==1:
    signo="capricornio"
elif dia>=21 and mes==1 or dia<=19 and mes==2:
    signo="acuario"
elif dia>=20 and mes==2 or dia<=19 and mes==3:
    signo="piscis"
elif dia>=21 and mes==3 or dia<=20 and mes==4:
    signo="aries"
elif dia>=21 and mes==4 or dia<=21 and mes==5:
    signo="tauro"
elif dia>=22 and mes==5 or dia<=21 and mes==6:
    signo="Géminis"
elif dia>=22 and mes==6 or dia<=22 and mes==7:
    signo="cáncer"
elif dia>=23 and mes==7 or dia<=23 and mes==8:
    signo="leo"
elif dia>=24 and mes==8 or dia<=22 and mes==9:
    signo="virgo"
elif dia>=23 and mes==9 or dia<=22 and mes==10:
    signo="libra"
else:
    dia>=23 and mes==10 or dia<=22 and mes==11
    signo="escorpión"
#Salida
print("Su edad es",edad,"y su signo zodiacal es",signo)


import calendar
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.http import JsonResponse
from django.shortcuts import render

from finance.models import BankStatements, TypeExpenses
from grafic_matplotlib.core.forms import Calendar, UserChoice, ChoiceYear, ManualInput, FilterExpenses
from grafic_matplotlib.figures import get_plot, get_bar_chart
from grafic_matplotlib.analytics.query_data import amount_expenses, expenses_per_month
from users.core.get_user import user_from_session_key

def sum_transactions(u, s, e):

    if s is None and e is None:
        u = [1, 2]
        s = '2020-11-01'
        e = '2020-11-30'
    list_amount_expenses = amount_expenses(users=u, start=s, end=e)
    expenses = []

    for percent in list_amount_expenses:
        expenses.append(percent['total_amount'])

    return sum(expenses)

def expenses_per_category(u, s, e):
    if s is None and e is None:
        u = [1, 2]
        s = '2020-11-01'
        e = '2020-11-30'
    list_amount_expenses = amount_expenses(users=u, start=s, end=e)
    amnt_expenses = []

    for amount in list_amount_expenses:
        amnt_expenses.append({amount['type_expenses_ru']: amount['total_amount']})

    return amnt_expenses

def month_expenses(u, y):
    if u is None:
        u = [1, 2]
        y = '2020'
    list_month_expenses = expenses_per_month(users=u, year=y)
    mnth_expenses = []

    for amount in list_month_expenses:
        mnth_expenses.append({calendar.month_abbr[int(amount['month'])]: amount['total_amount']})

    return mnth_expenses

@login_required(login_url='/users/login/')
def index(request):
    return render(request, 'grafic_matplotlib/analytics.html')

@login_required(login_url='/users/login/')
def index_p(request):
    pie_update = get_plot(users=[1, 2], s_day='2021-08-01', e_day='2021-08-31')

    if request.method == 'POST':
        form_cal = Calendar(request.POST)
        form_user = UserChoice(request.POST)

        if form_cal.is_valid() and form_user.is_valid():
            s = form_cal.cleaned_data['date_field_start']
            e = form_cal.cleaned_data['date_field_end']
            choice_user = [i.id for i in form_user.cleaned_data['user_field']]
            data_update = expenses_per_category(choice_user, s, e)
            pie_update = get_plot(choice_user, s, e)

            return render(request, 'grafic_matplotlib/pie.html', {'pie_fig': pie_update,
                                                                  'sum_expenses': sum_transactions(u=choice_user, s=s, e=e),
                                                                  'amount_expenses': data_update, 'form_cal': form_cal,
                                                                  'form_user': form_user})

    else:
        form_cal = Calendar()
        form_user = UserChoice()

    return render(request, 'grafic_matplotlib/pie.html', {'pie_fig': pie_update,
                                                          'sum_expenses': sum_transactions(u=None, s=None, e=None),
                                                          'amount_expenses': expenses_per_category(u=None, s=None, e=None),
                                                          'form_cal': form_cal, 'form_user': form_user})

@login_required(login_url='/users/login/')
def index_d(request):   #TODO сделать возможность ввести год
    bar_char = get_bar_chart(users=[1, 2], year='2020')

    if request.method == 'POST':
        form_year = ChoiceYear(request.POST)
        form_user = UserChoice(request.POST)

        if form_year.is_valid() and form_user.is_valid():
            choice_year = form_year.cleaned_data['year_field']
            choice_user = [i.id for i in form_user.cleaned_data['user_field']]
            data_update = month_expenses(choice_user, choice_year)
            bar_char = get_bar_chart(choice_user, choice_year)
            return render(request, 'grafic_matplotlib/diagram.html', {'bar_char': bar_char,
                                                                  'amount_expenses': data_update,
                                                                      'form_year': form_year, 'form_user': form_user})

    else:
        form_year = ChoiceYear()
        form_user = UserChoice()

    return render(request, 'grafic_matplotlib/diagram.html', {'bar_char': bar_char,
                                                              'amount_expenses': month_expenses(u=None, y=None),
                                                              'form_year': form_year, 'form_user': form_user})

@login_required(login_url='/users/login/')
def index_plan(request):
    if request.method == 'POST':
        form_cal = Calendar(request.POST)
        form_user = UserChoice(request.POST)

        if form_cal.is_valid() and form_user.is_valid():
            s = form_cal.cleaned_data['date_field_start']
            e = form_cal.cleaned_data['date_field_end']
            choice_user = [i.id for i in form_user.cleaned_data['user_field']]
            data_update = expenses_per_category(u=choice_user, s=s, e=e)
            return render(request, 'grafic_matplotlib/pie.html', {'sum_expenses': sum_transactions(s=s, e=e),
                                                          'amount_expenses': data_update,
                                                                  'form_cal': form_cal, 'form_user': form_user})

    else:
        form_cal = Calendar()
        form_user = UserChoice()

    return render(request, 'grafic_matplotlib/planning.html', {'sum_expenses': sum_transactions(u=None, s=None, e=None),
                                                               'amount_expenses': expenses_per_category(u=None, s=None, e=None),
                                                               'form_cal': form_cal, 'form_user': form_user})

# ручное создание транзакции/зачисления
@login_required(login_url='/users/login/')
def manual_input(request):
    session_k = request.session.session_key
    user = user_from_session_key(session_k)

    if request.method == 'POST':
        form_manual_input = ManualInput(request.POST)

        if form_manual_input.is_valid():
            trans_place = form_manual_input.cleaned_data['transaction_place']
            type_expenses = form_manual_input.cleaned_data['type_expenses']
            type_transaction = form_manual_input.cleaned_data['type_transaction']
            sum_transaction = form_manual_input.cleaned_data['sum_trans']
            date_of_trans = form_manual_input.cleaned_data['date_trans']
            user = user
            confirm = 'Данные успешно сохранены'
            new_data = BankStatements(
                transaction_place=trans_place,
                type_expenses_id=type_expenses.id,
                type_transaction_id=type_transaction.id,
                sum_transaction=sum_transaction * -1
                if type_transaction.id == 1 and sum_transaction > 0 else sum_transaction, # TODO не дать добавить -1 грн. для Зачисления
                date_of_trans=date_of_trans, user=user)
            new_data.save()

            return render(request, 'grafic_matplotlib/success_input.html', {'confirm': confirm})

    else:
        form_manual_input = ManualInput(request.POST)
        return render(request, 'grafic_matplotlib/manual_input.html', {'form_manual_input': form_manual_input})

# редактирование текущей записи о транзакции (тип расходов)
@login_required(login_url='/users/login/')
def get_expenses_list(request):
    session_k = request.session.session_key
    user = user_from_session_key(session_k)
    start_date = '2021-08-01'
    end_date = '2021-08-31'
    select_type_expenses = TypeExpenses.objects.all()
    if request.method == 'POST':
        try:
            form_cal = Calendar(request.POST)
            # form_user = UserChoice(request.POST)
            form_filter_exp = FilterExpenses(request.POST)
            if form_cal.is_valid() and form_filter_exp.is_valid():
                start_date = form_cal.cleaned_data['date_field_start']
                end_date = form_cal.cleaned_data['date_field_end']
                # choice_user = [i.id for i in form_user.cleaned_data['user_field']]
                type_expenses = form_filter_exp.cleaned_data['type_expenses']
                query_expenses = BankStatements.objects.filter(user_id=user, type_expenses=type_expenses.id,
                                                               type_transaction_id=1,
                                                               date_of_trans__range=[start_date, end_date])

                return render(request, 'grafic_matplotlib/change_type_expenses.html',
                              {'form_cal': form_cal, 'form_filter_exp': form_filter_exp,
                               'query_expenses': query_expenses, 'select_type_expenses': select_type_expenses})

        except ObjectDoesNotExist:
            return render(request, 'grafic_matplotlib/analytics.html')

    else:
        form_cal = Calendar()
        form_user = UserChoice()
        form_filter_exp = FilterExpenses()
        query_expenses = BankStatements.objects.filter(user_id=user, type_expenses=12, type_transaction_id=1,
                                                       date_of_trans__range=[start_date, end_date])

        return render(request, 'grafic_matplotlib/change_type_expenses.html',
                      {'form_cal': form_cal, 'form_filter_exp': form_filter_exp,
                       'form_user': form_user, 'query_expenses': query_expenses,
                       'select_type_expenses': select_type_expenses})

@login_required(login_url='/users/login/')
def update_expenses(request):
    if request.method == 'POST' and request.is_ajax:
        requested_data = request.POST
        new_type_expenses = requested_data.getlist('new_type')
        print(new_type_expenses)

        for type_expenses in new_type_expenses:

            if len(type_expenses.split('-')) > 1:  # проверяем, чтоб список не был ['0']
                print(type_expenses.split('-'))
                new_data = type_expenses.split('-')
                bankstatement_data = BankStatements.objects.get(id=int(new_data[0]))
                print(bankstatement_data)

                # проверяем, чтоб тип затрат отличался от полученного и обновляем
                if int(new_data[1]) != bankstatement_data.type_expenses_id:
                    bankstatement_data.type_expenses_id = int(new_data[1])
                    print(bankstatement_data)
                    bankstatement_data.save()

        return JsonResponse({'message': 'Данные обновлены'}, status=200)


import os, datetime, time
from flask import Flask, request, jsonify
from solve_captcha_with_model import CaptchaSolver

run_date = datetime.datetime.strptime("2021-01-05", "%Y-%m-%d")
today = datetime.datetime.strptime(time.strftime("%Y-%m-%d"), "%Y-%m-%d")

if today != run_date:
    print("Date mismatch!")
    exit()

app = Flask(__name__)
captchaSolver = CaptchaSolver()

app.config["DEBUG"] = True # turn off in prod

@app.route('/', methods=["GET"])
def health_check():
    """Confirms service is running"""
    return "Captcha solver service is up and running."

@app.route('/solve', methods=["POST"])
def solve_captcha():
    img = request.files['captcha']
    if img.filename != '':
        img.filename = 'test.jpg'
        time.sleep(2)
        img.save(img.filename)
        captcha_output = captchaSolver.solve()
    else:
        captcha_output = "Image file invalid! Please try again."
    return jsonify({"output":captcha_output})

if __name__ == '__main__':
    app.run(host="0.0.0.0")


''' Spectrum_fitter.py : an obect-oriented framework for fitting dielectric spectra. '''
from numpy import *
import matplotlib.pyplot as plt
from scipy import optimize
from scipy import special as sp

class Lineshape:
    """Class that holds some things common to all Lineshapes"""
    def __init__(self,params,bounds,name):
        self.p = params
        self.bounds = bounds
        self.name = name

class Debye(Lineshape):
    """Debye lineshape object.
    Note: the wD parameter is assumed to be in units of cm^-1
    """
    def __init__(self,params=[1,1],bounds=[(-float('inf'),+float('inf')),(-float('inf'),+float('inf'))],name="Debye"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wD"]
        self.type = "Debye"

    def __call__(self, w):
        rp = self.p[0]*self.p[1]**2/(self.p[1]**2 + w**2)
        cp = rp*w/self.p[1]
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return self.p[1]

    def print_params(self):
        print(u"%20s f =%7.5f \u03C9 = %6.2f 1/cm (%5.2f ps)" % (self.name, self.p[0], self.p[1], 33.34/(2*3.14159*self.p[1])))

    def print_params_latex(self):
        print(u"%20s & %7.5f & %6.2f & %5.2f &   & \\\\" % (self.name, self.p[0], self.p[1], 33.333/(2*3.14159*self.p[1])))

class DHO(Lineshape):
    """Damped harmonic oscillator object"""
    def __init__(self,params=[1,1,1],bounds=[(-float('inf'),+float('inf')),(-float('inf'),+float('inf'))],name="DHO"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "w", "gamma"]
        self.type = "DHO"

    def __call__(self, w):
        denom = (self.p[1]**2 - w**2)**2 + w**2*self.p[2]**2
        rp = self.p[0]*(self.p[1]**2)*(self.p[1]**2 - w**2)/denom
        cp = self.p[0]*(self.p[1]**2)*self.p[2]*w/denom
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print(u"%20s f =%7.5f \u03C9 = %6.2f + %6.2f i  (%6.3f ps)" % (self.name, self.p[0], self.p[1], self.p[2],  33.34/(2*3.141*self.p[1])))

    def print_params_latex(self):
        print(u"%20s & %7.5f &  %6.2f & %6.3f & %6.2f &  \\\\" % (self.name, self.p[0], self.p[1], 33.34/(2*3.141*self.p[1]), self.p[2] ))

class BrendelDHO(Lineshape):
    """"Brendel model for amorphous materials - Gaussian distribution of DHOs. Ref: J. Appl. Phys. 71, 1 (1992)"""
    def __init__(self,params=[1,1,1,1],bounds=[(0,+float('inf')),(0,+float('inf')),(0,+float('inf')),(0,+float('inf'))],name="BrendelDHO"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["wp**2/w0**2", "wT", "gamma","sigma"]
        self.type = "BrendelDHO"
        self.f = 0

    def __call__(self, w):
        sigma = self.p[3]
        x0 = self.p[1]
        g = self.p[2]
        a = sqrt(w**2 - 1j*g*w)
        a = a.real - 1j*a.imag #we want the imaginary part to the root to be positive
        prefac = 1j*sqrt(3.14149)*self.p[0]*x0**2/(sqrt(22)*sigma)
        eps = prefac*exp(-.5)*(1/a)*( sp.erfcx(-1j*(a-x0)/sigma) +  sp.erfcx(-1j*(a+x0)/sigma) )
        #self.f = 2*prefac*exp(-x0**2/(2*sigma**2))*(1 + sp.erf(1j*x0/sigma))
        self.f = eps.real[1]
        return (eps.real, eps.imag)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9 = %6.2f + %6.2f i  (%5.3f ps) \u03C3 = %6.2f cm^-1" % (self.name, self.p[0], self.p[1], self.p[2],  33.34/self.p[1], self.p[3]))

    def print_params_latex(self):
        print( u"%20s & %7.5f & %6.2f & %5.3f & %6.2f  & %6.2f \\\\" % (self.name, self.p[0], self.p[1], 33.34/self.p[1], self.p[2], self.p[3]))

class DistributionOfDebye(Lineshape):
    '''Under construction'''

    def __init__(self,params=[1,1],bounds=[(0,+float('inf')),(0,+float('inf'))],name="BrendelDHO"):
        Lineshape.__init__(self, params, bounds, name)
        #self.pnames = ["wp**2/w0**2", "wT", "gamma","sigma"]
        #self.type = "BrendelDHO"
        #self.f = 0
        #self.num_tau_pts=10000
        ##self.min_tau=
        ##self.max_tau=

        #tau_values = logspace(min_tau, max_tau, num_tau_pts)

        #def __call__(self, w):

        #for m in xrange(1,num_tau_pts+1):
            #gtau(m)*tau

        #def TikhonovRegularization(self):
        #der1 = gradient(gdist)
        #der2 = gradient(der1)
        #return linalg.norm(der2)**2

class StretchedExp(Lineshape):
    """Stretched Exponential lineshape """
    def __init__(self,params=[1,1,1],bounds=[(0,10000),(0,10000),(0,1)],name="Str exp"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "tau", "beta"]
        self.type = "StretchedExp"

    def __call__(self, w):
        (f, eps_omega) = self.calc_eps(w)
        rp = interp(w,f,real(eps_omega))
        cp = interp(w,f,imag(eps_omega))
        return (rp, cp)

    def calc_eps(self,w):
        deltaeps = self.p[0]
        tau = self.p[1]
        beta = self.p[2]
        timestep = 1/(2*3.141*max(w)) #timestep in ps
        maxt = 3*tau #length of corr function
        npts = int(maxt/timestep)
        times = array(range(0,npts))*timestep
        corr_fun = exp(-(times/tau)**beta)
        nextpow2 = int(2**ceil(log2(npts)))
        f = (1/(2.99*.01))*array(range(0,npts))/(timestep*nextpow2) #Frequencies (evenly spaced), inverse cm
        tderiv = -diff(corr_fun)/timestep #time derivative of corr fun
        eps_omega = deltaeps*ifft(tderiv,nextpow2) #inverse one-sided fourier
        return (f, eps_omega[0:npts])

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9 %6.2f 1/cm (%5.2f ps) \u03B2 = %6.2f" % (self.name, self.p[0], self.p[1], 33.34/(self.p[1]), self.p[2] ))

class PowerLawDebye(Lineshape):
    """Debye lineshape with additional "power law" wing.
    See J. Phys. Chem. B, 2005, 109 (12), pp 6031-6035

    Note: the wD parameter is assumed to be in units of cm^-1
    """
    def __init__(self,params=[1,1],bounds=[(0,+float('inf')),(0,+float('inf')),(0,+float('inf')),(1,10)],name="unnamed"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wD","A","q"]
        self.type = "PowerLawDebye"
        self.convfac = 1.0#/(2*3.141*2.99*.01)

    def __call__(self, w):
        A = self.p[2]
        q = self.p[3]
        tau = self.convfac/self.p[1]
        numomegas = len(w)
        start  = numomegas - len(w[w[:] > self.p[1]])
        HighFreqOmegas = w#0.0*array(w)
        #HighFreqOmegas[start:numomegas] = w[start:numomegas]
        TheWing = 1 + A*(HighFreqOmegas*tau)**q
        rp = TheWing*self.p[0]/(1 + (tau*w)**2)
        cp = TheWing*self.p[0]*w*tau/(1 + (tau*w)**2)
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return self.p[1]

    def print_params(self):
        print(u"%20s f =%7.5f \u03C9 %6.2f 1/cm (%5.2f ps) A = %6.2f q = %6.2f" % (self.name, self.p[0], self.p[1], 33.34/self.p[1], self.p[2], self.p[3] ))

class ColeCole(Lineshape):
    """Cole-Cole lineshape object.

    Note: the wD parameter is assumed to be in units of cm^-1
    """
    def __init__(self,params=[1,1,1],bounds=[(0,+float('inf')),(0,+float('inf')),(0,2)],name="unnamed"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wD","alpha"]
        self.type = "Debye"

    def __call__(self, w):
        rp = self.p[0]*self.p[1]**2/(self.p[1]**2 + w**2)
        cp = rp*w/self.p[1]
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return self.p[1]

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9 %6.2f 1/cm (%5.2f ps) \u03B1 %6.2f" % (self.name, self.p[0], self.p[1], 33.34/self.p[1], self.p[2] ))

class VanVleck(Lineshape):
    """Van Vleck and Weisskopf lineshape Rev. Mod. Phys., 17:227 236, Apr 1945."""
    def __init__(self,params=[1,1,1],bounds=[(-float('inf'),+float('inf')),(-float('inf'),+float('inf'))],name="VanVleck"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wT","gamma"]
        self.type = "VanVleck"

    #the real part has not been tested or checked to see if it is mathematically correct!!!
    def __call__(self, w):
        rp = .5*self.p[0]*(self.p[1]**2 + self.p[2]**2)( 1/((self.p[1] - w)**2 + self.p[2]**2)  + 1.00/((self.p[1] + w)**2 +  self.p[2]**2) )
        cp = .5*self.p[0]*self.p[2]*w*( 1/((self.p[1] - w)**2 + self.p[2]**2)  + 1.00/((self.p[1] + w)**2 +  self.p[2]**2) )
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9= %6.2f + %6.2f i  %6.3f ps" % (self.name, self.p[0], self.p[1], self.p[2],  33.34/(2*3.141*self.p[2]))    )

class Gaussian(Lineshape):
    """Gaussian peak in the imaginary part, ie. inertial absorption or homogenous broadening"""
    def __init__(self,params=[1,1,1],bounds=[(-float('inf'),+float('inf')),(-float('inf'),+float('inf'))],name="Gaussian"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["f", "wT","gamma"]
        self.type = "BRO"

    def __call__(self, w):
        # sp.dawsn
        rp = .5*self.p[0]*(self.p[1]**2 + self.p[2]**2)( 1/((self.p[1] - w)**2 + self.p[2]**2)  + 1.00/((self.p[1] + w)**2 +  self.p[2]**2) )
        cp = .5*self.p[0]*self.p[2]*w*( 1/((self.p[1] - w)**2 + self.p[2]**2)  + 1.00/((self.p[1] + w)**2 +  self.p[2]**2) )
        return (rp, cp)

    def get_freq(self):
        return self.p[1]

    def get_abs_freq(self):
        return sqrt( self.p[1]**2 + self.p[2]**2 )

    def print_params(self):
        print( u"%20s f =%7.5f \u03C9= %6.2f + %6.2f i  %6.3f" % (self.name, self.p[0], self.p[1], self.p[2],  33.34/(2*3.141*self.p[2])))

class constant(Lineshape):
    """this "lineshape" object is merely a constant term"""
    def __init__(self,params=[1],bounds=[(0,100)],name="constant"):
        Lineshape.__init__(self, params, bounds, name)
        self.pnames = ["Eps float('inf')."]
        self.type = "Constant"

    def __call__(self,w):
        rp = 0*w + self.p[0]
        cp = 0*w
        return (rp, cp)

    def print_params(self):
        print("%20s f =%7.5f" % (self.name, self.p[0]))

    def print_params_latex(self):
        print("%20s & %7.5f & & & & \\\\" % (self.name, self.p[0]))

#-----------------------------------------------------------------------------------------------------------
def fit_model_gLST_constraint(modelL, modelT, dataX, Tdatarp, Tdatacp):
        ''' fit both the transverse and longitudinal models at the same time with the gLST constraint  '''

        Ldatarp = 1.0 - Tdatarp/(Tdatarp**2 + Tdatacp**2)
        Ldatacp = Tdatacp/(Tdatarp**2 + Tdatacp**2)

        def diffsq(paramsL, paramsT):

            modelL.setparams(paramsL)
            modelT.setparams(paramsT)

            (Lrp, Lcp) = modelL(dataX)
            (Trp, Tcp) = modelT(dataX)

            Ldiff = (Ldatarp - Lrp)/Ldatarp + (Ldatacp - Lcp)/Ldatacp
            Tdiff = (Tdatarp - Trp)/Tdatarp + (Tdatacp - Tcp)/Tdatacp

            err = dot(Tdiff, Tdiff) + dot(Ldiff, Ldiff)

            return err

        def costfun(params):
            """Wrapper function needed for differential_evolution()

            Args:
                params: a list of parameters for the model
            Returns:
                The cost function
            """

            paramsL = params[0:len(params)//2]
            paramsT = params[len(params)//2:]

            eps0    = Tdatarp[0]
            eps_inf = Tdatarp[-1]

            fsumpenalty = ( ( eps0 - modelT.fsum())/Tdatarp[0] )**2

            gLST_RHS = eps0/eps_inf

            gLSTpenalty = ( gLST_LHS(modelL, modelT) - gLST_RHS )**2

            #print(diffsq(paramsL, paramsT) , gLSTpenalty , 100*fsumpenalty)

            return diffsq(paramsL, paramsT)  + 100*fsumpenalty + gLSTpenalty

        Lparams = modelL.getparams()
        Tparams = modelT.getparams()

        params = Lparams + Tparams

        boundsL = modelL.getbounds()
        boundsT = modelT.getbounds()

        bounds = boundsL + boundsT

        assert len(boundsL) == len(boundsT)
        assert len(params) == len(bounds)

        resultobject = optimize.minimize(costfun, x0=params, bounds=bounds, method='TNC')
        print("number of iterations = ", resultobject.nit)

        resultobject = optimize.minimize(costfun, x0=params, bounds=bounds, method='SLSQP')
        print("number of iterations = ", resultobject.nit)

        #optimize.fmin_l_bfgs_b(costfun, bounds=bounds)
        #optimize.differential_evolution(costfun, bounds)

        Lparams = modelL.getparams()
        Tparams = modelT.getparams()

        print("RMS error = ",sqrt(diffsq(Lparams, Tparams)))

#----------------------------------------------------------------------------------------------------
def print_gLST_ratios(modelL, modelT):
    '''try to print out the ratios for different modes. Note this may not be very accurate as the ordering of modes in the longitudinal and transverse model
        may not be the same'''

    ratios = ones(modelL.numlineshapes)

    if (modelL.numlineshapes == modelT.numlineshapes):

        for i in range(modelL.numlineshapes):
            if modelL.lineshapes[i].type == "Debye":
                ratios[i] = modelL.lineshapes[i].p[1]/modelT.lineshapes[i].p[1]

            if (modelL.lineshapes[i].type == "DHO") or (modelL.lineshapes[i].type == "VanVleck") or (modelL.lineshapes[i].type == "BrendelDHO"):
                ratios[i] = (modelL.lineshapes[i].p[1]**2 + modelL.lineshapes[i].p[2]**2)/modelT.lineshapes[i].p[1]**2

        set_printoptions(precision=2)
        print("LST Ratios = ", ratios)
        print("Prod of ratios =", prod(ratios))
    else:
        print("Can't compute gLST ratios, number of lineshapes in transverse not equal to number in longitudinal")

#----------------------------------------------------------------------------------------------------
def gLST_LHS(modelL,modelT):
    '''calculate the left hand side of the GLST equation'''

    numerator   = ones(modelL.numlineshapes)
    denominator = ones(modelT.numlineshapes)

    for i in range(modelL.numlineshapes):
        if modelL.lineshapes[i].type == "Debye":
            numerator[i] = modelL.lineshapes[i].p[1]

        if (modelL.lineshapes[i].type == "DHO") or (modelL.lineshapes[i].type == "VanVleck") or (modelL.lineshapes[i].type == "BrendelDHO"):
            numerator[i] = (modelL.lineshapes[i].p[1]**2 + modelL.lineshapes[i].p[2]**2)

    for i in range(modelT.numlineshapes):
        if modelT.lineshapes[i].type == "Debye":
            denominator[i] = modelT.lineshapes[i].p[1]

        if (modelT.lineshapes[i].type == "DHO") or (modelT.lineshapes[i].type == "VanVleck") or (modelT.lineshapes[i].type == "BrendelDHO"):
            denominator[i] = modelT.lineshapes[i].p[1]**2

    return prod(numerator)/prod(denominator)

##----------------------------------------------------------------------------------
##----- Printout all frequencies in system and left side of gLST equation  --------
##----------------------------------------------------------------------------------
def print_gLST_LHS_stuff(modelL, modelT, Tdatarp, Tdatacp):

    print("longitudinal model:")
    modelL.print_model()
    print("transverse model:")
    modelT.print_model()

    print_gLST_ratios(modelL, modelT)

    eps0    = Tdatarp[0]
    eps_inf = Tdatarp[-1]
    gLST_RHS = eps0/eps_inf

    print("LST LHS = %6.2f" % gLST_LHS(modelL,modelT))
    print("LST RHS = %6.2f" %  gLST_RHS)

#-------------------------------------------------------------------------------------------------------------
def plot_model(model,dataX,dataYrp,dataYcp,Myhandle,xmin=None,xmax=None,xscale='linear',yscale='log',ymin=None,ymax=None,show=False,Block=True,longitudinal=False,title='',peaks=[]):
    """displays a pretty plot of the real and complex parts of the model and data using matplotlib

    args:
        model: a spectral_model object
        dataX: a numpy array giving the experimental x-data
        dataYrp: a numpy array giving the real part of the experimental y-data
        dataYcp: a numpy array giving the complex part of the experimental y-data
        handle: an integer giving the plot window number
        xmin: scalar, minimum frequency to plot
        xmax: scalar, maximum frequency to plot
        xscale: string, xscale type 'linear' or 'log'
        yscale: string, yscale type 'linear' or 'log'
        show: logical, option to display plot
        blockoption: logical, option to block further processing after displaying window (Default True, False is experimental)
        """
    if (xmin == None):
        xmin = min(dataX)
    if (xmax == None):
        xmax = max(dataX)
    if (ymin == None):
        ymin = min(dataYrp)/600
    if (ymax == None):
        ymax = max(dataYrp)
    if (xscale == 'log'):
        plotomegas = logspace(log10(xmin), log10(xmax), 10000)
    else:
        plotomegas = linspace(xmin, xmax, 10000)

    #if (longitudinal == True):
    #    (rp, cp) = model.longeps(plotomegas)
    #    denom = dataYrp**2 + dataYcp**2
    #    (dataYrp,dataYcp) = (dataYrp/denom, dataYcp/denom)
    #    (xmin,xmax) = (min(dataX),max(dataX))
    #    (ymin,ymax) = (min(dataYrp),max(dataYrp))
    #else:
    (rp, cp) = model(plotomegas)

    # Two subplots, unpack the axes array immediately
    f, (ax1, ax2) = plt.subplots(nrows=2, sharex=True, sharey=False )

    ax1.plot(dataX, dataYrp, "g", plotomegas, rp,'b')
    #ax1.set_title('Real part')

    ax2.plot(dataX, dataYcp, "g", plotomegas, cp,'b')
    #ax2.set_title('Complex part')

    #plot all of the components
    for lineshape in model.lineshapes:
        (rpPart, cpPart) = lineshape(plotomegas)
        ax1.plot(plotomegas, rpPart ,'b--',linewidth=1)
        ax2.plot(plotomegas, cpPart ,'b--',linewidth=1)

    ax1.set_xscale(xscale)
    ax1.set_xlim([xmin,xmax])
    ax1.set_yscale(yscale)
    ax1.set_ylim([ymin,ymax])

    ax2.set_xscale(xscale)
    ax2.set_xlim([xmin,xmax])
    ax2.set_yscale(yscale)
    ax2.set_ylim([ymin,ymax])

    ax1.set_xlabel(r"$\omega$ (cm$^{-1}$)")
    ax2.set_xlabel(r"$\omega$ (cm$^{-1}$)")

    if (longitudinal == True):
        ax1.set_ylabel(r"Re$\lbrace\frac{1}{\varepsilon(\omega)}\rbrace$")
        ax2.set_ylabel(r"Im$\lbrace\frac{1}{\varepsilon(\omega)}\rbrace$")
    else:
        ax1.set_ylabel(r"Re$\lbrace\varepsilon(\omega)\rbrace$")
        ax2.set_ylabel(r"Im$\lbrace\varepsilon(\omega)\rbrace$")

    ax1.set_title(title)

   #ax.annotate('local max', xy=(3, 1),  xycoords='data')

#-----------------------------------------------------------------------
# Function to find the maxima of a dataset by looking where the sign of the slope changes
#-----------------------------------------------------------------------
def find_peaks(dataset,omegas):
    #Smooth dataset
    smoothing_length = 5
    dataset = np.convolve(dataset, np.ones(smoothing_length)/smoothing_length)

   # lowess = sm.nonparametric.lowess(dataset, omegas, frac=0.5)
    #dataset = lowess[:,1]

    npoints = len(dataset)
    data_shift = np.r_[0, dataset]
    diff = data_shift[0:npoints] - dataset
    peaks = []
    npoints = len(omegas) -1
    for i in range(0, npoints):
        if np.sign(diff[i]) != np.sign(diff[i+1]):
            #check if in useful range
            if ( 580 <= omegas[i] <= 1000 ) | ( 3000 <= omegas[i] <= 3500 ): #(1500 <= omegas[i] <= 1700)
                peaks =  peaks + [(omegas[i] + omegas[i+1])/2]
    return peaks