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

""" Código base para la práctica de IPM. Existen numerosos fallos de diseño que deben ser corregidos."""

__author__     = "Guillermo Martín Villar, Juan Luis Filgueiras Rilo"
__copyright__  = "GNU General Public Licencse v2"

from datetime import datetime, date, time

import time

import threading

from random import randint

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib, GObject

#internacionalización
import gettext
import locale

LOCALE_DIR = './locale'
APP_NAME = 'p1_mod'

gettext.textdomain(APP_NAME)
gettext.bindtextdomain(APP_NAME, LOCALE_DIR)
locale.setlocale(locale.LC_ALL, '')
_ = gettext.gettext

_DATE_FORMAT = _("%d/%m/%y")
#Cabecera
#Notificaciones
'''
Controlador
'''

class TaskList_Controller:

	INITIAL_STATE = {'spinner_running': False,
					'sync_button': True,
					'sync_status': _("Última sincronización: Aún no se ha sincronizado")}

	def __init__(self):
		self._view = TaskList_View()
		self._view.update_state(self.INITIAL_STATE)
		self._view.connect(self)

	def set_model(self, model):
		self._model = model

	#llamamos al metodo que muestra las cajas en la vista
	def on_show_add_dialog_button_clicked(self, widget):
		self._view.update_add(False)
		self._view.run_dialog_add()

	#método que borra una tarea de la vista y el modelo
	def remove_task(self, task):
		if (task != None):
			ok = self._model.remove(task[0])
			if (ok != -1):
				self._view.remove(task[0])
				self._view.remove_selection()
		#actualizamos los botones borrar todas y borras todas las hechas
		self._view.update_menu_options()

	#método que se lanza al seleccionar el botón eliminar, se obtienen las
	#tareas que han sido seleccionadas y las vamos borrando de una en una
	def on_button_remove_clicked(self, widget):
		tasklist = self._view.get_tasks()
		for task in tasklist:
			self.remove_task(task)

	#método que se lanza al intentar cerrar el programa
	def on_button_exit_clicked(self, widget, event):
		signal = self._view.exit(widget.get_toplevel())
		return signal

	#metodo que se lanza al editar la columna fecha de una tarea
	def on_task_date_edit(self, widget, position, text):
		#pasamos el string a datetime
		date = self._model.convert_string_to_datetime(text)
		#comprobamos que es correcta
		if (date == (None,"void-date")):
			self._view.run_dialog_provided_data_error(_("Error"),
					_("La fecha está vacía"))
		elif (date == (None,"bad-format")):
			self._view.run_dialog_provided_data_error(_("Error"),
					_("La fecha introducida no está en el formato correcto (dd/mm/yy)"))
		elif (date == (None,"prior-date")):
			self._view.run_dialog_provided_data_error(_("Error"),
					_("La fecha introducida tiene que ser posterior a la fecha actual"))
		else:
			#obtenemos la tarea que ha sido seleccionada
			tasklist = self._view.get_tasks()
			if ((len(tasklist)) != 0):
				task = tasklist[0]
				if (task != None):
					task = list(task)
					task[2] = date[0]
					task = tuple(task)
					data = (task[1], task[2], task[3])
					#editamos la fecha en la vista y en el modelo
					ok = self._model.edit(task[0], data)
					if ok != -1:
						self._view.edit(task[0], data)

	#metodo que se lanza al editar la columna nombre de una tarea
	def on_task_name_edit(self, widget, position, text):
		#obtenemos la tarea que ha sido seleccionada
		tasklist = self._view.get_tasks()
		#vemos que hay alguna tarea seleccionada, para evitar errores
		if ((len(tasklist)) != 0):
			#comprobamos que el nombre sea válido
			if not (self._model.validate_taskname(text)):
				self._view.run_dialog_provided_data_error(_("Error"),
					_("El nombre de la tarea no puede estar vacío"))
			else:
				task = self._view.get_tasks()[0]
				if (task != None):
					task = list(task)
					task[1] = text
					task = tuple(task)
					data = (task[1], task[2], task[3])
					#editamos el nombre ne la vista y en el modelo
					ok = self._model.edit(task[0], data)
					if ok != -1:
						self._view.edit(task[0], data)

	#metodo que se lanza al seleccionar la columna hecho
	def on_row_selected(self, widget, position, n_column):
		if (n_column.get_title() == _("Hecho")):
			task = self._view.get_tasks()[0]
			#convertimos a lista y despues reconvertimos a tupla pq las tuplas son
			#inmutables
			task = list(task)
			#cambiamos su valor
			task[3] = False if task[3] else True
			task = tuple(task)
			data = (task[1], task[2], task[3])
			#editamos en la vista y en el modelo
			ok = self._model.edit(task[0], data)
			if ok != -1:
				self._view.edit(task[0], data)
				self._view.update_menu_options()

	#metodo que se lanza al seleccionar el botón de añadir tarea
	def on_button_add_task_clicked(self, widget):
		#cogemos el texto que ha introducido el usuario
		data = self._view.get_data_from_add_dialog()
		data = list(data)
		#comprobamos que la fecha está bien
		date = self._model.convert_string_to_datetime(data[1])
		if (date == (None,"void-date")):
			self._view.run_dialog_provided_data_error(_("Error"),
					_("La fecha está vacía"))
		elif (date == (None,"bad-format")):
			self._view.run_dialog_provided_data_error(_("Error"),
					_("La fecha introducida no está en el formato correcto (dd/mm/yy)"))
		elif (date == (None,"prior-date")):
			self._view.run_dialog_provided_data_error(_("Error"),
					_("La fecha introducida tiene que ser posterior a la fecha actual"))
		else:
			#actualizamos la fecha de data
			data[1] = date[0]
			#comprobamos que el nombre esté bien
			if not (self._model.validate_taskname(data[0])):
				self._view.run_dialog_provided_data_error(_("Error"),
				_("El nombre de la tarea no puede estar vacío"))
			else:
				data = tuple(data)
				task_id = self._model.add(data)
				if task_id != -1:
					#borramos el texto de los entrys
					self._view.remove_entry_text()
					#activamos el botón que lanza el diálogo de añadir
					self._view.update_add(True)
					#desactivamos el botón para añadir una tarea
					self._view.update_add_task(False)
					#añadimos en la vista y en el modelo
					self._view.add(task_id,data)
					self._view.update_menu_options()

	#método que se lanza al seleccionar el botón sincronizar
	def on_button_sync_clicked(self, widget):
		prev_status = self._view._sync_label.get_text()
		state = {'spinner_running' : True,
				'sync_button' : False,
				'sync_status' : (_("Sincronizando")+'\u2026')}
		self._view.update_state(state)
		t = threading.Thread(target = self.sync, args = (prev_status, ))
		t.start()

	def sync(self, prev_status):
		sync_success = self._model.sync()
		if sync_success:
			state = {'spinner_running' : False,
					'sync_button' : True,
					'sync_status' : _("Última sincronización: ") + time.strftime("%H" + '\u2236' +"%M")}
		else:
			state =  {'spinner_running' : False,
					'sync_button' : True,
					'sync_status' : prev_status,
					'show_sync_error' : _("Error sincronizando")}
		self._view.update_state_on_main_thread(state)

	#método que se lanza al pulsar una tecla en los entrys del diálogo añadir
	def on_key_pressed(self, entry, eventkey):
		#se añade la tarea al pulsar la tecla enter solo si hay buffer en ambos entrys
		if ((eventkey.get_keyval()[1] == 65293)
				& (self._view.get_name_buffer_has_text())
				& (self._view.get_date_buffer_has_text())):
			self.on_button_add_task_clicked(entry)

	#método que se lanza cada vez que se modifica el campo donde se introduce
	#el nombre de la tarea en el diálogo añadir tarea
	def on_tarea_entry_changed(self, entry):
		length = entry.get_buffer().get_length()
		if (length > 0):
			self._view.update_name_buffer(True)
		else:
			self._view.update_name_buffer(False)

	#método que se lanza cada vez que se modifica el campo donde se introduce
	#la fecha de la tarea en el diálogo añadir tarea
	def on_fecha_entry_changed(self, entry):
		length = entry.get_buffer().get_length()
		if (length > 0):
			self._view.update_date_buffer(True)
		else:
			self._view.update_date_buffer(False)

	#método que se lanza al pulsar una tecla sobre el treeview
	def on_supr_pressed(self, entry, eventkey):
		#comprobamos que la tecla es SUPR
		if ((eventkey.get_keyval()[1] == 65535)):
			self.on_button_remove_clicked(entry)

	#método que se lanza al seleccionar la opción borrar todas las tareas
	def on_delete_all_clicked(self, menuitem):
		#cogemos la lista de tareas y las borramos una a una
		task_list = self._view.get_task_list()
		for task in task_list:
			self.remove_task(task)

	#método que se lanza al seleccionar la opción borrar todas las tareas hechas
	def on_delete_all_done_clicked(self, menuitem):
		#cogemos la lista de tareas
		task_list = self._view.get_task_list()
		#vamos comprobando una a una que tengan el campo hecho activado
		for task in task_list:
			if (task[3]):
				self.remove_task(task)

	def on_tree_selection_changed(self, widget):
		self._view.update_delete(True)

	#método que se lanza al seleccionar el botón de cancelar del diálogo de añadir tarea
	def on_cancel_add_task_button_clicked(self, widget):
		#borramos el texto de los entrys
		self._view.remove_entry_text()
		#activamos el botón que lanza el diálogo de añadir
		self._view.update_add(True)
		#desactivamos el botón para añadir una tarea
		self._view.update_add_task(False)

'''
Vista
'''

class TaskList_View:
	def __init__(self):

		def date_cell_data_func(column, renderer, model, treeiter, data):
			fecha = model[treeiter][2]
			renderer.set_property('text', fecha.strftime("%x"))

		def compare_date(model, treeiter1, treeiter2, user_data):
			if model[treeiter1][2] < model[treeiter2][2]:
				return -1
			if model[treeiter1][2] > model[treeiter2][2]:
				return 1
			return 0

		#creamos la ventana con el título
		self._win = Gtk.Window()
		self._win.set_size_request(500, 500)

		#creamos la header bar donde irán los botones principales
		header_bar = Gtk.HeaderBar()
		header_bar.set_show_close_button(True)
		header_bar.props.title = _("Práctica 1 ") + '\u2013' + _(" IPM 17/18")
		self._win.set_titlebar(header_bar)

		#creamos la caja (vertical) principal de la ventana, donde se meterán todos los elementos
		box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
		#introducimos la caja en la ventana
		self._win.add(box)

		#creamos la ListStore y le añadimos todos los elementos
		self.store = Gtk.ListStore(int, str, GObject.TYPE_PYOBJECT, bool)
		self.store.append([100,"Llevar coche al taller", datetime.today(), False])
		self.store.append([101,"Lavar el coche", datetime.today(), False])
		self.store.append([102,"Pagar el seguro", datetime.today(), False])
		self.store.append([103,"Arreglar mando garaje", datetime.today(), False])
		self.store.append([104,"Recoger ropa del tinte", datetime.today(), False])
		self.store.append([105,"Regalo cumpleaños Nico", datetime.today(), False])
		self.store.append([106,"Devolver libro a la biblioteca", datetime.today(), True])
		self.store.append([107,"Ordenar el congelador", datetime.today(), False])
		self.store.append([108,"Lavar las cortinas", datetime.today(), False])
		self.store.append([109,"Organizar el cajón de los mandos", datetime.today(), False])
		self.store.append([110,"Poner flores en las jardineras", datetime.today(), False])

		#se crea un treeview sobre la lista store
		self.tree = Gtk.TreeView(self.store)
		#activamos que la activación de una fila se produzca en un simple click en vez
		#de doble click
		self.tree.set_activate_on_single_click(True)
		self.selection = self.tree.get_selection()
		#desactivamos la búsqueda
		self.tree.set_enable_search(False)
		#activamos la seleccion multiple
		self.selection.set_mode(Gtk.SelectionMode.MULTIPLE)
		#diferenciamos entre el renderer del nombre y de la fecha pq a la hora de editar
		#seran eventos diferentes
		self.renderer_name = Gtk.CellRendererText()
		#marcamos la columna entera como editable
		self.renderer_name.set_property("editable", True)
		#centramos el texto que irá dentro de la columna
		self.renderer_name.set_alignment(0.5, 0)
		column = Gtk.TreeViewColumn(_("Tarea"), self.renderer_name, text=1)
		#permitimos que la columna se pueda expandir
		column.set_expand(True)
		#centramos el texto del título de la columna
		column.set_alignment(0.5)
		self.tree.append_column(column)
		column.set_sort_column_id(1)
		self.renderer_date = Gtk.CellRendererText()
		#marcamos la columna entera como editable
		self.renderer_date.set_property("editable", True)
		#centramos el texto que irá dentro de la columna
		self.renderer_date.set_alignment(0.5, 0)
		column = Gtk.TreeViewColumn(_("Fecha"), self.renderer_date)
		#permitimos que la columna se pueda expandir
		column.set_expand(True)
		#centramos el texto del título de la columna
		column.set_alignment(0.5)
		column.set_cell_data_func(self.renderer_date, date_cell_data_func)
		self.tree.append_column(column)
		column.set_sort_column_id(2)
		self.store.set_sort_func(2, compare_date, None)
		renderer_make = Gtk.CellRendererToggle()
		column = Gtk.TreeViewColumn(_("Hecho"), renderer_make, active=3)
		#permitimos que la columna se pueda expandir
		column.set_expand(True)
		#centramos el texto del título de la columna
		column.set_alignment(0.5)
		self.tree.append_column(column)
		column.set_sort_column_id(3)

		#creamos todos los botones que irán en la header bar
		self.show_add_dialog_button = Gtk.Button.new_from_icon_name(Gtk.STOCK_ADD,1)
		self.show_add_dialog_button.get_style_context().add_class('suggested-action')
		self._delete_button = Gtk.Button.new_from_icon_name(Gtk.STOCK_DELETE,1)
		self._delete_button.get_style_context().add_class('destructive-action')
		self._delete_button.set_sensitive(False)
		self._sync_button = Gtk.Button.new_from_icon_name(Gtk.STOCK_REFRESH,1)
		self._sync_button.set_alignment(1,0)
		menu_button = Gtk.MenuButton()

		#creamos el menú y lo asociamos el menu_button
		menu = Gtk.Menu()
		self.delete_all = Gtk.MenuItem(_("Borrar todas las tareas"))
		self.delete_all.show()
		self.delete_done_tasks = Gtk.MenuItem(_("Borrar todas las tareas hechas"))
		self.delete_done_tasks.show()
		menu.append(self.delete_all)
		menu.append(self.delete_done_tasks)
		menu_button.set_popup(menu)
		self.delete_all.set_sensitive(False)

		#espacio donde irá el sync label y sync spinner
		box_sync = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
		self.sync_spinner = Gtk.Spinner()
		self._sync_label = Gtk.Label("")
		#lo alineamos casi abajo del todo
		self._sync_label.set_alignment(0.5, 0.8)
		#dejamos un poco de espacio por arriba y por abajo para que no
		#se vea tan pequeño
		self._sync_label.set_size_request(0, 30)

		#diálogo añadir

		#metemos los entrys en una caja nueva por el final
		self.tareaEntry = Gtk.Entry()
		self.fechaEntry = Gtk.Entry()
		#creamos los labels y los justificamos a l izquierda
		name_label = Gtk.Label(_("Nombre"))
		name_label.set_xalign(1)
		date_label = Gtk.Label(_("Fecha"))
		date_label.set_xalign(1)
		#creamos el botón de añadir y lo centramos
		self.add_task_button = Gtk.Button.new_from_icon_name(Gtk.STOCK_ADD, 1)
		self.add_task_button.get_style_context().add_class('suggested-action')
		self.cancel_add_task_button = Gtk.Button.new_from_icon_name(Gtk.STOCK_CANCEL, 1)

		self.add_task_button.set_sensitive(False)
		self.add_task_button.set_alignment(0.5, 0.5)

		#creamos las cajas dónde ira el diálogo añadir (1 horizontal y 3 verticales)
		self.hbox_add_dialog = Gtk.Box(orientation = Gtk.Orientation.HORIZONTAL, spacing = 0)
		self.vbox_add_dialog1 = Gtk.Box(orientation = Gtk.Orientation.VERTICAL, spacing = 6)
		self.vbox_add_dialog2 = Gtk.Box(orientation = Gtk.Orientation.VERTICAL, spacing = 6)
		self.vbox_add_dialog3 = Gtk.Box(orientation = Gtk.Orientation.VERTICAL, spacing = 8)

		#lo metemos todo en sus respectivas cajas
		#metemos los elementos de añadir en sus cajas verticales
		self.vbox_add_dialog1.pack_start(name_label, True, True, 0)
		self.vbox_add_dialog1.pack_end(date_label, True, True, 0)
		self.vbox_add_dialog2.pack_start(self.tareaEntry, True, True, 0)
		self.vbox_add_dialog2.pack_end(self.fechaEntry, True, True, 0)
		#espacio que irá entre los bordes de la caja y el botón (arriba y abajo)
		self.vbox_add_dialog3.pack_start(self.add_task_button, True, True, 8)
		self.vbox_add_dialog3.pack_start(self.cancel_add_task_button, True, True, 8)
		#metemos esas 3 cajas en la caja horizontal que englobará a las 3 cajas verticales
		#espacio que irá entre los border de la caja y la caja que metemos a izquierda y derecha
		self.hbox_add_dialog.pack_start(self.vbox_add_dialog1, True, True, 18)
		self.hbox_add_dialog.pack_start(self.vbox_add_dialog2, True, True, 0)
		#espacio que irá entre los border de la caja y la caja que metemos a izquierda y derecha
		self.hbox_add_dialog.pack_end(self.vbox_add_dialog3, True, True, 18)
		#metemos la caja horizontal en la caja principal por el final
		#espacio que irá entre los border de la caja y la caja que metemos arriba y abajo
		box.pack_end(self.hbox_add_dialog, False, False, 18)
		#metemos el treeview en la caja principal por el final
		box.pack_end(self.tree, True, True, 0)
		#metemos los elementos de sincronización en su caja
		box_sync.pack_start(self.sync_spinner, False, False, 0)
		box_sync.pack_start(self._sync_label, True, True, 0)
		#metemos en la header bar los botones que contendrá
		# header_bar.pack_start(menu_button)
		# header_bar.pack_end(self.show_add_dialog_button)
		# header_bar.pack_end(self._delete_button)
		# header_bar.pack_end(self._sync_button)
		header_bar.pack_start(self.show_add_dialog_button)
		header_bar.pack_end(menu_button)
		header_bar.pack_end(self._sync_button)
		header_bar.pack_end(self._delete_button)

		#metemos la caja con los elementos de sincronización en la caja principal por el ppio
		box.pack_start(box_sync, False, False, 0)

		#mostramos todos los elementos menos el diálogo de añadir
		self._win.show_all()
		self.hbox_add_dialog.hide()

		#variables que controlarán si hay texto en los buffers del diálogo añadir
		#por defecto inicializadas a false
		self.name_buffer_has_text = False
		self.date_buffer_has_text = False

		#actualizo los botones del menú contextual, cuento las tareas que hay creadas y/o activadas
		#y se desactivarán en función de si el número de tareas es igual a 0
		self.update_menu_options()

	#todas las señales
	def connect(self, controller):
		self._win.connect("delete-event", controller.on_button_exit_clicked)
		self.show_add_dialog_button.connect('clicked', controller.on_show_add_dialog_button_clicked)
		self._delete_button.connect('clicked', controller.on_button_remove_clicked)
		#seleccionar una fila
		self.tree.connect('row-activated', controller.on_row_selected)
		#editar el nombre de la tarea
		self.renderer_name.connect('edited', controller.on_task_name_edit)
		#editar la fecha de la tarea
		self.renderer_date.connect('edited', controller.on_task_date_edit)
		self.add_task_button.connect('clicked', controller.on_button_add_task_clicked)
		self._sync_button.connect('clicked', controller.on_button_sync_clicked)
		#pulsar Enter en entrys del diálogo de añadir
		self.tareaEntry.connect('key-press-event', controller.on_key_pressed)
		self.fechaEntry.connect('key-press-event', controller.on_key_pressed)
		#buffer alterado
		self.tareaEntry.connect('changed', controller.on_tarea_entry_changed)
		self.fechaEntry.connect('changed', controller.on_fecha_entry_changed)
		#pulsar suprimir sobre el treeview
		self.tree.connect('key-press-event', controller.on_supr_pressed)
		self.delete_all.connect('activate', controller.on_delete_all_clicked)
		self.delete_done_tasks.connect('activate', controller.on_delete_all_done_clicked)
		self.selection.connect("changed", controller.on_tree_selection_changed)
		self.cancel_add_task_button.connect('clicked', controller.on_cancel_add_task_button_clicked)

	#metodo con el que mostramos las dos cajas del fondo
	def run_dialog_add(self):
		self.hbox_add_dialog.show_all()

	def get_name_buffer_has_text(self):
		return self.name_buffer_has_text

	def get_date_buffer_has_text(self):
		return self.date_buffer_has_text

	#metodo con el que añadimos la tarea a la vista y al modelo
	def get_data_from_add_dialog(self):
		data = (self.tareaEntry.get_text(), self.fechaEntry.get_text(),False)
		return data

	#método que muestra un error al introducir mal los datos
	def run_dialog_provided_data_error(self, title, secondary_text):
		dialog = Gtk.MessageDialog(self._win, 0,
			Gtk.MessageType.INFO, Gtk.ButtonsType.OK,
			title)
		dialog.format_secondary_text(secondary_text)
		dialog.run()
		dialog.destroy()

	#se devuelve la tarea seleccionada
	def get_task(self):
		task = None
		selection = self.selection
		treeiter = selection.get_selected()[1]
		if treeiter != None:
			task = self.store.get(treeiter,0,1,2,3)
		return task

	#se devuelven todas las tareas seleccionadas
	def get_tasks(self):
		tasklist = []
		#devuelve liststore y treepaths
		selection = self.selection.get_selected_rows()

		lliststore, treepaths = selection
		for i in range (len(treepaths)):
			treeiter = lliststore.get_iter(treepaths[i])
			if treeiter != None:
				task = self.store.get(treeiter, 0, 1, 2, 3)
				tasklist.append(task)
		return tasklist

	#se saca un diálogo y en función de la opción escogida se cerrará el programa o no
	def exit(self, parent):
		dialog = Gtk.Dialog(_("¡Atención!"), parent, Gtk.DialogFlags.DESTROY_WITH_PARENT,
				(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
				Gtk.STOCK_OK, Gtk.ResponseType.OK))
		vbox = Gtk.VBox(spacing = 10)
		#meto el diálogo en la caja
		dialog.get_content_area().add(vbox)
		#creo los etiquetas con el texto
		etiqueta1 = Gtk.Label(_("¿Quieres cerrar la aplicación?"))
		etiqueta2 = Gtk.Label(_("Si no se cancela, la aplicación se cerrará"))
		#meto ambas por el principio del diálogo
		vbox.pack_start(etiqueta1, True, True, 0)
		vbox.pack_start(etiqueta2, True, True, 0)
		vbox.show_all()
		#cojo la respuesta del usuario
		respuesta = dialog.run()
		#en función de la respuesta, cierro el programa o no
		if respuesta == Gtk.ResponseType.OK:
			Gtk.main_quit()
		else:
			dialog.destroy()
			return True

	#método añadir tareas a la liststore
	def add(self, task_id, data):
		data = list(data)
		data.insert(0,task_id)
		data = tuple(data)
		self.store.append(data)

	#método editar una tarea de la liststore
	def edit(self, task_id, data):
		for task in self.store:
			if task[0] == task_id:
				self.store.set(task.iter, 1, data[0], 2, data[1], 3, data[2])

	#método borrar una tarea de la liststore (por task_id)
	def remove(self, task_id):
		for task in self.store:
			if task[0] == task_id:
				self.store.remove(task.iter)

	#método para actualizar el botón de borrar
	def update_delete(self, active):
		self._delete_button.set_sensitive(active)

	#método que actualiza la variable que controlan el buffer nombre del diálogo añadir
	#y además actualiza el botón añadir tarea
	def update_name_buffer(self, active):
		self.name_buffer_has_text = active
		self.update_add_task(self.get_name_buffer_has_text()
			& self.get_date_buffer_has_text())

	#método que actualiza la variable que controlan el buffer fecha del diálogo añadir
	#y además actualiza el botón añadir tarea
	def update_date_buffer(self, active):
		self.date_buffer_has_text = active
		self.update_add_task(self.get_name_buffer_has_text()
			& self.get_date_buffer_has_text())

	#método que actualiza el botón borrar todas las tareas del menú contextual
	def update_delete_all_button(self):
		if (len(self.store) == 0):
			self.delete_all.set_sensitive(False)
		else:
			self.delete_all.set_sensitive(True)

	#método que actualiza el botón borrar todas las tareas hechas del menú contextual
	def update_delete_all_done_button(self):
		#miramos si hay alguna tarea marcada como hecha
		for task in self.store:
			if task[3]:
				self.delete_done_tasks.set_sensitive(True)
				return
		#si no hay ninguna, desactivamos el botón
		self.delete_done_tasks.set_sensitive(False)

	#método que llama a los dos métodos anteriores
	def update_menu_options(self):
		self.update_delete_all_button()
		self.update_delete_all_done_button()

	#método que actualiza el bóton que lanza el diálogo añadir
	def update_add(self, active):
		self.show_add_dialog_button.set_sensitive(active)

	#método que actualiza el botón de añadir una tarea
	def update_add_task(self, active):
		self.add_task_button.set_sensitive(active)

	def update_state_on_main_thread(self, state):
		GLib.idle_add(self.update_state, state)

	def update_state(self, state):
		for key, value in state.items():
			method = getattr(self, 'update_state_'+key, None)
			if callable(method):
				method(value, state)

	def update_state_sync_status(self, text, state):
		self._sync_label.set_text(text)

	def update_state_sync_button(self, change, state):
		self._sync_button.set_sensitive(change)

	def update_state_spinner_running(self, start, state):
		if start:
			self.sync_spinner.show()
			self.sync_spinner.start()
		else:
			self.sync_spinner.hide()
			self.sync_spinner.stop()

	def update_state_show_sync_error(self, title, state):
		dialog = Gtk.MessageDialog(self._win, 0,
			Gtk.MessageType.INFO, Gtk.ButtonsType.OK,
			title)
		dialog.format_secondary_text(_("¡No se puede conectar con el servidor!"))
		dialog.run()
		dialog.destroy()

	#método que limpia los entrys del diálogo añadir y además los oculta
	def remove_entry_text(self):
		self.tareaEntry.set_text("")
		self.fechaEntry.set_text("")
		self.hbox_add_dialog.hide()

	#método que devuelve la liststore
	def get_task_list(self):
		return self.store

	#método que des-selecciona todo
	def remove_selection(self):
		self.selection.unselect_all()
		self.update_delete(False)

'''
Modelo
'''

class TaskList_Model:

	def __init__(self):
		self.ID = 0
		self.model_task_list = []
		self.model_task_list.append([100,"Llevar coche al taller", datetime.today(), False])
		self.model_task_list.append([101,"Lavar el coche", datetime.today(), False])
		self.model_task_list.append([102,"Pagar el seguro", datetime.today(), False])
		self.model_task_list.append([103,"Arreglar mando garaje", datetime.today(), False])
		self.model_task_list.append([104,"Recoger ropa del tinte", datetime.today(), False])
		self.model_task_list.append([105,"Regalo cumpleaños Nico", datetime.today(), False])
		self.model_task_list.append([106,"Devolver libro a la biblioteca", datetime.today(), True])
		self.model_task_list.append([107,"Ordenar el congelador", datetime.today(), False])
		self.model_task_list.append([108,"Lavar las cortinas", datetime.today(), False])
		self.model_task_list.append([109,"Organizar el cajón de los mandos", datetime.today(), False])
		self.model_task_list.append([110,"Poner flores en las jardineras", datetime.today(), False])

	#
	##   add asigna un ID de tarea único a la lista de
	##   tareas y la concatena en la lista del modelo devolviendo el ID
	##   Si la informacion es nula, simplemente devuelve -1 a modo de error
	#
	def add(self, data):
		done = -1
		if data != None:
			data = list(data)
			data.insert(0, self.ID)
			data = tuple(data)
			self.model_task_list.append(data)
			done = self.ID
			self.ID += 1
		return done

	#edita la tarea de la lista y devuelve su id en caso de que la operación se haya
	#podido realizar (-1 en caso contrario)
	def edit(self, task_id, data):
		done = -1
		#cojo el ID para buscar si está ese elemento en la lista
		for task in self.model_task_list:
			if task_id == task[0]:
				task = (task_id, data[0], data[1], data[2])
				done = task_id
				break
		return done

	#borra la tarea de la lista y devuelve su id en caso de que la operación se haya
	#podido realizar (-1 en caso contrario)
	def remove(self, task_id):
		done = -1
		for task in self.model_task_list:
			if (task_id == task[0]):
				done = task_id
				self.model_task_list.remove(task)
				break
		return done

	def sync(self):

		def get_random():
			i = randint(1,100)
			return i

		aux = get_random()
		if (aux < 50):
			temp = 80
			success = False
		else:
			temp = 8
			success = True
		for i in range (temp):
			time.sleep(0.2)
		return success

	#metodo que valida el nombre de una tarea, devuelve True si el valor
	#introducido por parametro es valido y False en caso contrario
	def validate_taskname(self, name):
		if (name == ""):
			return False
		return True

	#metodo que valida la fecha de una tarea, devuelve True si el valor
	#introducido por parametro es valido y False en caso contrario
	def validate_taskdate(self, date):
		if not ( (datetime.today().date() <= date.date())):
		  return False
		return True

	#metodo que intenta pasar un string a datetime, en caso de no poder, lanza un
	#dialogo de error
	def convert_string_to_datetime(self, string_to_convert):
		if (string_to_convert == ""):
			return (None,"void-date")
		else:
			try:
				date = (datetime.strptime(string_to_convert, _DATE_FORMAT))
			except Exception:
				return (None,"bad-format")
			validate = self.validate_taskdate(date)
			if not (validate):
				return (None, "prior-date")
			else:
				return (date, "")

if __name__ == '__main__':

	# Workarround para el control-c https://bugzilla.gnome.org/show_bug.cgi?id=622084#c4
	import signal
	signal.signal(signal.SIGINT, signal.SIG_DFL)

	TaskList_Controller().set_model(TaskList_Model())
	Gtk.main()


import pandas as pd
import numpy as np
import lightgbm as lgb
from sklearn.preprocessing import LabelEncoder

def get_df(path):
    df = pd.read_csv(path)
    date = pd.to_datetime(df.dates, format='%Y%m%d%H')
    df['dates'] = date + df.foretimes.apply(lambda x: pd.Timedelta(x, unit='h'))
    df['t2m_obj'] = df.t2m_obs - df.t2m_M
    df['rh2m_obj'] = df.rh2m_obs - df.rh2m_M
    df['w10m_obj'] = df.w10m_obs - df.w10m_M
    min_date = date.min()
    df.insert(0, 'nday', (date - min_date).apply(lambda x: x.days))
    return df.drop('station_date_time', axis=1)

str_today = '1103'

df = get_df(f'all_data.csv')
cat_var_list = ['stations', 'foretimes']

# 既包含当时的，也包含均值
def get_fea(df, postfix):
    df_fea = pd.merge(
        df,
        df.drop('stations', axis=1).groupby(['dates', 'foretimes'], as_index=False).mean(),
        left_on=['dates', 'foretimes'],
        right_on=['dates', 'foretimes']
    )
    return df_fea.rename(columns=dict(zip(df_fea.columns[4:], [f'{col}_{postfix}' for col in df_fea.columns[4:]])))

df_all = df.copy()
df_fea = df.copy().drop(['nday'], axis=1)
df_fea['dates'] = df_fea['dates'] + pd.Timedelta('2 days')
df_all = pd.merge(
    df_all,
    get_fea(df_fea, '2d'),
    left_on=['stations', 'dates', 'foretimes'],
    right_on=['stations', 'dates', 'foretimes']
)
df_fea = df.copy().drop(['nday'], axis=1)
df_fea['dates'] = df_fea['dates'] + pd.Timedelta('7 days')
df_all = pd.merge(
    df_all,
    get_fea(df_fea, '7d'),
    left_on=['stations', 'dates', 'foretimes'],
    right_on=['stations', 'dates', 'foretimes']
)
df_fea = df.copy().drop(['nday'], axis=1)
df_fea['dates'] = df_fea['dates'] + pd.Timedelta('365 days')
df_all = pd.merge(
    df_all,
    get_fea(df_fea, '1y'),
    left_on=['stations', 'dates', 'foretimes'],
    right_on=['stations', 'dates', 'foretimes']
)

# 所有columns里包含d10m的列，都这么处理
d10m_var_list = [col for col in df_all.columns if 'd10m' in col]
d10m_var_list.remove('d10m_obs')
for d10m_var in d10m_var_list:
    df_all[d10m_var].fillna(-1, inplace=True)
    df_all[d10m_var] = df_all[d10m_var].round().astype(int)
cat_var_list += d10m_var_list

df_all.insert(2,"hour",df_all.dates.dt.hour)
df_all.insert(2,"week",df_all.dates.dt.week)
df_all.insert(2,"day",df_all.dates.dt.day)
df_all.insert(2,"month",df_all.dates.dt.month)
df_all.drop('dates', axis=1, inplace=True)
cat_var_list += ['month', 'day', 'week', 'hour']

cat_var_lblenc_dict = {}
for cat_var in cat_var_list:
    lblenc = LabelEncoder().fit(df_all[cat_var])
    df_all[cat_var] = lblenc.transform(df_all[cat_var])
    cat_var_lblenc_dict[cat_var] = lblenc

df_test = df_all[lambda x: x.nday == x.nday.max()]
df_train = df_all[lambda x: x.nday < x.nday.max()]

df_train = df_train[lambda x: (x.psfc_M >= 850.) & (x.psfc_M <= 1100.) & \
                    (x.t2m_M >= -40.) & (x.t2m_M <= 55.) & \
                    (x.rh2m_M >= 0.) & (x.rh2m_M <= 100.) & \
                    (x.w10m_M >= 0.) & (x.w10m_M <= 30.)
                   ]

df_train.dropna(subset=['t2m_obj', 'rh2m_obj', 'w10m_obj'], inplace=True)
df_train_y = df_train[['t2m_obj', 'rh2m_obj', 'w10m_obj']]
df_train.drop(df_train.columns[36:48], axis=1, inplace=True)
df_test.drop(df_train.columns[36:48], axis=1, inplace=True)

split_end = df_train.nday.max()
val_days = 30
df_val = df_train[lambda x: (x.nday >= split_end-val_days+1) & (x.nday <= split_end)]
df_tr = df_train[lambda x: x.nday < split_end-val_days+1]

df_tr_X = df_tr[df_train.columns[1:]]
df_val_X = df_val[df_val.columns[1:]]
df_test_X = df_test[df_test.columns[1:]]

df_val_y = df_train_y.loc[df_val_X.index]
df_tr_y = df_train_y.loc[df_tr_X.index]

def train_bst(X_tr, y_tr, X_val, y_val, cat_val_list):
    params = {
        'num_leaves': 31,
        'objective': 'regression_l2',
        'min_data_in_leaf': 300,
        'learning_rate': 0.05,
        'feature_fraction': 0.8,
        'bagging_fraction': 0.8,
        'bagging_freq': 3,
        'metric': 'rmse',
        'num_threads': 8,
        'min_data_in_bin': 1,
        #'device': 'gpu',
    }

    MAX_ROUNDS = 10000
    dtrain = lgb.Dataset(
        X_tr, label=y_tr,
    )
    dval = lgb.Dataset(
        X_val, label=y_val, reference=dtrain,
    )
    bst = lgb.train(
        params, dtrain, num_boost_round=MAX_ROUNDS, categorical_feature=cat_val_list,
        valid_sets=[dtrain, dval], early_stopping_rounds=50, verbose_eval=100
    )
    return bst

X_tr, y_tr, X_val, y_val = df_tr_X, df_tr_y.values, df_val_X, df_val_y.values
bst_t2m = train_bst(X_tr, y_tr[:, 0], X_val, y_val[:, 0], cat_var_list)
bst_t2m.save_model('bst_t2m_gbdt_{}_new.txt'.format(str_today))
bst_rh2m = train_bst(X_tr, y_tr[:, 1], X_val, y_val[:, 1], cat_var_list)
bst_rh2m.save_model('bst_rh2m_gbdt_{}_new.txt'.format(str_today))
bst_w10m = train_bst(X_tr, y_tr[:, 2], X_val, y_val[:, 2], cat_var_list)
bst_w10m.save_model('bst_w10m_gbdt_{}_new.txt'.format(str_today))
df_submit = pd.DataFrame([
    [f'{item[0]}_{int(item[1]):02d}' for item in zip(cat_var_lblenc_dict['stations'].inverse_transform(df_test.stations),
                                                     cat_var_lblenc_dict['foretimes'].inverse_transform(df_test.foretimes))],
    (df_test.t2m_M + bst_t2m.predict(df_test_X)).tolist(),
    (df_test.rh2m_M + bst_rh2m.predict(df_test_X)).tolist(),
    (df_test.w10m_M + bst_w10m.predict(df_test_X)).tolist(),
]).T.rename(columns={0: 'FORE_data', 1: 't2m', 2: 'rh2m', 3: 'w10m'})
df_submit.to_csv(f'forecast-2018{str_today}03_gbdt_new.csv', index=False)

def train_bst(X_tr, y_tr, X_val, y_val, cat_val_list):
    params = {
        'boosting_type': 'dart',
        'num_leaves': 31,
        'objective': 'regression_l2',
        'min_data_in_leaf': 300,
        'learning_rate': 0.05,
        'feature_fraction': 0.8,
        'bagging_fraction': 0.8,
        'bagging_freq': 3,
        'metric': 'rmse',
        'num_threads': 8,
        'min_data_in_bin': 1,
        #'device': 'gpu',
    }

    MAX_ROUNDS = 10000
    dtrain = lgb.Dataset(
        X_tr, label=y_tr,
    )
    dval = lgb.Dataset(
        X_val, label=y_val, reference=dtrain,
    )
    bst = lgb.train(
        params, dtrain, num_boost_round=MAX_ROUNDS, categorical_feature=cat_val_list,
        valid_sets=[dtrain, dval], early_stopping_rounds=50, verbose_eval=100
    )
    return bst

bst_t2m = train_bst(X_tr, y_tr[:, 0], X_val, y_val[:, 0], cat_var_list)
bst_t2m.save_model('bst_t2m_dart_{}_new.txt'.format(str_today))
bst_rh2m = train_bst(X_tr, y_tr[:, 1], X_val, y_val[:, 1], cat_var_list)
bst_rh2m.save_model('bst_rh2m_dart_{}_new.txt'.format(str_today))
bst_w10m = train_bst(X_tr, y_tr[:, 2], X_val, y_val[:, 2], cat_var_list)
bst_w10m.save_model('bst_w10m_dart_{}_new.txt'.format(str_today))
df_submit = pd.DataFrame([
    [f'{item[0]}_{int(item[1]):02d}' for item in zip(cat_var_lblenc_dict['stations'].inverse_transform(df_test.stations),
                                                     cat_var_lblenc_dict['foretimes'].inverse_transform(df_test.foretimes))],
    (df_test.t2m_M + bst_t2m.predict(df_test_X)).tolist(),
    (df_test.rh2m_M + bst_rh2m.predict(df_test_X)).tolist(),
    (df_test.w10m_M + bst_w10m.predict(df_test_X)).tolist(),
]).T.rename(columns={0: 'FORE_data', 1: 't2m', 2: 'rh2m', 3: 'w10m'})
df_submit.to_csv(f'forecast-2018{str_today}03_dart_new.csv', index=False)

df_submit1 = pd.read_csv(f'forecast-2018{str_today}03_gbdt_new.csv')
df_submit2 = pd.read_csv(f'forecast-2018{str_today}03_dart_new.csv')

df_submit1['t2m'] = (df_submit1['t2m'] + df_submit2['t2m']) / 2
df_submit1['rh2m'] = (df_submit1['rh2m'] + df_submit2['rh2m']) / 2
df_submit1['w10m'] = (df_submit1['w10m'] + df_submit2['w10m']) / 2

df_submit1.to_csv(f'forecast-2018{str_today}03_new.csv', index=False)


n = int(input())

matrix = [[0 for i in range(n)] for i in range(n)]

i, j, k = 0, 0, 1
direction = "r"

while k < pow(n,2):
    matrix[i][j] = k
    if direction == "r":
        if j + 1 < n and matrix[i][j+1] == 0:
            j += 1
        else:
            direction = "d"
            continue
    elif direction == "d":
        if i + 1 < n and matrix[i+1][j] == 0:
            i += 1
        else:
            direction = "l"
            continue
    elif direction == "l":
        if j - 1 >= 0 and matrix[i][j-1] == 0:
            j -= 1
        else:
            direction = "u"
            continue
    elif direction == "u":
        if i - 1 >= 0 and matrix[i-1][j] == 0:
            i -= 1
        else:
            direction = "r"
            continue
    k += 1

matrix[i][j] = k
i, j = 0, 0

while i < n:
    while j < n:
        print(matrix[i][j], end=" ")
        j += 1
    i += 1
    j = 0
    print()


"""
  Qsim 2: Electric Boogaloo
  Now using MatPlotLib to plot things!
  *shakes fist at Python 2*

  This particular version doesn't do 'time to run', this one
  does it until there is nobody in the queue
"""

# libraries required
import random
import sys
import matplotlib.pyplot as plt # graphing goodness

# Variables
sizeOfQueue = 100 # this is just the queue at time=0
pJoinQueue = 0.5 # probabilities
pLeaveByPaying = 0.5
noOfCashiers = 4

# main procedure
if __name__ == "__main__":
    time = 0
    queueHistory = []
    timeSeries = []
    queueEmpty = False

    timeSeries.append(0)
    queueHistory.append(sizeOfQueue)
    while queueEmpty == False:
        time += 1
        timeSeries.append(time)
        for cashier in range(1, noOfCashiers):
            if(random.random() > pLeaveByPaying):
                sizeOfQueue -= 1
        if(random.random() > pJoinQueue):
            sizeOfQueue += 1
        if sizeOfQueue < 0:
            queueEmpty = True
            sizeOfQueue = 0
        queueHistory.append(sizeOfQueue)

    # the plotting goodness
    #print timeSeries
    #print queueHistory
    plt.plot(timeSeries, queueHistory)
    plt.xlabel('Time Periods')
    plt.ylabel('Size of Queue, in Persons')
    plt.show()


# -*- coding:utf-8 -*-
'''
__author__:liubin

'''
import unittest
from conf import settings
from lib import send_email

def suite():

    test_cases = unittest.defaultTestLoader.\
        discover(settings.TEST_PATH,pattern=settings.TEST_PATTERN,top_level_dir=None)

    # #装载测试用例
    # test_cases = unittest.TestLoader().loadTestsFromTestCase(TestStringMethods)
    #
    # #使用测试套件并打包测试用例
    # test_suit = unittest.TestSuite()
    # test_suit.addTests(test_cases)

    return test_cases

if __name__ == '__main__':

    test_result = unittest.TextTestRunner(verbosity=2).run(suite())

    print(test_result.testsRun)
    send_email.send_mail('hello.html')


#!/usr/bin/env python
import os
import sys
import getpass

Contact_file = "contact.txt"

def get_number():
    number = input("Enter Contact Mobile Number: ")
    if len(number) == 10:
        #print(len(number))
        return number

    else:
        print('digits in phone number is less then 10')
        get_number()

def add_contact():
    with open(Contact_file, "a") as f:
        print("Enter Contact Name: ")
        f.write(str(sys.stdin.readline().strip()) + ":")
        number = get_number()
        f.write(number + "\n")

def get_contact(name=None):
    while not check_contact():
        pass
    while True:
        with open(Contact_file, "r") as f:
            lines = [line.strip().split(":", 2) for line in f.readlines()]
        if name is not None:
            for name, mobile in lines:
                if name == name.strip():
                    return name, mobile
        print("Which contact do you want to send msg? (Type number)")
        for ind, (name, mobile) in enumerate(lines):
            print("%d: %s" % (ind + 1, name))
        #print("%d: %s" % (0, "add another contact."))
        print("%d: %s" % (-1, "delete all contact."))
        try:
            ind = input().split(',')
            print(ind)
            if len(ind) == 1:
                if int(ind[0]) == -1:
                    delete_contact()
                    check_contact()
                    continue
                if int(ind[0]) - 1 in list(range(len(lines))):
                    return lines[int(ind[0]) - 1]
            else:
                contact_list = list()
                for choice in ind:
                    choice = int(choice)
                    if choice - 1 in list(range(len(lines))):
                        contact_list.append(lines[choice - 1])
                return contact_list

        except Exception as e :
            print(e)
            print("Wrong input. I need the number of contact to use.")

def check_contact():
    while True:
        if os.path.exists(Contact_file):
            with open(Contact_file, "r") as f:
                try:
                    name, mobile = f.readline().strip().split(":")
                    if len(name) < 1 or len(mobile) < 10:

                        print("Data in 'contact.txt' file is invalid. "
                              "We will delete it and try again.")

                        os.remove(Contact_file)
                    else:
                        return True
                except:
                    print("Your file is broken. We will delete it "
                          "and try again.")
                    os.remove(Contact_file)
        else:
            while True:
                add_contact()
                print("Do you want to add another contact? (y/n)")
                if "y" not in sys.stdin.readline():
                    break

def delete_contact():
    if os.path.exists(Contact_file):
        os.remove(Contact_file)


import os
import deepdish as dd
import shutil
import torch
import pickle
from torch.utils.data import DataLoader
import torchvision.transforms as transforms

from helpers import ImageDataset

def compute_mean_std(dataset, filename=None, outdir='./dataset_info', verbose=False):
    batch_size = 100
    loader = DataLoader(dataset, batch_size=batch_size, num_workers=4)

    mean = []
    std = []
    for i, img in enumerate(loader):
        if isinstance(img, tuple):          # in case of dataset of shape (data, target)
            img = img[0]
        if verbose:
            print('{}/{}'.format(i+1, len(loader)))
        img = img.view(img.shape[0], 3, -1)
        m = [im.mean(dim=1) for im in img]
        s = [im.std(dim=1) for im in img]
        mean.append(torch.stack(m).mean(dim=0))
        std.append(torch.stack(s).mean(dim=0))

    mean = torch.stack(mean).mean(dim=0)
    std = torch.stack(std).mean(dim=0)

    if filename is None:
        try:
            filename = dataset.impath.split('/')[-1]        # use name of image folder
        except AttributeError:
            filename = raw_input('Please enter name of Dataset to save mean_std file.')
    filename = '{}_mean_std.pkl'.format(filename)

    if not os.path.isdir(outdir):
        os.makedirs(outdir)

    with open(filename, 'w') as f:
        pickle.dump({'mean': list(mean.numpy()), 'std': list(std.numpy())}, f)

    if verbose:
        print('saved \n\tstat file: {}'.format(filename))

def load_ImageDataset(impath, normalization_file=None, extensions=('.jpg', '.png'), size=None, verbose=False):
    """Returns normalized Tensor Dataset. If 'size' is specified the data is also resized."""
    dataset = ImageDataset(impath, extensions=extensions, transform=transforms.ToTensor())
    if normalization_file is None:
        normalization_file = '{}_mean_std.pkl'.format(dataset.impath.split('/')[-1])    # use name of image folder

    if not os.path.isfile(normalization_file):
        outdir = './dataset_info'
        compute_mean_std(dataset, normalization_file.replace('_mean_std.pkl', ''), outdir=outdir, verbose=verbose)
        normalization_file = os.path.join(outdir, normalization_file)

    with open(normalization_file, 'r') as f:
        data_dict = pickle.load(f)
        mean = torch.FloatTensor(data_dict['mean'])
        std = torch.FloatTensor(data_dict['std'])

    transform_list = [
        transforms.ToTensor(),
        transforms.Normalize(mean=mean, std=std),
    ]

    if size is not None:
        transform_list.insert(0, transforms.Resize((size, size)))

    return ImageDataset(impath, extensions=extensions, transform=transforms.Compose(transform_list))

def make_separate_ImgFolder(info_file, impath, outdir, copy=True, extension='.jpg'):
    """Transfers images listed in info file to outdir. If copy is True images are copied instead of cutted."""
    # info_file = '/export/home/kschwarz/Documents/Masters/WebInterface/MapNetCode/pretraining/wikiart_datasets/info_elgammal_subset_val.hdf5'
    # impath = '/export/home/kschwarz/Documents/Data/Wikiart_Elgammal/resize_224'
    # outdir = '/export/home/kschwarz/Documents/Data/Wikiart_Elgammal/resize_224/val'
    # copy = False
    # extension = '.jpg'

    img_ids = dd.io.load(info_file)['df']['image_id'].values

    if not os.path.isdir(outdir):
        os.makedirs(outdir)

    def get_filepath(img_id):
        return os.path.join(impath, img_id + extension)

    src = map(get_filepath, img_ids)

    if copy:
        mapfunc = lambda x: shutil.copy2(x, dst=outdir)
    else:
        mapfunc = lambda x: shutil.move(x, dst=outdir)

    map(mapfunc, src)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
import books.models

class Migration(migrations.Migration):

    dependencies = [
        ('books', '0014_auto_20160304_2237'),
    ]

    operations = [
        migrations.AlterField(
            model_name='monetarydonation',
            name='ctrlid',
            field=models.CharField(help_text="Payment processor's id for this donation, if any.", default=books.models.next_monetarydonation_ctrlid, unique=True, max_length=40),
        ),
    ]


import random
from typing import Union
import uuid

from gamechannels.redismgr import redis_connection
from gamechannels.gameexceptions import *

redis = redis_connection()
alias_chars = list('abcdefghijklmnopqrstuvwxyz0123456789')
MAX_TRIES = 5

def alias_key(alias: str):
    return 'gamealias::' + str(alias)

def create_game_alias(game_id: Union[str, uuid.UUID], length: int = 5) -> str:
    success = 0
    n_tries = 0
    while not success and n_tries < MAX_TRIES:
        alias = "".join([random.choice(alias_chars)
                         for _ in range(length)])
        key = alias_key(alias)
        success = redis.setnx(key, str(game_id))
        n_tries += 1

    if not success:
        return None

    redis.expire(key, 86400)
    return alias

def dealias_game(alias: str) -> str:
    dealiased = redis.get(alias_key(alias))
    if dealiased is None:
        raise GameAliasNotFound(f'No game found with alias [{alias}].')
    return dealiased


import random
import os.path

class cell:

    def __init__(self, x, y):
        self.N = False
        self.E = False
        self.S = False
        self.W = False

        self.x = x
        self.y = y

    def HasUncarved(self):
        return self.N and self.E and self.S and self.W

def ConnectCells(start, end, dir):
    if dir == 'N':
        start.N = True
        end.S = True
    elif dir == 'E':
        start.E = True
        end.W = True
    elif dir == 'S':
        start.S = True
        end.N = True
    elif dir == 'W':
        start.W = True
        end.E = True

def AddDirection(pos, dir):
    if dir == 'N':
        return (pos[0], pos[1]+1)
    elif dir == 'E':
        return (pos[0]+1, pos[1])
    elif dir == 'S':
        return (pos[0], pos[1]-1)
    elif dir == 'W':
        return (pos[0]-1, pos[1])

def Carve(grid, currPos, visited):
    visited.append(currPos)

    dirs = ['N', 'E', 'S', 'W']
    for tries in range(4):
        dir = random.choice(dirs)
        newPos = AddDirection(currPos, dir)
        if newPos not in visited and 0 <= newPos[0] < width and 0 <= newPos[1] < height:
            ConnectCells(grid[currPos[0]][currPos[1]], grid[newPos[0]][newPos[1]], dir)
            grid, visited = Carve(grid, newPos, visited)
        dirs.remove(dir)

    return grid, visited

def RenderToString(grid):
    str = ""
    str += ((wallChar+" ")*(width*2+1)) + "\n"
    for y in range(height):
        h = wallChar+" "
        v = wallChar+" "
        for x in range(width):
            h += (spaceChar+" "+spaceChar+" ") if grid[x][y].E else (spaceChar+" "+wallChar+" ")
            v += (spaceChar+" "+wallChar+" ") if grid[x][y].N else (wallChar+" "+wallChar+" ")
        str += h + "\n"
        if y < width-1:
            str += (v) + "\n"
    str += ((wallChar+" ")*(width*2+1)) + "\n"

    return str

width, height = [int(x) for x in input("Enter Maze Dimensions:\n> ").split()]
wallChar = input("Enter Wall Character:\n> ")
spaceChar = input("Enter Space Character:\n> ")
gr = []
for x in range(width):
    gr.append([cell(x, y) for y in range(height)])

gr, _ = Carve(gr, (0, 0), [])

mapStr = RenderToString(gr)

if width <= 30 and height <= 30:
    print(mapStr)

filepath = input("Filename to save to (leave blank if not saving):\n> ")
if filepath != "":
    ext = os.path.splitext(filepath)[1]

    if ext == ".txt":
        file = open(filepath, "w")
        file.write(mapStr)
        file.close()
    elif ext == ".png" or ext == ".jpg":
        from PIL import Image
        img = Image.new('RGB', (width*2+1, height*2+1))
        for x in range(width):
            for y in range(height):
                img.putpixel((x*2+1, y*2+1), (255, 255, 255))
                img.putpixel((x*2+2, y*2+2), (0, 0, 0))
                img.putpixel((x*2+2, y*2+1), ((255, 255, 255) if gr[x][y].E else (0, 0, 0)))
                img.putpixel((x*2+1, y*2+2), ((255, 255, 255) if gr[x][y].N else (0, 0, 0)))
        img.save(filepath)
    else:
        print("File extension not recognised\nOnly .txt, .png and .jpg files are supported")


from keras.layers import Dense, Conv2D, Permute, MaxPooling2D, AveragePooling2D, LSTM, Reshape, Flatten, Dropout
from keras.layers import multiply, add, average, maximum, Concatenate, Lambda
import keras
import tensorflow as tf

from sklearn.model_selection import train_test_split
import numpy as np
import os
import cv2

def crop(dimension, start, end):
    # Crops (or slices) a Tensor on a given dimension from start to end
    # example : to crop tensor x[:, :, 5:10]
    # call slice(2, 5, 10) as you want to crop on the second dimension
    def func(x):
        if dimension == 0:
            return x[start: end]
        if dimension == 1:
            return x[:, start: end]
        if dimension == 2:
            return x[:, :, start: end]
        if dimension == 3:
            return x[:, :, :, start: end]
        if dimension == 4:
            return x[:, :, :, :, start: end]
    return Lambda(func)

petal = 1 #1,2 or 4
root = r"C:\Users\Zach\Downloads\Table_extract_robust"

data_final = np.load(os.path.join(root, "DATA_concatenate_cols.npy"), allow_pickle=True)
LABELS = np.load(os.path.join(root, "LABELS_concatenate_cols.npy"), allow_pickle=True)

print(data_final.shape)

x_train, x_valid, y_train, y_valid = train_test_split(data_final, LABELS, test_size = 0.2, shuffle = True)

keras_input = keras.layers.Input(shape=(100,200, 1))

center_data_original = crop(2, 90, 110)(keras_input)
center_data_original = Conv2D(32, (5,5), activation="relu")(center_data_original)
center_data_original = MaxPooling2D((2,2))(center_data_original)
for i in range(3):
    temp0 = Conv2D(32, (3,3), activation="relu", padding='same')(center_data_original)
    temp1 = Conv2D(32, (3,3), activation="relu", padding='same')(temp0)
    temp2 = Conv2D(32, (3,3), activation="relu", padding='same')(temp1)
    center_data_original = keras.layers.concatenate([center_data_original,temp2])
    center_data_original = Conv2D(32, (3,3), activation="relu")(center_data_original)
    center_data_original = MaxPooling2D((2,1))(center_data_original)
    center_data_original = Dropout(.1)(center_data_original)
center_data_original = Flatten()(center_data_original)

ver_data = AveragePooling2D((100,1))(keras_input)
ver_data = MaxPooling2D((1,4))(ver_data)
ver_data = Conv2D(6, (1, 3), activation='relu')(ver_data)
ver_data = Conv2D(6, (1, 3), activation='relu')(ver_data)
ver_data = Conv2D(6, (1, 3), activation='relu')(ver_data)
ver_data = Dropout(.3)(ver_data)
ver_data = Flatten()(ver_data)

full_data = MaxPooling2D((2,2))(keras_input)
full_data = Conv2D(32, (5, 5), activation='relu')(full_data)
full_data = MaxPooling2D((2,2))(full_data)
full_data = Conv2D(64, (3, 3), activation='relu')(full_data)
full_data = MaxPooling2D((2,2))(full_data)
full_data = Conv2D(64, (3, 3), activation='relu')(full_data)
full_data = MaxPooling2D((2,2))(full_data)
full_data = Conv2D(64, (3, 3), activation='relu')(full_data)
full_data = MaxPooling2D((2,2))(full_data)
full_data = Dropout(.3)(full_data)
full_data = Flatten()(full_data)

data = Concatenate()([ver_data, full_data])
data = Dense(512, activation='relu')(data)
data = Dropout(.2)(data)
data = Dense(512, activation='relu')(data)
out = Dense(2, activation='sigmoid')(data)

conc = keras.models.Model(inputs=keras_input, outputs= out)
conc.compile(loss="binary_crossentropy", optimizer="adam", metrics = ["accuracy"])
conc.fit(x_train, y_train[:,1:], validation_data = (x_valid, y_valid[:,1:]), epochs = 15, batch_size = 32)

#y_train[:, 0]
conc.save(r"C:\Users\Zach\Downloads\Table_extract_robust\valid_cells.h5")

pred = conc.predict(data_final)
if(1):
    for i in range(len(pred)):
        if((pred[i][0] > .5) != LABELS[i][0]):
            print(pred[i][0], " ", LABELS[i][0])
            #print(LABELS[i][1], " ", LABELS[i][2])
            print("")
            temp_img = cv2.cvtColor(data_final[i],cv2.COLOR_GRAY2RGB)
            cv2.line(temp_img, (100, 0), (100, 100), (255,0,0), 1)
            cv2.line(temp_img, (90, 0), (90, 100), (0,255,0), 1)
            cv2.line(temp_img, (110, 0), (110, 100), (0,255,0), 1)
            cv2.imshow('image', temp_img)
            cv2.waitKey(0)
            cv2.destroyAllWindows()
else:
    for i in range(len(pred)):
        if(((pred[i][0] > .5) != LABELS[i][0]) or ((pred[i][1] > .5) != LABELS[i][1]) or ((pred[i][2] > .5) != LABELS[i][2])):
            print(pred[i][0], " ", LABELS[i][0])
            print(pred[i][1], " ", LABELS[i][1])
            print(pred[i][2], " ", LABELS[i][2])
            print("")
            cv2.imshow('image',data_final[i])
            cv2.waitKey(0)
            cv2.destroyAllWindows()


# uncompyle6 version 3.6.7
# Python bytecode 3.5 (3350)
# Decompiled from: Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: /home/nivekuil/code/amp/python3/amp/player.py
# Compiled at: 2016-10-28 21:41:15
# Size of source mod 2**32: 4619 bytes
__doc__ = '\nPlayer daemon that handles asynchronous playback.\n'
import sys, os, time, atexit, signal, subprocess, pafy
from .process import kill_process_tree
import logging
logging.getLogger().setLevel(logging.ERROR)
PIDFILE = '/tmp/amp.pid'
INFOFILE = '/tmp/amp.info'

class Player:
    """Player"""

    def __init__(self, url, show_video=False, verbose=False):
        self.pidfile = PIDFILE
        self.infofile = INFOFILE
        self.url = url
        self.show_video = show_video
        self.verbose = verbose

    def print_info(self):
        """Prints video information and usage output. If --verbose is set,
        prints to stdout in addition to infofile."""
        video_data = pafy.new(self.url)
        print('Now playing: ' + video_data.title + ' [' + video_data.duration + ']')
        if self.verbose:
            print('URL: ' + self.url)
            print('Description: ' + video_data.description)
        if self.show_video:
            print('Showing video in an external window.')
        with open(INFOFILE, 'w+') as (f):
            f.write('Description: %s\n\nTitle: %s\nDuration: %s\n' % (video_data.description, video_data.title,
             video_data.duration))

    def daemonize(self):
        """Daemonize class. UNIX double fork mechanism."""
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError as err:
            sys.stderr.write('fork #1 failed: {0}\n'.format(err))
            sys.exit(1)

        os.chdir('/')
        os.setsid()
        os.umask(0)
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError as err:
            sys.stderr.write('fork #2 failed: {0}\n'.format(err))
            sys.exit(1)

        sys.stdout.flush()
        sys.stderr.flush()
        si = open(os.devnull, 'r')
        so = open(os.devnull, 'a+')
        se = open(os.devnull, 'a+')
        os.dup2(si.fileno(), sys.stdin.fileno())
        atexit.register(self.delete_info_files)
        pid = str(os.getpid())
        with open(self.pidfile, 'w+') as (f):
            f.write(pid + '\n')

    def delete_info_files(self):
        os.remove(self.pidfile)
        os.remove(self.infofile)

    def start(self):
        try:
            with open(self.pidfile, 'r') as (f):
                pid = int(f.read().strip())
        except IOError:
            pid = None

        if pid:
            print('Stopping current song..')
            kill_process_tree(pid)
            self.delete_info_files()
        self.print_info()
        self.daemonize()
        self.run()

    def stop(self):
        """Stop the daemon."""
        try:
            with open(self.pidfile, 'r') as (pf):
                pid = int(pf.read().strip())
        except IOError:
            pid = None

        if not pid:
            message = 'pidfile {0} does not exist. ' + 'Daemon not running?\n'
        sys.stderr.write(message.format(self.pidfile))
        return
        try:
            while True:
                os.kill(pid, signal.SIGTERM)
                time.sleep(0.1)

        except OSError as err:
            e = str(err.args)
            if e.find('No such process') > 0:
                if os.path.exists(self.pidfile):
                    self.delete_info_files()
            else:
                print(str(err.args))
                sys.exit(1)

    def restart(self):
        """Restart the daemon."""
        self.stop()
        self.start()

    def run(self):
        subprocess_args = [
         'mpv', self.url, '--really-quiet']
        if self.show_video:
            subprocess_args.append('--fs')
        else:
            subprocess_args.append('--no-video')
        try:
            subprocess.call(subprocess_args)
        except OSError as e:
            if e.errno == 2:
                print('mpv cannot be found.')
                sys.exit(1)


"""
Global attention takes a matrix and a query vector. It
then computes a parameterized convex combination of the matrix
based on the input query.

        H_1 H_2 H_3 ... H_n
          q   q   q       q
            |  |   |       |
              \ |   |      /
                      .....
                  \   |  /
                          a

Constructs a unit mapping.
    $$(H_1 + H_n, q) => (a)$$
    Where H is of `batch x n x dim` and q is of `batch x dim`.

    The full def is  $$\tanh(W_2 [(softmax((W_1 q + b_1) H) H), q] + b_2)$$.:

"""

import torch
import torch.nn as nn
import math
from IPython import embed

class GlobalAttention(nn.Module):
    def __init__(self, dim, method='concat'):
        super(GlobalAttention, self).__init__()
        self.linear_in = nn.Linear(dim, dim, bias=False)
        self.sm = nn.Softmax()
        self.linear_concatWa = nn.Linear(dim*2, dim, bias=False)
        self.linear_concatVa = nn.Linear(dim, 1, bias=False)
        self.tanh = nn.Tanh()
        self.mask = None
        self.method = method
        print('use %s attention method'%(method))

    def applyMask(self, mask):
        self.mask = mask

    def general(self, input, context):
        targetT = self.linear_in(input).unsqueeze(2) # batch x dim x 1
        return torch.bmm(context, targetT).squeeze(2) # batch x 1

    def dot(self, input, context):
        targetT = input.unsqueeze(2) # batch x dim x 1
        return torch.bmm(context, targetT).squeeze(2) # batch x 1

    def concat(self, input, context):
        targetT = input.unsqueeze(1).expand(input.size(0),context.size(1),input.size(1)) # batch x sourceL x dim
        ht_hs = torch.cat((targetT,context),2) # batch x sourceL x dim*2
        size = ht_hs.size()[:2]
        ht_hs = ht_hs.view(size[0]*size[1], -1) # batch*sourceL x dim*2
        Wa_ht_hs = self.linear_concatWa(ht_hs) # batch*sourceL x dim
        tanh_Wa_ht_hs = self.tanh(Wa_ht_hs)
        return self.linear_concatVa(tanh_Wa_ht_hs).view(size[0],1,-1).squeeze(1) # batch x 1

    def forward(self, input, context):
        """
        input: batch x dim
        context: batch x sourceL x dim
        """
        if self.method == 'general':
            attn = self.general(input,context)
        if self.method == 'dot':
            attn = self.dot(input,context)
        if self.method == 'concat':
            attn = self.concat(input,context)
        if self.mask is not None:
            attn.data.masked_fill_(self.mask, -float('inf'))
        attn = self.sm(attn)
        attn3 = attn.view(attn.size(0), 1, attn.size(1))  # batch x 1 x sourceL
        weightedContext = torch.bmm(attn3, context).squeeze(1)  # batch x dim
        return weightedContext, attn


#!/usr/bin/env python

from path import path
from jinja2 import Template
import sys

SKIP_DIRS = ["native"]
SKIP_FILES = ["README"]
NON_AUTOLOAD_MODULES = ["ads", "analytics", "payment"]
NON_AUTOLOAD_FILES = {
    "payment": [
        "paymentproviderandroidgoogle",
        "paymentproviderandroidamazon",
        "paymentproviderappleios",
        "paymentproviderautounlock"
    ]
}
MONKEY = Template("""Strict

Public

{% for filename in filenames -%}
Import {{ module }}.{{ filename }}
{% endfor %}""")

def walkdir(dirpath, proc_func, rec_func):
    def is_valid_dir(dirpath):
        if dirpath.islink():
            return False
        if dirpath.name.startswith(".") or dirpath.name in SKIP_DIRS:
            return False
        return True

    [rec_func(dirpath / x.name) for x in dirpath.dirs() if is_valid_dir(x)]
    proc_func(dirpath)

def create_import_files(dirname):
    def is_valid(module, filename):
        if filename.startswith(".") or filename in SKIP_FILES:
            return False

        try:
            return filename not in NON_AUTOLOAD_FILES[module]
        except:
            return True

    def process(dirpath):
        filenames = [x.stripext().name for x in dirpath.files()]
        filenames = [x for x in filenames if is_valid(dirpath.name, x)]
        module = "bono." + dirpath.replace("/", ".")
        rendered = MONKEY.render(filenames=filenames, module=module)
        (dirpath + ".monkey").write_text(rendered)

    walkdir(path(dirname), process, create_import_files)

def add_reflection_rule():
    def replace_public(instr):
        return instr.replace(
            "Public",
            "Public\n\n#REFLECTION_FILTER+=\"*test|*src.tests*\"")

    filepath = path("src/tests.monkey")
    filepath.write_text(replace_public(filepath.text()))

def remove_non_autoload_modules():
    def is_autoload(importstr):
        for checkstr in NON_AUTOLOAD_MODULES:
            if checkstr in importstr:
                return False
        return True

    filepath = path("src.monkey")
    filepath.write_lines([x for x in filepath.lines() if is_autoload(x)])

if __name__ == "__main__":
    create_import_files("src")
    create_import_files("tests")
    add_reflection_rule()
    remove_non_autoload_modules()

    path("src.monkey").rename("bono.monkey")
    path("tests.monkey").rename("testimport.monkey")


from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
import requests
import os, json, boto3
from botocore.client import Config
import botocore

#botocore.session.Session().set_debug_logger()

from .models import Greeting
from . import models, forms

# Create your views here.
def index(request):
    # return HttpResponse('Hello from Python!')
    return render(request, "index.html")
    #return HttpResponseRedirect(reverse("submit_form"))
    #r = requests.get('http://httpbin.org/status/418')
    #print(r.text)
    #return HttpResponse('<pre>' + r.text + '</pre>')

    # load $TIMES, otherwise substitute 3
    #times = int(os.environ.get('TIMES',3))
    #return HttpResponse('Hello! ' * times)

def db(request):

    greeting = Greeting()
    greeting.save()

    greetings = Greeting.objects.all()

    return render(request, "db.html", {"greetings": greetings})

def sign_s3(request):
    S3_BUCKET = os.environ.get("S3_BUCKET")
    #print("AWS_ACCESS_KEY_ID: "+os.environ.get("AWS_ACCESS_KEY_ID")+\
    #    "\n AWS_SECRET_ACCESS_KEY: "+os.environ.get("AWS_SECRET_ACCESS_KEY"))
    file_name = request.GET["file_name"]
    file_type = request.GET["file_type"]

    s3 = boto3.client("s3")#, aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"), aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY"),)#, config = Config( signature_version = 's3v4'))

    print(S3_BUCKET)
    presigned_post = s3.generate_presigned_post(
        Bucket = S3_BUCKET,
        Key = file_name,

        Fields = None, #{ "acl": "public-read", "Content-Type": file_type },
        Conditions = None, #[ {"acl": "public-read"}, {"Content-Type": file_type},],

        ExpiresIn = 3600,
    )

    return HttpResponse( json.dumps({
        "data": presigned_post,
        "url": 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name),
        "key": file_name,
    }), content_type="text/json")

def get_image_url(request):
    filename = request.GET["file_name"]
    S3_BUCKET = os.environ.get("S3_BUCKET")

    params = {"Bucket": S3_BUCKET, "Key": filename}
    expire = 3600
    s3_client = boto3.client("s3")

    url = s3_client.generate_presigned_url("get_object", Params=params, ExpiresIn=expire)
    return HttpResponse(url, content_type="text/plain")

def submit_form(request):
    form2 = forms.ProfileChangeForm()
    if request.POST:
        form = forms.ProfileChangeForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data["username"]
            full_name = form.cleaned_data["full_name"]
            avatar_url = form.cleaned_data["avatar_url"]
            models.Account.update_account(username, full_name, avatar_url)
            return render(request, "hello/update_profile_success.html")

    return render(request, "hello/submit_form.html", {"form": form2} )


import numpy as np
import sys

import PyQt5.QtWidgets as qw
import PyQt5.QtCore as qc
import PyQt5.QtGui as qg

class App(qw.QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'Aufgabe 1b: Spline Kurven'
        self.setMinimumHeight(qw.QDesktopWidget().height() // 3)
        self.setMinimumWidth(qw.QDesktopWidget().width() // 3)
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle('Aufgabe 1b: Spline Kurven')
        self.setCentralWidget(DrawWidget(self))
        self.show()

class DrawWidget(qw.QWidget):
    def __init__(self, parent):
        qw.QWidget.__init__(self, parent)
        self.main_window = parent  # Main Window
        self.pane = Pane(self)
        sizePolicy = qw.QSizePolicy(qw.QSizePolicy.Ignored, qw.QSizePolicy.Ignored)
        self.pane.setSizePolicy(sizePolicy)
        #self.pane.setScaledContents(True)

        hbox = qw.QHBoxLayout()
        vbox = qw.QVBoxLayout()

        b_new = qw.QPushButton('New path', self)
        b_new.setToolTip('New path')
        b_new.clicked.connect(self.on_click_new_path)

        b_clear = qw.QPushButton('Clear', self)
        b_clear.setToolTip('Clear the Graph')
        b_clear.clicked.connect(self.on_click_clear)

        b_clear_pane = qw.QPushButton('Undo', self)
        b_clear_pane.setToolTip('remove last change')
        b_clear_pane.clicked.connect(self.on_click_undo)

        """b_plot = qw.QPushButton('Plot', self)
        b_plot.setToolTip('Plot a Graph')
        b_plot.clicked.connect(self.on_click_plot)"""

        """self.cm_type = qw.QComboBox(self)
        self.cm_type.addItem("normal")
        self.cm_type.addItem("speed up")
        self.cm_type.addItem("slow down")
        self.cm_type.activated.connect(self.on_click_type)"""

        cm_style = qw.QComboBox(self)
        cm_style.setToolTip('choose a style')
        cm_style.addItem("Fusion")
        cm_style.addItem("Windows")
        cm_style.addItem("macintosh")
        #m_style.addItem("Plastique")
        #cm_style.addItem("Cleanlooks")
        cm_style.addItem("windowsvista")
        cm_style.activated[str].connect(self.style_choice)

        b_show_cv = qw.QCheckBox('Show CV', self)
        b_show_cv.clicked.connect(lambda: self.on_click_show_cv(b_show_cv.checkState()))
        b_show_cv.setChecked(True)

        vbox.addWidget(b_new)
        vbox.addWidget(b_clear)
        vbox.addWidget(b_clear_pane)
        #vbox.addWidget(b_plot)
        #vbox.addWidget(self.cm_type)
        vbox.addWidget(cm_style)
        vbox.addWidget(b_show_cv)

        vbox.addStretch(1)

        hbox.addWidget(self.pane)

        hack = qw.QWidget()
        hack.setLayout(vbox)
        hack.setFixedWidth(110)

        hbox.addWidget(hack)

        self.setLayout(hbox)

    def on_click_clear(self):
        self.pane.clear_all_surfaces()

    def on_click_plot(self):
        self.pane.plot()

    def on_click_new_path(self):
        if len(self.pane.current_cv) != 0:
            self.pane.paths.append(self.pane.current_path)
            self.pane.current_path = qg.QPainterPath()

            self.pane.cvs.append(self.pane.current_cv)
            self.pane.current_cv = np.array([]).reshape(0, 2)

    def on_click_undo(self):
        self.pane.undo()

    def on_click_show_cv(self, value):
        self.pane.show_cv(value)

    def style_choice(self, text):
        qw.QApplication.setStyle(qw.QStyleFactory.create(text))

    def on_click_type(self):
        text = self.cm_type.currentText()
        self.pane.current_path.changed_style(text)
        self.pane.plot()

    def on_click_hight(self, text):
        self.pane.hight = int(text)
        self.pane.resolution_of_surfases()

    def on_click_width(self, text):
        self.pane.width = int(text)
        self.pane.resolution_of_surfases()

    def resizeEvent(self, event):
        self.pane.resolution_of_surfases()

class Pane(qw.QLabel):
    """ Paint surface class """
    def __init__(self, parent):
        """ creates Pane """
        super().__init__()
        self.parent = parent  # App - Main window
        main_window = parent.main_window
        self.style = "normal"
        self.color = qc.Qt.red
        self.thickness = 3
        self.grid = False

        # background for black background with lines of grid/crystal if activated
        self.ebene_pane = qg.QPixmap(self.width(), self.height())
        self.ebene_cv = qg.QPixmap(self.width(), self.height())
        self.ebene_schlitten = qg.QPixmap(self.width(), self.height())
        self.ebene_total = qg.QPixmap(self.width(), self.height())

        self.fill_all_default()     # cleans all surfaces
        self.set_all_painters()     # create all painters

        self.paths = []
        self.cvs = []
        self.current_path = qg.QPainterPath()

        self.painter_cv.setPen(qg.QPen(self.color, 3, qc.Qt.SolidLine))
        self.painter_cv.drawPath(self.current_path)

        self.current_cv = np.array([]).reshape(0, 2)
        self.showCV = True

        self.update()

    def resolution_of_surfases(self):
        self.end_all_painters()

        self.ebene_pane = qg.QPixmap(self.width(), self.height())
        self.ebene_cv = qg.QPixmap(self.width(), self.height())
        self.ebene_schlitten = qg.QPixmap(self.width(), self.height())
        self.ebene_total = qg.QPixmap(self.width(), self.height())

        #print(self.width(), self.h)
        self.fill_all_default()

        self.set_all_painters()

        self.update()
        self.plot()

    def fill_all_default(self):
        self.ebene_pane.fill(qg.QColor(0, 0, 0))
        self.ebene_cv.fill(qg.QColor(0, 0, 0, 0))
        self.ebene_schlitten.fill(qg.QColor(0, 0, 0, 0))
        self.ebene_total.fill(qg.QColor(0, 0, 0, 0))

    def set_all_painters(self):
        self.painter_cv = qg.QPainter(self.ebene_cv)
        self.painter_cv.setRenderHint(qg.QPainter.Antialiasing, True)
        self.painter_pane = qg.QPainter(self.ebene_pane)
        self.painter_pane.setRenderHint(qg.QPainter.Antialiasing, True)
        self.painter_schlitten = qg.QPainter(self.ebene_schlitten)
        self.painter_total = qg.QPainter(self.ebene_total)

    def end_all_painters(self):
        self.painter_cv.end()
        self.painter_pane.end()
        self.painter_schlitten.end()
        self.painter_total.end()

    def clear_all_surfaces(self):
        self.end_all_painters()
        self.fill_all_default()
        self.set_all_painters()

        self.paths = []
        self.current_path = qg.QPainterPath()

        self.cvs = []
        self.current_cv = np.array([]).reshape(0, 2)
        self.update()

    def undo(self):
        if len(self.current_cv) == 0:
            if len(self.cvs) != 0:
                self.current_cv = self.cvs[-1]
                self.cvs = self.cvs[:-1]
                self.paths = self.paths[:-1]

        if len(self.current_cv) != 0:
            self.current_cv = self.current_cv[:-1]
            if len(self.current_cv) != 0:
                self.current_path = qg.QPainterPath()
                self.current_path.moveTo(self.current_cv[0][0],self.current_cv[0][1])
                for i in range(len(self.current_cv)):
                    self.current_path.lineTo(self.current_cv[i][0], self.current_cv[i][1])
        self.update()
        self.plot()

    def show_cv(self, value):
        self.showCV = value
        self.update()

    def update(self):
        """ draws control points (vertexes) and Paths """
        """for i in range(self.k):
            if len(self.paths) == 0:
                return None
            if len(self.paths[i]) != 0:
                path = self.paths[i][-1][0]
                thickness = self.paths[i][-1][1]
                self.painter_pane.setPen(qg.QPen(self.color, thickness, qc.Qt.SolidLine))
                self.painter_pane.drawPath(path)"""

        """ draws control points and paths """
        self.ebene_cv.fill(qg.QColor(0, 0, 0, 0))

        if self.showCV:
            path = self.current_path
            color = qc.Qt.blue
            thickness = 1
            self.painter_cv.setPen(qg.QPen(color, thickness, qc.Qt.SolidLine))
            # draw actual path
            self.painter_cv.drawPath(path)
            # draw old paths
            for i in range(len(self.paths)):
                path = self.paths[i]
                self.painter_cv.drawPath(path)

            # draw old paths
            for j in range(len(self.cvs)):
                for i in range(self.cvs[j].shape[0]):
                    self.painter_cv.setPen(qg.QPen(color, 6, qc.Qt.SolidLine))
                    self.painter_cv.drawPoint(self.cvs[j][i][0], self.cvs[j][i][1])
            # draw actual path
            for i in range(self.current_cv.shape[0]):
                self.painter_cv.setPen(qg.QPen(color, 6, qc.Qt.SolidLine))
                self.painter_cv.drawPoint(self.current_cv[i][0],self.current_cv[i][1])

        self.ebene_total.fill(qg.QColor(0, 0, 0, 0))
        self.painter_total.drawPixmap(0, 0, self.ebene_pane)
        self.painter_total.drawPixmap(0, 0, self.ebene_cv)
        self.painter_total.drawPixmap(0, 0, self.ebene_schlitten)
        self.setPixmap(self.ebene_total)
        #print("drawing all")

    def plot(self):
        self.painter_pane.end()
        self.ebene_pane.fill(qg.QColor(0, 0, 0))
        self.painter_pane = qg.QPainter(self.ebene_pane)
        self.painter_pane.setRenderHint(qg.QPainter.Antialiasing, True)

        def p_1(t):
            return 1 / 6 * t ** 3

        def p_2(t):
            return 1 / 6 * (1 + 3 * t + 3 * t ** 2 - 3 * t ** 3)

        def p_3(t):
            return 1 / 6 * (4 - 6 * t ** 2 + 3 * t ** 3)

        def p_4(t):
            return 1 / 6 * (1 - 3 * t + 3 * t ** 2 - t ** 3)

        def b(t):
            if t <= 0:
                return 0
            elif t <= 1:
                return p_1(t)
            elif t <= 2:
                return p_2(t - 1)
            elif t <= 3:
                return p_3(t - 2)
            elif t <= 4:
                return p_4(t - 3)
            else:
                return 0

        def b_sp(t, i):
            return b(t - i)

        def change_color(color):
            if color%2 == 1:
                return qc.Qt.green
            else:
                return qc.Qt.darkCyan

        def test(x,y,color):
            path = qg.QPainterPath()

            break_j = 0
            farbe = change_color(color[0])
            self.painter_pane.setPen(qg.QPen(farbe, 3, qc.Qt.SolidLine))
            path.moveTo(x[0], y[0])
            for j in range(len(x)):
                path.lineTo(x[j], y[j])
                if j + 1 != len(color):
                    if color[j] != color[j + 1]:
                        break_j = j+1
                        break
            self.painter_pane.drawPath(path)
            if  break_j != 0:
                #print(f"len(x):{len(x)}, len(color):{len(color)}, break_j:{break_j}")
                return test(x[break_j:], y[break_j:], color[break_j:])

        def spline(cv):
            """
            :param cv: Control vertexes
            :return: x and y array for spline-curve
            """
            k = len(cv)  # Amount of CV
            if k < 4:
                print("insufficient control points")
                return False

            t_min, t_max = 1, k - 2  # Axe for shifted basis functions
            x = []
            y = []
            color = []
            color_temp = 0
            color_temp_v2 = 1
            t = t_min
            while t <= t_max:
                subsum_x = 0
                subsum_y = 0
                for i in range(0, k):
                    b = b_sp(t, i - 2)
                    # if b > 0.66:
                    #    color_temp = i
                    subsum_x += cv[i][0] * b
                    #print(f"P_x:{cv[i][0]} b_sp({t},{i}):{b}")
                    subsum_y += cv[i][1] * b
                if color_temp_v2 + 1 <= t:
                    color_temp_v2 += 1
                x.append(subsum_x)
                y.append(subsum_y)
                color.append(color_temp_v2)

                t += 0.01

            #print("x:", x)
            #print("y:", y)
            #print("color: ", color)
            return x, y, color

        def bspline(cv, n=100, degree=3):
            """ Calculate n samples on a bspline
                cv :      Array of control vertices
                n  :      Number of samples to return
                degree:   Curve degree
            """
            cv = np.asarray(cv)
            count = len(cv)

            degree = np.clip(degree,1,count-1)

            # Calculate knot vector
            kv = None
            kv = np.clip(np.arange(count+degree+1)-degree,0,count-degree)

            # Calculate query range
            u = np.linspace(False,(count-degree),n)

            # Calculate result
            #return np.array(si.splev(u, (kv,cv.T,degree))).T

        self.painter_pane.setPen(qg.QPen(qc.Qt.red, 3, qc.Qt.SolidLine))

        for i in range(len(self.cvs)):
            #p = bspline(self.cvs[i], n=len(self.cvs[i])*10)
            #x, y = p.T
            temp = spline(self.cvs[i])
            if temp:
                x,y,color = temp[0], temp[1], temp[2]
                test(x,y,color)
                """
                path = qg.QPainterPath()

                path.moveTo(x[0],y[0])
                for j in range(len(x)):
                    path.lineTo(x[j],y[j])

                self.painter_pane.drawPath(path)"""

        # actual path, if it is not empty!
        if len(self.current_cv) != 0:
            #p = bspline(self.current_cv, n=len(self.current_cv)*10) # n - amount of interpolated points
            #x, y = p.T
            temp = spline(self.current_cv)
            if temp:
                x,y, color = temp[0], temp[1], temp[2]
                #if len(x) > 10:
                    #x, y = x[5:], y[5:]
                    #x, y = x[:-5], y[:-5]
                #print(x)
                test(x,y, color)
                """
                path = qg.QPainterPath()

                path.moveTo(x[0], y[0])
                for j in range(len(x)):
                    path.lineTo(x[j], y[j])
                    if j+1 != len(x):
                        if color[j] != color[j+1]:

                self.painter_pane.drawPath(path)"""

        self.update()

        #print(self.current_cv)
        #p = bspline(self.test_cv, n=100)
        #x, y = p.T
        #print(x,y)

    def mousePressEvent(self, event):
        #print("click")
        x = event.pos().x()
        y = event.pos().y()
        if self.current_path.isEmpty():
            self.current_path.moveTo(x, y)
            self.current_path.lineTo(x+0.1, y+0.1)
        self.current_path.lineTo(x, y)

        self.current_cv = np.r_[self.current_cv, [[x, y]]]
        #print(self.current_cv, self.current_cv[:, 0] )

        self.update()
        self.plot()

if __name__ == '__main__':
    app = qw.QApplication(sys.argv)
    ex = App()
    sys.exit(app.exec_())


'''
  Für LoLin - Board
  Modifiziert von 'Micropython mit ESP32', Lektion 19, WebWetter9.py
  Erste Test für Kommunikation mit Smartdisplay
'''

from netzwerk import *
from geheim import *
from webseiten import startHTTP, log, hp, wetter
from openweathermap import *
import time
import gc
import esp
import machine

esp.osdebug(None)

wifi = WiFi()
owm = WetterService(owm_id, owm_lat, owm_lon, owm_ort, owm_land, 600)
uart = machine.UART(2,9600,rx=2,tx=15)

def zeit_text(zeit):
    return datum_zeit_text(owm.get_zeit_lokal(zeit))

def zeige_taeglich():
    wetter.add("Tägliche Entwicklung")
    for w in taeglich:
        datum = datum_text(owm.get_zeit_lokal(w.get("dt")))
        temp = w.get("temp").get("day")
        feuchte = w.get("humidity")
        txt = w.get("weather")[0].get("description")
        wetter.add("{}: {} Grad, {} % Luftfeuchtigkeit, {}".format(datum,temp,feuchte,txt))
    wetter.add()

def zeige_stunden():
    wetter.add("Stündliche Entwicklung")
    for w in stuendlich:
        zeit = datum_zeit_text(owm.get_zeit_lokal(w.get("dt")))
        temp = w.get("temp")
        feuchte = w.get("humidity")
        txt = w.get("weather")[0].get("description")
        wetter.add("{}: {} Grad, {} % Luftfeuchtigkeit, {}".format(zeit,temp,feuchte,txt))
    wetter.add()

def zeige_aktuell(aktuell):
    if aktuell:
        messzeit = owm.get_messzeit_text()

        wetter.clear()
        wetter.add("Aktuelles Wetter in {}, {}: {}".format(owm.get_ort_name(),owm.get_land(),aktuell.get("weather")[0].get("description")))
        wetter.add("Gemessen am {}".format(messzeit))
        wetter.add()
        wetter.add("Temperatur:   {} Grad".format(aktuell.get("temp")))
        wetter.add("Luftdruck:    {} hPa".format(aktuell.get("pressure")))
        wetter.add("Feuchtigkeit: {} %".format(aktuell.get("humidity")))
        wetter.add()
        wetter.add("Wind:")
        wetter.add("Geschwindigkeit: {} m/s".format(aktuell.get("wind_speed")))
        wetter.add("Richtung:        {} Grad".format(aktuell.get("wind_deg")))
        wetter.add()

        ort = "[ort]={}, {}\r".format(owm.get_ort_name(),owm.get_land())
        beschreibung = "[beschreibung]={}\r".format(aktuell.get("weather")[0].get("description"))
        zeit = "[zeit]={}\r".format(messzeit)

        temp = "[temp]={}\r".format(aktuell.get("temp"))
        feuchte = "[feuchte]={}\r".format(aktuell.get("humidity"))
        druck = "[druck]={}\r".format(aktuell.get("pressure"))

        wind_geschw = "[wind_geschw]={}\r".format(aktuell.get("wind_speed"))
        wind_richtung = "[wind_richtung]={}\r".format(aktuell.get("wind_deg"))

        print()
        print("Senden an Display:")
        print(zeit)
        print(ort)
        print(beschreibung)
        print(temp)
        print(feuchte)
        print(druck)
        print(wind_geschw)
        print(wind_richtung)

        uart.write(zeit)
        uart.write(ort)
        uart.write(beschreibung)
        uart.write(temp)
        uart.write(feuchte)
        uart.write(druck)
        uart.write(wind_geschw)
        uart.write(wind_richtung)

        print("<show>")
        uart.write("<show>\r")

def homepage():
    ip = wifi.get_ip()
    hp.add("Die ESP32 - Wetterstation kennt momentan folgende Funktionen:")
    hp.add()
    hp.add('Das aktuelle Wetter: http://{}/wetter'.format(ip,ip))
    hp.add('Ein LOG als Debug-Hilfe beim Programmieren: http://{}/log'.format(ip,ip))

print("Mit Netzwerk verbinden ...")
log.add_log("Mit WLAN verbinden...");

if wifi.connect(wlan_ssid,wlan_passwort):
    print(wifi.get_ssid())
    print(wifi.get_ip())

    startHTTP()
    log.add_log("Mit {} verbunden, IP-Adresse {}".format(wifi.get_ssid(),wifi.get_ip()))
    homepage()
    aktuell, stuendlich, taeglich = owm.get_alle()
    log.add_log("Wetter geladen");
    zeige_aktuell(aktuell)
    zeige_stunden()
    zeige_taeglich()

    while True:
        time.sleep(60)
        aktuell, stuendlich, taeglich = owm.get_alle()
        zeige_aktuell(aktuell)

else:
   print("Kein Netzwerk gefunden!")
   log.add_log("Keine Verbindung möglich")
   log.print()


#!/usr/bin/env python2.7

import sys
from case_util.common import WXATF_TFLEX_SERVER_PORT_NAME

ext_lib_path = "/home/ezhao/atf_package/wxATF/brion/wxatf-lib/wxtflex_main.py"
ui_toplevel_file = "/home/ezhao/atf_package/atf_ui/toplevel_wins.py"

def _parse_options(argv):
    argv = argv[1:]

    pos = argv.index('--app')
    return [argv[pos + 1]] + argv[:pos] + argv[pos + 2:]

def _run_app(app):
    from wxatf import client
    return client.runapp(app)

def _init_tflex(conn):
    gui = conn.remote_env()
    gui.load_ext_lib(ext_lib_path)
    gui.ui.load_ui(ui_toplevel_file, 'ui_root')

    gui.importlib('os')
    gui.os.environ[WXATF_TFLEX_SERVER_PORT_NAME] = str(conn.remote_port)

    from extensions.main import install_extensions
    install_extensions(gui)

if __name__ == "__main__":
    app = _parse_options(sys.argv)
    conn, proc = _run_app(app)
    _init_tflex(conn)

    proc.wait()


import sqlite3

try:
    conn = sqlite3.connect('data/discord.db')
    print('Database online')
except:
    print('Database creation failed')

c = conn.cursor()
def create_table_my_prefix():
    sql_statement = ('CREATE TABLE IF NOT EXISTS my_prefix(prefix TEXT, guild_id INTEGER)')
    c.execute(sql_statement)
    try:
        conn.commit()
        print("Database table 'my_prefix' online")
    except:
        print("Error in table my_prefix")
create_table_my_prefix()

def create_table_commands():
    sql_statement = ("CREATE TABLE IF NOT EXISTS commands(alias TEXT,malias TEXT, desc TEXT)")
    c.execute(sql_statement)
    try:
        conn.commit()
        print("Database table 'commands' online")
    except:
        print("Error in table commands")
create_table_commands()

def create_table_users():
    sql_statement = ("CREATE TABLE IF NOT EXISTS users (user_id INTEGER, wallet INTEGER, bank INTEGER)")
    c.execute(sql_statement)
    try:
        conn.commit()
        print("Database table 'users'' is online")
    except:
        print("Error in table users")

create_table_users()


import json
import os
import pickle as pkl

import requests

from MovieFunc import MovieFunc
from MovieOptimizer import MovieOptimizer

class MovieEngine:
    def __init__(self):
        self.optimizer = MovieOptimizer()
        self.func = MovieFunc()
        self.valid_movies = {}
        self.invalid_movies = {}
        try:
            self.dir_path = pkl.load(open('.dir.str', 'rb'))
        except IOError:
            self.dir_path = ''
        try:
            self.valid_movies = pkl.load(open('.valid_movies.dict', 'rb'))
            self.invalid_movies = pkl.load(open('.invalid_movies.dict', 'rb'))
        except IOError:
            self.valid_movies = {}
            self.invalid_movies = {}
        self.save()

    def directory_isvalid(self):
        try:
            os.listdir(self.dir_path)
            return True
        except IOError:
            os.remove('.dir.str')
            return False

    def save(self):
        pkl.dump(self.dir_path, open('.dir.str', 'wb'))
        pkl.dump(self.valid_movies, open('.valid_movies.dict', 'wb'))
        pkl.dump(self.invalid_movies, open('.invalid_movies.dict', 'wb'))

    def sync_local(self):
        self.invalid_movies = {}
        for id_ in os.listdir(self.dir_path):
            if id_ not in self.valid_movies:
                self.invalid_movies[id_] = {}
        delete_list = []
        for id_ in self.valid_movies:
            if id_ not in os.listdir(self.dir_path):
                delete_list.append(id_)
        for id_ in delete_list:
            del self.valid_movies[id_]
        self.save()

    def sync_remote(self):
        delete_list = []
        failed_list = []
        c = 0
        for name in self.invalid_movies:
            try:
                print('Fetching Data for movie %d/%d.' % (c + 1, len(self.invalid_movies)))
                id_ = self.func.imdb_id(name)
                resp = json.loads(requests.get(self.func.query(id_), verify=False).text)
                add = resp
                if 'Title' not in add:
                    raise AttributeError
                add['Score'] = -1
                self.func.rename(name, id_, self.dir_path)
                print('Renamed movie %s --> %s' % (name, id_))
                self.valid_movies[id_] = add
                delete_list.append(name)
            except AttributeError:
                print('Fetch failed.')
                failed_list.append(name + ' fail.')
            c += 1
        for name in delete_list:
            del self.invalid_movies[name]
        self.save()
        return failed_list

    def core_list(self, **kwargs):
        function = kwargs.get('function', 'val')
        id_dict_list = self.valid_movies
        id_list = []
        if function == 'val':
            id_list = list(id_dict_list)
        elif function == 'unw':
            id_list = []
            for id_ in list(id_dict_list):
                if id_dict_list[id_]['Score'] == -1:
                    id_list.append(id_)
        elif function == 'rec':
            id_score = []
            for id_ in list(id_dict_list):
                if self.valid_movies[id_]['Score'] == -1:
                    id_dict = self.valid_movies[id_]
                    id_score.append((id_, self.optimizer.predict(id_dict)))
            id_score.sort(key=lambda x: x[1], reverse=True)
            id_list = []
            for i in range(len(id_score)):
                id_list.append(id_score[i][0])
        filter_list = kwargs.get('filt', [])
        delete_list = []
        for id_ in id_list:
            genres = id_dict_list[id_]['Genre'].split(', ')
            if not self.func.pass_filter(genres, filter_list):
                delete_list.append(id_)
        for id_ in delete_list:
            id_list.remove(id_)
        dict_list = {}
        for id_ in id_list:
            dict_list[id_] = self.valid_movies[id_]
        return dict_list