# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import
import re

from django import forms
from django.core import validators
from django.db import IntegrityError
from django.forms import ModelForm

from crispy_forms.bootstrap import StrictButton
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Field

from .models import Quote

class QuoteForm(ModelForm):
    """
    Form for sending a new message
    """
    message = forms.CharField(label='Desahógate aquí',
                              max_length=140,
                              initial='Me caga ')

    class Meta:
        model = Quote
        fields = ['message',]

    def __init__(self, *args, **kwargs):
        super(QuoteForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = True
        self.helper.html5_required = True
        self.helper.layout = Layout(
            Field('message', style="width: 680px;"),
            StrictButton('Enviar', type="submit", name="submit-btn", css_class="btn-primary")
        )

    def clean_message(self):
        """
        Checks for a valid message
        """
        quote = self.cleaned_data['message']
        if not quote:
            raise forms.ValidationError("Me caga que intentes enviar un mensaje vacío.")
        # check for quotes without the primary words
        phrase = re.compile(r'me\s+caga', re.I)
        if not phrase.match(quote):
            raise forms.ValidationError("Mensaje inválido. Sólo dinos qué te caga.")
        # check for short or empty quote
        if quote.lower() == 'me caga' or len(quote) <= 7:
            raise forms.ValidationError("Tu mensaje es demasiado corto.")
        # check for long quotes
        if len(quote) > 140:
            raise forms.ValidationError("Tu mensaje esta demasiado largo. Dinos qué te caga en 140 caracteres.")
        # check for urls
        if re.search(r'(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?', quote):
            raise forms.ValidationError("A mi me caga que pongas URLs en tu mensaje.")
        # check for emails
        if re.search(r'([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})', quote):
            raise forms.ValidationError('Me caga que pongas emails en tu mensaje.')
        return self.cleaned_data['message']


import sys

import os
from django.shortcuts import render, redirect
from .models import Image, Theme
from .forms import ImageForm, ThemeForm

# Create your views here.
def index(request):
    return render(request, 'settings_index.html', {})

def themes_index(request):
    themes = Theme.objects.all().order_by('name')
    return render(request, 'themes_index.html', {'themes': themes})

def themes_add(request):
    if not request.method == "POST":
        form = ThemeForm()
        return render(request, 'themes_add.html', {'form': form})
    else:
        form = ThemeForm(request.POST)
        if form.is_valid():
            i = Theme()
            i.name = form.cleaned_data['name']
            i.description = form.cleaned_data['description']
            i.save()
            return redirect('/settings/themes')
        else:
            return render(request, 'themes_add.html', {'form': form})

def themes_delete(request, id):
    theme = Theme.objects.get(pk=id)
    theme.delete()
    return redirect('/settings/themes')

def images_index(request):
    images = Image.objects.all().order_by('theme')
    return render(request, 'images_index.html', {'images': images})

def images_add(request):
    if not request.method == "POST":
        form = ImageForm()
        return render(request, 'images_add.html', {'form': form})
    else:
        form = ImageForm(request.POST, request.FILES)
        if form.is_valid():
            i = Image()
            i.image = form.cleaned_data['image']
            i.theme = form.cleaned_data['theme']
            i.save()
            return redirect('/settings/images')
        else:
            return render(request, 'images_add.html', {'form': form})

def images_delete(request, id):
    image = Image.objects.get(pk=id)
    if os.path.isfile(image.image.path):
        os.remove(image.image.path)
    image.delete()
    return redirect('/settings/images')


import json

states = {
    "Andhra Pradesh": "Hyderabad",
    "Karnataka": "Bengaluru",
    "Maharashtra": "Mumbai",
    "Odisha": "Bhubaneswar",
    "Punjab": "Chandigarh",
    "Tamil Nadu": "Chennai",
    "Uttar Pradesh": "Lucknow"
}

with open('states.json', 'w') as f:
    json.dump(states, f)


import logging

import module_a
from utils import MyLogger

logger = MyLogger(name=__name__)
logger.setLevel(logging.DEBUG)
logger.debug("This is debug from main")
logger.info("This is info from main")

def divide_func(x,y):
    try:
        result = x / y
    except ZeroDivisionError:
        logger.exception(f"Cannot divide x={x} with y={y}")
    else:
        return result
divide_func(10,0)


# -*- coding: utf-8 -*-
"""
Created on Fri May 22 11:16:18 2020

@author: Mack Pro
"""

import random

import matplotlib.pyplot as plt
import numpy as npy

import volmdlr as volmdlr
import volmdlr.primitives2D as primitives2D
import volmdlr.primitives3D as primitives3D

######## SWEEP TEST RANDOM

nb_point1, nb_point2 = 6, 5

radius_circle1, radius_circle2 = 0.008, 0.01
c1 = volmdlr.Circle2D(volmdlr.Point2D((0,0)), radius_circle1)
contour1 = volmdlr.Contour2D([c1])

c2 = volmdlr.Circle2D(volmdlr.Point2D((0,0)), radius_circle2)
contour2 = volmdlr.Contour2D([c2])

mini, maxi = -1, 1
pts1 = []
for k in range (nb_point1):
    a1, a2, a3 = random.randint(mini, maxi), random.randint(mini, maxi), random.randint(mini, maxi)
    c1, c2, c3 = random.randrange(0,100,1), random.randrange(0,100,1), random.randrange(0,100,1)
    pts1.append(volmdlr.Point3D((a1*c1/100, a2*c2/100, a3*c3/100)))

radius1 = {1: 0.03, 2: 0.01, 3: 0.07, 4: 0.01}#, 5: 0.07, 6: 0.02, 7: 0.03, 8: 0.04}
rl1 = primitives3D.OpenedRoundedLineSegments3D(pts1, radius1, adapt_radius=True, name='wire1')
sweep1 = primitives3D.Sweep(contour1, rl1, name = 'pipe1')

pts2 = []
for k in range (nb_point2):
    a1, a2, a3 = random.randint(mini, maxi), random.randint(mini, maxi), random.randint(mini, maxi)
    c1, c2, c3 = random.randrange(0,100,1), random.randrange(0,100,1), random.randrange(0,100,1)
    pts2.append(volmdlr.Point3D((a1*c1/100, a2*c2/100, a3*c3/100)))

radius2 = {1: 0.01, 2: 0.05, 3: 0.06}#, 4: 0.02, 5: 0.01, 6: 0.03}
rl2 = primitives3D.OpenedRoundedLineSegments3D(pts2, radius2, adapt_radius=True, name='wire2')
sweep2 = primitives3D.Sweep(contour2, rl2, name = 'pipe2')

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
for prim1 in rl1.primitives :
    prim1.MPLPlot(ax=ax)
for prim2 in rl2.primitives :
    prim2.MPLPlot(ax=ax)

minimum_distance = rl1.minimum_distance(rl2)
print('minimum_distance', minimum_distance)

try:
    distance_sweep = sweep1.distance_to_shell(sweep2)
    print('distance_sweep', distance_sweep.distance)

    pt1, pt2 = distance_sweep.points

    dmin, p1 ,p2 = sweep1.faces[0].minimum_distance(sweep2.faces[0], return_points=True)
    face_min1, face_min2 = sweep1.faces[0], sweep2.faces[0]
    # print('dmin', dmin)
    for face1 in sweep1.faces :
        for face2 in sweep2.faces :
            dtest, ptest1, ptest2 = face1.minimum_distance(face2, return_points=True)
            # print('dtest', dtest)
            if dtest < dmin :
                p1, p2 = ptest1, ptest2
                dmin = dtest
                face_min1, face_min2 = face1, face2

    print('distancep1p2', (p1-p2).Norm())

    pt1.MPLPlot(ax=ax, color='g')
    pt2.MPLPlot(ax=ax, color='g')
    p1.MPLPlot(ax=ax, color='r')
    p2.MPLPlot(ax=ax, color='r')

    # model=volmdlr.VolumeModel([sweep1, sweep2])

    # model.babylonjs()

    vol = volmdlr.VolumeModel([sweep1, sweep2, p1, p2])
    vol.babylonjs_from_script()

    vol = volmdlr.VolumeModel([sweep1, sweep2, pt1, pt2])
    vol.babylonjs_from_script()
except AttributeError:
    print('Nothing was tested,  CylindricalFace3D object has no attribute linesegment_intersection')


import math

import torch
import torch.nn as nn
import numpy as np
import torch.nn.functional as F
#from  attention_is_all_you_need_pytorch_master.transformer.Modules import ScaledDotProductAttention
#from attention_is_all_you_need_pytorch_master.transformer.SubLayers import MultiHeadAttention
torch.set_printoptions(sci_mode=False)

class AttFeatTrans(nn.Module):
    def __init__(self, config, name):
        super(AttFeatTrans,self).__init__()
        self.config = config
        self.name = name
        self.head = config.num_head
        # some setting
        self.in_feat_dim = config.in_feat_dim
        self.feat_dim = config.feat_dim  # don't know where it is manifested since then
        self.query = nn.Linear(self.in_feat_dim, self.in_feat_dim, bias=config.qk_have_bias)
        self.key = nn.Linear(self.in_feat_dim, self.in_feat_dim, bias=config.qk_have_bias)
        self.value = nn.Linear(self.in_feat_dim, self.in_feat_dim, bias = config.v_has_bias)
        #self.out_trans = MultiHeadAttention(self.head, self.in_feat_dim * self.head, self.in_feat_dim, self.in_feat_dim, dropout=0.1) #some dim in it
        self.att_dropout = nn.Dropout(config.attention_probs_dropout_prob)
        self.feat_dim_onehead = self.in_feat_dim // self.head

        self.intermediate = config.act_fun #gelu
        self.tie_qk_scheme = config.tie_qk_scheme  #not use it first
        print("{} in_feat_dim: {}, feat_dim: {}, qk_have_bias: {}".format(
        self.name, self.in_feat_dim, self.feat_dim, config.qk_have_bias))

    def tie_qk(self, tie_qk_scheme=None):
        # override config.tie_qk_scheme
        if tie_qk_scheme is not None:
            self.tie_qk_scheme = tie_qk_scheme

        print("Initialize QK scheme: {}".format(self.tie_qk_scheme))
        if self.tie_qk_scheme == 'shared':
            self.key.weight = self.query.weight
            if self.key.bias is not None:
                self.key.bias = self.query.bias

        elif self.tie_qk_scheme == 'loose':
            self.key.weight.data.copy_(self.query.weight)
            if self.key.bias is not None:
                self.key.bias.data.copy_(self.query.bias)

    def transpose_for_scores(self, x):
        x_new_shape = x.size()[:-1] + (self.head, -1)
        x = x.view(*x_new_shape)
        return x.permute(0, 2, 1, 3)

    def forward(self, in_query, in_key=None, pos_biases=None): #[50,256,768] [50,1,768]
        if in_key is None:
            in_key = in_query

        mixed_query_feat = self.query(in_query) #[50,256,768]
        mixed_key_feat = self.key(in_key)       #[50,1,768]
        v_first_feat = self.value(in_key)       #[50,1,768]#q,v will same?  infact the dim of qv not same
        '''
        n_head = self.head
        B = in_query.shape[0]
        D = in_query.shape[2]
        q = mixed_query_feat.view(B, n_head , -1 , D)
        k = mixed_key_feat.view(B, n_head, -1, D)
        v = mixed_value_feat.view(B, n_head, -1, D)
        '''
        q = self.transpose_for_scores(mixed_query_feat) #[50 2 256 384]
        k = self.transpose_for_scores(mixed_key_feat)   #[50 2 1 384]
        att_score = torch.matmul(q,k.transpose(-1, -2))
        #output = self.out_trans(mixed_query_feat,mixed_key_feat,mixed_value_feat)
        att_score = att_score / math.sqrt(q.shape[3])  #[50 2 256 1]
        attention_probs = F.softmax(att_score, dim=-1)
        attention_probs = self.att_dropout(attention_probs) #[50 2 256 1]

        # about v(f)
        v_first_feat = v_first_feat.permute(0, 2, 1)  #[50 786 1]
        shape_4d = (v_first_feat.shape[0], self.head, self.feat_dim_onehead, v_first_feat.shape[2]) # [50 2 384 1]
        v_first_feat_4d = v_first_feat.view(shape_4d).permute([0, 1, 3, 2]) #[50 2 1 384]
        v_first_feat_fusion = torch.matmul(attention_probs, v_first_feat_4d) #[50, 2, 256, 384]
        #v_first_feat_fusion_3d = v_first_feat_fusion.permute([0, 1, 3, 2]).reshape(v_first_feat.shape)
        v_first_feat_fusion_3d = v_first_feat_fusion.permute([0, 1, 3, 2]).reshape(v_first_feat.shape[0],v_first_feat.shape[1], -1) # 50 768 256
        v_first_feat = v_first_feat_fusion_3d.permute([0,2,1]) #50 256 768

        v_mid_feat = self.intermediate(v_first_feat) #gelu #50 256 768
        v_last_feat = v_mid_feat + v_first_feat #res #50 256 768
        v_trans_feat = v_last_feat  #50 256 768
        trans_feat = v_trans_feat.squeeze(1) #50 256 768
        return trans_feat

class InitWeights(nn.Module):
    def __init__(self, config, *inputs, **kwargs):
        super(InitWeights, self).__init__()
        self.config = config
        self.act_fun = F.gelu

    def init_weights(self, module):
            if isinstance(module, (nn.Linear, nn.Embedding)):
                if (np.array(module.weight.shape) < self.config.min_feat_dim).all():
                    print("Skip init of Linear weight %s" % (list(module.weight.shape)))
                else:
                    base_initializer_range = self.config.base_initializer_range
                    module.weight.data.normal_(mean=0.0, std=base_initializer_range)
                # Slightly different from the TF version which uses truncated_normal
                # for initialization cf https://github.com/pytorch/pytorch/pull/5617
            if isinstance(module, nn.Linear) and module.bias is not None:
                module.bias.data.zero_()

    def tie_qk(self, module):
            if isinstance(module, AttFeatTrans) and module.tie_qk_scheme != 'none':
                module.tie_qk()
    '''
        def add_identity_bias(self, module):
            if isinstance(module, AttFeatTrans) or isinstance(module, ExpandedFeatTrans):
                module.add_identity_bias()
     '''


from urllib.request import urlopen
from datetime import datetime
from monitor.models import client, leftClient

# ===========================================================================
# Check the availability of existing clients
# ===========================================================================
def check_client_availability():
	all_clients = client.objects.all()
	for cl in all_clients:
		check_url = "http://%s:8717/latest" % cl.ip
		print(check_url)
		print("[Client-INFO]Checking Client " + cl.name + " availability!")
		try:
			rsp = urlopen(check_url)
			cl.last_visit = datetime.now()
			cl.save()
		except:
			print("[Client-INFO]Client " + cl.name + " leaves the system!")
			num_results = leftClient.objects.filter(ip=cl.ip).count()
			if num_results > 0:
				cur_obj = leftClient.objects.filter(ip=cl.ip)[0]
				cur_obj.left_ts = datetime.now()
				cur_obj.save()
			else:
				left_cl = leftClient(name=cl.name, ip=cl.ip)
				left_cl.save()
			pass


import torch.nn as nn

class CompletionNetwork(nn.Module):

    def __init__(self):
        super(CompletionNetwork, self).__init__()
        # input shape: (None, 4, height, width), with mask
        # output (input_channel, output_channel)
        self.conv1 = nn.Conv2d(4, 64, kernel_size=5, stride=1, padding=2)
        self.bn1 = nn.BatchNorm2d(64)
        self.act1 = nn.ReLU()

        self.conv2 = nn.Conv2d(64, 128, kernel_size=3, stride=2, padding=1)
        self.bn2 = nn.BatchNorm2d(128)
        self.act2 = nn.ReLU()

        self.conv3 = nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1)
        self.bn3 = nn.BatchNorm2d(128)
        self.act3 = nn.ReLU()

        self.conv4 = nn.Conv2d(128, 256, kernel_size=3, stride=2, padding=1)
        self.bn4 = nn.BatchNorm2d(256)
        self.act4 = nn.ReLU()

        self.conv5 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.bn5 = nn.BatchNorm2d(256)
        self.act5 = nn.ReLU()

        self.conv6 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.bn6 = nn.BatchNorm2d(256)
        self.act6 = nn.ReLU()

        self.conv7 = nn.Conv2d(256, 256, kernel_size=3, stride=1, dilation=2, padding=2)
        self.bn7 = nn.BatchNorm2d(256)
        self.act7 = nn.ReLU()

        self.conv8 = nn.Conv2d(256, 256, kernel_size=3, stride=1, dilation=4, padding=4)
        self.bn8 = nn.BatchNorm2d(256)
        self.act8 = nn.ReLU()

        self.conv9 = nn.Conv2d(256, 256, kernel_size=3, stride=1, dilation=8, padding=8)
        self.bn9 = nn.BatchNorm2d(256)
        self.act9 = nn.ReLU()

        self.conv10 = nn.Conv2d(256, 256, kernel_size=3, stride=1, dilation=16, padding=16)
        self.bn10 = nn.BatchNorm2d(256)
        self.act10 = nn.ReLU()

        self.conv11 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.bn11 = nn.BatchNorm2d(256)
        self.act11 = nn.ReLU()

        self.conv12 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.bn12 = nn.BatchNorm2d(256)
        self.act12 = nn.ReLU()

        # deconv
        self.deconv13 = nn.ConvTranspose2d(256, 128, kernel_size=4, stride=2, padding=1)
        self.bn13 = nn.BatchNorm2d(128)
        self.act13 = nn.ReLU()

        self.conv14 = nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1)
        self.bn14 = nn.BatchNorm2d(128)
        self.act14 = nn.ReLU()

        self.deconv15 = nn.ConvTranspose2d(128, 64, kernel_size=4, stride=2, padding=1)
        self.bn15 = nn.BatchNorm2d(64)
        self.act15 = nn.ReLU()

        self.conv16 = nn.Conv2d(64, 32, kernel_size=3, stride=1, padding=1)
        self.bn16 = nn.BatchNorm2d(32)
        self.act16 = nn.ReLU()

        # output layer (None, 3, height. width)
        self.conv17 = nn.Conv2d(32, 3, kernel_size=3, stride=1, padding=1)
        self.act17 = nn.Sigmoid()

    def forward(self, x):
        x = self.bn1(self.act1(self.conv1(x)))
        x = self.bn2(self.act2(self.conv2(x)))
        x = self.bn3(self.act3(self.conv3(x)))
        x = self.bn4(self.act4(self.conv4(x)))
        x = self.bn5(self.act5(self.conv5(x)))
        x = self.bn6(self.act6(self.conv6(x)))
        x = self.bn7(self.act7(self.conv7(x)))
        x = self.bn8(self.act8(self.conv8(x)))
        x = self.bn9(self.act9(self.conv9(x)))
        x = self.bn10(self.act10(self.conv10(x)))
        x = self.bn11(self.act11(self.conv11(x)))
        x = self.bn12(self.act12(self.conv12(x)))
        x = self.bn13(self.act13(self.deconv13(x)))
        x = self.bn14(self.act14(self.conv14(x)))
        x = self.bn15(self.act15(self.deconv15(x)))
        x = self.bn16(self.act16(self.conv16(x)))
        x = self.act17(self.conv17(x))
        return x

if __name__ == '__main__':
    net = CompletionNetwork()
    print(net)


from sklearn.metrics import matthews_corrcoef #计算MCC
from sklearn.metrics import confusion_matrix, accuracy_score, matthews_corrcoef, recall_score, roc_curve, roc_auc_score
from sklearn.metrics.ranking import auc
import pandas  as pd
import matplotlib.pyplot as plt
test_label=pd.read_csv("_label.csv", header=None)
print(test_label.shape)

p=pd.read_csv("test.csv", header=None)
p=p.iloc[:,2]
print(p.shape)
pp=[i>0.5 for i in p]
fpr, tpr, threshold = roc_curve(test_label, p)
roc_auc = auc(fpr, tpr)
print("MCC: %f " %matthews_corrcoef(test_label,pp))
print("AUC",roc_auc)

plt.figure(figsize=(10,10))
plt.plot(fpr, tpr, color='red',lw=2, label='PPIformer :ROC curve (area = %0.2f)' % roc_auc) ###假正率为横坐标，真正率为纵坐标做曲线
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC curve comparison of the models')
'''
#Data  A
Ctest_label=pd.read_csv("_label.csv", header=None)
print(Ctest_label.shape)
Cp=pd.read_csv("test_111_2.csv", header=None)
Cp=Cp.iloc[:,2]
print(Cp.shape)
fpr, tpr, threshold = roc_curve(Ctest_label, Cp)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color='green',lw=2, label='without Data Augmentation :ROC curve (area = %0.2f)' % roc_auc)##假正率为横坐标，真正率为纵坐标做曲线

'''
#RF
Ctest_label=pd.read_csv("RF_label.csv", header=None)
print(Ctest_label.shape)
Cp=pd.read_csv("RF.csv", header=None)
Cp=Cp.iloc[:,1]
print(Cp.shape)
fpr, tpr, threshold = roc_curve(Ctest_label, Cp)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color='green',lw=2, label='RF:ROC curve (area = %0.2f)' % roc_auc)##假正率为横坐标，真正率为纵坐标做曲线

#textCNN
Ctest_label=pd.read_csv("CNN_label.csv", header=None)
print(Ctest_label.shape)
Cp=pd.read_csv("CNN2.csv", header=None)
Cp=Cp.iloc[:,2]
print(Cp.shape)
fpr, tpr, threshold = roc_curve(Ctest_label, Cp)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color='blue',lw=2, label='TextCNN:ROC curve (area = %0.2f)' % roc_auc) ###假正率为横坐标，真正率为纵坐标做曲线
#svm
Ctest_label=pd.read_csv("SVM_label.csv", header=None)
print(Ctest_label.shape)
Cp=pd.read_csv("SVM.csv", header=None)
Cp=Cp.iloc[:,0]
print(Cp.shape)
fpr, tpr, threshold = roc_curve(Ctest_label, Cp)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color='orange',lw=2, label='SVM:ROC curve (area = %0.2f)' % roc_auc) ###假正率为横坐标，真正率为纵坐标做曲线

#DNN
Ctest_label=pd.read_csv("DNN_label.csv", header=None)
print(Ctest_label.shape)
Cp=pd.read_csv("DNN2.csv", header=None)
Cp=Cp.iloc[:,2]
print(Cp.shape)
fpr, tpr, threshold = roc_curve(Ctest_label, Cp)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color='pink',lw=2, label='DNN:ROC curve (area = %0.2f)' % roc_auc) ###假正率为横坐标，真正率为纵坐标做曲线
#LR
Ctest_label=pd.read_csv("LR_label.csv", header=None)
print(Ctest_label.shape)
Cp=pd.read_csv("LR.csv", header=None)
Cp=Cp.iloc[:,1]
print(Cp.shape)
fpr, tpr, threshold = roc_curve(Ctest_label, Cp)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color='yellow',lw=2, label='LR:ROC curve (area = %0.2f)' % roc_auc) ###假正率为横坐标，真正率为纵坐标做曲线
#lstm
Ctest_label=pd.read_csv("lstm_label.csv", header=None)
print(Ctest_label.shape)
Cp=pd.read_csv("lstm10.csv", header=None)
Cp=Cp.iloc[:,1]
print(Cp.shape)
fpr, tpr, threshold = roc_curve(Ctest_label, Cp)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color='purple',lw=2, label='LSTM:ROC curve (area = 0.52)' )
plt.legend(loc=0)
plt.legend(loc="lower right")
plt.show()


from numba import njit
from settings import *
from player import Player
from enemy import Enemy
import pygame
import numpy

@njit
def _display(player_x: float, player_y: float, player_angle: float, textures: numpy.ndarray, map: numpy.ndarray, frame: numpy.ndarray) -> numpy.ndarray:
	for vert_ray in range(VERT_NUM_RAYS):
		angle = player_angle + numpy.deg2rad(vert_ray / FOV - 30)

		sin = numpy.sin(angle)
		cos = numpy.cos(angle)
		fov_cos = numpy.cos(numpy.deg2rad(vert_ray / FOV - 30))

		x, y = player_x, player_y
		while not map[int(x)][int(y)]:
			x, y = x + cos * 0.02, y + sin * 0.02

		n = abs((x - player_x) / cos)
		height = int(HOR_NUM_RAYS / (fov_cos * n + 0.0001))

		xx = int(x * 2 % 1 * (TEXTURE_RES - 1))
		if x % 1 < 0.02 or x % 1 > 0.98:
			xx = int(y * 2 % 1 * (TEXTURE_RES - 1))
		yy = numpy.linspace(0, (TEXTURE_RES - 1) * 2, height * 2) % (TEXTURE_RES - 1)

		shade = 0.3 + (height / HOR_NUM_RAYS) * 0.7
		if shade > 1: shade = 1

		for k in range(height * 2):
			if HOR_NUM_RAYS - height + k >= 0 and HOR_NUM_RAYS - height + k < HOR_NUM_RAYS * 2:
				frame[vert_ray][HOR_NUM_RAYS - height + k] = shade * textures[1][xx][int(yy[k])]

		for hor_ray in range(HOR_NUM_RAYS - height):
			n = (HOR_NUM_RAYS / (HOR_NUM_RAYS - hor_ray)) / fov_cos
			x, y = player_x + cos * n, player_y + sin * n
			xx, yy = int(x * 2 % 1 * (TEXTURE_RES - 1)), int(y * 2 % 1 * (TEXTURE_RES - 1))
			shade = 0.2 + 0.8 * (1 - hor_ray / HOR_NUM_RAYS)

			frame[vert_ray][HOR_NUM_RAYS * 2 - hor_ray - 1] = shade * textures[0][xx][yy]
			frame[vert_ray][hor_ray] = shade * textures[2][xx][yy]

	return frame

def display(player: Player, enemies: list[Enemy], wall_textures: numpy.ndarray, enemy_textures: numpy.ndarray, map: numpy.ndarray, screen: pygame.Surface) -> numpy.ndarray:
	frame = numpy.empty((VERT_NUM_RAYS, HOR_NUM_RAYS * 2, 3))
	frame = _display(player.x, player.y, player.angle, wall_textures, map, frame)

	surface = pygame.surfarray.make_surface(frame * 255)
	surface = pygame.transform.scale(surface, RES)

	screen.blit(surface, (0, 0))

	for enemy in enemies:
		enemy_angle = numpy.arctan((enemy.y - player.y) / (enemy.x - player.x))
		if abs(player.x + numpy.cos(enemy_angle) - enemy.x) > abs(player.x - enemy.x):
			enemy_angle = (enemy_angle - numpy.pi) % (numpy.pi * 2)
		angle_difference = (player.angle - enemy_angle) % (numpy.pi * 2)

		if angle_difference > numpy.pi * 11 / 6 or angle_difference < numpy.pi / 6:
			distance = numpy.sqrt((player.x - enemy.x) ** 2 + (player.y - enemy.y) ** 2)
			enemy.angle_difference, enemy.distance = angle_difference, 1 / distance

			# cos, sin = 0.01 * (player.x - enemy.x) / distance, 0.01 * (player.y - enemy.y) / distance
			# for _ in range(int(distance / 0.01)):
			# 	x, y = enemy.x + cos, enemy.y + sin
			# 	if map[int(x)][int(y)]:
			# 		enemy.distance = 999
		else:
			enemy.distance = 999

	enemies = sorted(enemies, key = lambda enemy: enemy.distance)
	for index, enemy in enumerate(enemies):
		if enemy.distance > MAP_SIZE:
			break

		scaling = min(enemy.distance, 2) / numpy.cos(enemy.angle_difference)
		x = HALF_WIDTH - WIDTH * numpy.sin(enemy.angle_difference) - TEXTURE_RES * scaling / 2
		y = HALF_HEIGHT + HALF_HEIGHT * scaling - TEXTURE_RES * scaling / 2
		surface = pygame.transform.scale(enemy_textures[int(enemy.index)], (TEXTURE_RES * scaling, TEXTURE_RES * scaling))

		screen.blit(surface, (x, y))

		if player.shooting_state:
			if x < HALF_WIDTH < x + TEXTURE_RES * scaling:
				enemy.health -= 1
				if enemy.health <= 0:
					enemies = numpy.delete(enemies, index)
				player.shooting_state = False
	player.shooting_state = False

	return enemies


import owncloud
import argparse
import numpy as np
import pickle
import json
import csv
import sys
import os

def setup_cmdline_parser():
    parser = argparse.ArgumentParser(description='Submission system setup!')
    parser.add_argument(
        '--student_link_file',
        dest='student_link_file',
        default=None,
        help='Student pickle file with link and path information')
    parser.add_argument(
        '--config_file',
        dest='config_file',
        default=None,
        help='JSON config file (e.g., config.json)')
    args = parser.parse_args()
    return args

def main(argv):
    args = setup_cmdline_parser()

    assert args.config_file is not None
    if not os.path.exists(args.config_file):
        print('Config file {} not found!'.format(args.config_file))
        sys.exit(-1)

    with open(args.config_file) as json_file:
        data = json.load(json_file)
        url = data['url']
        login = data['user']
        app_key = data['app_key']

    oc = owncloud.Client(url)
    oc.login(login, app_key)

    students = pickle.load( open( args.student_link_file, "rb" ) )
    for k,v in students.items():
        share_list = oc.get_shares(v['path'])
        if len(share_list)>0:
            oc.delete_share(share_list[0].get_id())

if __name__ == '__main__':
    main(sys.argv)


import os
import fixtures
import tarfile
import threading

from pyftpdlib import (
    authorizers,
    handlers,
    servers
)

from testtools.matchers import (
    DirExists,
    FileContains,
    FileExists
)

from snapcraft.tests import integration

class FtpServerRunning(fixtures.Fixture):

    def __init__(self, directory):
        super().__init__()
        self.directory = directory

    def setUp(self):
        super().setUp()
        self._start_ftp_server()

    def _start_ftp_server(self):
        authorizer = authorizers.DummyAuthorizer()
        authorizer.add_anonymous(self.directory)
        handler = handlers.FTPHandler
        handler.authorizer = authorizer
        self.server = servers.FTPServer(('', 2121), handler)

        server_thread = threading.Thread(target=self.server.serve_forever)
        server_thread.start()
        self.addCleanup(self._stop_ftp_server, server_thread)

    def _stop_ftp_server(self, thread):
        self.server.close_all()
        thread.join()

class DumpPluginTestCase(integration.TestCase):

    def test_stage_dump_plugin(self):
        self.run_snapcraft('stage', 'dump')

        expected_files = [
            'flat',
            os.path.join('flatdir', 'flat2'),
            'onedeep',
            os.path.join('onedeepdir', 'onedeep2'),
            'oneflat',
            'top-simple',
            'notop',
            'parent',
            'slash',
            'readonly_file',
        ]
        for expected_file in expected_files:
            self.assertThat(
                os.path.join(self.stage_dir, expected_file),
                FileExists())
        expected_dirs = [
            'dir-simple',
            'notopdir',
        ]
        for expected_dir in expected_dirs:
            self.assertThat(
                os.path.join(self.stage_dir, expected_dir),
                DirExists())

        # Regression test for
        # https://bugs.launchpad.net/snapcraft/+bug/1500728
        self.run_snapcraft('pull')

    def test_download_file_with_content_encoding_set(self):
        """Download a file with Content-Encoding: gzip LP: #1611776"""
        self.run_snapcraft('pull', 'compressed-content-encoding')

    def test_download_file_from_ftp_source(self):
        """Download a file from a FTP source, LP: #1602323"""
        ftp_dir = os.path.join(self.path, 'ftp')
        os.mkdir(ftp_dir)
        ftp_server = FtpServerRunning(ftp_dir)
        self.useFixture(ftp_server)

        test_file_path = os.path.join(self.path, 'test')
        with open(test_file_path, 'w') as test_file:
            test_file.write('Hello ftp')
        with tarfile.open(os.path.join(ftp_dir, 'test.tar.gz'), 'w:gz') as tar:
            tar.add(test_file_path)

        self.run_snapcraft('pull', 'ftp-source')
        self.assertThat(
            os.path.join(self.parts_dir, 'ftp-part', 'src', 'test'),
            FileContains('Hello ftp'))


import io
import os
import requests
import urllib.request
from bs4 import BeautifulSoup
import random
import string
from google.cloud import vision
from os import listdir
from imageHTML import downloadImg, generateName, uploadFile

# Imports the Google Cloud client library
from google.cloud import storage

# Collects data from images and organizes it
def cVision(safe, labels):
    #safe search check
    adultContent.add(safe.adult)
    medicalContent.add(safe.medical)
    spoofedContent.add(safe.spoof)
    violentContent.add(safe.violence)
    racyContent.add(safe.racy)

class Statistic(object):

    vLikely = 5
    likely = 4
    possible = 3
    unlikely = 2
    vUnlikely = 1
    unknown = 0

    def __init__ (self, cat):
        self.cat = cat
        self.data = [0,0,0,0,0,0]
        self.total = 0;
        self.possible = 0;

    def add(self, input):
        self.data[input] += 1
        self.total += 1

# Instantiates storage and vision clients
storage_client = storage.Client()
client = vision.ImageAnnotatorClient()

# Stats to be collected
adultContent = Statistic("adult")
medicalContent = Statistic("medical");
spoofedContent = Statistic("spoofed");
violentContent = Statistic("violent");
racyContent = Statistic("racy")
allContent = [adultContent,medicalContent,spoofedContent,violentContent,racyContent]

def main(url):
    # Generate name for new bucket to be made in the cloud
    newBucketName = generateName(6)

    # Make the bucket, will be deleted
    bucket = storage_client.create_bucket(newBucketName)

    # Receives a url and returns it as text
    r = requests.get(url)
    soup = BeautifulSoup(r.text, 'html.parser')

    num = 0
    for image in soup.find_all('img'):
        image_url = image['src']
        #print(image_url)
        if(image_url != "" and image_url.find("http") != -1):
            if(image_url.split('.')[-1] != 'svg'):
                downloadImg(image['src'], "images", newBucketName, num)
                num += 1

    # List of items in cloud bucket
    bucketList = bucket.list_blobs()

    # Checks each image in bucket using cloud vision
    for x in bucketList:
        print('checking ' + x.name)
        content = x.download_as_bytes()
        image = vision.Image(content=content)
        labelresponse = client.label_detection(image=image)
        ssresponse = client.safe_search_detection(image=image)

        checkSafe = ssresponse.safe_search_annotation
        checkLabels = labelresponse.label_annotations

        cVision(checkSafe, checkLabels)

        x.delete()

    bucket = storage_client.get_bucket(newBucketName)
    bucket.delete()

# Data output functions

# Number of images 'possibly,' 'likely,' and 'very likely' belonging to a specified sensitive category
def calcPossible():
    for i in allContent:
        i.possible = i.data[5] + i.data[4] + i.data[3]

# List numbers of 'very likely' images there are in each category
def vLikely():
    out = [adultContent.data[5],medicalContent.data[5],spoofedContent.data[5],violentContent.data[5],racyContent.data[5]]
    return out

# List numbers of 'possible' images there are in each category
def possible():
    out = [adultContent.data[3],medicalContent.data[3],spoofedContent.data[3],violentContent.data[3],racyContent.data[3]]
    return out

# List numbers of 'likely' images there are in each category
def likely():
    out = [adultContent.data[4],medicalContent.data[4],spoofedContent.data[4],violentContent.data[4],racyContent.data[4]]
    return out

# List percent (<1) of images belonging to each category per category
def percentLikely():
    calcPossible()
    return [ adultContent.possible / (adultContent.total - adultContent.data[0]),
    medicalContent.possible / (medicalContent.total - medicalContent.data[0]),
    spoofedContent.possible / (spoofedContent.total - spoofedContent.data[0]),
    violentContent.possible / (violentContent.total - violentContent.data[0]),
    racyContent.possible / (racyContent.total - racyContent.data[0])]

# Returns total amount of images processed
def total():
    return adultContent.total


from lib.fetch import fetch_url
from lib.networks import Network
import json
import sys

# Public location of the services.json file.
SERVICES_URL = "https://s3.us-east-2.amazonaws.com/ndau-json/services_localnet.json"

def fetch_services():
    """
    Fetch and return the json text from services.json.
    """

    services_response = fetch_url(SERVICES_URL)
    if services_response is None:
        sys.exit(f"Unable to fetch {SERVICES_URL}")

    return services_response.content

def parse_all_services(services_json):
    """
    Return API and RPC dictionaries with network name keys and values from parse_services().
    """

    network_apis = {}
    network_rpcs = {}

    for network in list(Network):
        network_name = str(network)
        network_apis[network_name], network_rpcs[network_name] = parse_services(
            network_name, None, services_json
        )

    return network_apis, network_rpcs

def parse_services(network_name, node_name, services_json):
    """
    Return a dictionary with node name keys and protocol://domain:port for the values for the
    given network's node from services_json.
    The dictionary will contain all urls on the given network if node_name is None.
    Two dictionaires are returned, one with ndauapi urls, one with tendermint RPC urls.
    """

    # Key names in services.json
    networks_name = "networks"
    nodes_name = "nodes"
    api_name = "api"
    rpc_name = "rpc"

    try:
        services_obj = json.loads(services_json)
    except:
        services_obj = None
    if services_obj is None:
        sys.exit("Unable to parse services json")

    if not networks_name in services_obj:
        sys.exit("Unable to find networks object")
    networks_obj = services_obj[networks_name]

    if not network_name in networks_obj:
        sys.exit(f"Unable to find {network_name} network object")
    network_obj = networks_obj[network_name]

    if not nodes_name in network_obj:
        sys.exit("Unable to find nodes object")
    nodes_obj = network_obj[nodes_name]

    # Ensure support for testnet-backup and mainnet-backup.  They are not published in
    # services.json, but we know of their existence and we want to manage them on AWS.
    if network_name == "testnet" or network_name == "mainnet":
        new_node_name = f"{network_name}-backup"
        if not new_node_name in nodes_obj:
            nodes_obj[new_node_name] = {
                api_name: f"{new_node_name}.ndau.tech:3030",
                rpc_name: f"{new_node_name}.ndau.tech:26670",
            }

    apis = {}
    rpcs = {}

    for node_obj_name in nodes_obj:
        if node_name is None or node_name == node_obj_name:
            node_obj = nodes_obj[node_obj_name]
            if not api_name in node_obj:
                sys.exit(f"Unable to find api object in {node_obj}")
            if not rpc_name in node_obj:
                sys.exit(f"Unable to find rpc object in {node_obj}")
            if network_name == "localnet":
                apis[node_obj_name] = f"http://{node_obj[api_name]}"
                rpcs[node_obj_name] = f"http://{node_obj[rpc_name]}"
            else:
                apis[node_obj_name] = f"https://{node_obj[api_name]}"
                rpcs[node_obj_name] = f"https://{node_obj[rpc_name]}"

    return apis, rpcs


from .functions import get_namespace_by_classname
from .PhpFileAnalyzer import PhpFileAnalyzer
from lxml import etree as xml

class GraphMLExporter:

    def __init__(self):
        self.xmlns_namespace = "http://graphml.graphdrawing.org/xmlns"
        self.xsi_namespace = "http://www.w3.org/2001/XMLSchema-instance"
        self.ygraphml_namespace = "http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd"
        self.y_namespace = "http://www.yworks.com/xml/graphml"
        self.nsmap = {None : self.xmlns_namespace}

        self.xmlns = "{%s}" % self.xmlns_namespace
        self.xsi   = "{%s}" % self.xsi_namespace
        self.y     = "{%s}" % self.y_namespace

    def exportClassGraphhToFile(
        self,
        plugin,
        storage,
        classes,
        filePath,
        depth=0,
        classesExcluded=[],
        options = {}
    ):

        ### FETCH NODES AND EDGES BY DEPTH

        allNodes = []
        allEdges = []

        cleanedClasses = []
        for className in classes:
            className = self.__clearClassName(className)
            cleanedClasses.append(className)
        classes = cleanedClasses

        cleanedClassesExcluded = []
        for className in classesExcluded:
            className = self.__clearClassName(className)
            cleanedClassesExcluded.append(className)
        classesExcluded = cleanedClassesExcluded

        if depth > 0:
            lastAddedClasses = classes
            while depth > 0:
                classesToAdd = []
                for className in lastAddedClasses:
                    if className not in classesExcluded:
                        nodes, edges = self._fetchRelatedEdges(className, plugin, storage, options)
                        allNodes += nodes
                        allEdges += edges
                        for node in nodes:
                            nodeClassName, nodeType = node.split('@')
                            classesToAdd.append(nodeClassName)
                classes += classesToAdd
                classes = list(set(classes))
                lastAddedClasses = list(set(classesToAdd))
                depth -= 1
            nodes = allNodes
            edges = allEdges

        else:
            nodes = []
            edges = [] # TODO: fill edges from nodes
            for nodeFullClassName in list(set(classes)):
                nodeNamespace, nodeClassName = get_namespace_by_classname(nodeFullClassName)
                classType = storage.get_class_type(nodeNamespace, nodeClassName)
                nodes.append(nodeFullClassName + "@" + classType)

        ### INIT XML

        # http://lxml.de/tutorial.html

        xmlns_namespace = "http://graphml.graphdrawing.org/xmlns"
        xsi_namespace = "http://www.w3.org/2001/XMLSchema-instance"
        ygraphml_namespace = "http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd"
        nsmap = {None : xmlns_namespace}

        xmlns = "{%s}" % xmlns_namespace
        xsi   = "{%s}" % xsi_namespace

        tree = xml.ElementTree()

        graphmlXml = xml.Element(self.xmlns + "graphml", nsmap=self.nsmap)
        graphmlXml.set(self.xsi + "schemaLocation", self.xmlns_namespace + " " + self.ygraphml_namespace)

        tree._setroot(graphmlXml)

        graphXml = xml.SubElement(graphmlXml, self.xmlns + "graph", edgedefault="directed")
        graphXml.set("id", "G")

        for keyAttributes in [
            {"for": "graph", "id": "d0", "attr.type": "string", "attr.name": "description"},
            {"for": "node",  "id": "d1", "attr.type": "string", "attr.name": "url"},
            {"for": "node",  "id": "d2", "attr.type": "string", "attr.name": "description"},
            {"for": "node",  "id": "d3", "yfiles.type": "nodegraphics"},
            {"for": "edge",  "id": "d4", "attr.type": "string", "attr.name": "url"},
            {"for": "edge",  "id": "d5", "attr.type": "string", "attr.name": "description"},
            {"for": "edge",  "id": "d6", "yfiles.type": "edgegraphics"}
        ]:
            keyXml = xml.Element("key")
            for key, value in keyAttributes.items():
                keyXml.set(key, value)
            graphmlXml.append(keyXml)

        ### WRITE NODES AND EDGES TO XML

        classToNodeIndexMap = {}
        counter = 0
        for node in nodes:
            fullClassName, classType = node.split("@")
            if fullClassName not in classToNodeIndexMap:
                classToNodeIndexMap[fullClassName] = counter
                namespace, className = get_namespace_by_classname(fullClassName)

                headerText = className + "\n" + namespace

                if classType != "class":
                    headerText = "<<" + classType + ">>\n" + headerText

                bodyText = ""

                if "contain_methods" not in options or options["contain_methods"]:
                    for methodName in storage.get_all_class_methods(namespace, className):
                        methodData = storage.get_method(namespace, className, methodName)
                        visibility, is_static, methodFilePath, line, column, doccomment, returnType = methodData
                        methodPrefix = "+"
                        if visibility == "protected":
                            methodPrefix = "#"
                        if visibility == "private":
                            methodPrefix = "-"
                        methodReturnTypeDef = ""
                        if returnType != None:
                            methodReturnTypeDef = " : " + returnType
                        bodyText += methodPrefix + " " + methodName + "()" + methodReturnTypeDef + "\n"

                if "contain_members" not in options or options["contain_members"]:
                    for memberName in storage.get_all_class_members(namespace, className):
                        memberData = storage.get_member(namespace, className, memberName)
                        visibility, is_static, memberFilePath, line, column, doccomment, typeHint = memberData
                        memberPrefix = "+"
                        if visibility == "protected":
                            memberPrefix = "#"
                        if visibility == "private":
                            memberPrefix = "-"
                        memberTypeDef = ""
                        if typeHint != None:
                            memberTypeDef = " : " + typeHint
                        bodyText += memberPrefix + " " + memberName + memberTypeDef + "\n"

                classFilePath, classLine, classColumn = storage.get_class_position(namespace, className)

                self._writeNodeXml(counter, headerText, bodyText, classType, graphXml, classFilePath)
                counter += 1

        edgeToIdMap = {}
        counter = 0
        for edge in edges:
            if edge not in edgeToIdMap:
                edgeToIdMap[edge] = counter
                sourceClassName, edgeType, targetClassName = edge.split("-")

                sourceIndex = classToNodeIndexMap[sourceClassName]
                targetIndex = classToNodeIndexMap[targetClassName]

                self._writeEdgeXml(counter, sourceIndex, targetIndex, edgeType, graphXml)
                counter += 1

        tree.write(filePath)

    def _writeNodeXml(self, index, headerText, bodyText, nodeType, graphXml, url=None):
        nodeXml = xml.SubElement(graphXml, "node")
        nodeXml.set("id", "n"+str(index))

        if url != None:
            urlDataXml = xml.Element("data", key="d1")
            urlDataXml.text = url
            nodeXml.append(urlDataXml)

        nodeXml.append(xml.Element("data", key="d2"))
        nodeGraphicsDataXml = xml.SubElement(nodeXml, "data", key="d3")

        lineCount = 0
        highestColumnCount = 0
        for line in headerText.split("\n"):
            lineCount += 1
            if len(line) > highestColumnCount:
                highestColumnCount = len(line)
        for line in bodyText.split("\n"):
            lineCount += 1
            if len(line) > highestColumnCount:
                highestColumnCount = len(line)

        yGenericNodeXml = xml.SubElement(
            nodeGraphicsDataXml,
            self.y + "GenericNode",
            configuration="com.yworks.entityRelationship.big_entity"
        )

        nodeWidth  = 10 + (highestColumnCount * 7)
        nodeHeight = 10 + (lineCount * 14)

        if nodeType == "interface":
            foregroundColor = "#E8F7F7"
            backgroundColor = "#B7E3E3"

        elif nodeType == "trait":
            foregroundColor = "#F2F7E8"
            backgroundColor = "#D3E3B7"

        else:
            foregroundColor = "#E8EEF7"
            backgroundColor = "#B7C9E3"

        yGeometryXml = xml.SubElement(
            yGenericNodeXml,
            self.y + "Geometry",
            height=str(nodeHeight),
            width=str(nodeWidth),
            x="0.0",
            y="0.0"
        )

        yFillXml = xml.SubElement(
            yGenericNodeXml,
            self.y + "Fill",
            color=foregroundColor,
            color2=backgroundColor,
            transparent="false"
        )

        yBorderStyleXml = xml.SubElement(
            yGenericNodeXml,
            self.y + "BorderStyle",
            color="#000000",
            type="line",
            width="1.0"
        )

        yNodeLabelHeaderXml = xml.SubElement(
            yGenericNodeXml,
            self.y + "NodeLabel",
            alignment="center",
            autoSizePolicy="content",
            backgroundColor=backgroundColor,
            configuration="com.yworks.entityRelationship.label.name",
            fontFamily="Monospace",
            fontSize="12",
            fontStyle="plain",
            hasLineColor="false",
            height="31.9375",
            modelName="internal",
            modelPosition="t",
            textColor="#000000",
            visible="true",
            width="137.880859375",
            x="16.5595703125",
            y="4.0"
        )

        yNodeLabelHeaderXml.text = headerText

        yNodeLabelBodyXml = xml.SubElement(
            yGenericNodeXml,
            self.y + "NodeLabel",
            alignment="left",
            autoSizePolicy="content",
            configuration="com.yworks.entityRelationship.label.attributes",
            fontFamily="Monospace",
            fontSize="12",
            fontStyle="plain",
            hasBackgroundColor="false",
            hasLineColor="false",
            height="4.0",
            modelName="custom",
            textColor="#000000",
            visible="true",
            width="4.0",
            x="2.0",
            y="43.9375"
        )

        yNodeLabelBodyXml.text = bodyText

        yLabelModelXml = xml.SubElement(
            yNodeLabelBodyXml,
            self.y + "LabelModel"
        )

        yErdAttributesNodeLabelModelXml = xml.SubElement(
            yLabelModelXml,
            self.y + "ErdAttributesNodeLabelModel"
        )

        yModelParameterXml = xml.SubElement(
            yNodeLabelBodyXml,
            self.y + "ModelParameter"
        )

        yErdAttributesNodeLabelModelParameterXml = xml.SubElement(
            yModelParameterXml,
            self.y + "ErdAttributesNodeLabelModelParameter"
        )

        yStylePropertiesXml = xml.SubElement(
            yGenericNodeXml,
            self.y + "StyleProperties"
        )

        yPropertyXml = xml.SubElement(
            yStylePropertiesXml,
            self.y + "Property",
            name="y.view.ShadowNodePainter.SHADOW_PAINTING",
            value="true"
        )
        yPropertyXml.set("class", "java.lang.Boolean")

    def _writeEdgeXml(self, index, sourceIndex, targetIndex, edgeType, graphXml):
        edgeXml = xml.SubElement(
            graphXml,
            "edge",
            id="e"+str(index),
            source="n"+str(sourceIndex),
            target="n"+str(targetIndex)
        )

        edgeXml.append(xml.Element("data", key="d4"))
        edgeXml.append(xml.Element("data", key="d5"))

        edgeGraphicsDataXml = xml.SubElement(edgeXml, "data", key="d6")

        yPolyLineEdgeXml = xml.SubElement(edgeGraphicsDataXml, self.y + "PolyLineEdge")

        if edgeType == "generalization":
            lineColor = "#000000"
            lineType = "line"
            sourceArrow = "none"
            targetArrow = "white_delta"

        elif edgeType == "implementation":
            lineColor = "#000000"
            lineType = "dashed"
            sourceArrow = "none"
            targetArrow = "white_delta"

        elif edgeType == "composition":
            lineColor = "#000000"
            lineType = "line"
            sourceArrow = "diamond"
            targetArrow = "none"

        else: # association
            lineColor = "#aaaaaa"
            lineType = "line"
            sourceArrow = "none"
            targetArrow = "short"

        yPathXml = xml.SubElement(
            yPolyLineEdgeXml,
            self.y + "Path",
            sx="0.0",
            sy="0.0",
            tx="0.0",
            ty="0.0"
        )
        yLineStyleXml = xml.SubElement(
            yPolyLineEdgeXml,
            self.y + "LineStyle",
            color=lineColor,
            type=lineType,
            width="1.0"
        )
        yArrowsXml = xml.SubElement(
            yPolyLineEdgeXml,
            self.y + "Arrows",
            source=sourceArrow,
            target=targetArrow
        )
        yBendStyleXml = xml.SubElement(
            yPolyLineEdgeXml,
            self.y + "BendStyle",
            smoothed="false"
        )

    def _calculateCoupling(self, nodes, edges):
        couplingByNode = {}
        for node in nodes:
            nodeClassName, nodeType = node.split('@')
            coupling = 0
            for edge in edges:
                edgeBaseClass, edgeTargetClass, edgeType = edge.split("-")
                if edgeBaseClass == nodeClassName or edgeTargetClass == nodeClassName:
                    coupling += 1
            couplingByNode[node] = coupling
        return couplingByNode

    def _fetchRelatedEdges(self, fullClassName, plugin, storage, options={}):
        nodes = []
        edges = []

        fullClassName = self.__clearClassName(fullClassName)

        internalTypes = ["string", "array", "int", "float", "object", "bool"]

        if len(fullClassName) > 0:
            namespace, className = get_namespace_by_classname(fullClassName)

            classes = [fullClassName]

            ### INTERFACES

            interfacesImplemented = []

            if "include_interfaces" not in options or options["include_interfaces"]:
                interfaces = storage.get_class_interfaces(namespace, className)
                for interface in interfaces:
                    interface = self.__clearClassName(interface)
                    interfacesImplemented.append(interface)
                    classes.append(interface)
                    edges.append(fullClassName + "-implementation-" + interface)

            ### PARENT / CHILDREN

            if "include_parental_inheritance" not in options or options["include_parental_inheritance"]:
                parentClassName = storage.get_class_parent(namespace, className)
                if parentClassName != None:
                    parentClassName = self.__clearClassName(parentClassName)
                    classes.append(parentClassName)
                    edges.append(fullClassName + "-generalization-" + parentClassName)

            if "include_children_inheritance" not in options or options["include_children_inheritance"]:
                children = storage.get_class_children(fullClassName)
                for childClassName in children:
                    childClassName = self.__clearClassName(childClassName)
                    if childClassName not in interfacesImplemented:
                        classes.append(childClassName)
                        edges.append(childClassName + "-generalization-" + fullClassName)

            ### COMPOSITIONS & AGGREGATIONS

            if "include_has_a_composition" not in options or options["include_has_a_composition"]:
                members = storage.get_all_class_members(namespace, className)
                for memberName in members:
                    memberData = storage.get_member(namespace, className, memberName)
                    typeHint = memberData[6]
                    if typeHint != None and len(typeHint) > 0 and typeHint not in internalTypes:
                        typeHint = self.__clearClassName(typeHint)
                        classes.append(typeHint)
                        edges.append(fullClassName + "-composition-" + typeHint)
                methods = storage.get_all_class_methods(namespace, className)
                for methodName in methods:
                    methodData = storage.get_method(namespace, className, methodName)
                    returnType = methodData[6]
                    if returnType != None and len(returnType) > 0 and returnType not in internalTypes:
                        returnType = self.__clearClassName(returnType)
                        classes.append(returnType)
                        edges.append(fullClassName + "-composition-" + returnType)

            if "include_is_part_of_composition" not in options or options["include_is_part_of_composition"]:
                members = storage.get_members_by_type_hint(namespace, className)
                for memberNamespace, memberClassname, memberName in members:
                    memberFullClassname = memberNamespace + "\\" + memberClassname
                    memberFullClassname = self.__clearClassName(memberFullClassname)
                    classes.append(memberFullClassname)
                    edges.append(memberFullClassname + "-composition-" + fullClassName)

            ### REFERENCES

            if "include_uses_references" not in options or options["include_uses_references"]:
                uses = storage.get_class_uses(fullClassName)
                for usingFilePath, line, column, usingClassName, functionName in uses:
                    usingClassName = self.__clearClassName(usingClassName)
                    classes.append(usingClassName)
                    edges.append(usingClassName + "-association-" + fullClassName)

            if "include_usedby_references" not in options or options["include_usedby_references"]:
                uses = storage.get_class_uses_by_class(fullClassName)
                for usingFilePath, line, column, userClassName, functionName in uses:
                    userClassName = self.__clearClassName(userClassName)
                    classes.append(userClassName)
                    edges.append(fullClassName + "-association-" + userClassName)

            ### BUILD NODES FROM CLASSES

            for nodeFullClassName in list(set(classes)):
                nodeNamespace, nodeClassName = get_namespace_by_classname(nodeFullClassName)
                classType = storage.get_class_type(nodeNamespace, nodeClassName)
                nodes.append(nodeFullClassName + "@" + classType)

        return [nodes, edges]

    def __clearClassName(self, className):
        if className != None and len(className) > 0 and className[0] != "\\":
            className = "\\" + className
        return className


"""Reader module contains only dataset loaders
that are used to iterate over items."""
import csv
import gzip
import io
import struct
import zipfile
from collections import OrderedDict
from os import path

import numpy as np

from .var import NP2STRUCT

__all__ = ["Dataset", "Resource", "Container", "READER_LIST"]

class Resource(object):

    """Dataset resource."""

    def __init__(self, attributes, outputs):
        assert isinstance(
            attributes, np.ndarray), "attributes have to be a numpy array"
        assert isinstance(
            outputs, np.ndarray), "outputs have to be a numpy array"
        self.attributes = attributes
        self.outputs = outputs
        self.__idx = 0

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

    def __iter__(self):
        self.__idx = 0
        while self.__idx < len(self.attributes):
            yield (self.attributes[self.__idx], self.outputs[self.__idx])
            self.__idx += 1

    def __getitem__(self, idx):
        return (self.attributes[idx].copy(), self.outputs[idx].copy())

    def __setitem__(self, idx, val):
        self.attributes[idx], self.outputs[idx] = val
        return (self.attributes[idx].copy(), self.outputs[idx].copy())

    def repeat(self, num_rep, target='attributes'):
        """Add a third dimension and duplicate data.

        Example:
            - with 3 repetitions:

                from [ [1, 2], [3, 4] ]

                to [
                    [ [1, 2], [3, 4] ],
                    [ [1, 2], [3, 4] ],
                    [ [1, 2], [3, 4] ]
                ]

        Note:
            np.array([tmp] * num_rep) is more performing than
            np.tile(tmp, (num_rep, 1, 1))

            tmp = np.array([ [1, 2], [3, 4] ])

            %time _ = [np.tile(tmp, (3, 1, 1)) for _ in range(1000000)]
            CPU times: user 6.9 s, sys: 189 ms, total: 7.09 s
            Wall time: 7.14 s

            %time _ = [np.array([tmp]*3) for _ in range(1000000)]
            CPU times: user 3.03 s, sys: 147 ms, total: 3.18 s
            Wall time: 3.19 s
        """
        if target == 'attributes':
            self.attributes = np.array([self.attributes] * num_rep)
        elif target == 'outputs':
            self.outputs = np.array([self.outputs] * num_rep)
        else:
            raise Exception("Unrecognized target '{}'".format(target))
        return self

    def shuffle(self, seed=None):
        """Shuffle resource items."""
        np.random.seed(seed)
        indexes = np.random.permutation(len(self.attributes))
        self.attributes = self.attributes[indexes]
        self.outputs = self.outputs[indexes]
        return self

    def extract(self, indexes):
        """Remove items from this resource."""
        attributes = self.attributes[indexes].copy()
        outputs = self.outputs[indexes].copy()
        self.attributes = np.delete(self.attributes, indexes, 0)
        self.outputs = np.delete(self.outputs, indexes, 0)
        return Resource(attributes, outputs)

    def split(self, num_of_splits):
        """Split the current resource."""
        attributes = np.array_split(self.attributes, num_of_splits)
        outputs = np.array_split(self.outputs, num_of_splits)
        return [Resource(attributes[idx], outputs[idx]) for idx in range(len(attributes))]

    def copy(self):
        """Copy all the items of this resource."""
        return Resource(self.attributes.copy(), self.outputs.copy())

    def convert_type(self, type_):
        """Convert data type."""
        assert type_ == 'double' or type_ == 'float', "Output data can be double or float"
        if type_ == 'double':
            self.attributes = self.attributes.astype(np.float64)
            self.outputs = self.outputs.astype(np.float64)
        elif type_ == 'float':
            self.attributes = self.attributes.astype(np.float32)
            self.outputs = self.outputs.astype(np.float32)

    def to_bin(self):
        """Convert to binary this resource."""
        values = [self.attributes.flatten(), self.outputs.flatten()]
        data = np.concatenate(values, axis=0)
        return struct.pack("{}{}".format(
            data.size,
            NP2STRUCT[self.attributes.dtype]
        ), *data)

    def __add__(self, other):
        if len(self.attributes) > 0:
            attributes = np.concatenate(
                [self.attributes, other.attributes], axis=0)
            outputs = np.concatenate([self.outputs, other.outputs], axis=0)
        else:
            attributes = other.attributes
            outputs = other.outputs
        return Resource(attributes, outputs)

    def __iadd__(self, other):
        if len(self.attributes) > 0:
            self.attributes = np.append(
                self.attributes, other.attributes, axis=0)
            self.outputs = np.append(self.outputs, other.outputs, axis=0)
        else:
            self.attributes = other.attributes
            self.outputs = other.outputs
        return self

class Container(object):

    """Special container for Train, Validation and Test sets."""

    def __init__(self, *args, **kwargs):
        self.resources = []

    def insert(self, source):
        """Insert a resource into this container."""
        if isinstance(source, list):
            self.resources.extend(source)
        else:
            self.resources.append(source)
        return self

    def delete(self, idx):
        """Remove a resource."""
        self.resources.pop(idx)
        return self

    def __iter__(self):
        for resource in self.resources:
            yield resource

    def __len__(self):
        return sum([len(resource) for resource in self.resources])

    def __getitem__(self, idx):
        target_idx = idx
        for resource in self.resources:
            if target_idx < len(resource):
                return resource[target_idx]
            target_idx -= len(resource)
        raise IndexError()

    def __setitem__(self, idx, val):
        target_idx = idx
        for resource in self.resources:
            if target_idx < len(resource):
                resource[target_idx] = val
                return resource[target_idx]
            target_idx -= len(resource)
        raise IndexError()

class Dataset(object):

    """Base dataset object."""

    def __init__(self, normalized=False, onehot=False, kind="reg"):
        assert kind == "cls" or kind == "reg", "kind can be 'cls' (classification) or 'reg' (regression)"
        self.kind = kind
        self.normalized = normalized
        self.onehot = onehot
        self._train = Container()
        self._validation = Container()
        self._test = Container()
        self.data = OrderedDict([
            ('train', self._train),
            ('validation', self._validation),
            ('test', self._test)
        ])

    @property
    def train(self):
        """Train set."""
        return self._train

    @property
    def validation(self):
        """Validation set."""
        return self._validation

    @property
    def test(self):
        """Test set."""
        return self._test

    def insert(self, source, target="train"):
        """Insert a resoure in a proper container."""
        assert isinstance(
            source, Resource), "source have to be a Resource object"
        assert target == "train" or target == "validation" or target == "test", "target can be 'train', 'validation' or 'test'"
        cur_target = self.data[target]
        cur_target.insert(source)

    def __iter__(self):
        for set_ in self.data.values():
            for resource in set_.resources:
                for data in resource:
                    yield data

    def __getitem__(self, idx):
        target_idx = idx
        for set_ in self.data.values():
            for resource in set_.resources:
                if target_idx < len(resource):
                    return resource[target_idx]
                target_idx -= len(resource)
        raise IndexError()

    def __len__(self):
        return sum(
            [len(set_) for set_ in self.data.values()]
        )

class MAGICGammaTelescopeDataset(Dataset):

    """MAGIC Gamma Telescope dataset."""

    def __init__(self, magic_source_folder=None, normalized=True, onehot=True):
        super(MAGICGammaTelescopeDataset, self).__init__(
            normalized=normalized, onehot=onehot, kind='cls')

        data = []
        labels = []

        attributes = [
            'fLength',
            'fWidth',
            'fSize',
            'fConc',
            'fConc1',
            'fAsym',
            'fM3Long',
            'fM3Trans',
            'fAlpha',
            'fDist',
            'class'
        ]

        with open(path.join(magic_source_folder, "magic04.data"), "rb") as csvfile:
            file_wrapper = io.TextIOWrapper(csvfile, newline='')
            reader = csv.DictReader(file_wrapper,
                                    delimiter=',',
                                    fieldnames=attributes
                                    )
            rows = list(reader)

            min_max = check_min_max(rows)

            for row in rows:
                new_data = []
                for attr in attributes[:-1]:
                    tmp = float(row[attr])
                    if normalized:
                        tmp = (
                            tmp - min_max[attr][0]) / (
                            min_max[attr][1] - min_max[attr][0]
                        )
                    new_data.append(tmp)
                data.append(np.array(new_data))

                if onehot:
                    if row['class'] == 'g':
                        labels.append(np.array([0, 1]))
                    else:
                        labels.append(np.array([1, 0]))
                else:
                    labels.append(1 if row['class'] == 'g' else 0)

        data = np.array(data)
        labels = np.array(labels)

        self.insert(Resource(data, labels))

class QSARDataset(Dataset):

    """QSAR dataset."""

    def __init__(self, qsar_source_folder=None, normalized=True, onehot=True):
        super(QSARDataset, self).__init__(
            normalized=normalized, onehot=onehot, kind='cls')

        data = []
        labels = []

        attributes = [
            'SpMax_L',
            'J_Dz',
            'nHM',
            'F01',
            'F04',
            'NssssC',
            'nCb',
            'C',
            'nCp',
            'nO',
            'F03',
            'SdssC',
            'from',
            'LOC',
            'SM6_L',
            'F03',
            'Me',
            'Mi',
            'nN',
            'nArNO2',
            'nCRX3',
            'SpPosA_B',
            'nCIR',
            'B01',
            'B03',
            'N',
            'SpMax_A',
            'Psi_i_1d',
            'B04',
            'SdO',
            'TI2_L',
            'nCrt',
            'C',
            'F02',
            'nHDon',
            'SpMax_B',
            'Psi_i_A',
            'nN',
            'SM6_B',
            'nArCOOR',
            'nX',
            'class'
        ]

        with open(path.join(qsar_source_folder, "biodeg.csv"), "rb") as csvfile:
            file_wrapper = io.TextIOWrapper(csvfile, newline='')
            reader = csv.DictReader(file_wrapper,
                                    delimiter=';',
                                    fieldnames=attributes
                                    )
            rows = list(reader)

            min_max = check_min_max(rows)

            for row in rows:
                new_data = []
                for attr in attributes[:-1]:
                    tmp = float(row[attr])
                    if normalized:
                        tmp = (
                            tmp - min_max[attr][0]) / (
                            min_max[attr][1] - min_max[attr][0]
                        )
                    new_data.append(tmp)
                data.append(np.array(new_data))
                if onehot:
                    if row['class'] == 'RB':
                        labels.append(np.array([0, 1]))
                    else:
                        labels.append(np.array([1, 0]))
                else:
                    labels.append(1 if row['class'] == 'RB' else 0)

        data = np.array(data)
        labels = np.array(labels)

        self.insert(Resource(data, labels))

def check_min_max(rows):
    """Check min and max in a csv table."""
    min_max = {}
    for row in rows:
        for key, value in row.items():
            try:
                tmp = float(value)
                if key not in min_max:
                    min_max[key] = [0, 0]
                if tmp > min_max[key][1]:
                    min_max[key][1] = tmp
                elif tmp < min_max[key][0]:
                    min_max[key][0] = tmp
            except ValueError:
                pass
    return min_max

class GasSensorArrayDriftDataset(Dataset):

    """Gas Sensor Array Drif dataset."""

    def __init__(self, gass_source_file=None, normalized=True, onehot=True):
        super(GasSensorArrayDriftDataset, self).__init__(
            normalized=normalized, onehot=onehot, kind='cls')

        assert gass_source_file, "You have to specify the GasSensorArrayDrift zip file"

        data = []
        labels = []

        mins = np.zeros(128)
        maxs = np.zeros(128)

        with zipfile.ZipFile(gass_source_file, 'r') as gas_zip:

            for batch_file in gas_zip.namelist():
                if batch_file.find(".dat") != -1:
                    cur_batch = gas_zip.read(batch_file).decode("utf-8")
                    for line in cur_batch.split("\n"):
                        tmp = line.strip().split(" ")
                        if len(tmp) > 1:
                            class_ = int(tmp[0]) - 1
                            cur_data = [float(feature.split(":")[1])
                                        for feature in tmp[1:]]
                            class_ = int(tmp[0]) - 1
                            cur_data = [float(feature.split(":")[1])
                                        for feature in tmp[1:]]
                            ##
                            # Min max
                            for idx, val in enumerate(cur_data):
                                if val < mins[idx]:
                                    mins[idx] = val
                                if val > maxs[idx]:
                                    maxs[idx] = val
                            if len(cur_data) != 128:
                                raise Exception(
                                    "Error on extract gas features")
                            data.append(np.array(cur_data))
                            if onehot:
                                labels.append(np.zeros(6))
                                labels[-1][class_] = 1
                            else:
                                labels.append(class_)

                    if normalized:
                        for record in data:
                            for idx, val in enumerate(record):
                                record[idx] = (val - mins[idx]) / \
                                    (maxs[idx] - mins[idx])

                    self.insert(Resource(np.array(data), np.array(labels)))

                    data = []
                    labels = []

class MNISTDataset(Dataset):

    """MNIST dataset."""

    def __init__(self, mnist_source_folder=None, normalized=True, onehot=True):
        super(MNISTDataset, self).__init__(
            normalized=normalized, onehot=onehot, kind='cls')

        assert mnist_source_folder, "You have to specify in which folder are the mnist files"

        train_images = load_mnist_images(
            path.join(mnist_source_folder, 'train-images-idx3-ubyte.gz'), normalized)
        train_labels = load_mnist_labels(
            path.join(mnist_source_folder, 'train-labels-idx1-ubyte.gz'), onehot)
        test_images = load_mnist_images(
            path.join(mnist_source_folder, 't10k-images-idx3-ubyte.gz'), normalized)
        test_labels = load_mnist_labels(
            path.join(mnist_source_folder, 't10k-labels-idx1-ubyte.gz'), onehot)

        self.insert(Resource(train_images, train_labels))
        self.insert(Resource(test_images, test_labels), 'test')

class NBitParity(Dataset):

    """n-bit parity dataset."""

    def __init__(self, nbit=3, nsample_training=5000, nsample_test=1000,  normalized=True, onehot=True):
        super(NBitParity, self).__init__(normalized=normalized, onehot=onehot, kind='cls')

        def tofuzzyclass(i):
             clazz_min = int(np.min(i))
             clazz_max = int(np.max(i))
             clazz = clazz_max - clazz_min + 1
             size = np.size(i)
             out = np.zeros((size,clazz))
             for k in range(0,size):
                 out[k,int(i[k]) - clazz_min]=1.0
             return out

        training_x_set = (np.random.rand(nsample_training,nbit) > 0.5).astype(float)
        training_y_set = (np.sum(training_x_set, axis=1) % 2 != 0).astype(float)

        test_x_set = (np.random.rand(nsample_test,nbit) > 0.5).astype(float)
        test_y_set = (np.sum(test_x_set, axis=1) % 2 != 0).astype(float)

        self.insert(Resource(training_x_set, tofuzzyclass(training_y_set)))
        self.insert(Resource(test_x_set, tofuzzyclass(test_y_set)), 'test')

class FashionMNISTDataset(Dataset):

    """Fashion-MNIST dataset."""

    def __init__(self, fashion_mnist_source_folder=None, normalized=True, onehot=True):
        super(FashionMNISTDataset, self).__init__(
            normalized=normalized, onehot=onehot, kind='cls')

        assert fashion_mnist_source_folder, "You have to specify in which folder are the fashion-mnist files"

        train_images = load_mnist_images(
            path.join(fashion_mnist_source_folder, 'train-images-idx3-ubyte.gz'), normalized)
        train_labels = load_mnist_labels(
            path.join(fashion_mnist_source_folder, 'train-labels-idx1-ubyte.gz'), onehot)
        test_images = load_mnist_images(
            path.join(fashion_mnist_source_folder, 't10k-images-idx3-ubyte.gz'), normalized)
        test_labels = load_mnist_labels(
            path.join(fashion_mnist_source_folder, 't10k-labels-idx1-ubyte.gz'), onehot)

        self.insert(Resource(train_images, train_labels))
        self.insert(Resource(test_images, test_labels), 'test')

def load_mnist_images(file_name, normalized):
    """Load MNIST images."""
    with gzip.open(file_name, 'rb') as mnist_file:
        _, num_images, rows, cols = struct.unpack(
            ">IIII", mnist_file.read(16))
        buf = mnist_file.read(rows * cols * num_images)
        data = np.frombuffer(buf, dtype=np.uint8)
        if normalized:
            data = np.divide(data, 255.)
        data = data.reshape(num_images, rows * cols)
        return data

def load_mnist_labels(file_name, onehot, num_classes=10):
    """Load MNIST image labels."""
    with gzip.open(file_name, 'rb') as mnist_file:
        _, num_labels = struct.unpack(
            ">II", mnist_file.read(8))
        buf = mnist_file.read(num_labels)
        labels = np.frombuffer(buf, dtype=np.uint8)
        if onehot:
            data = np.zeros((num_labels, num_classes))
            data[np.arange(labels.size), labels] = 1
        else:
            data = labels
        return data

READER_LIST = {
    'MNISTDataset': MNISTDataset,
    'FashionMNISTDataset': FashionMNISTDataset,
    'GasSensorArrayDriftDataset': GasSensorArrayDriftDataset,
    'MAGICGammaTelescopeDataset': MAGICGammaTelescopeDataset,
    'QSARDataset': QSARDataset,
    'NBitParity': NBitParity
}


from .models import *
from .forms import *
from django.shortcuts import render, redirect, get_object_or_404
from datetime import datetime, timedelta
from django.utils import timezone

# 스플래쉬 화면
def splash(request):
    return render(request, 'splash.html')
# 홈페이지
def home(request):

    # DB에 담긴 product 데이터 전부 가져오기
    products = Product.objects.all()

    return render(request, 'index.html', {'products':products })

# 상세페이지 보여지도록 하는 함수 ; 어떤 데이터를 넘겨줄지 정의하는 부분
# url path 정의할 때 blog_id 변수 가져옴.
def detail(request, product_id):
    # blog_id 번째 블로그 글을 데이터베이스로부터 가져와서
    # Blog 객체를 가져올 건데 pk값이 blog_id인 객체를 가져올 거야.
    product_detail = get_object_or_404(Product, pk=product_id)
    bid_info = Bid.objects.filter(product_id=product_id).first()
    bid_list = product_detail.bid.all()
    # 댓글 입력 폼
    comment_form = CommentForm()
    # blog_id 번째 블로그 글을 detail.html 로 띄워주는 코드
    return render(request, 'detail.html', {'product_detail': product_detail, 'bid_info':bid_info, 'bid_list':bid_list ,'comment_form':comment_form})

# 입찰 페이지
def bid(request):
    return render(request, 'bid.html')

# model form으로 만들어진 form은 models.py에서 정의한 모델을 기반으로 만들어져 자체적으로 save 메서드를 갖고 있다.
# 반면 django form 으로 만들어진 form은 models.py에서 정의한 객체를 만들고 값을 넣어준 다음 그 객체에서 save해줘야함.
# def productformcreate(request):
#     # post 요청
#     if (request.method == 'POST' or request.method == 'FILES'):
#         form = ProductForm(request.POST)
#         if form.is_valid():
#             form.save()
#             return redirect('home')

#     # get요청 ; 모델 폼 틀 보여줌.
#     else:
#         form = ProductForm()

#     # 'form_create.html' 그대로 사용해도 상관없음.
#     return render(request, 'formcreate.html', {'form': form})

# 사용자가 작성한 댓글을 저장하는 함수
def create_comment(request, product_id):
    # POST형식으로 들어온 요청을 처리
    filled_form = CommentForm(request.POST)

    # 사용자가 작성한 댓글이 유효하다면 저장.
    if filled_form.is_valid():
        # 근데 주의. 저장하기 전에 어떤 글의 댓글인지 알기 위한 blog_id도 함께 저장해야함.
        # -> 아직 저장하지 않고 대기
        finished_form = filled_form.save(commit=False)
        # -> 어떤 글에 대한 댓글인지 CommentForm 의 post 정보 입력
        finished_form.product_id = get_object_or_404(Product, pk=product_id)
        # -> 그 다음 저장.
        finished_form.save()

    return redirect('detail', product_id)

def productformcreate(request):
    # post 요청
    if (request.method == 'POST' or request.method == 'FILES'):
      form = ProductForm(request.POST, request.FILES)

      if form.is_valid():
        filled_form = form.save(commit=False)
        I = range(1, 5)
        i = 1
        for i in I:
          b = Locker.objects.get(id = i)
          if b.locker_status ==  0:
            break
          i = i+1
        filled_form.locker = b
        filled_form.save()
      filled_locker = Locker.objects.get(id = i)
      filled_locker.locker_status = 1
      filled_locker.save()
      return render(request, 'product_check.html', {'filled_locker':filled_locker})

    # get요청 ; 모델 폼 틀 보여줌.
    else:
        form = ProductForm()

    return render(request, 'formcreate.html', {'form': form})

# 바로구매 확정페이지로 렌더링하는 함수
def purchase(request, product_id):
    # get요청 ; 모델 폼 틀 보여줌.
    product_info = get_object_or_404(Product, pk=product_id)

    return render(request, 'confirm_purchase.html',{'product_info': product_info})

def bidformcreate(request, product_id):
    # post 요청
    # if (request.method == 'POST'):
    #     form = BidForm(request.POST)
    #     if form.is_valid():
    #         form.save()
    #         return redirect('detail', product_id)

    # get요청 ; 모델 폼 틀 보여줌.
    if (request.method == "GET"):
        # 상품정보 불러오기 위해 product 객체 가져옴.
        product_info = get_object_or_404(Product, pk=product_id)
        # 현재 최고입찰가 가져오는 객체
        latest_bid = Bid.objects.filter(product_id=product_id).last()

        # 입력폼
        form = BidForm()

    # 'form_create.html' 그대로 사용해도 상관없음.
    return render(request, 'bid.html', {'form': form, 'product_info': product_info, 'latest_bid':latest_bid})

# 사용자가 작성한 입찰정보를 저장하는 함수
def create_bid(request, product_id):
    # POST형식으로 form에 입력된 요청을 처리
    filled_form = BidForm(request.POST)

    # 사용자가 작성한 댓글이 유효하다면 저장.
    if filled_form.is_valid():
        # 아직 저장하지 않고 대기
        finished_form = filled_form.save(commit=False)

        # filter는 쿼리셋 받아옴.
        # before_bid = Bid.objects.filter(product_id=product_id, pk=pk_count)
        latest_bid = Bid.objects.filter(product_id=product_id).first()
        # first_bid id가 가장 최근.id - 1

        # filter로 받아온 쿼리셋을 get하면 객체 불러옴.
        # before_bid_test = before_bid.get()
        # print(before_bid_test)
        print(latest_bid)
        # 존재하는지 확인
        if latest_bid is not None:
            # before_bid = Bid.objects.get(pk=pk_count)

            print(f"bid 객체 status : {latest_bid.product_id.product_status}")
            # 낙찰될 때까지 입찰과정 반복
            if latest_bid.product_id.product_status == 0 :
                # 이전 bid객체의 bid_price 보다 입력된 입찰가가 높을 4
                if (finished_form.bid_price > latest_bid.bid_price):

                    # -> 어떤 상품에 대한 입찰인지 BidForm 의 post 정보 입력
                    finished_form.product_id = get_object_or_404(Product, pk=product_id)
                    # -> 그 다음 저장.
                    finished_form.save()

                    print('굳굳')
                    # first_bid.product_id.product_status = 1
                # 입찰가가 즉시거래가와 같으면 객체 생성되면서, product_status = 1로 바꿔주기
                elif (finished_form.bid_price == latest_bid.product_id.buyout_price):
                    finished_form.product_id = get_object_or_404(Product, pk=product_id)

                    latest_bid.product_id.product_status = 1
                    print(f"bid 객체 status : {latest_bid.product_id.product_status}")

                    finished_form.save()

                    print('즉시구매 되엇습니다!')

                # 마감시간 지나면 status 바뀌는 것도 짜야함. -> 시간설정 필요; 타임델타

                # 입찰가가 이전 입찰가보다 낮을 때 객체생성x
                else:
                    print('이전 입찰가보다 높은 가격을 입력해주세요!!')

        # 즉시거래가 입력하면 바로 낙찰
        # 기존에 입찰이 없으면 첫번째 입찰 생성
        else:
            finished_form.product_id = get_object_or_404(Product, pk=product_id)
            finished_form.save()

            print('첫번째 Bid 객체 생성. ')
        return redirect('detail', product_id)

# 사용자가 작성한 바로구매정보를 저장하는 함수
def create_purchase(request, product_id):
    # POST요청 처리 ; 바로구매 정보 담김
    if (request.method =="POST"):
        product_info = get_object_or_404(Product, pk=product_id)
        # Bid 객체 생성
        Bid.objects.create(
            product_id = product_info,
            bid_price = product_info.buyout_price,
            bid_time = timezone.now(),

        )
        # 낙찰
        product_info.product_status = 1
        product_info.save()
    # render는 같은 url안에 렌더링만 바꿔줌. redirect는 url 바꿔줌.
    # redirect 는 url name만 적어줘도 됨.
    return render(request, 'buy_locker_check.html', {'product_info':product_info})

    # filled_form = BidForm(request.POST)

    # # 사용자가 작성한 댓글이 유효하다면 저장.
    # if filled_form.is_valid():
    #     # 근데 주의. 저장하기 전에 어떤 글의 댓글인지 알기 위한 blog_id도 함께 저장해야함.
    #     # -> 아직 저장하지 않고 대기
    #     finished_form = filled_form.save(commit=False)
    #     # -> 어떤 글에 대한 댓글인지 CommentForm 의 post 정보 입력
    #     finished_form.product_id = get_object_or_404(Product, pk=product_id)
    #     # -> 그 다음 저장.
    #     finished_form.save()

    # return redirect('detail', product_id)


import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

#from fields import SCATTER_2_ELECTRIC_NODES

def PLOT_TIME_SOURCE(v_f,time_source,current_density,del_l,fig_num,location,del_t):
    #plots the source over time in terms of electric field components
    #time_source - holds the sources scatter components at each time step - np.array, shape(n_t,n_f)
    #del_l - space step in all three directions - float

    n_t,n_f = np.shape(time_source)
    eta_0 = 119.9169832*np.pi

    plt.figure(fig_num[0])
    plt.plot(np.arange(n_t)*del_t*1.0e15,-v_f[location[0],location[1],location[2],2,:]/del_l)
    plt.ylabel('V/m')
    plt.xlabel('fs')
    plt.title('free source fields at source location - z component')

    plt.figure(fig_num[1])
    plt.plot(np.arange(n_t)*del_t*1.0e15,time_source[:,2])
    plt.ylabel('V')
    plt.xlabel('fs')
    plt.title('free voltage source - z component')

    plt.figure(fig_num[2])
    plt.plot(np.arange(n_t)*del_t*1.0e15,current_density)
    plt.ylabel('A/m^2')
    plt.xlabel('fs')
    plt.title('current density')

def PLOT_TIME_SOURCE_LUMERICAL(v_f,fig_num,location):
    #plots the source over time in terms of electric field components
    #time_source - holds the sources scatter components at each time step - np.array, shape(n_t,n_f)

    plt.figure(fig_num)
    plt.plot(v_f[location[0],location[1],location[2],2])
    plt.title('free source fields - z component')

def PLOT_RESULTS_2(f_final,del_l,fig_num):

    plt.figure(fig_num)
    plt.plot(np.squeeze(-f_final/del_l), 'b')
    plt.ylabel('V/m')
    plt.title('final field value - z polarized')

def PLOT_VIDEO_1D(f_time,del_l,fig_num):

    fig = plt.figure(fig_num)

    ims = []

    #get number of time steps
    n_x,n_y,n_z,n_t = np.shape(f_time)

    for t in range(n_t):

        im, = plt.plot(np.squeeze(-f_time[:,:,:,t]/del_l), 'b',animated=True)
        plt.title('Lorentz Dielectric - Wrapping Boundary Conditions')
        plt.ylabel('V/m')

        ims.append([im])

    ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
                                    repeat_delay=1000)

    plt.show()

    ani.save("foward_movie.mp4")

def PLOT_COMPARISON_VIDEO_1D(f_time,f_lumerical_time,del_l,fig_num):

    fig = plt.figure(fig_num)

    ims = []

    #get number of time steps
    _,_,_,n_t = np.shape(f_time)

    for t in range(n_t):

        im1,im2 = plt.plot(np.squeeze(-f_time[:,:,:,t]/del_l), 'b',np.squeeze(-f_lumerical_time[:,:,:,t]/del_l),'r',animated=True)
        plt.title('Lorentz Dielectric - Wrapping Boundary Conditions')
        #plt.ylim(-2,2)

        ims.append([im1,im2])

    ani = animation.ArtistAnimation(fig, ims, interval=5, blit=True,
                                    repeat_delay=1000)

    ani.save("foward_movie.mp4")
    plt.show()

def PLOT_VIDEO_2D(f_time,del_l,fig_num):

    fig = plt.figure(fig_num)

    ims = []

    #get number of time steps
    n_x,n_y,n_z,n_t = np.shape(f_time)

    for t in range(n_t):

        im, = plt.imshow(np.squeeze(-f_time[:,:,:,t]/del_l),animated=True)
        plt.colorbar

        ims.append([im])

    ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
                                    repeat_delay=1000)

    #ani.save("foward_movie.mp4")
    plt.show()

def PLOT_BOUNDARY_1D(boundary,fig_num):
    #plots boundary tensor assuming 1d simulation
    #boundary: boundary tensor - np.array data_type, shape (n_x,n_y,n_z,n_c)
    #fig_num: figure number - int, shape(1,)

    plt.figure(fig_num)
    plt.imshow(np.squeeze(boundary))
    plt.colorbar()
    plt.title('boundary')

def PLOT_DISPERSION_PARAMETERS_1D(inf_x,w_0,damp,del_x,fig_num):
    #plot the dispersion parameters assuming number of field components equals 3
    # inf_x: high frequency susceptibility tensor - np.constant, shape(n_1)
    # w_0: Lorentz resonance frequency tensor (rad/s) - np.constant, shape(n_1,n_r)
    # damp: Lorentz damping frequency tensor (rad/s) - np.constant, shape(n_1,n_r)
    # del_x: change in susceptibility tensor (unitless) - np.constant, shape(n_1,n_r)
    # fig_num: numbers for figures - list, shape(2,)

    #get size of first spatial axis, number of electric field components and number of resonances
    n_1,n_r = np.shape(w_0)

    #susceptibility
    plt.figure(fig_num[0])
    plt.plot(inf_x,label = 'infinite susceptibility')

    #over all resonances
    for r in range(n_r):

        plt.plot(del_x[:,r],label = 'change in susceptibility: ' + str(r))
        plt.ylabel('Susceptibility')
        plt.xlabel('Simulation points')
        plt.title("Susceptibility for each Resonance")

    plt.legend()

    #resonant frequency
    plt.figure(fig_num[1])

    #over all resonances
    for r in range(n_r):

        plt.plot(w_0[:,r]*10**-12,label = 'resonance frequency: ' + str(r))
        plt.plot(damp[:,r]*10**-12,label = 'damping frequency: ' + str(r))
        plt.ylabel('THz')
        plt.xlabel('Simulation point')
        plt.title("frequency")

    plt.legend()

def PLOT_SPECTRUM_Z(fig_num,f_time,location,del_t):
    # fig_num: the figure number
    # f_time: the field over all time - shape(n_x,n_y,n_z,6,n_t)
    # location: the location of the point monitor - shape(3,)

    #get number of time steps
    _,_,_,_,n_t = np.shape(f_time)

    plt.figure(fig_num)

    #determine location
    x = location[0]
    y = location[1]
    z = location[2]

    time_signal = f_time[x,y,z,2,:]

    t = np.arange(0,del_t*n_t,del_t)
    sp = np.fft.fft(time_signal)
    freq = np.fft.fftfreq(t.shape[-1])
    l = len(freq)
    plt.plot(10**-12*freq[0:l//2-1]/del_t, np.abs(sp[0:l//2-1]))
    plt.xlabel('THz')
    plt.ylabel('Spectrum')
    plt.show()