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

#   Widgets.py por:
#       Flavio Danesse <fdanesse@gmail.com>
#       Uruguay
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import os

from gi.repository import Gtk
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import GdkPixbuf

from Globales import get_separador
from Globales import get_pixels
from Globales import describe_archivo
from Globales import describe_uri
from Globales import get_colors

BASEPATH = os.path.dirname(__file__)

#GObject.threads_init()

class Toolbar(Gtk.Toolbar):

    __gtype_name__ = 'JAMediaConverterToolbar'

    __gsignals__ = {
    'salir': (GObject.SIGNAL_RUN_LAST,
        GObject.TYPE_NONE, []),
    'load': (GObject.SIGNAL_RUN_LAST,
        GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT, ))}

    def __init__(self):

        Gtk.Toolbar.__init__(self)

        self.modify_bg(0, get_colors("window"))

        self.insert(get_separador(draw=False,
            ancho=3, expand=False), -1)

        item = Gtk.ToolItem()
        item.set_expand(True)
        self.menu = Menu()
        self.menu.show()
        item.add(self.menu)
        self.insert(item, -1)
        '''
        archivo = os.path.join(BASEPATH,
            "Iconos", "salir.svg")
        boton = get_boton(archivo, flip=False,
            pixels=get_pixels(1))
        boton.set_tooltip_text("Salir")
        boton.connect("clicked", self.__salir)
        self.insert(boton, -1)
        '''
        self.insert(get_separador(draw=False,
            ancho=3, expand=False), -1)

        self.show_all()

        self.menu.connect(
            "load", self.__emit_load)

    def __emit_load(self, widget, archivos):

        self.emit('load', archivos)

    def __salir(self, widget):
        """
        Cuando se hace click en el boton salir.
        """

        self.emit('salir')

class Menu(Gtk.MenuBar):
    """
    Toolbar Principal.
    """

    __gtype_name__ = 'JAMediaConverterMenu'

    __gsignals__ = {
    'load': (GObject.SIGNAL_RUN_LAST,
        GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT, ))}

    def __init__(self):

        Gtk.MenuBar.__init__(self)

        item_Procesar = Gtk.MenuItem('Cargar')
        menu_Procesar = Gtk.Menu()
        item_Procesar.set_submenu(menu_Procesar)
        self.append(item_Procesar)

        item = Gtk.MenuItem('Directorio ...')
        item.connect("activate", self.__emit_accion)
        menu_Procesar.append(item)

        item = Gtk.MenuItem('Archivos ...')
        item.connect("activate", self.__emit_accion)
        menu_Procesar.append(item)

        self.show_all()

    def __emit_accion(self, widget):

        valor = widget.get_label()

        mtype = ["audio/*", "video/*"]

        if valor == 'Directorio ...':
            filechooser = FileChooser(
                parent_window=self.get_toplevel(),
                title="Cargar Archivos",
                action=Gtk.FileChooserAction.SELECT_FOLDER,
                #path=path,
                mime=mtype,
                )

            filechooser.connect('load', self.__emit_load)

        elif valor == 'Archivos ...':
            filechooser = FileChooser(
                parent_window=self.get_toplevel(),
                title="Cargar Archivos",
                action=Gtk.FileChooserAction.OPEN,
                #path=path,
                mime=mtype,
                )

            filechooser.connect('load', self.__emit_load)

    def __emit_load(self, widget, archivos):

        self.emit('load', archivos)

class FileChooser(Gtk.FileChooserDialog):

    __gtype_name__ = 'JAMediaConverterFileChooser'

    __gsignals__ = {
    'load': (GObject.SIGNAL_RUN_LAST,
        GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT, ))}

    def __init__(self,
        parent_window=None,
        filter_type=[],
        title=None,
        #path=None,
        action=Gtk.FileChooserAction.OPEN,
        mime=[]):

        Gtk.FileChooserDialog.__init__(self,
            parent=parent_window,
            action=action,
            flags=Gtk.DialogFlags.MODAL,
            title=title)

        self.action = action
        self.set_default_size(640, 480)
        self.modify_bg(0, get_colors("window"))

        #if os.path.isfile(path):
        #    self.set_filename(path)

        #else:
        #    self.set_current_folder_uri("file://%s" % path)

        if self.action == Gtk.FileChooserAction.OPEN:
            self.set_select_multiple(True)

            if filter_type:
                filter = Gtk.FileFilter()
                filter.set_name("Filtro")

                for fil in filter_type:
                    filter.add_pattern(fil)

                self.add_filter(filter)

            elif mime:
                filter = Gtk.FileFilter()
                filter.set_name("Filtro")

                for m in mime:
                    filter.add_mime_type(m)

                self.add_filter(filter)

        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)

        abrir = Gtk.Button("Abrir")
        salir = Gtk.Button("Salir")

        hbox.pack_end(salir, True, True, 5)
        hbox.pack_end(abrir, True, True, 5)

        self.set_extra_widget(hbox)

        salir.connect("clicked", self.__salir)
        abrir.connect("clicked", self.__abrir)

        self.show_all()

        #self.connect("file-activated", self.__file_activated)

    #def __file_activated(self, widget):
    #    """
    #    Cuando se hace doble click sobre un archivo.
    #    """

    #    self.__abrir(None)

    def __abrir(self, widget):
        """
        Emite el path del archivo seleccionado.
        """

        files = self.get_filenames()

        if self.action == Gtk.FileChooserAction.SELECT_FOLDER:
            self.emit('load', files)

        elif self.action == Gtk.FileChooserAction.OPEN:
            if not files:
                self.__salir(None)
                return

            archivos = []
            for file in files:
                direccion = str(file).replace("//", "/")

                if os.path.exists(direccion) and os.path.isfile(direccion):
                    archivos.append(direccion)

            self.emit('load', archivos)

        self.__salir()

    def __salir(self, widget=None):

        self.destroy()

class Lista(Gtk.TreeView):
    """
    Lista generica.
    """

    __gsignals__ = {
    "nueva-seleccion": (GObject.SIGNAL_RUN_FIRST,
        GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT, ))}

    def __init__(self):

        Gtk.TreeView.__init__(self)

        self.set_property("rules-hint", True)
        self.set_headers_clickable(True)
        self.set_headers_visible(True)

        self.permitir_select = True
        self.valor_select = None

        self.modelo = Gtk.ListStore(
            GdkPixbuf.Pixbuf,
            GObject.TYPE_STRING,
            GObject.TYPE_STRING)

        self.__setear_columnas()

        self.treeselection = self.get_selection()
        self.treeselection.set_select_function(
            self.__selecciones, self.modelo)

        self.set_model(self.modelo)
        self.show_all()

    def __selecciones(self, treeselection,
        model, path, is_selected, listore):
        """
        Cuando se selecciona un item en la lista.
        """

        if not self.permitir_select:
            return True

        # model y listore son ==
        _iter = model.get_iter(path)
        valor = model.get_value(_iter, 2)

        if not is_selected and self.valor_select != valor:
            self.scroll_to_cell(model.get_path(_iter))
            self.valor_select = valor
            self.emit('nueva-seleccion', self.valor_select)

        return True

    def __setear_columnas(self):

        self.append_column(self.__construir_columa_icono('', 0, True))
        self.append_column(self.__construir_columa('Nombre', 1, True))
        self.append_column(self.__construir_columa('', 2, False))

    def __construir_columa(self, text, index, visible):

        render = Gtk.CellRendererText()

        columna = Gtk.TreeViewColumn(text, render, text=index)
        columna.set_sort_column_id(index)
        columna.set_property('visible', visible)
        columna.set_property('resizable', False)
        columna.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)

        return columna

    def __construir_columa_icono(self, text, index, visible):

        render = Gtk.CellRendererPixbuf()

        columna = Gtk.TreeViewColumn(text, render, pixbuf=index)
        columna.set_property('visible', visible)
        columna.set_property('resizable', False)
        columna.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)

        return columna

    def limpiar(self):

        self.permitir_select = False
        self.modelo.clear()
        self.permitir_select = True

    def agregar_items(self, elementos):
        """
        Recibe lista de: [texto para mostrar, path oculto] y
        Comienza secuencia de agregado a la lista.
        """

        self.get_toplevel().set_sensitive(False)
        self.permitir_select = False

        GLib.idle_add(self.__ejecutar_agregar_elemento, elementos)

    def __ejecutar_agregar_elemento(self, elementos):
        """
        Agrega los items a la lista, uno a uno, actualizando.
        """

        if not elementos:
            self.permitir_select = True
            self.seleccionar_primero()
            self.get_toplevel().set_sensitive(True)
            return False

        texto, path = elementos[0]

        descripcion = describe_uri(path)

        icono = None
        if descripcion:
            if descripcion[2]:
                # Es un Archivo
                tipo = describe_archivo(path)

                if 'video' in tipo or 'application/ogg' in tipo or \
                    'application/octet-stream' in tipo:
                    icono = os.path.join(BASEPATH,
                        "Iconos", "video.svg")

                elif 'audio' in tipo:
                    icono = os.path.join(BASEPATH,
                        "Iconos", "sonido.svg")

                else:
                    icono = os.path.join(BASEPATH,
                        "Iconos", "sonido.svg")

        else:
            icono = os.path.join(BASEPATH,
                "Iconos", "sonido.svg")

        try:
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(icono,
                get_pixels(0.8), -1)
            self.modelo.append([pixbuf, texto, path])

        except:
            pass

        elementos.remove(elementos[0])

        GLib.idle_add(self.__ejecutar_agregar_elemento, elementos)

        return False

    def seleccionar_siguiente(self, widget=None):

        modelo, _iter = self.treeselection.get_selected()

        try:
            self.treeselection.select_iter(modelo.iter_next(_iter))

        except:
            self.seleccionar_primero()

        return False

    def seleccionar_anterior(self, widget=None):

        modelo, _iter = self.treeselection.get_selected()

        try:
            self.treeselection.select_iter(modelo.iter_previous(_iter))

        except:
            self.seleccionar_ultimo()

        return False

    def seleccionar_primero(self, widget=None):

        self.treeselection.select_path(0)

    def seleccionar_ultimo(self, widget=None):

        model = self.get_model()
        item = model.get_iter_first()

        _iter = None

        while item:
            _iter = item
            item = model.iter_next(item)

        if _iter:
            self.treeselection.select_iter(_iter)
            #path = model.get_path(iter)


import random
import sys

board=[i for i in range(0,9)]
player, computer = '',''

# Esquinas, centro y otros
moves=((1,7,3,9),(5,),(2,4,6,8))
# Combinaciones ganadoras
winners=((0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6))
# Tabla
tab=range(1,10)

def print_board():
    x=1
    for i in board:
        end = ' | '
        if x%3 == 0:
            end = ' \n'
            if i != 1: end+='---------\n'
        char=' '
        if i in ('X','O'): char=i
        x+=1
        print(char,end=end)

def select_char():
    chars=('X','O')
    if random.randint(0,1) == 0:
        return chars[::-1]
    return chars

def can_move(brd, player, move):
    if move in tab and brd[move-1] == move-1:
        return True
    return False

def can_win(brd, player, move):
    places=[]
    x=0
    for i in brd:
        if i == player: places.append(x)
        x+=1
    win=True
    for tup in winners:
        win=True
        for ix in tup:
            if brd[ix] != player:
                win=False
                break
        if win == True:
            break
    return win

def make_move(brd, player, move, undo=False):
    if can_move(brd, player, move):
        brd[move-1] = player
        win=can_win(brd, player, move)
        if undo:
            brd[move-1] = move-1
        return (True, win)
    return (False, False)

# IA
def computer_move():
    move=-1
    #
    for i in range(1,10):
        if make_move(board, computer, i, True)[1]:
            move=i
            break
    if move == -1:
        #
        for i in range(1,10):
            if make_move(board, player, i, True)[1]:
                move=i
                break
    if move == -1:
        #
        for tup in moves:
            for mv in tup:
                if move == -1 and can_move(board, computer, mv):
                    move=mv
                    break
    return make_move(board, computer, move)

def space_exist():
    return board.count('X') + board.count('O') != 9

player, computer = select_char()
print('Eres [%s] y la computadora es [%s]' % (player, computer))
result=' Empate ! '
while space_exist():
    print_board()
    print('# Elegí un casillero ! [1-9] : ', end='')
    move = int(input())
    moved, won = make_move(board, player, move)
    if not moved:
        print(' >> Numero incorrecto! Intenta de nuevo')
        continue
    #
    if won:
        result='*** Ganaste!! ***'
        break
    elif computer_move()[1]:
        result='=== Perdiste!! =='
        break

print_board()
print(result)


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

from lxml import etree
import os

def get_indentation_level(row, level_indent=4):
    row = row.replace("\t", " "*level_indent)
    i = 0
    while row[i] == " ":
        i += 1
    return int(i / level_indent)

def validate(rows):
    current_level = 0
    for row in rows:
        level = get_indentation_level(row)
        if level - current_level > 1:
            return False
        current_level = level
    return True

def get_path(elem):
    return "/".join([e.get("name", "") for e in elem.xpath("./ancestor-or-self::*")])

def parse_taxonomy(rows):
    rows = list(map(lambda x: x.decode("utf-8"), rows))
    assert validate(rows), "Wrong structure"
    tax = etree.Element("tax")
    current_root = None
    current_level = 0
    for k, row in enumerate(rows):
        level = get_indentation_level(row)
        elem = etree.Element("node")
        name = row.strip().lower().capitalize()
        elem.set("name", name)
        elem.set("num", str(k))
        if level == 0 :
            current_level = level
            tax.append(elem)
        elif level == current_level + 1 :
            current_root.append(elem)
            current_level = level
        else:
            step = current_level - level + 1
            while step > 0 :
                step -= 1
                current_root = current_root.getparent()
            current_root.append(elem)
            current_level = level
        current_root = tax.xpath("//*[@num = '"+str(k)+"']")[0]
        current_root.set("path", get_path(current_root))
    return tax

if __name__ == "__main__":
    import sys
    from lxml import etree
    with open(sys.argv[1]) as f :
        print (etree.tounicode(parse_tax(f)))


import wx
import os
from os.path import basename
from include.utils import  dict2

class ast_Call(dict2):
	def __init__(self, *args, **kwargs):
		dict2.__init__(self, *args, **kwargs)
	def setTree(self, tree):
		self.tree=tree
	def set_Call(self, **kwargs):
		key, nodes = kwargs['key'], kwargs['nodes']

		last0=self.append_Call(key= key,nodes= nodes, lineno=kwargs['lineno'])
		if last0: self.tree.Expand(last0)
	def append_Call(self, **kwargs):
		key, nodes, root = kwargs['key'], kwargs['nodes'], kwargs.get('root', None),
		lineno = kwargs['lineno']
		tree=self.tree
		if not root: return
		asrt (root, 'Root is not defined for leaf "1" nodes')
		for node in [node for node in nodes if node.col_offset==1]:
			#print(lineno, node.lineno, node.end_lineno)
			if key != node.name:
				btn = wx.Button(tree.GetMainWindow(), -1, node.name)
				btn.SetSize(btn.GetBestSize())
				if 1:

					tree.gen_bind(wx.EVT_BUTTON, btn, tree.OnEditFile, (tree.pyscript.script_loc, node.lineno))
				last1 = tree.AppendItem(root, node.name, wnd=btn)
			elif hasattr(node, 'names'):
				label = ','.join(node.names)
				if hasattr(node, 'module'):
					label = '%s [%s]' % (node.module, label)
				last1 = tree.AppendItem(root, label)
		return last1


from rest_framework import serializers

from fix_the_news.communications import models

class CommunicationReadOnlySerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Communication
        fields = (
            'id',
            'text',
            'title',
            'type',
        )
        read_only_fields = fields


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

# In[3]:

# Install a pip package in the current Jupyter kernel
import sys
get_ipython().system('{sys.executable} -m pip install pandas')

# In[3]:

import pandas as pd
df = pd.read_csv("D:\Python\Pandas\weather.csv")

# In[5]:

df

# In[6]:

df.Temperature.max()

# In[7]:

df['Temperature'].max()

# In[8]:

df['EST'][df['Events'] == 'Rain']

# In[14]:

df.fillna(0, inplace=True)
df['WindSpeedMPH'].mean()

# In[15]:

df['WindSpeedMPH'].mode()

# In[16]:

df['WindSpeedMPH'].median()

# In[17]:

df['TestData1'] + df['TestDataB']

# In[18]:

df.describe()

# In[22]:

weather_data = {
    'day': ['1/1/2017','1/2/2017','1/3/2017','1/4/2017','1/5/2017','1/6/2017'],
    'temperature': [32,35,28,24,32,31],
    'windspeed': [6,7,2,7,4,2],
    'event': ['Rain', 'Sunny', 'Snow','Snow','Rain', 'Sunny']
}
df = pd.DataFrame(weather_data)
df = pd.read_csv("weather_data.csv")
df

# In[24]:

df.shape

# In[25]:

rows, columns = df.shape

# In[26]:

rows

# In[27]:

columns

# In[28]:

df.head()

# In[29]:

df.head(2)

# In[30]:

df.tail()

# In[31]:

df.tail(1)

# In[33]:

df[2:5]

# In[34]:

df.columns

# In[35]:

df.day

# In[37]:

df.event
df['event']

# In[38]:

type(df['event'])

# In[40]:

df[['event', 'day', 'temperature']]

# In[41]:

df

# In[43]:

df.temperature.max()

# In[44]:

df.temperature.mean()

# In[45]:

df.temperature.std()

# In[46]:

df.describe()

# In[47]:

df[df.temperature >= 32]

# In[49]:

df[df.temperature == df.temperature.max()]

# In[54]:

df['day'][df.temperature == df.temperature.max()]

# In[56]:

df[['day','temperature']][df.temperature == df.temperature.max()]

# In[57]:

df

# In[58]:

df.index

# In[ ]:

df.set_index('day', inplace=True)

# In[69]:

df

# In[71]:

df.loc['1/1/2017']

# In[72]:

df.reset_index(inplace=True)

# In[73]:

df

# In[74]:

df.set_index('event', inplace=True)

# In[75]:

df

# In[77]:

df.loc['Snow']


# encoding: utf-8
from report import db

class ServiceCheckResult(db.Model):
    """

    """
    __tablename__ = 'service_check_result'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    service_name = db.Column(db.String(16))
    service_state = db.Column(db.String(32))
    image_url = db.Column(db.String(256), nullable=True)
    classes = db.Column(db.String(32))
    on_watch = db.Column(db.String(16))
    date = db.Column(db.String(32))

    def __repr__(self):
        return '<ServiceCheckResult %r>' % self.__tablename__

    @staticmethod
    def from_json(json_post):
        """"""

        service_name = json_post.get('service_name')
        service_state = json_post.get('service_state')
        image_url = json_post.get('image_url')
        classes = json_post.get('classes')
        on_watch = json_post.get('on_watch')
        date = json_post.get('date')
        return ServiceCheckResult(service_name=service_name,
                                  service_state=service_state,
                                  image_url=image_url,
                                  classes=classes,
                                  on_watch=on_watch,
                                  date=date)

class IdcCheckResult(db.Model):
    """

    """
    __tablename__ = 'idc_check_result'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    ca_temperature = db.Column(db.String(16))
    ca_humidity = db.Column(db.String(16))
    two_temperature = db.Column(db.String(16))
    two_humidity = db.Column(db.String(16))
    five_temperature = db.Column(db.String(16))
    five_humidity = db.Column(db.String(16))
    check_user = db.Column(db.String(32))
    check_time = db.Column(db.DATETIME())
    classes = db.Column(db.String(32))
    on_watch = db.Column(db.String(16))
    date = db.Column(db.String(32))

    def __repr__(self):
        return '<IdcCheckResult %r>' % self.__tablename__

    @staticmethod
    def from_json(json_post):
        """"""

        ca_temperature = json_post.get('ca_temperature')
        ca_humidity = json_post.get('ca_humidity')
        two_temperature = json_post.get('two_temperature')
        two_humidity = json_post.get('two_humidity')
        five_temperature = json_post.get('five_temperature')
        five_humidity = json_post.get('five_humidity')
        check_user = json_post.get('check_user')
        check_time = json_post.get('check_time')
        on_watch = json_post.get('on_watch')
        date = json_post.get('date')
        classes = json_post.get('classes')
        return IdcCheckResult(ca_temperature=ca_temperature,
                              ca_humidity=ca_humidity,
                              two_temperature=two_temperature,
                              two_humidity=two_humidity,
                              five_temperature=five_temperature,
                              five_humidity=five_humidity,
                              check_user=check_user,
                              check_time=check_time,
                              on_watch=on_watch,
                              date=date,
                              classes=classes)

class CheckDetails(db.Model):
    """

    """
    __tablename__ = 'check_details'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    hardware = db.Column(db.Text())
    system = db.Column(db.Text())
    network = db.Column(db.Text())
    service = db.Column(db.Text())
    is_handle = db.Column(db.Integer, default=1)
    is_report = db.Column(db.Integer, default=0)
    alert_source = db.Column(db.String(32))
    classes = db.Column(db.String(32))
    on_watch = db.Column(db.String(16))
    date = db.Column(db.String(32))

    def __repr__(self):
        return '<CheckDetails %r>' % self.__tablename__

    @staticmethod
    def from_json(json_post):
        """"""

        hardware = json_post.get('hardware')
        system = json_post.get('system')
        network = json_post.get('network')
        service = json_post.get('service')
        is_handle = json_post.get('is_handle')
        is_report = json_post.get('is_report')
        alert_source = json_post.get('alert_source')
        on_watch = json_post.get('on_watch')
        date = json_post.get('date')
        classes = json_post.get('classes')
        return CheckDetails(hardware=hardware,
                            system=system,
                            network=network,
                            service=service,
                            is_handle=is_handle,
                            is_report=is_report,
                            alert_source=alert_source,
                            on_watch=on_watch,
                            date=date,
                            classes=classes)


from database import *
from SQLoperation import *
from exceptions import *
from condition import *
from antlr4 import *
from .miniSQLParser import miniSQLParser
from functools import reduce
from copy import copy

class Visitor(ParseTreeVisitor):

    def __init__(self):
        ParseTreeVisitor.__init__(self)

        self.relationNames = dict() # alias -> real name
        self.attributeNames = dict() # alias -> Attribute(table,name)
        self.attributeNeeded = dict() # alias -> Attribute(table,name)
        self.aggregate = dict() # name -> operator

        self.allAttr = False
        self.hasAggreg = False

        self.dataManager = DataManager() # will handle relation loading

    def reset(self):
        print_debug("Reseting all attributes of visitor class")
        self.relationNames = dict()
        self.attributeNames = dict()
        self.aggregate = dict()
        self.allAttr = False
        self.hasAggreg = False
        self.dataManager = DataManager()

    def visitMain(self, ctx:miniSQLParser.MainContext):
        print_debug("visitMain")
        resultRelation = self.visit(ctx.sql())
        self.dataManager.discard()
        return resultRelation

    # ________________________ sql rules _______________________________________
    def visitSqlNormal(self, ctx:miniSQLParser.SqlNormalContext):
        # SELECT (DISTINCT)? atts FROM rels (WHERE cond)? (GROUPBY att)? orderby?
        print_debug("visitSqlNormal")

        # 1/ Get the tables in main query
        relations = self.visit(ctx.rels())

        # 2/ Get eventual tables from subqueries
        if ctx.cond() is not None:
            condTree,relList,_ = self.visit(ctx.cond())
            print_debug("Relations from cond:", relList)
            relations.update(relList)

        # 3/ Getting attributes
        attributes = self.visit(ctx.atts())
        print_debug(" Attributes :", attributes)
        print_debug(" Aggregates :", self.aggregate)

        # 4/ Only one relation => using special operators
        if len(relations)==1:
            attributes = self.visit(ctx.atts())

            if not self.aggregate:
                print_debug("Calling readSelectProjectRename")
                rel = relations.pop()
                condTree = None
                if ctx.cond() is not None:
                    condTree,_,_ = self.visit(ctx.cond())
                return readSelectProjectRename(rel[0], rel[1], attributes, self.allAttr, Or(condTree))

            elif ctx.GROUPBY() is not None:
                print_debug("Calling readSelectRenameGroupByProject")
                rel = relations.pop()
                condTree = None
                if ctx.cond() is not None:
                    condTree,_,_ = self.visit(ctx.cond())
                grpAttr = self.visit(ctx.att())
                return readSelectRenameGroupByProject(rel[0], rel[1], attributes, self.allAttr, Or(condTree), grpAttr, self.aggregate)

        # 5/ Load all the tables
        print_debug(" Relations 0:" + str(self.relationNames))
        temp = set()
        for (fileName,tableName) in relations :
            self.dataManager.load(fileName)
            self.relationNames[tableName]=fileName
            if fileName!=tableName :
                self.dataManager.rename_table(fileName,tableName)
            temp.add(tableName) # get rid of fileName : not useful from now on
        relations = temp
        print_debug(" Relations :" + str(self.relationNames))

        # 6/ Completing attributeNeeded, if is a 'SELECT *'
        if self.allAttr :
            for tableName,fileName in self.visit(ctx.rels()) :
                for attribute in self.dataManager(tableName).get_keys() :
                    self.attributeNeeded[attribute.fullName] = attribute
        print_debug(" AttributeNeeded :", self.attributeNeeded)

        # 7/ Perform a join on the tables, only on usefull attributes
        def simplif(x):
            return project( x, [attr for attr in self.attributeNeeded.values() if attr.table == x.name ] )
        tables = [simplif(x) for x in self.dataManager.get_tables(relations)]
        resultRelation = reduce(lambda x,y : join(x,y), tables)

        # 8/ 2nd pass over conditions to get condition tree
        if ctx.cond() is not None:
            condTree,_,notIn = self.visit(ctx.cond())
            if notIn:
                r1,r2 = Table.duplicate(resultRelation)
                resultNormal = select(r1, Or(condTree), True)
                #print_debug("-------------------------------Le normal : ---------------------------------------")
                #print_debug(resultNormal)

                resultWithIn = select(r2, Or(condTree), False)
                #print_debug("-------------------------------Le withIn : ---------------------------------------")
                #print_debug(resultWithIn)

                resultRelation = minus(resultNormal,resultWithIn)
                #print_debug("-------------------------------Le final : ---------------------------------------")
                #print_debug(resultRelation)
            else:
                resultRelation = select(resultRelation, Or(condTree))
            print_debug(" Conditions : " + str(condTree))

        # 9/ Sorting of output
        if ctx.orderby() is not None :
            orderkeys,desc = self.visit(ctx.orderby())
            print_debug("Order keys : ", orderkeys)
            resultRelation = orderBy(resultRelation, orderkeys, desc=desc)

        # 10/ Group By or aggregate result
        if ctx.GROUPBY() is not None:
            print_debug("Group By")
            grpAttr = self.visit(ctx.att())
            resultRelation = groupBy(resultRelation, grpAttr, self.aggregate)
        elif self.hasAggreg:
            resultRelation = aggregate(resultRelation, self.aggregate)

        # 11/ Perform final projection if not a 'SELECT *'
        if not self.allAttr:
            resultRelation = project(resultRelation, attributes)

        # 12/ Delete duplicates
        if ctx.DISTINCT() is not None :
            print_debug("Select Distinct")
            resultRelation = select_distinct(resultRelation)

        return resultRelation

    def visitSqlMinus(self, ctx:miniSQLParser.SqlMinusContext):
        # LPAR sql RPAR MINUS LPAR sql RPAR
        print_debug("visitSqlMinus")
        rel1 = self.visit(ctx.sql(0))
        self.reset()
        rel2 = self.visit(ctx.sql(1))
        return minus(rel1,rel2)

    def visitSqlUnion(self, ctx:miniSQLParser.SqlUnionContext):
        # LPAR sql RPAR UNION LPAR sql RPAR
        print_debug("visitSqlUnion")
        rel1 = self.visit(ctx.sql(0))
        self.reset()
        rel2 = self.visit(ctx.sql(1))
        return union(rel1,rel2)

    # _________________________ subsql rules ___________________________________
    def visitSubSql(self, ctx, attr):
        """
        Called when visiting a sub query
        """
        print_debug("visitSubSql")
        clue = ctx.getChild(3).getText()
        if clue == 'MINUS':
            return self.visitSubSqlMinus(ctx,attr)
        elif clue == 'UNION':
            return self.visitSubSqlUnion(ctx,attr)
        else:
            return self.visitSubSqlNormal(ctx,attr)

    def visitSubSqlNormal(self, ctx, attr):
        print_debug("visitSubSqlNormal")
        attributes = self.visit(ctx.atts())
        assert(len(attributes)==1) # There should be only one here
        subAttr = attributes[0]
        relations = self.visit(ctx.rels())
        condTree, rels, _ = self.visit(ctx.cond()) # condTree a list of list : CDF form
        return [Or(condTree),Condition(attr,Op.EQ,subAttr)], (relations | rels)

    def visitSubSqlMinus(self, ctx, attr): # TODO : false version
        print_debug("visitSubSqlUnion")
        condTree1, rels1 = self.visitSubSql(ctx.sql(0), attr)
        condTree2, rels2 = self.visitSubSql(ctx.sql(1), attr)
        return [Or([And(condTree1),And(condTree2)])], (rels1 | rels2)

    def visitSubSqlUnion(self, ctx, attr):
        print_debug("visitSubSqlUnion")
        condTree1, rels1 = self.visitSubSql(ctx.sql(0), attr)
        condTree2, rels2 = self.visitSubSql(ctx.sql(1), attr)
        return [Or([And(condTree1),And(condTree2)])], (rels1 | rels2)

    # _________________________ Order By rules _____________________________________

    def visitOrderBy(self, ctx:miniSQLParser.OrderByContext):
        # ORDERBY atts (DESC|ASC)?
        orderkeys = self.visit(ctx.atts())
        desc = ctx.DESC() is not None
        return orderkeys,desc

    # _________________________ atts rules _____________________________________
    def visitAttributeDeclAll(self, ctx:miniSQLParser.AttributeDeclAllContext):
        # SELECT *
        print_debug("visitAttributeDeclAll")
        self.allAttr = True
        return []

    def visitAttributeDeclList(self, ctx:miniSQLParser.AttributeDeclListContext):
        print_debug("visitAttributeDeclList")
        queueOfAttrList = self.visit(ctx.atts())
        firstAttrElem, aggr =  self.visit(ctx.attd())
        self.aggregate[firstAttrElem] = aggr
        return [firstAttrElem]+queueOfAttrList

    def visitAttributeDeclSimple(self, ctx:miniSQLParser.AttributeDeclSimpleContext):
        print_debug("visitAttributeDeclSimple")
        attr, aggr = self.visit(ctx.attd())
        self.aggregate[attr] = aggr
        return [attr]

    # ___________________ attd rules ___________________________________________
    def visitAttributeSimple(self, ctx:miniSQLParser.AttributeSimpleContext):
        print_debug("visitAttributeSimple")
        attr = self.visit(ctx.att())
        self.attributeNames[attr.fullName] = attr
        self.attributeNeeded[attr.fullName] = attr
        return attr, Aggregation.NONE

    def visitAttributeAs(self, ctx:miniSQLParser.AttributeAsContext):
        print_debug("visitAttributeAs")
        attr = self.visit(ctx.att())
        alias = ctx.ID().getText()
        self.attributeNames[alias] = attr
        self.attributeNeeded[alias] = attr
        return attr, Aggregation.NONE

    def visitAttributeAggr(self, ctx:miniSQLParser.AttributeAggrContext):
        print_debug("visitAttributeAggr")
        attr = self.visit(ctx.att())
        self.attributeNames[attr.fullName] = attr
        self.attributeNeeded[attr.fullName] = attr
        self.hasAggreg = True
        aggr = ctx.aggr().getText()
        if aggr == "MAX":
            aggr = Aggregation.MAX
        elif aggr == "MIN":
            aggr = Aggregation.MIN
        elif aggr == "COUNT":
            aggr = Aggregation.COUNT
        elif aggr == "SUM":
            aggr = Aggregation.SUM
        return attr, aggr

    # __________________ att rule ______________________________________________
    def visitAtt(self, ctx:miniSQLParser.AttContext):
        print_debug("visitAtt")
        tableName = ctx.ID(0).getText()
        attrName = ctx.ID(1).getText()
        return Attribute(tableName,attrName)

    # __________________ rels rules ____________________________________________
    def visitRelationDeclList(self, ctx:miniSQLParser.RelationDeclListContext):
        print_debug("visitRelationDeclList")
        queueRel = self.visit(ctx.rels())
        firstRel = self.visit(ctx.rel())
        queueRel.add(firstRel)
        return queueRel

    def visitRelationDeclSimple(self, ctx:miniSQLParser.RelationDeclSimpleContext):
        print_debug("visitRelationDeclSimple")
        x = self.visit(ctx.rel())
        out = set()
        out.add(x) #Not juste set of x because it unpacks tuples...
        return out

    # __________________ rel rules _____________________________________________
    def visitRelationID(self, ctx:miniSQLParser.RelationIDContext):
        print_debug("visitRelationID")
        fileName = ctx.FILENAME().getText()
        tableName = ctx.ID().getText()
        return (fileName,tableName)

    def visitRelationSubQuery(self, ctx:miniSQLParser.RelationSubQueryContext):
        # When a table in the FROM is a subquery
        print_debug("visitRelationSubQuery")
        tableName = ctx.ID().getText()

        mem = self.allAttr
        self.allAttr = False
        rel = self.visit(ctx.sql())
        self.allAttr = mem

        self.relationNames[tableName]=tableName
        rel.rename(tableName)
        self.dataManager.add_table(rel)

        return (tableName,tableName)

    # _____________________ cond rules _________________________________________
    def visitCondOrList(self, ctx:miniSQLParser.CondOrListContext):
        print_debug("visitCondOrList")
        queueCond, setRel1, notIn1 = self.visit(ctx.cond())
        firstCond, setRel2, notIn2 = self.visit(ctx.and_cond())
        return [And(firstCond)]+queueCond, (setRel1 | setRel2), (notIn1 or notIn2)

    def visitCondOrSimple(self, ctx:miniSQLParser.CondOrSimpleContext):
        print_debug("visitCondOrSimple")
        cond , setRel, notIn = self.visit(ctx.and_cond())
        return [And(cond)], setRel, notIn

    # ____________________ and_cond rules ______________________________________
    def visitCondAndOr(self, ctx:miniSQLParser.CondAndOrContext):
        print_debug("visitCondAndOr")
        queueCond, setRel1, notIn1 = self.visit(ctx.and_cond())
        firstCond, setRel2, notIn2 = self.visit(ctx.cond())
        return [Or(firstCond)]+queueCond, (setRel1 | setRel2), (notIn1 or notIn2)

    def visitCondAndList(self, ctx:miniSQLParser.CondAndListContext):
        print_debug("visitCondAndList")
        queueCond, setRel1, notIn1 = self.visit(ctx.and_cond())
        firstCond, setRel2, notIn2 = self.visit(ctx.at_cond())
        return firstCond+queueCond, (setRel1 | setRel2), (notIn1 or notIn2)

    def visitCondAndSimple(self, ctx:miniSQLParser.CondAndSimpleContext):
        print_debug("visitCondAndSimple")
        cond, rel, notIn = self.visit(ctx.at_cond())
        return (cond, rel, notIn)

    # ____________________ at_cond rules _______________________________________
    def visitCompSimple(self, ctx:miniSQLParser.CompSimpleContext):
        print_debug("visitCompSimple")
        op = text_to_OP(ctx.op().getText())
        if ctx.CONST() is not None :
            attr,const = self.visit(ctx.att(0)), ctx.CONST().getText()
            self.attributeNeeded[attr.fullName] = attr
            return [ConstCondition(attr,op,const)], set(), False
        else:
            attr1,attr2 = self.visit(ctx.att(0)), self.visit(ctx.att(1))
            self.attributeNeeded[attr1.fullName] = attr1
            self.attributeNeeded[attr2.fullName] = attr2
            return [Condition(attr1,op,attr2)], set(), False

    def visitCompIn(self, ctx:miniSQLParser.CompInContext):
        print_debug("visitCompIn")
        attr = self.visit(ctx.att())
        self.attributeNeeded[attr.fullName] = attr
        cond, rel = self.visitSubSql(ctx.sql(), attr)
        return cond, rel, False

    def visitCompNotIn(self, ctx:miniSQLParser.CompNotInContext):
        print_debug("visitCompNotIn")
        attr = self.visit(ctx.att())
        self.attributeNeeded[attr.fullName] = attr
        cond,rel = self.visitSubSql(ctx.sql(), attr)
        return [NotInCond(cond)], rel, True


# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import re
EMAIL_REGEX = re.compile(r'^[a-zA-Z0-9\.\+_-]+@[a-zA-Z0-9\._-]+\.[a-zA-Z]*$')
from django.shortcuts import render, redirect
from django.contrib import messages
from models import Email

# Create your views here.
def index(request):
    return render(request, "test_app/index.html")

def process(request):
    if request.method == "POST":
        if not EMAIL_REGEX.match(request.POST["email"]):
            messages.add_message(request, messages.ERROR, "Email is not valid!")
            return redirect("/")
        else:
            request.session['email'] = request.POST['email']
            Email.objects.create(name=request.POST['email'])
            context = {'emails': Email.objects.all()}
            return render(request, 'test_app/process.html', context)


from model.task import Task
from config.config import storage_path, test_suits_folder_path
from model.task_status import TaskStatus
from model.response import Response
from dateutil import parser
from datetime import timedelta
import simplejson
import re

"""
This controller for json storage of Task entities

Provide all methods to manage with Task entities
"""

class DataManager:
    def __init__(self, next_id: int, tasks: [Task], file_path=None):
        """
        Constructor for DataManager object

        :param next_id: id of task, that will be created next
        :param tasks: list of Task entity;
        """
        self.next_id = next_id
        self.tasks = tasks
        self.storage_path = file_path if file_path is str else storage_path

    def __json__(self):
        """
        JSON serialization for DataManager object

        :return: dict with all inner fields
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> a.__json__().__str__() == open(test_suits_folder_path + "/test_suit1.txt", 'r').read()
        True
        """
        return {
            'next_id': self.next_id,
            'tasks': DataManager.tasks_to_json(self.tasks),
        }

    for_json = __json__  # supported by simplejson

    @classmethod
    def from_json(cls, json_obj):
        """
        Creating DataManager object from JSON object

        :param json_obj: JSON object (dict)
        :return: instance of DataManager
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> b = DataManager.from_json(a.__json__())
        >>> b.next_id
        2
        >>> b.tasks.__len__()
        1
        """
        return cls(json_obj['next_id'], DataManager.tasks_from_json(json_obj['tasks']))

    @staticmethod
    def tasks_from_json(storage_obj):
        """
        Deserialize Tasks from JSON object

        :param storage_obj: JSON serialized Tasks
        :return: list of Task entities
        >>> data_str = open(test_suits_folder_path + "/test_suit1.json", 'r').read()
        >>> storage_obj = simplejson.loads(data_str)['tasks']
        >>> a = DataManager.tasks_from_json(storage_obj)[0].__json__()
        >>> a['name']
        'Name'
        >>> a['date_start']
        '1999-08-28T21:03:05'
        """
        return list(map(lambda x: Task.from_json(x), storage_obj))

    @staticmethod
    def tasks_to_json(tasks):
        """
        Deserialize Tasks from JSON object

        :param tasks: JSON serialized Tasks
        :return: list of Task entities
        >>> arr = [Task(1, "Name", "nothing", parser.parse("1999-08-28T21:03:05"), \
            parser.parse("1999-08-28T05:55:23"), True)]
        >>> a = DataManager.tasks_to_json(arr)[0]
        >>> a['name']
        'Name'
        >>> a['date_start']
        '1999-08-28T21:03:05'
        >>> a['id']
        1
        """
        return list(map(lambda x: x.__json__(), tasks))

    @classmethod
    def load_from_file(cls, file_path: str):
        """
        Create DataManager instance from file with JSON data

        :param file_path: set explicitly file path of data storage
        :return: instance of DataManager
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> a.next_id
        2
        >>> a.tasks.__len__()
        1
        """
        data_str = open(file_path, 'r').read()
        storage_obj = simplejson.loads(data_str)
        instance = DataManager.from_json(storage_obj)
        instance.storage_path = file_path
        return instance

    def set_storage_path(self, file_path: str):
        """
        Set storage path for data

        :param file_path: file path to json file
        :return: None
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> prev = a.storage_path
        >>> a.set_storage_path("/path")
        >>> a.storage_path == "/path" and a.storage_path != prev
        True
        """
        self.storage_path = file_path

    def save_to_file(self, file_path: str):
        """
        Save changes(tasks ans next_id) in data file

        :param file_path: set explicitly file path of data storage
        :return: None
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> a.save_to_file(test_suits_folder_path + "/test_suit2.json")
        >>> b = open(test_suits_folder_path + "/test_suit1.json", 'r').read()
        >>> c = open(test_suits_folder_path + "/test_suit2.json", 'r').read()
        >>> b == c
        True
        """
        with open(file_path, 'w') as outfile:
            simplejson.dump(self, outfile, indent=4, for_json=True)

    def update_from_file(self, file_path: str):
        """
        Get changes( tasks ans next_id) from data file

        :param file_path: set explicitly file path of data storage
        :return: None
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> a.save_to_file(test_suits_folder_path + "/test_suit2.json")
        >>> a.change_task_status(1, False)
        True
        >>> b = DataManager.load_from_file(test_suits_folder_path + "/test_suit2.json")
        >>> a.tasks[0] != b.tasks[0]
        True
        >>> a.update_from_file(test_suits_folder_path + "/test_suit2.json")
        >>> a.tasks[0] == b.tasks[0]
        True
        >>> a.change_task_status(1, True)
        True
        >>> a.save_to_file(test_suits_folder_path + "/test_suit1.json")
        """
        data_str = open(file_path, 'r').read()
        storage_obj = simplejson.loads(data_str)
        self.next_id = storage_obj['next_id']
        self.tasks = DataManager.tasks_from_json(storage_obj['tasks'])

    def get_all(self, offset=0, limit=None, query=None):
        """
        Get all filtered and paginated tasks

        :param offset: count of skipping tasks
        :param limit: count of tasks in page
        :param query: search parameter
        :return: list of Task entities
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> f = a.get_all().tasks
        >>> task = Task(1, "Name", "nothing", parser.parse("1999-08-28T21:03:05"), \
            parser.parse("1999-08-28T05:55:23"), True)
        >>> f[0] == task
        True
        >>> a.get_all(offset=1).tasks.__len__()
        0
        """
        self.update_from_file(self.storage_path)
        return DataManager.__paginate_and_search__(self.tasks, offset, limit, query)

    def get_with_status(self, status: TaskStatus, offset=0, limit=None, query=None):
        """
        Get all filtered and paginated tasks with selected status

        :param status: selected status of Task
        :param offset: count of skipping tasks
        :param limit: count of tasks in page
        :param query: search parameter
        :return: list of Task entities
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> a.get_with_status(status=TaskStatus.UNCOMPLETED).tasks
        []
        >>> a.get_with_status(status=TaskStatus.COMPLETED).tasks.__len__()
        1
        """
        self.update_from_file(self.storage_path)
        filter_function = {
            TaskStatus.COMPLETED: lambda x: x.completed(),
            TaskStatus.UNCOMPLETED: lambda x: not x.completed(),
            TaskStatus.PLANNED: lambda x: not x.is_finished() and not x.is_running(),
            TaskStatus.RUNNING: lambda x: x.is_running(),
            TaskStatus.FINISHED: lambda x: x.is_finished(),
        }[status]
        result = list(filter(filter_function, self.tasks))
        return DataManager.__paginate_and_search__(result, offset, limit, query, status)

    def get_by_id(self, task_id: int):
        """
        Get Task entity with selected id

        :param task_id: id of searched Task
        :return: Task entity if task with selected id exists else False
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> task = Task(1, "Name", "nothing", parser.parse("1999-08-28T21:03:05"), \
            parser.parse("1999-08-28T05:55:23"), True)
        >>> a.get_by_id(1) == task
        True
        >>> a.get_by_id(-1)
        False
        """
        self.update_from_file(self.storage_path)
        for i, task in enumerate(self.tasks):
            if task.task_id == task_id:
                return self.tasks[i]
        return False

    def update_task(self, task_id: int, new_task: Task):
        """
        Update Task by id

        :param task_id: id of updating Task
        :param new_task: Task entity with updating info
        :return: True if entity was updated else
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit3.json")
        >>> task = Task(1, "TEST val", "nothing", parser.parse("1999-08-28T21:03:05"), \
            parser.parse("1999-08-28T05:55:23"), True)
        >>> a.update_task(1, task)
        True
        >>> a.get_by_id(1) == task
        True
        >>> task.name = "TEst N2"
        >>> a.update_task(1, task)
        True
        >>> a.get_by_id(1) == task
        True
        """
        self.update_from_file(self.storage_path)
        new_task.task_id = task_id
        for i, task in enumerate(self.tasks):
            if task.task_id == task_id:
                self.tasks[i] = new_task
                self.save_to_file(self.storage_path)
                return True
        return False

    def change_task_status(self, task_id: int, is_completed: bool):
        """
        Change Task status

        :param task_id: id of updating Task
        :param is_completed: Task status
        :return:True if entity was updated else False
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit3.json")
        >>> a.change_task_status(1, False)
        True
        >>> a.get_by_id(1).completed()
        False
        >>> a.change_task_status(1, True)
        True
        >>> a.get_by_id(1).completed()
        True
        >>> a.change_task_status(-23, True)
        False
        """
        self.update_from_file(self.storage_path)
        for i, task in enumerate(self.tasks):
            if task.task_id == task_id:
                self.tasks[i].is_completed = is_completed
                self.save_to_file(self.storage_path)
                return True
        return False

    def update_task_info(self, task_id: int, name: str, description: str, date_start: str, duration: int):
        """
        Update Task info

        :param task_id: id of updating Task
        :param name: updated name of Task
        :param description: updated description of Task
        :param date_start: updated start date of Task
        :param duration: updated duration of Task
        :return: True if entity was updated else False
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit4.json")
        >>> temp = a.get_by_id(1)
        >>> a.update_task_info(1, "tEsT", "-.-", "2018", 3600)
        True
        >>> task = Task(1, "tEsT", "-.-", parser.parse("2018-06-03T00:00:00"), \
            parser.parse("2018-06-03T01:00:00"), True)
        >>> a.get_by_id(1) == task
        True
        >>> a.update_task(1, temp)
        True
        >>> a.update_task(144, temp)
        False
        >>> a.update_task_info(-1, "tEsT", "-.-", "2018", 3600)
        False
        """
        self.update_from_file(self.storage_path)
        for i, task in enumerate(self.tasks):
            if task.task_id == task_id:
                self.tasks[i].name = name
                self.tasks[i].description = description
                self.tasks[i].date_start = parser.parse(date_start)
                self.tasks[i].date_end = parser.parse(date_start) + timedelta(seconds=duration)
                self.save_to_file(self.storage_path)
                return True
        return False

    def delete_task(self, task_id: int):
        """
        Delete Task

        :param task_id: id of deleted Task
        :return: True if entity was deleted else False
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit4.json")
        >>> temp = open(test_suits_folder_path + "/test_suit4.json", 'r').read()
        >>> a.delete_task(2)
        False
        >>> a.delete_task(1)
        True
        >>> file = open(test_suits_folder_path + "/test_suit4.json", "w")
        >>> file.write(temp)
        281
        >>> file.close()
        """
        self.update_from_file(self.storage_path)
        length = self.tasks.__len__()
        self.tasks = list(filter(lambda task: task.task_id != task_id, self.tasks))
        self.save_to_file(self.storage_path)
        return length != self.tasks.__len__()

    def add_task(self, task: Task):
        """
        Add new Task to storage

        :param task: new Task entity
        :return: added Task entity
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit5.json")
        >>> task = Task(1, "quest", "desc", parser.parse("2018"), parser.parse("2019"), False)
        >>> a.add_task(task) == task
        True
        """
        self.update_from_file(self.storage_path)
        task.task_id = self.next_id
        self.tasks.append(task)
        self.next_id += 1
        self.save_to_file(self.storage_path)
        return task

    def create_task(self, name: str, description: str, date_start: str, duration: int):
        """
        Create new Task

        :param name: name of new Task
        :param description: description of new Task
        :param date_start: start date of new Task
        :param duration: duration of new Task
        :return: created Task entity
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit5.json")
        >>> task = Task(1, "quest", "desc", parser.parse("2018"), parser.parse("2018-06-03T00:00:34"), False)
        >>> b = a.create_task("quest", "desc", "2018", 34)
        >>> task.task_id = a.next_id - 1
        >>> b == task
        True
        """
        self.update_from_file(self.storage_path)
        task = Task.create(self.next_id, name, description, date_start, duration)
        self.tasks.append(task)
        self.next_id += 1
        self.save_to_file(self.storage_path)
        return task

    @staticmethod
    def __paginate_array__(array, offset=0, limit=None):
        """
        Paginate list of Tasks

        :param array: list of Tasks
        :param offset: count of skipping tasks
        :param limit: count of Tasks in page
        :return: paginated list of Tasks
        >>> print(DataManager.__paginate_array__([1,2,3,4,5]))
        [1, 2, 3, 4, 5]
        >>> print(DataManager.__paginate_array__([1,2,3,4,5], offset=2))
        [3, 4, 5]
        >>> print(DataManager.__paginate_array__([1,2,3,4,5], offset=1, limit=3))
        [2, 3, 4]
        >>> print(DataManager.__paginate_array__([1,2,3,4,5], offset=-5, limit=0))
        [1, 2, 3, 4, 5]
        """
        if isinstance(offset, int) and offset >= 0 and ((isinstance(limit, int) and limit > 0) or limit is None):
            return array[offset:(limit + offset if limit is not None else None)]
        return array

    @staticmethod
    def __search_filter__(array: [Task], query=None):
        """
        Search Tasks in list

        :param array: list of Tasks
        :param query: searched parameter
        :return: list of Tasks that consist searched parameter
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> DataManager.__search_filter__(a.tasks).__len__()
        1
        >>> DataManager.__search_filter__(a.tasks, query="Just").__len__()
        0
        >>> DataManager.__search_filter__(a.tasks, query="Name").__len__()
        1
        >>> DataManager.__search_filter__(a.tasks, query="nam").__len__()
        1
        """
        if not isinstance(query, str) or query.__len__() == 0:
            return array
        return list(filter(lambda x: re.search(query, x.name + x.description, re.IGNORECASE), array))

    @staticmethod
    def __paginate_and_search__(array, offset=0, limit=None, query=None, status_filter=None):
        """
        Paginate list of Tasks and Search Tasks in it

        :param array: list of Tasks
        :param offset: count of skipping tasks
        :param limit: count of Tasks in page
        :param query: searched parameter
        :param status_filter: searched Task status
        :return: paginated list of Tasks that consist searched parameter
        >>> a = DataManager.load_from_file(test_suits_folder_path + "/test_suit1.json")
        >>> DataManager.__paginate_and_search__(a.tasks).tasks.__len__()
        1
        >>> DataManager.__paginate_and_search__(a.tasks, offset=3).tasks.__len__()
        0
        >>> DataManager.__paginate_and_search__(a.tasks, query="nothing").tasks.__len__()
        1
        """
        filtered = DataManager.__search_filter__(array, query)
        length = filtered.__len__()
        tasks_result = DataManager.__paginate_array__(filtered, offset, limit)
        return Response(tasks_result, offset, limit, query, length, status_filter)


"""
@version: 1.1
@author: yipeihuai
@mail: yiph@ihep.ac.cn
@file: simu_so.py
@time: 2018/10/15 10:58
@modify time: 2018/11/27
"""

import numpy as np
import ctypes
import random
import sys
import logging
from decimal import Decimal
from ctypes import *

# extract cdf_sampling_wrapper function pointer in the shared object simu_so.so
def get_cdf_sampling_wrapper():
    dll = ctypes.CDLL('./simu_so.so', mode=ctypes.RTLD_GLOBAL)
    func = dll.CDF_Sampling_wrapper
    func.argtypes = [POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_int), c_int, c_int, c_int, c_int]
    func.restype = c_float
    return func

def get_cdf_sampling_wrapper_C():
    dll = ctypes.CDLL('./simu_c.so', mode=ctypes.RTLD_GLOBAL)
    func = dll.CDF_Sampling_wrapper
    func.argtypes = [POINTER(c_double), POINTER(c_double), POINTER(c_double), c_int, c_int, c_int]
    func.restype = c_double
    return func

# create __cuda_cdf_sampling function with get_cdf_sampling_wrapper()
__cuda_cdf_sampling   = get_cdf_sampling_wrapper()
__cuda_cdf_sampling_C = get_cdf_sampling_wrapper_C()
# convenient python wrapper for __cuda_cdf_sampling
# it does all job with types convertation
# from python ones to C++ ones
def cuda_cdf_sampling(a, b, c, seed, total_num, size, n, time):
    a_p = a.ctypes.data_as(POINTER(c_double))
    b_p = b.ctypes.data_as(POINTER(c_double))
    c_p = c.ctypes.data_as(POINTER(c_double))
    seed_p = seed.ctypes.data_as(POINTER(c_int))

    return __cuda_cdf_sampling(a_p, b_p, c_p, seed_p, total_num, size, n, time)

def cuda_cdf_sampling_C(a, b, c, total_num, n, time):
    a_p = a.ctypes.data_as(POINTER(c_double))
    b_p = b.ctypes.data_as(POINTER(c_double))
    c_p = c.ctypes.data_as(POINTER(c_double))

    return __cuda_cdf_sampling_C(a_p, b_p, c_p, total_num, n, time)

def create_npe_histo(max_n):
    # max_n 最大光子数量
    _range = Decimal('100')
    prob = []
    for item in range(max_n-1):
        _prob = Decimal(random.randrange(0,_range,1))
        prob.append(Decimal(_prob/100))
        _range = _range - _prob
    prob.append(1-sum(prob))
    histo = [str(i) for i in prob]
    return histo

def create_hittime_histo(max_time):
    # max_time 最大击中时间
    _range = Decimal('100')
    prob_list = []
    prob = []
    for item in range(max_time-1):
        _prob = Decimal(random.randrange(0,_range,1))
        prob.append(Decimal(_prob/100))
        _range = _range - _prob
    prob.append(1-sum(prob))
    histo = [str(i) for i in prob]
    return histo

def create_seed():
    _seed =random.randint(0,100000000)
    return _seed

def run(pmt_num,loc_num):
    #数据生成
    # pmt_num = 500
    # loc_num = 100
    max_n = 10
    max_time = 10
    total = str(pmt_num * loc_num)
    count = 1
    temp_list_npe = []
    temp_list_hit = []
    temp_list_seed = []
    for i in range(loc_num):
        for j in range(pmt_num):
            temp_list_npe.append([0,0,0,0,0.5,0,0.2,0,0.3,0])
            temp_list_hit.append([0,0.2,0.2,0.1,0,0,0,0.2,0.2,0.1])
            temp_list_seed.append(create_seed())
            # print("当前进度" + str(count) + "/" + total)
            count += 1
    temp_np_npe = np.array(temp_list_npe).astype('double')
    temp_np_hit = np.array(temp_list_hit).astype('double')
    temp_np_seed = np.array(temp_list_seed).astype('int')
    # print("数据生成任务已完成")

    #假定两种表内存一致大小，即：max_n= max_time
    # 8 :sizeof(double) = 8
    size=int(pmt_num * loc_num *max_n*8 )

    result = np.zeros(size/8).astype('double')

    gputime = cuda_cdf_sampling(temp_np_npe, temp_np_hit, result, temp_np_seed, pmt_num*loc_num, size, max_n, max_time)
    # print("GPU执行结束")
    # logging.info(gputime)
    # print("CPU开始执行")
    cputime = cuda_cdf_sampling_C(temp_np_npe, temp_np_hit, result, pmt_num*loc_num,max_n,max_time)
    # print("CPU执行结束")
    # logging.info(cputime)

    return gputime,cputime
    #强制打印numpy数组全部元素
    # np.set_printoptions(threshold=np.nan)
    # for index in range(0,len(result),max_n):
    #     logging.info(result[index:index+max_n])

if __name__ == '__main__':
    logging.basicConfig(filename='logger.log', filemode='w', level=logging.INFO)
    if len(sys.argv)>3:
        begin = int(sys.argv[1])
        end = int(sys.argv[2])
        step = int(sys.argv[3])
        gpu_time_list = []
        cpu_time_list = []

        for i in range(begin,end+step,step):
            print("total num:"+str(i))
            logging.info("total num:"+str(i))
            gpu_time_list = []
            cpu_time_list = []
            for j in range(10):
                gpu,cpu = run(int(i/10),10)
                gpu_time_list.append(gpu)
                cpu_time_list.append(cpu)
            print("gpu time:"+str(sum(gpu_time_list)/10.0))
            logging.info("gpu time:"+str(sum(gpu_time_list)/10.0))
            print("cpu time:"+str(sum(cpu_time_list)/10.0))
            logging.info("cpu time:"+str(sum(cpu_time_list)/10.0))
            # print("gpu time:"+str(gpu))
            # logging.info("gpu time:"+str(gpu))
            # print("cpu time:"+str(cpu))
            # logging.info("cpu time:"+str(cpu))
    elif len(sys.argv)>2:
        pmt_num = int(sys.argv[1])
        loc_num = int(sys.argv[2])
        run(pmt_num,loc_num)
    else:
        pmt_num = 10
        loc_num = 2
        run(pmt_num,loc_num)


import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

#******************** Sobel、Laplacia 边缘检测 ********************
'''img=cv.imread('2.jpg',0)
laplacian=cv.Laplacian(img,cv.CV_64F)#64F代表每一个像素点元素占64位浮点数
sobelx=cv.Sobel(img,cv.CV_64F,1,0,ksize=5)
sobely=cv.Sobel(img,cv.CV_64F,0,1,ksize=5)
plt.subplot(2,2,1),plt.imshow(img,cmap='gray')
plt.title('Oridinal'),plt.xticks([]),plt.yticks([])
plt.subplot(2,2,2),plt.imshow(laplacian,cmap='gray')
plt.title('Laplacian'),plt.xticks([]),plt.yticks([])
plt.subplot(2,2,3),plt.imshow(sobelx,cmap='gray')
plt.title('sobelx'),plt.xticks([]),plt.yticks([])
plt.subplot(2,2,4),plt.imshow(sobely,cmap='gray')
plt.title('sobely'),plt.xticks([]),plt.yticks([])
plt.show()'''
'''
但这有一个小问题。黑色到白色的过渡被视为正斜率（具有正值），而白色到黑色的过渡被视为负斜率（具有负值）。因此，当您将数据转换为np.uint8时，所有负斜率均设为零。简而言之，您会错过这一优势。
如果要检测两个边缘，更好的选择是将输出数据类型保留为更高的形式，例如cv.CV_16S，cv.CV_64F等，取其绝对值，然后转换回cv.CV_8U。下面的代码演示了水平Sobel滤波器的处理过程以及结果的差异。
'''

#******************** 如果要检测两个边缘，先将其输出为更高精度然后再转回低精度 ********************
'''img = cv.imread('edge.PNG',0)
# Output dtype = cv.CV_8U
sobelx8u = cv.Sobel(img,cv.CV_8U,1,0,ksize=5)
# Output dtype = cv.CV_64F. Then take its absolute and convert to cv.CV_8U
sobelx64f = cv.Sobel(img,cv.CV_64F,1,0,ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)
plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2),plt.imshow(sobelx8u,cmap = 'gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3),plt.imshow(sobel_8u,cmap = 'gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])
plt.show()'''

#******************** canny 边缘检测 ********************
#步骤：1、降噪 2、查找图像的强度梯度 3、非最大抑制 4、滞后阈值法
img=cv.imread('2.jpg',0)
edges=cv.Canny(img,100,200)
plt.subplot(121),plt.imshow(img,cmap='gray')
plt.title('Original Image'),plt.xticks([]),plt.yticks([])#plt.xticks([]),plt.yticks([])不显示坐标轴
plt.subplot(122),plt.imshow(edges,cmap='gray')
plt.title('Edge Image'),plt.xticks([]),plt.yticks([])
plt.show()


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('data/L6-FOL-daily.csv', index_col=0, parse_dates=True)
# print(df[df.isnull().any(axis=1)])
df.fillna(method='ffill', inplace=True) # fill missing data

df.plot.scatter('storage', 'elevation')
plt.xlabel('Storage (TAF)')
plt.ylabel('Water Surface Elevation (ft)')

# # then fit a quadratic and keep the equation for the next code example.
p = np.polyfit(df.storage.values, df.elevation.values, 2)
print('Regression: Elevation = %f S**2 + %f S + %f' % tuple(p))
f = np.poly1d(p)

plt.plot(df.storage.values, f(df.storage.values), color='r', linewidth=2)
plt.show()


import numpy as np
from vizdoom import *
import random
import time
from skimage import transform
from collections import deque
import matplotlib.pyplot as plt
import cv2
from collections import deque

# root path for test scenarios
test_path = './test/'
# each folder will contain the target images for all steps in the scenario. also, a file that contains the final position of the
# agent at the end of the scenario.

# num of scenarios to test on, each scenario has num_action steps
num_scenarios = 100
num_actions = 20

# all actions
backward = [0, 0, 0, 1]
forward = [0, 0, 1, 0]
right = [1, 0, 0, 0]
left = [0, 1, 0, 0]
all_actions = [right, left, forward, backward]

# function to initialize the environment before each scenario
def init_env():
	game = DoomGame()
	game.load_config('dset_create.cfg')
	game.set_doom_scenario_path('test_map.wad')
	game.init()
	return game

game = init_env()

# generate n test scenarios, each with 10 actions
def get_test_scenario_actions():
	test_scenario_actions = []
	# generate 100 test scenario actions
	for i in range(num_scenarios):
		actions_in_scenario = []
		for j in range(num_actions):
			action_choice = np.random.choice(len(all_actions))
			action = all_actions[action_choice]
			actions_in_scenario.append(action)
		test_scenario_actions.append(actions_in_scenario)

	test_scenario_actions = np.array(test_scenario_actions).astype(np.float32)
	return test_scenario_actions

# Run a scenario in our doom environment and store all the observations (will be used as human demonstrations)
def get_target_states_for_scenario(scenario_num, test_scenario_actions):
	game.new_episode()
	end_pos_fname = test_path + str(scenario_num) + '/pos.txt' # will hold the final position of the agent for a scenario (target location)
	actions_in_scenario = test_scenario_actions[scenario_num]
	for i in range(num_actions): # represents the step number in the episode
		# perform action for the step
		action = list(actions_in_scenario[i])
		print('The action is : ', action)
		reward = game.make_action(action)
		print('Performed action.')

		state = game.get_state()
		frame = state.screen_buffer # (240, 320, 3)
		frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) # (240, 320, 1)
		target_image_single_channel = frame
		target_image = np.append(frame, frame)
		target_image = np.append(target_image, target_image_single_channel)
		target_image = np.reshape(target_image, (240, 320, 3))

		# get the position of the agent in the environment
		pos_x = game.get_game_variable(GameVariable.POSITION_X)
		pos_y = game.get_game_variable(GameVariable.POSITION_Y)

		target_fname = test_path +  str(scenario_num) + '/' + str(i) + '_.png'
		res = cv2.imwrite(target_fname, target_image)
		print('Saving : ', target_fname)
		print('Saved target state.')
		time.sleep(0.1)
	# get the final position of the agent in the environment and write it to file
	final_x = game.get_game_variable(GameVariable.POSITION_X)
	final_y = game.get_game_variable(GameVariable.POSITION_Y)
	f = open(end_pos_fname, 'w')
	f.write(str(final_x) + ',' + str(final_y))
	f.close()

# create the test dataset (iterate through the scenarios and execute the actions that are considered as human demonstrations)
def create_human_demonstrations():
	test_scenario_actions = get_test_scenario_actions()
	for i in range(num_scenarios):
		get_target_states_for_scenario(i, test_scenario_actions)
		time.sleep(1)
	print('Done creating targets to be used as human demonstrations.')
	game.close()

create_human_demonstrations()


# Data Mining Assignment 1
# Authors: Mimi Chenyao and Yasmeen Wilson

def support(itemset, database):
    count = 0
    for eachset in database:
        if eachset.issuperset(itemset):
            count += 1
    return count

def confidence(precedent, antecedent, database):
    confidence = support(antecedent, database) / support(precedent, database)
    return confidence

def findFrequentItemsets(database, minSupport):
    candidates = set()
    frequents = set()

    for each_set in database:
        candidates.add(each_set)
        for each_element in each_set:
            candidates.add(frozenset([each_element]))

    for candidate_set in candidates:
        if support(candidate_set, database) >= minSupport:
            frequents.add(candidate_set)
    return frequents

def findRules(frequentItemsets, database, minConfidence):

    rules = list()

    for each_set in frequentItemsets:
        for each_element in (frequentItemsets - each_set):
            if confidence(each_set, each_element, database) >= minConfidence:
                rules.append((each_set, each_element))
    for each_rule in rules:
        set(each_rule)

    return rules

"""# Test
DB = (frozenset([1,2,3]), frozenset([2,3]), frozenset([4,5]), frozenset([1,2]), frozenset([1,5]))
out = findFrequentItemsets(DB, 2)
print(out)
# should print something contains sets {1},{2},{3},{5},{1,2}, and {2,3}.

# Should print something like {2} ===> {1,2}, {1} ===> {1,2}, {3} ===> {2,3}, and {2} === {2,3}
#for r in findRules(out, DB, 0.4):
#   print(str(r[0])+ "  ===>   " +str(r[1]))"""

with open('bakery.txt') as raw_datafile:
    raw_data = [line.rstrip('\n') for line in raw_datafile]

frozen_dataset = set()

for each_number_string in raw_data:

    fs = each_number_string.replace(" ", ",")
    frozen_convert =frozenset(int(fs))
    frozen_dataset.add(frozen.convert)

"""
# Alternative method tried: Stores all values as frozensets in a set
for each_item in dataset:
    try:
        frozenset(int(each_item))
        frozen_dataset.add(each_item)
    except ValueError as e:
        pass
"""
frequent_itemsets = findFrequentItemsets(frozen_dataset, 3)
findRules(frequent_itemsets, frozen_dataset, 0.5)


import responses
from unittest.mock import patch

from csbot.test import BotTestCase, read_fixture_file

#: Tests are (number, url, content-type, fixture, expected)
json_test_cases = [
    # (These test case are copied from the actual URLs, without the lengthy transcripts)

    # "Latest"
    (
        "0",  # 0 is latest
        "http://xkcd.com/info.0.json",
        "application/json; charset=utf-8",
        'xkcd_latest.json',
        ('http://xkcd.com/99999', 'Chaos', 'Although the oral exam for the doctorate was just \'can you do that weird laugh?\'')
    ),

    # Normal
    (
        "1",
        "http://xkcd.com/1/info.0.json",
        "application/json; charset=utf-8",
        'xkcd_1.json',
        ('http://xkcd.com/1', 'Barrel - Part 1', 'Don\'t we all.')
    ),

    # HTML Entities
    (
        "259",
        "http://xkcd.com/259/info.0.json",
        "application/json; charset=utf-8",
        'xkcd_259.json',
        ('http://xkcd.com/259', 'Clichéd Exchanges', 'It\'s like they say, you gotta fight fire with clichés.')
    ),

    # Unicode
    (
        "403",
        "http://xkcd.com/403/info.0.json",
        "application/json; charset=utf-8",
        'xkcd_403.json',
        ('http://xkcd.com/403', 'Convincing Pickup Line', 'Check it out; I\'ve had sex with someone who\'s had sex with someone who\'s written a paper with Paul Erdős!')
    ),

    # Long alt text
    (
        "1363",
        "http://xkcd.com/1363/info.0.json",
        "application/json; charset=utf-8",
        'xkcd_1363.json',
        ('http://xkcd.com/1363', 'xkcd Phone', 'Presented in partnership with Qualcomm, Craigslist, Whirlpool, Hostess, LifeStyles, and the US Chamber of Commerce. M...')
    ),

    # No alt text
    (
        "1506",
        "http://xkcd.com/1506/info.0.json",
        "application/json; charset=utf-8",
        'xkcd_1506.json',
        ('http://xkcd.com/1506', 'xkcloud', '')
    )
]

class TestXKCDPlugin(BotTestCase):
    CONFIG = """\
    [@bot]
    plugins = xkcd
    """

    PLUGINS = ['xkcd']

    @responses.activate
    def test_correct(self):
        for _, url, content_type, fixture, _ in json_test_cases:
            responses.add(responses.GET, url, body=read_fixture_file(fixture),
                          content_type=content_type)

        for num, url, _, _, expected in json_test_cases:
            with self.subTest(url=url):
                result = self.xkcd._xkcd(num)
                self.assertEqual(result, expected, url)

        # Also test the empty string
        self.assertEqual(self.xkcd._xkcd(""), json_test_cases[0][4])

        # !xkcd 221
        with patch("random.randint", return_value=1):
            self.assertEqual(self.xkcd._xkcd("rand"), json_test_cases[1][4])

    @responses.activate
    def test_error(self):
        _, url, content_type, fixture, _ = json_test_cases[0]  # Latest
        # Test if the comics are unavailable by making the latest return a 404
        responses.add(responses.GET, url, body="404 - Not Found",
                      content_type="text/html", status=404)
        self.assertRaises(self.xkcd.XKCDError, self.xkcd._xkcd, "")
        responses.reset()

        # Now override the actual 404 page and the latest "properly"
        responses.add(responses.GET, url, body=read_fixture_file(fixture),
                      content_type=content_type)
        responses.add(responses.GET, "http://xkcd.com/404/info.0.json",
                      body="404 - Not Found", content_type="text/html",
                      status=404)

        self.assertRaises(self.xkcd.XKCDError, self.xkcd._xkcd, "flibble")
        self.assertRaises(self.xkcd.XKCDError, self.xkcd._xkcd, "404")  # Missing comic
        self.assertRaises(self.xkcd.XKCDError, self.xkcd._xkcd, "-5")
        self.assertRaises(self.xkcd.XKCDError, self.xkcd._xkcd, "1000000")  # Testing "latest"

class TestXKCDLinkInfoIntegration(BotTestCase):
    CONFIG = """\
    [@bot]
    plugins = linkinfo xkcd
    """

    PLUGINS = ['linkinfo', 'xkcd']

    @responses.activate
    def test_integration(self):
        for _, url, content_type, fixture, _ in json_test_cases:
            responses.add(responses.GET, url, body=read_fixture_file(fixture),
                          content_type=content_type)

        for num, _, _, _, (_, title, alt) in json_test_cases:
            with self.subTest(num=num):
                url = 'http://xkcd.com/{}'.format(num)
                result = self.linkinfo.get_link_info(url)
                self.assertIn(title, result.text)
                self.assertIn(alt, result.text)

        # Error case
        result = self.linkinfo.get_link_info("http://xkcd.com/flibble")
        self.assertTrue(result.is_error)


from datetime import timedelta
from timeit import default_timer as timer

import numpy as np
import pandas as pd
from sklearn import datasets

from neo_force_scheme.neo_force_scheme import NeoForceScheme, ProjectionMode

#################################
projection_n_dimensions = 3
nfs = NeoForceScheme(metric="euclidean", verbose=True, learning_rate0=0.2,
                     decay=0.95, max_it=300, cuda=False)
starting_projection_mode = ProjectionMode.TSNE
fix_column_to_z_projection_axis = -1
drop_columns_from_dataset = [-1]
scaler = (0, 1)
z_axis_moving_range = (-0.2, 0.2)
confidence_interval = 0.9
# by default z_axis_moving_range is (0, 0), which means not allowing any movement
plot = False

# data = np.loadtxt('./datasets/mammals.data', delimiter=",")
# data = pd.read_csv('./datasets/whr2019.csv', delimiter=",").values
# data = np.concatenate((datasets.load_iris().data.T,[datasets.load_iris().target.T])).T
data = np.concatenate((datasets.load_breast_cancer().data.T,[datasets.load_breast_cancer().target.T])).T
# data = np.tile(data, (100, 1)) # use this make the dataset 100x larger for performance test

#################################

# execute force scheme
start = timer()
projection = nfs.fit_transform(X=data,
                               starting_projection_mode=starting_projection_mode,
                               random_state=1,
                               n_dimension=projection_n_dimensions,
                               fix_column_to_z_projection_axis=fix_column_to_z_projection_axis,
                               drop_columns_from_dataset=drop_columns_from_dataset,
                               scaler=scaler,
                               z_axis_moving_range=z_axis_moving_range,
                               confidence_interval=confidence_interval)
error = nfs.projection_error_
end = timer()

print(f'ForceScheme took {timedelta(seconds=end - start)} to execute with error {error}')

# calculate stress
stress = nfs.score(projection)
print('Kruskal stress {0}:'.format(stress))

# save projection
# np.savetxt("projection.txt", projection, delimiter=" ", fmt="%s")

if plot:
    if projection_n_dimensions == 2:
        # show projection
        """
        # method1
        import plotly.express as px
        fig = px.scatter(x=projection[:, 0],
                         y=projection[:, 1],
                         labels={'x':'x', 'y':'y'})
        fig.show()
        """
        """
        # method2
        import numpy as np
        import plotly.express as px

        ar = np.arange(100).reshape((10, 10))
        fig = px.scatter(projection,
                         x=projection[:, 0],
                         y=projection[:, 1],
                         size=1,
                         color=1)
        fig.show()
        """

        # method3
        import plotly.graph_objects as go
        import numpy as np

        fig = go.Figure(
            data=go.Scatter(
                x=projection[:, 0],
                y=projection[:, 1],
                mode='markers',
                marker=dict(
                    size=16,
                    color=np.random.randn(500),
                    colorscale='Viridis',
                    showscale=True)
            )
        )
        fig.show()
    else:
        import plotly.graph_objects as go

        fig = go.Figure(
            data=[go.Scatter3d(x=projection[:, 0],
                               y=projection[:, 1],
                               z=projection[:, 2],
                               mode='markers',
                               marker=dict(
                                   size=12,
                                   color=projection[:, 2],  # set color to an array/list of desired values
                                   colorscale='Viridis',  # choose a colorscale
                                   opacity=0.8
                               )
                               )])

        fig.show()