from __future__ import print_function
import logging, sys
import argparse
import wget
import os
import xmltodict
import xml.etree.ElementTree as ET
from datetime import datetime
from collections import OrderedDict
from functools import partial
import time

logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

def wget_from_url(url, name=None):
    name = url.rsplit('/', 1)[-1] if not name else name
    if os.path.exists(name):
      os.remove(name)
    wget.download(url, out=name)

def download(option):
  motc_prefix = 'https://tisvcloud.freeway.gov.tw/history/motc20/'
  if option == 'static' or option == 'all':
    [wget_from_url(motc_prefix + x)
      for x in ['Section.xml',      # Basic information of road section
                'SectionShape.xml', # Map shape information of road section (wkt info)
                'SectionLink.xml',  # SectionID to LinkIDs information
                'ETag.xml',         # Etag information of LinkID
                'ETagPair.xml'
                ]]

  if option == 'dynamic' or option == 'all':
    [wget_from_url(motc_prefix + x)
      for x in ['LiveTraffic.xml',  # Real-time traffic information on road section
                'ETagPairLive.xml'
                ]]

  else:
    eprint('invalid download option (dynamic/static/all)')

def extract_data(xml_file, callback=None):
  if not callback:
    eprint('The callback option is needed (a function to deal with the xml root)')
    sys.exit('Error on extract_data')

  tree = ET.parse(xml_file)
  root = tree.getroot()
  prefix = root.tag.split('}', 1)[0] + '}'
  return callback(root=root, prefix=prefix)

def shapes_process(root, prefix=''):
  Dict = {}
  for child in root.find(prefix + 'SectionShapes'):
    section_id = child.find(prefix + 'SectionID').text
    shape = child.find(prefix + 'Geometry').text

    logging.debug(f' SectionID: {section_id}, Shape: {shape}')

    Dict[section_id] = shape
  return Dict

def livetraffic_process(root, prefix=''):
  Dict = {}
  for child in root.find(prefix + 'LiveTraffics'):
    section_id = child.find(prefix + 'SectionID').text
    travel_time = child.find(prefix + 'TravelTime').text
    congestion_level = child.find(prefix + 'CongestionLevel').text
    travel_speed = child.find(prefix + 'TravelSpeed').text

    logging.debug(f' SectiondID: {section_id}, travel time: {travel_time}, congestion: {congestion_level}, travel speed: {travel_speed}')

    Dict[section_id] = {'TravelTime': travel_time, 'CongestionLevel': congestion_level, 'TravelSpeed': travel_speed}
  return Dict

def linkid_process(root, prefix=''):
  Dict = {}
  for child in root.find(prefix + 'SectionLinks'):
    sec_id = child.find(prefix + 'SectionID').text
    link_ids = child.find(prefix + 'LinkIDs')
    result = [l.text for l in link_ids.findall(prefix + 'LinkID')]

    logging.debug(f' SectionID: {sec_id}, linkIDs: {result}')

    Dict[sec_id] = result
  return Dict

def etag_process(root, prefix=''):
  Dict = {}
  for child in root.find(prefix + 'ETags'):
    etag_id = child.find(prefix + 'ETagGantryID').text
    link_id = child.find(prefix + 'LinkID').text
    road_id = child.find(prefix + 'RoadID').text

    logging.debug(f' Etag: {etag_id}, LinkID: {link_id}, RoadID: {road_id}')

    Dict [etag_id] = {'LinkID': link_id, 'RoadID': road_id}
  return Dict

def etag_pair_live_process(root, prefix=''):
  Dict = {}
  for child in root.find(prefix + 'ETagPairLives'):
    etag_pair_id = child.find(prefix + 'ETagPairID').text
    start_status = child.find(prefix + 'StartETagStatus').text
    end_status = child.find(prefix + 'EndETagStatus').text

    count = 0
    flows = {}
    for flow in child.find(prefix + 'Flows'):
      vehicle_type = flow.find(prefix + 'VehicleType').text
      vehicle_count = flow.find(prefix + 'VehicleCount').text
      count += int(vehicle_count)

      flows[vehicle_type] = {'VehicleCount': vehicle_count}

    # logging.debug(f' Etag: {etag_id}, LinkID: {link_id}, RoadID: {road_id}')

    Dict [etag_pair_id] = {'StartETagStatus': start_status,
                           'EndETagStatus': end_status,
                           'VehicleCount': count,
                           'Flows': flows
                          }
  return Dict

def etag_pair_process(root, prefix=''):
  Dict = OrderedDict()
  for child in root.find(prefix + 'ETagPairs'):
    etag_pair_id = child.find(prefix + 'ETagPairID').text
    start_etag = child.find(prefix + 'StartETagGantryID').text
    end_etag = child.find(prefix + 'EndETagGantryID').text
    description = child.find(prefix + 'Description').text
    distance = child.find(prefix + 'Distance').text
    start_link_id = child.find(prefix + 'StartLinkID').text
    end_link_id = child.find(prefix + 'EndLinkID').text

    logging.debug(f' Etag: {etag_pair_id}, description: {description}')

    Dict [etag_pair_id] = {'StartETagGantryID': start_etag,
                           'EndETagGantryID': end_etag,
                           'Description': description,
                           'Distance': distance,
                           'StartLinkID': start_link_id,
                           'EndLinkID': end_link_id
                          }
  return Dict

# The default road for id_process is 國道 1 號 (000010)
def id_process(root, road='000010', prefix=''):
  Dict = {'N': OrderedDict(), 'S': OrderedDict()}

  for child in root.find(prefix + 'Sections'):
    road_id = child.find(prefix + 'RoadID').text

    # only the giving road will be processed
    if road_id != road:
      continue

    road_direction = child.find(prefix + 'RoadDirection').text
    section_id = child.find(prefix + 'SectionID').text
    _sec = child.find(prefix + 'RoadSection')
    start, end = _sec.find(prefix + 'Start').text, _sec.find(prefix + 'End').text
    sec_length = child.find(prefix + 'SectionLength').text

    logging.debug(f' SectionID: {section_id}, RoadID: {road_id}, ({start}, {end}), Length: {sec_length}')

    Dict[road_direction][section_id] = {'RoadID': road_id, 'Start': start, 'End': end, 'Length': sec_length}
  return Dict

# Date, Time, Congestion, Speed
def collect_dynamic_traffic(traffic_list, save='./data'):
  etag_pair = extract_data('ETagPair.xml', callback=etag_pair_process)
  while True:
    allfiles = OrderedDict()
    for traffic in traffic_list:
      for i in traffic:
        allfiles[i[0]] = open(f"{save}/travel_time_{i[0]}.txt", "a")

    # download dynamic data
    download('dynamic')
    live_traffic = extract_data('LiveTraffic.xml', callback=livetraffic_process)
    etag_pair_live = extract_data('ETagPairLive.xml', callback=etag_pair_live_process)
    etag_description_to_count = {}
    for key, value in etag_pair_live.items():
      if key in etag_pair:
        etag_description_to_count[etag_pair[key]['Description']] = value['VehicleCount']

    # record time
    now = datetime.now()
    current_time = now.strftime("%H:%M:%S")

    for key, value in etag_description_to_count.items():
      f = open(f"{save}/etag_{key}.txt", "a")
      f.write(f'{current_time} {value}\n')
      f.flush()
      f.close()

    for traffic in traffic_list:
      new_traffic = []
      for key, value in traffic:
        if key in live_traffic:
          new_traffic.append((key, value))
      traffic = new_traffic

      t_s = OrderedDict([(key, live_traffic[key]['TravelTime']) for key, value in traffic])
      l_s = OrderedDict([(key, live_traffic[key]['CongestionLevel']) for key, value in traffic])
      s_s = OrderedDict([(key, live_traffic[key]['TravelSpeed']) for key, value in traffic])

      for key, _ in traffic:
        tt = allfiles[key]
        tt.write(f'{current_time} {t_s[key]} {l_s[key]} {s_s[key]}\n')
        tt.flush()
        tt.close()
    time.sleep(120)

# e.g. 台北交流道, 新竹交流道
def traffic_of_two_points(start, end, section_ids):
  # e.g. section_ids = extract_data('Section.xml', callback=partial(id_process, road='000010'))
  ## Create an inverse table from section_ids
  last_elem = next(reversed(section_ids['S'].items()))

  inverse_table = OrderedDict([(value['Start'], (i, key)) for i, (key, value) in enumerate(section_ids['S'].items())] + \
                              [(last_elem[1]['End'], (len(section_ids['S']), last_elem[0]))])

  x1 = inverse_table[start]
  x2 = inverse_table[end]

  direction = ('S', 1) if x1[0] < x2[0] else ('N', -1)
  fix = 1 if direction[0] == 'N' else 0

  traffic = list(section_ids[direction[0]].items())[x1[0]-fix:x2[0]-(fix if x2[0] != 0 else 0):direction[1]] +\
            ([list(section_ids[direction[0]].items())[x2[0]]] if x2[0] == 0 else [])

  return traffic

logging.disable(logging.DEBUG)

def main():
  parser = argparse.ArgumentParser(description='MOTC extractor example')
  parser.add_argument('--download', type=str, default='none', metavar='N',
                      help='Download the data from MOTC (static/dynamic/all)')
  # parser.add_argument('--save-dict', action='store_true', default=False,
  #                       help='For Saving the current dict')
  parser.add_argument('--debug', action='store_true', default=False,
                        help='Debug info')
  parser.add_argument('--collect', action='store_true', default=False,
                        help='Collect dynamic traffic to data/')
  args = parser.parse_args()

  # if args.debug:
  #   logging.enable(logging.DEBUG)

  # Usage
  ## Download the data from motc (static / dynamic / all)
  ## dynamic: only the real-time information will be downloaded from MOTC
  ## static: the static information ...
  ## all: dynamic + static
  if args.download != 'none':
    download(args.download)

  ## Extract the Section IDs information on giving road (e.g. 國道 1 號: 000010) -> OrderedDict(key=section_id)
  section_ids = extract_data('Section.xml', callback=partial(id_process, road='000010'))

  ## Extract the Live Traffic information -> Dict(key=section_id)
  live_traffic = extract_data('LiveTraffic.xml', callback=livetraffic_process)

  ## Extract the Live Traffic information -> Dict
  shapes = extract_data('SectionShape.xml', callback=shapes_process)

  ## Extract the Mapping of SectionID to LinkID -> Dict
  section_links = extract_data('SectionLink.xml', callback=linkid_process)

  etag_pair_live = extract_data('ETagPairLive.xml', callback=etag_pair_live_process)

  etag_pair = extract_data('ETagPair.xml', callback=etag_pair_process)

  etag_description_to_count = {}
  for key, value in etag_pair_live.items():
    if key in etag_pair:
      etag_description_to_count[etag_pair[key]['Description']] = value['VehicleCount']
  # print(etag_description_to_count)

  if args.collect:
    tl = [traffic_of_two_points('基隆端', '高雄端', section_ids), traffic_of_two_points('高雄端', '基隆端', section_ids)]
    collect_dynamic_traffic(tl)

  # print('Travel Time: ', sum([int(live_traffic[key]['TravelTime']) for key, value in traffic]))

if __name__ == '__main__':
  main()


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 -*-
"""
Created on Sat Aug 13 16:49:46 2022

@author: Giorgia
"""

from types import SimpleNamespace
import time
import itertools as it
import numpy as np
from scipy import optimize
#from scipy.interpolate import RegularGridInterpolator
from scipy.io import loadmat
import os
import scipy.interpolate as spi

def prob_workT(par,options,Vp,Cp,j_pos):
    r_sav     = par.r_sav
    r_debt    = par.r_debt
    beta      = par.beta
    gammac    = par.gammac
    w         = par.w
    Lambda    = par.Lambda

    S = par.grids[0][j_pos]## matlab uses {} because par.grids is a cell array which I do not manage to convert in python
    EDUC      = par.educ
    AGE_PROF  = par.inc.age_prof
    INNO_pos  = par.inc.inno_pos
    FE_pos    = par.inc.fe_pos

    Sp = np.zeros([len(INNO_pos),len(EDUC),len(S),len(FE_pos)])
    C = np.zeros([len(INNO_pos),len(EDUC),len(S),len(FE_pos)])
    V = np.zeros([len(INNO_pos),len(EDUC),len(S),len(FE_pos)])
    boundgrid = np.zeros([len(INNO_pos),len(FE_pos),len(EDUC)])

    for educ in range (0,len(EDUC)):
        S       = par.grids[educ][j_pos]
        Spgrid  = par.grids[educ][j_pos+1]

        FE        = par.inc.fe[educ]
        INNO      = par.inc.z_val[educ][j_pos,:]

        r         = (r_sav * (Spgrid>=0) + r_debt * (Spgrid<0)).T
        rs        = (r_sav * (S>=0) + r_debt * (S<0))

        for ife in range (0,len(FE_pos)):
            splVp = spi.interp1d(Spgrid,Vp[educ,:,ife],axis=0, fill_value="extrapolate")
            # People don't work next period so only disutility of consumption.
            Cpp = Cp[educ,:,ife]
            ucp = beta*(1+r)*Cpp**(-gammac)

            for inno  in range (0,len(INNO_pos)):
                dispinc = (1-Lambda) * exp(AGE_PROF[educ][0][j_pos]) * exp(FE[ife]) * exp(INNO[inno]) #AGE_PROF[educ][0][j_pos], i THINK THE [0] IS NEEDED ONLY BECAUSE IT IS A 1 DIMENSION DICTIONARY(FLEXIBLE)

                feasible = (dispinc + (1+rs)*S - Spgrid[0]>0)
                not_feasible = (dispinc + (1+rs)*S - Spgrid[0]<=0)

                C[inno,educ,feasible,ife],Sp[inno,educ,feasible,ife],boundgrid[inno,ife,educ] = EGM(par,ucp,dispinc,Spgrid,S[feasible])

                vp = splVp(Sp[inno,educ,feasible,ife])
                V[inno,educ,feasible,ife] = (C[inno,educ,feasible,ife]**(1-gammac))/(1-gammac) + beta*vp
                C[inno,educ,not_feasible,ife] = 0
                V[inno,educ,not_feasible,ife] = (-(10**(5/gammac))**(1-gammac))/(1-gammac)
                Sp[inno,educ,not_feasible,ife]= Spgrid[0]

    errors = sum(boundgrid[:])/np.size(C[:])
    if options.timer_on == 'Y':
            if sum(boundgrid[:]) >= len(EDUC)*len(FE_pos)*len(INNO_pos):
                 print(f"j : {par.age[j_pos-1]}, Share of errors (increase grid) = {errors}")
##################################################################################################
    return V, C, Sp

#########################THE PROBLEM IS THAT i AM MIZING TYPES IN A LIST
#compare with matlab calling C[32][4][2] or any other combination of [inno][educ], first row [0] is 00000 for C and S, -2 for V. if we comment out " C[inno,educ,not_feasible,ife] = 0", everything is fine
#it works great except C[32][:][:][0],
#C(not_feasible,ife,educ,inno)


import numpy as np
import cv2

img = cv2.imread("imagens/estrada.jpg")
vermelho = (0, 0, 255)
verde = (0, 255, 0)
azul = (255, 0, 0)
cv2.line(img, (0, 0), (100, 200), verde)
cv2.line(img, (300, 200), (150, 150), vermelho, 5)
cv2.rectangle(img, (20, 20), (120, 120), azul, 10)
cv2.rectangle(img, (200, 50), (225, 125), verde, -1)

(x, y) = (img.shape[0]//2, img.shape[0]//2)

for raio in range(0, 175, 15):
    cv2.circle(img, (x, y), raio, vermelho)

cv2.imshow("imagem alterada", img)
cv2.waitKey()

PDI(processamento digital de imagem)/estudos sobe PDI/desenhando_na_imagem.py


"""Setup script"""

from setuptools import find_packages, setup

extras_require = { # pylint: disable=invalid-name
    'lint': [
        'pylint>=2.3.0,<3'
    ],
    'dev': [
        'rope>=0.14.0,<0.15'
    ]
}

extras_require['dev'] = (
    extras_require['lint'] +
    extras_require['dev']
)

setup(
    name='gasstation-express-oracle',
    version='0.1.0',
    license='MIT',
    description='Ethereum Gas Price Oracle',
    long_description_markdown_filename='README.md',
    author='Marcus R. Brown',
    author_email='contact@marcusrbrown.com',
    url='https://github.com/igetgames/gasstation-express-oracle',
    packages=find_packages(),
    scripts=['gasstation-express-oracle'],
    include_package_data=True,
    python_requires='>=3.6,<4',
    install_requires=[
        'numpy>=1.17.0,<2',
        'pandas>=0.25.0,<0.26',
        'web3>=5.1.0,<6',
    ],
    setup_requires=['setuptools-markdown'],
    extras_require=extras_require,
    zip_safe=True,
    classifiers=[
        'Development Status :: 4 - Beta',
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: 3.7',
    ]
)


from pymongo import MongoClient

uri = 'mongodb://127.0.0.1:27017'
client = MongoClient(uri)
db = client['services']
eventDatacollection = db.get_collection('serviceconfigdetails')
all_event_details = eventDatacollection.find({})
################################################################
authDatacollection = db.get_collection('authdetails')
all_auth_details = authDatacollection.find({})

########################## SERVICE #########################################
trigger_results =[]
action_results = []
for event in all_event_details:
    eventData = []
    eventData.append(event['service_idnetifier'])
    eventData.append(event['eventName'])
    if event['eventType'] == 'trigger':
        trigger_results.append(eventData)
    elif event['eventType'] == 'action':
        action_results.append(eventData)
############################ AUTHENTICATED #################################
all_auth_details_list  = []
for authService in all_auth_details:
    serviceID = authService['service_idnetifier']
    connected = authService['connected']
    if connected:
        all_auth_details_list.append(serviceID)

print(trigger_results)
for authService in all_auth_details_list:
    print(authService)
    ii = 0
    for item in trigger_results:
        if authService == item[0]:
            ii = ii + 1
            if ii == 1:
                print('is a trigger service !!')
            print(item[1])
    ii2 = 0
    for item2 in action_results:
        if authService == item2[0]:
            ii2 = ii2 + 1
            if ii2 == 1:
                print('is a action service !!')
            print(item2[1])

    print('###########################')


import numpy
import matplotlib.pylab as plt
from os import listdir
import sys

def getNextFilename(filename_base):
    plots_dir = 'plots'
    filename_int_length = 2

    heatmap_files = [file for file in listdir(plots_dir) if file.startswith(filename_base)]
    if not heatmap_files:
        next_int = 0
    else:
        heatmap_files.sort()
        next_int = int(heatmap_files[-1][-6:-4]) + 1

    next_int_str = str(next_int).zfill(filename_int_length)
    return plots_dir + '/' + filename_base + '-' + next_int_str + '.png'

matrix = numpy.loadtxt("matrix")
matrix_magnify=numpy.zeros((matrix.shape[0]*10,matrix.shape[1]))
for i in range(matrix.shape[0]):
    for j in range(10):
        matrix_magnify[i*10+j,:]=matrix[i,:]
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plt.imshow(matrix_magnify, interpolation='nearest', cmap=plt.cm.Blues)
plt.colorbar()

if (len(sys.argv) > 1):
    filename_base = sys.argv[1]
else:
    filename_base = 'heatmap'

heatmapFileName = getNextFilename(filename_base)
print('Creating heatmap image: ' + heatmapFileName)
plt.savefig(heatmapFileName)


#!/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 matplotlib.pyplot as plt
# from sklearn.preprocessing import StandardScaler
# from sklearn.cluster import KMeans
import ipaddress
import heapq
import os, sys
path = "D:/data_analyzis/bps,pps/data/test2/"
lists = os.listdir(path)

print("Running.......")
for name in lists:
    # name = j
    dataset = pd.read_csv(path + name , header=None, delim_whitespace=False)  #+ ".csv": neu co duoi .csv
    dataset = dataset.rename(columns={0: 'src'})
    dataset = dataset.rename(columns={6: 'len'})  # vị trí số 6 trong file csv
    dataset = dataset.rename(columns={7: 'proto'})

    dataset['src'].unique().tolist()
    df = dataset.pivot_table(index=['src', 'len', 'proto'], aggfunc='size')
    df = df.to_frame().reset_index().rename(columns={0: 'count'})

    src = df['src'][0:-1].to_numpy()
    x = 0
    for i in src:
        src[x] = int(ipaddress.ip_address(i)) # convert sang decimal
        x = x+1
    df['src'][0:-1] = src
    # ====================================================
    df = pd.DataFrame(df, columns=['src', 'len', 'proto', 'count', 'bps'])
    pktlen = df['len'][0:-1]
    count = df['count'][0:-1]
    proto = df['proto'][0:-1]
    sport_slot = []
    for i in range(len(src)):
        sport_slot.append(float(count[i])*float(pktlen[i])/600)
    df['bps'][0:-1] = sport_slot                                    # thêm 1 cột bps
    df = df.drop(df[df.src == df['src'][len(src)]].index)
    df = df.drop(df[((df.src < 3232301055) & (df.src > 3232235520)) | ((df.src < 2886795263) & (df.src > 2886729728)) | (
        (df.src < 184549375) & (df.src > 167772160))].index)  # | for or, & for and, và ~ cho not
    df = df.reset_index()
    df = df.drop('index', 1)                        # 1 la xoa cot, 0 la xoa hang

    ip_numbers = df['src'].unique().tolist()
    src = df['src'].to_numpy()
    bps = df['bps'].to_numpy()
    proto = df['proto'].to_numpy()

    df1 = df[df['proto'] == "1"]
    src1 = df1['src'].to_numpy()
    bps1 = df1['bps'].to_numpy()
    proto1 = df1['proto'].to_numpy()
    ip_numbers1 = df1['src'].unique().tolist()

    df6 = df[df['proto'] == "6"]
    src6 = df6['src'].to_numpy()
    bps6 = df6['bps'].to_numpy()
    proto6 = df6['proto'].to_numpy()
    ip_numbers6 = df6['src'].unique().tolist()

    df17 = df[df['proto'] == "17"]
    src17 = df17['src'].to_numpy()
    bps17 = df17['bps'].to_numpy()
    proto17 = df17['proto'].to_numpy()
    ip_numbers17 = df17['src'].unique().tolist()

    print("******")
    print(df1)
    print(df6)
    print(df17)

    fig,axes = plt.subplots(1,3,figsize=(12, 6))
    plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0.3, hspace=None)

    axes[0].scatter(src1, bps1)
    axes[0].set_xlabel("IP")
    axes[0].set_ylabel("Bytes/s")
    axes[0].set_title(name + " " + str(len(ip_numbers1)) + " IP-ICMP")

    axes[1].scatter(src6, bps6)
    axes[1].set_xlabel("IP")
    axes[1].set_ylabel("Bytes/s")
    axes[1].set_title(name + " " + str(len(ip_numbers6)) + " IP-TCP")

    axes[2].scatter(src17, bps17)
    axes[2].set_xlabel("IP")
    axes[2].set_ylabel("Bytes/s")
    axes[2].set_title(name + " " + str(len(ip_numbers17)) + " IP-UDP")

    nlarget = heapq.nlargest(5, bps)
    print("("+name+")"+"5 IP larget:")
    for i in range(len(nlarget)):
        print(df[df['bps'] == nlarget[i]])
    # plt.savefig("./figure/" + name + ".png")
    plt.show()

    # mal_ip=[]
    # mal_ip[:]=str(df[df['cluster name']==1].iloc[:]['ip'])
    # with open("D:/data_analyzis/malicious_ip.txt","w") as f:
    #     for i in mal_ip:
    #       # L=i+"\n"
    #       f.writelines(i)
    # print('completed!!')

print("End")


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

from FP import Maybe, List
from os_helpers import get_directories, get_files_from_root
from feature_helpers import extract_image_features, process_image, split_data, normalize_data, normalize_data_prediction, feature_reduction
from ml_helpers import save_data, load_data, experiment, train_model, save_model, load_model, predict_with_model
from lambdas import list_to_tuple, nothing_if_empty, is_not_none, split_to_tuple, add_reducer
from decorating import animated
import argparse
import time

#### Server

#from app import im2text_pb2, im2text_pb2_grpc

import im2text_pb2_grpc
import im2text_pb2

from concurrent import futures
import time
import grpc

_ONE_DAY_IN_SECONDS = 60 * 60 * 24

class Im2Text(im2text_pb2_grpc.Im2TxtServicer):

    def Run(self, request, context):
        fn = request.text

        res = 'unknown'
        try:
            res = predict([fn])[0]
        except Exception as e:
            print(e)

        return im2text_pb2.Im2TxtReply(text=str(res))

#### Emotion detection

# OPTIMIZATIONS TO BE DONE (hopefully)
# - Eliminate lambdas
# - Do more FP
# - Use keyword arguments

IMAGE_DIR = './images'
OLD_MODEL_PATH = './old_emotion_detector.pkl'
NEW_MODEL_PATH = './emotion_detector.pkl'
DATA_PATH = './data.pkl'
EMOTIONS = get_directories(IMAGE_DIR)

model = None

def accept_commands():
    data_arg, train_arg, predict_arg = parse_args()

    if data_arg is not None:
        generate_data(data_arg[0])

    elif train_arg is True:
        train()

    elif predict_arg is not None:
        print(predict(predict_arg))

def parse_args():
    parser = argparse.ArgumentParser(description='Emotion Detection Application')
    parser.add_argument('--train', action='store_true', help='start training the program to predict emotions')
    parser.add_argument('--data', nargs=1, help='process images from specified folder into usable data', metavar='path_to_training_folder')
    parser.add_argument('--predict', nargs='+', help='predict the emotion of face in image', metavar='path_to_input_image')
    args = parser.parse_args()
    unpacked_args = vars(args)
    data_arg = unpacked_args['data']
    train_arg = unpacked_args['train']
    predict_arg = unpacked_args['predict']

    return data_arg, train_arg, predict_arg

def generate_data(image_dir=IMAGE_DIR):
    return List.of(get_directories(image_dir)) \
        .chain(get_files_from_root(image_dir)) \
        .reduce(add_reducer) \
        .map(extract_image_features) \
        .reduce(split_data, ([], [])) \
        .map(normalize_data) \
        .map(feature_reduction(OLD_MODEL_PATH, True)) \
        .map(split_to_tuple) \
        .map(save_data) \
        .value

@animated
def train(data_dir=DATA_PATH):
    print("Training start...")

    Maybe.of(load_data()) \
        .map(experiment) \
        .map(train_model) \
        .map(save_model)

    print("Training complete.")

def predict(image_paths):
    print("Predicting...")
    print(image_paths)
    # get the time of a prediction

    t = time.process_time()
    preprocess = List(image_paths) \
        .map(process_image) \
        .filter(is_not_none) \
        .fold(nothing_if_empty) \
        .reduce(list_to_tuple, ())

    elapsed_time = time.process_time() - t
    print("Preprocessing time {}".format(elapsed_time))

    t = time.process_time()

    result = preprocess \
        .map(normalize_data_prediction) \
        .map(feature_reduction(OLD_MODEL_PATH)) \
        .map(predict_with_model(model)) \
        .map(get_emotions) \
        .value

    elapsed_time = time.process_time() - t
    print("Prediction time {}".format(elapsed_time))

    return result

# Remove DS Store from images: rm ./app/images/*/.DS_Store

def get_emotions(emotion_indices):
    return [EMOTIONS[index] for index in emotion_indices]

def init():
    """Sets up things we only need to do once"""
    print("Loaded model")
    global model
    model = load_model()

def serve():
    print("Serving started")
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    im2text_pb2_grpc.add_Im2TxtServicer_to_server(Im2Text(), server)
    server.add_insecure_port('[::]:50051')
    server.start()

    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        server.stop(0)

if __name__ == '__main__':
    init()
    accept_commands()
    print(model)
    serve()


from django.conf.urls import url

from .views import blog_list, create_blog, blog_detail, blog_delete

urlpatterns = [

    url(r'^list/', blog_list, name='list'),
    url(r'^create/', create_blog, name='create'),
    url(r'^detail/(?P<pk>\d+)$', blog_detail, name='detail'),
   # url(r'^update/(?P<pk>\d+)$', TweetUpdateView.as_view(), name='update'),
    url(r'^delete/(?P<pk>\d+)$',blog_delete, name='delete'),

]


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


import pandas as pd
from collections import Counter
import time
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
import os
import numpy as np

def binomial_distribution(data):
    numtails = pd.Series(data)
    hdata = pd.Series(Counter(numtails)).astype(int)
    plot = hdata.plot(kind='bar')
    plot.set_xlabel('')
    plot.set_ylabel('')
    plot.set_title('')
    fig = plot.get_figure()
    timestamp = int(time.time())
    output_file = str(timestamp) + ".png"
    fig.savefig( os.path.join(os.path.dirname(__file__), 'plots/' + output_file))
    plt.close()
    return output_file

def heat_capacity_of_solids(mcup, m1, T1, T2, Teq, m2):
    m = m1 - mcup
    M = m2 - m1
    c = 1.0
    delta_m = 2 * 0.05
    delta_T = 1
    C = ( M * c * ( T2 - Teq ) - m * c * ( Teq - T1 ) ) / ( Teq - T1 )
    p_1 = ( c * ( T2 - Teq ) + c * ( Teq - T1 ) ) * delta_m / ( Teq - T1 )
    p_2 = C
    p_3 = abs( ( T2 - Teq ) - ( Teq - T1) ) * 2 * M * c / (( Teq - T1 ) * ( Teq - T1 ))
    delta_C = p_1 + p_2 + p_3
    r_error = delta_C / C
    return {
        'M': round(M,2),
        'ccal': round(C,2),
        'abs_error': round(delta_C,2),
        'rel_error': '%'+str(round(r_error,2))
    }

def heat_capacity_of_multiple_materials(data, m, C):
    for key in data:
        heat_cap = calculate_heat_capacity_of_material(data[key], m, C)
        data[key]['c_material'] = heat_cap['c_material']
        data[key]['rel_error'] = heat_cap['rel_error']

    return data

def calculate_heat_capacity_of_material(material, m, C):
    c_material = ( ( float(material['Tf']) - float(material['T1']) ) * float(material['m_water']) ) + ( float(C) * ( float(material['Tf']) - float(material['T1']) ) ) / abs ( m * ( float(material['Tf']) - float(material['T1']) ) )
    rel_error = abs( float(material['c_real']) - c_material ) * 100.0 / float(material['c_real'])
    return {
        'c_material': round(c_material, 2),
        'rel_error': '%'+str(round(rel_error, 2))
    }

def latent_heat_of_water(m1, m2, T1, m3, T2):
    m1 = float(m1)
    m2 = float(m2)
    m3 = float(m3)
    T1 = float(T1)
    T2 = float(T2)
    m_water = m2 - m1
    m_ice = m3 - m2
    c_water = 1.0
    m_1c_c = 30.0
    Q_out = m_1c_c * ( T1 - T2 ) + m_water * c_water * ( T1 - T2 )
    # print "The heat (Qout) energy given off by the vessel+hot water equals to %f" %Q_out
    L = ( m_1c_c * ( T1 - T2 ) + m_water * c_water * ( T1 - T2 ) - m_ice * c_water * T2 ) / m_ice
    # print "The Latent heat for solid to liquid phase change of water is %f" %L
    L_literature = 80.0
    L_error = abs( L - L_literature ) * 100.0 / L_literature
    # print "The error percentage of L is  %  %f." %L_error
    return {
        'Q_out': round(Q_out, 2),
        'L': round(L, 2),
        'rel_error': '%'+str(round(L_error,2)),
        'm_water': round(m_water,2),
        'm_ice': round(m_ice,2)
    }

def thermal_expansion_coefficient(T1, L1, L2, L3, L4, L5, L6, L7, L8, a_real=0.000019):
    fig = plt.figure()
    ax = fig.add_subplot(111)
    x = [T1,25,30,40,50.,60,70,80]
    y = [0, L2, L3, L4, L5, L6, L7, L8]
    ax.plot(x, y)
    ax.set_xlabel('T2 (C)')
    ax.set_ylabel('dL (mm))')
    ax.set_title('The grapH of L with respect to T2')
    timestamp = int(time.time())
    output_file = str(timestamp) + ".png"
    fig.savefig( os.path.join(os.path.dirname(__file__), 'plots/' + output_file))
    slope, b = np.polyfit(x, y, 1) # y = slope*x+b
    a = slope/(L1)
    a_error=(abs(a_real-a)*100.0)/a_real
    plt.close()
    return {
        'a': a,
        'rel_error': '%'+str(round(a_error,2)),
        'fig': output_file,
        'slope': round(slope,4)
    }

# ideal gas law
def ideal_gas_plots(data):
    f, (ax1, ax2, ax3, ax4, ax5, ax6) = plt.subplots(6, sharex=True, sharey=True)
    ax1.plot( ideal_sub( **data['10'] )['x'], ideal_sub( **data['10'] )['y'], label="10 C" )
    ax1.set_title('The graph of P with respect to V')
    ax2.plot( ideal_sub( **data['20'])['x'], ideal_sub( **data['20'] )['y'], label="20 C" )
    ax3.plot( ideal_sub( **data['30'])['x'], ideal_sub( **data['30'] )['y'], label="30 C" )
    ax3.set_ylabel('P (cm-Hg)')
    ax4.plot( ideal_sub( **data['40'])['x'], ideal_sub( **data['40'] )['y'], label="40 C" )
    ax5.plot( ideal_sub( **data['50'])['x'], ideal_sub( **data['50'] )['y'], label="50 C" )
    ax6.plot( ideal_sub( **data['60'])['x'], ideal_sub( **data['60'] )['y'], label="60 C" )
    ax6.set_xlabel('V (cm3)')
    ax1.legend(loc='upper right', shadow=True)
    ax2.legend(loc='upper right', shadow=True)
    ax3.legend(loc='upper right', shadow=True)
    ax4.legend(loc='upper right', shadow=True)
    ax5.legend(loc='upper right', shadow=True)
    ax6.legend(loc='upper right', shadow=True)
    # Fine-tune figure; make subplots close to each other and hide x ticks for
    # all but bottom plot.
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    timestamp = time.time()
    output_file = str(timestamp) + ".png"
    plt.savefig( os.path.join(os.path.dirname(__file__), 'plots/' + output_file))
    plt.close()
    return output_file

def ideal_sub(V_1,V_2,V_3,V_4,V_5,P_1,P_2,P_3,P_4,P_5):
    return {
        'x': [V_1,V_2,V_3,V_4,V_5],
        'y': [P_1,P_2,P_3,P_4,P_5]
        }

def numberOfMol(P,V,T):
    t=T+273.15
    R=8.3145
    n=(P*V)/(R*t)
    return n

# joule thomson
def joule_thomson(V_1,V_2,V_3,V_4,V_5,V_6,V_7,V_8,V_9,V_10,V_11, gas):
    x = [100,90,80,70.,60,50,40,30,20,10,0]
    y = [V_1,V_2,V_3,V_4,V_5,V_6,V_7,V_8,V_9,V_10,V_11]
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(x, y)
    ax.set_xlabel('P (kPa))')
    ax.set_ylabel('T (K)')
    ax.set_title('The graph of T with respect to P for ' + gas)
    timestamp = time.time()
    output_file = str(timestamp) + ".png"
    fig.savefig( os.path.join(os.path.dirname(__file__), 'plots/' + output_file))
    mu , b = np.polyfit(x, y, 1)
    mu_real=7.16*(10**-6) if gas == 'CO2' else 3.75*(10**-6)
    mu_error=abs(mu_real-mu)*100.0/mu_real
    plt.close()
    return {
        'mu': round(mu,2),
        'rel_error': '%'+str(round(mu_error,2)),
        'fig': output_file
    }

# thermal conductivity
def thermal_conductivity_part_one(mcal,mw_mcup,twater,teq):
    m_water=mw_mcup-mcal
    c=1.0
    T_room=22.0
    ccal=m_water*c*(twater-teq)/(teq-T_room)
    return {
        'mhot': round(m_water,2),
        'ccal': round(ccal,2)
    }

def thermal_conductivity_part_two(data):
    dq = [0]
    dt = [] # for average dt
    for i in range(9):
        dt.append( data['dt_'+str(i+1)] )
        dq.append(
            (data['dt_'+str(i+2)] - data['dt_1']) * (data['mcold'] + data['ccal'])
        )

    t = [0,180,360,540,720,900,1080,1260,1440,1620]
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(t, dq)
    ax.set_xlabel('t (sn)')
    ax.set_ylabel('dQ (cal)')
    ax.set_title('The graph of dQ with respect to t')
    slope , b = np.polyfit(t, dq, 1)
    dx=31.5
    A=4.91
    K_calculated=6*(-(slope*dx)/(A*np.mean(dt)))
    K_literature=0.5 # (cal/sec)/(cm2 C/cm)
    K_error=abs(K_calculated-K_literature)*100.0/K_literature
    timestamp = time.time()
    output_file = str(timestamp) + ".png"
    fig.savefig( os.path.join(os.path.dirname(__file__), 'plots/' + output_file))
    plt.close()
    return {
        'K_calculated': round(K_calculated,2),
        'K_error': '%'+str(round(K_error,2)),
        'fig': output_file,
        'slope': round(slope,2)
    }

# # maxwellian
# from pylab import *
# import math
# import numpy as np

# def plotMaxwell(M,R,T,Vin,Fin):
#     Vmin=V.min()
#     Vmax=V.max()
#     Vout=np.linspace(Vmin,Vmax,100);
#     fout=4*pi(M/(2*pi*R*T))**(3/2)*math.exp(-M*Vout/(2*R*T));
#     fig=figure()
#     ax=fig.gca()
#     ax.set_xlabel("V")
#     ax.set_ylabel("F(V)")
#     ax.plot(Vout,fout)
#     ax.plot(Vin,Fin,'x')
#     #return V1D,f

# #example for function call
# # V=np.array([1, 2, 3.0,4.1,5.])
# # F=np.array([1.1,2.,3.4,3.99,4.65])
# # plotMaxwell(1.,1.,1.,V,F)