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

# Main program to interface with home automation through the Web and the serial port
# Javier Gonzalez 08/2015
# Migrated to Python 3 in 08/2016

import serial
import RPi.GPIO as GPIO
import time
import json

from flask import Flask, render_template, request, abort, redirect, url_for

app = Flask(__name__)
app.config.update(
    DEBUG=True,
    JSON_AS_ASCII=False
)

#DS1820
import os                       # import os module
import glob                     # import glob module
import time                     # import time module

from DhomoNet import *          # import dhomoNet protocol constants
# from dhomodb  import createdb   # import dhomoDB sqlite querys

#Define global variables

dhconfig = {}
packets = {}
msgnum = 0
hdevscan = {}
topmenu = []
setupactions = []
actions = []

#define global constants for pins
pins = {}
pinname = 0
pinstate = 1

#define global constants for SQL Querys to sqlite3
import sqlite3
from collections import OrderedDict

global dbhome, dbconn

appliances = OrderedDict()
selappliances = OrderedDict()
SQLAppliances = '''SELECT Appliance.* FROM Appliance ORDER BY ApplOrder'''

# devices = {DevID : 0 DevTag, 1 DevNotes, 2 DevOrder, 3 DevIconIdx, 4 DevNet, 5 DevNode, 6 LocID_Dev, 7 DevModelID_CP)}
devices = OrderedDict()
SQLDevices = '''SELECT Device.* FROM Device ORDER BY DevOrder'''

# devlocations : {LocID: (0 ZoneID, 1 ZoneTag, 2 LocTag, 3 LocOrder)}
devlocations = OrderedDict()
SQLLocations = '''SELECT LocID, ZoneID, ZoneTag, LocTag, LocOrder
    FROM Zone LEFT JOIN Location ON Zone.ZoneID = Location.ZoneID_Loc
    ORDER BY ZoneOrder, LocOrder'''

# devzones : {ZoneID: (0 HomeTag, 0 ZoneTag, 1 ZoneOrder)}
devzones = OrderedDict()
SQLZones = '''SELECT ZoneID, HomeID, HomeTag, ZoneTag, ZoneOrder
    FROM Zone
    ORDER BY HomeID, ZoneOrder'''

# applbylocation = {ApplID : (0 ZoneID, 1 ZoneTag, 2 LocID, 3 LocTag, 4 DevID, 5 DevTag, 6 ApplID, 7 ApplTag, 8 DevNet, 9 DevNode, 10 ApplObj, 11 ObjTypeID, 12 ObjTypeTag, 13 SubTypeID, 14 SubTypeTag)
applbylocation = OrderedDict()
SQLZUCA_OT = '''SELECT ApplID, ZoneID, ZoneTag, LocID, LocTag, DevID, DevTag, ApplID, ApplTag, DevNet, DevNode, ApplObj, ObjTypeID, ObjTypeTag, SubTypeID, SubtypeTag
FROM (((((Zone LEFT JOIN Location ON Zone.ZoneID = Location.ZoneID_Loc) LEFT JOIN Device ON Location.LocID = Device.LocID_Dev) LEFT JOIN Appliance ON Device.DevID = Appliance.DevID_Ap) LEFT JOIN  KObjs ON KObjs.ObjID = Appliance.ApplObj ) LEFT JOIN  KObjTypes ON KObjs.ObjTypeID_Ob = KObjTypes.ObjTypeID ) LEFT JOIN KObjSubTypes ON Appliance.SubTypeID_Ap = KObjSubTypes.SubTypeID
ORDER BY Zone.ZoneOrder, Location.LocOrder, KObjTypes.ObjTypeOrder, Device.DevOrder,  Appliance.ApplOrder'''

# SQLZUA = '''SELECT Zone.*, Location.*, Appliance.*
# FROM ((Zone LEFT JOIN Location ON Zone.ZoneID = Location.ZoneID_Loc) LEFT JOIN Appliance ON Location.LocID = Appliance.LocID_Ap)
# ORDER BY Zone.ZoneOrder, Location.LocOrder, Appliance.ApplOrder'''

def sql2orddict(conn, SQLquery):
    orddict = OrderedDict()
    cursor = conn.execute(SQLquery)
    for row in cursor:
        if row[0] is not None:          # Evita pasar elementos sin indice
            orddict[row[0]] = row[1:]   # Asigna 1a columna como indice y el resto como contenido (una tupla)
    return orddict

def testtime():
    tstart = time.clock()
    for i in range(1000):
        conn = sqlite3.connect(dbhome)
        conn.close
    tend = time.clock()
    print("Texec: {:4.2f} ms.".format((tend-tstart)*1000.0))

# ================================================================================================================================
# Initialize at global level

def initglobal():
    # No necesario en Python 3, por defecto es UTF-8
    # import sys
    # reload(sys)
    # sys.setdefaultencoding("utf-8")

    # Create a list of tuples called topmenu to store the options names
    global rootmenu
    rootmenu = [
        ('/home/topmenu/home'    ,  'Home'),
        ('/home/topmenu/action'  ,  'Action'),
        ('/home/topmenu/setupdb' ,  'Setup DB'),
        ('/home/topmenu/misc'    ,  'Misc')
    ]

    global actionmenu
    actionmenu = [
        ('/home/topmenu/home'           , 'Home'),
        ('/home/select/locations/all'   , 'Locations'),
        ('/home/select/locations/alive' , 'Alive Locs'),
        ('/home/select/appliances/all'  , 'Appliances')
    ]

    global setupdbmenu
    setupdbmenu = [
        ('/home/topmenu/home'        , 'Home'),
        ('/home/setup/listzones'     , 'Zones'),
        ('/home/setup/listlocations' , 'Locations'),
        ('/home/setup/listdevices'   , 'Devices'),
        ('/home/setup/listappliances', 'Appliances'),
        ('/home/setup/listZUCA'      , 'Appl by Arch')
    ]

    global miscmenu
    miscmenu = [
        ('/home/topmenu/home'       , 'Home'),
        ('/home/setup/savedevs'     , 'Save Devs'),
        ('/home/setup/loaddevs'     , 'Load Devs'),
        ('/home/setup/scannet'      , 'Scan NFeat'),
        ('/home/setup/scandevices'  , 'Scan Devs'),
        ('/etcpins'                 , 'RPi Pins')
    ]

    global statdomenu
    statdomenu = [
        ('/home/actions/stat'       , 'Stat')
    ]

    global lampdomenu
    lampdomenu = [
        ('/home/actions/on'         , 'On'),
        ('/home/actions/off'        , 'Off'),
        ('/home/actions/stat'       , 'Stat')
    ]

    global blinddomenu
    blinddomenu = [
        ('/home/actions/top'        , 'Top'),
        ('/home/actions/up'         , 'Up'),
        ('/home/actions/stop'       , 'Stop'),
        ('/home/actions/down'       , 'Down'),
        ('/home/actions/bottom'     , 'Bottom'),
        ('/home/actions/stat'       , 'Stat')
    ]

    global setupactions
    setupactions = [
        ('/home/topmenu/home'       , 'Home'),
        ('/home/topmenu/home'       , 'TBD'),
    ]

    # Sets the topmenu by default
    global topmenu
    topmenu = rootmenu

    # Initialize the Dictionaries from the sqlite database
    global dbhome, dbconn
    global appliances, devices, devzones, devlocations, applbylocation

    dbhome = "auroralite.db"    # Pendiente recuperarlo del fichero de configuración
    dbconn = sqlite3.connect(dbhome)
    devlocations = sql2orddict( dbconn, SQLLocations )
    devzones = sql2orddict( dbconn, SQLZones )
    appliances = sql2orddict( dbconn, SQLAppliances )
    devices = sql2orddict( dbconn, SQLDevices )
    applbylocation = sql2orddict( dbconn, SQLZUCA_OT )
    dbconn.close()

def initpins():
    # Initialize the GPIO port
    global pins

    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)     # Avoid Warning messages regarding that ports are in use.

    # Create a dictionary called pins to store the pin number, name, and pin state:
    pins = {
        8  : ['SPI CLR  08',GPIO.LOW],
    #    10 : ['SPI MOSI 10',GPIO.HIGH],
    #    11 : ['SPI CLK  11',GPIO.LOW],
    #    22 : ['test     22',GPIO.LOW],
    #    23 : ['coffee   23',GPIO.LOW],
        24 : ['lamp     24', GPIO.LOW],
        25 : ['blinds   25', GPIO.LOW]
        }

    # Set each pin as an output and set to the default state:
    for pin in pins:
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, pins[pin][pinstate])

    # Restore non clear status on SPI CLR pin
    GPIO.output(8, GPIO.HIGH)

# ================================================================================================================================
# Define the DS1820 functions

temp_avg = -100.0
global ds1820device_file

# def initds1820():
#     # Initialize the DS1820 temp sensor
#     global ds1820device_file
#     os.system('modprobe w1-gpio')                              # load one wire communication device kernel modules
#     os.system('modprobe w1-therm')
#     base_dir = '/sys/bus/w1/devices/'                          # point to the address
#     device_folder = glob.glob(base_dir + '28*')[0]             # find device with address starting from 28*
#     ds1820device_file = device_folder + '/w1_slave'                  # store the details

# def read_temp_raw():
#     global ds1820device_file

#     f = open(ds1820device_file, 'r')
#     lines = f.readlines()                                   # read the device details
#     f.close()
#     return lines

def read_temp():
#     global temp_avg
#     lines = read_temp_raw()
#     while lines[0].strip()[-3:] != 'YES':                   # ignore first line
#         time.sleep(0.2)
#         lines = read_temp_raw()
#     equals_pos = lines[1].find('t=')                        # find temperature in the details
#     if equals_pos != -1:
#         temp_string = lines[1][equals_pos + 2:]
#         if temp_avg != -100:
#             temp_avg = (3.0 * temp_avg + float(temp_string) / 1000.0) / 4.0
#         else:
#              temp_avg = float(temp_string) / 1000.0
#         temp_c = round(temp_avg, 1)
#         # return temp_c, temp_f
#         return temp_c
    return 0

# ================================================================================================================================
# Define the serial functions

#port = 'COM5'  # for PC
port = "/dev/ttyAMA0"   # for Raspberry Pi

# ================================================================================================================================
# Define the JSON functions to handle the config

def loadconfig( cfgfile ):          # Load the configuration file
    try:
        with open(cfgfile, 'r') as fconfig:
        # fconfig = open(cfgfile, 'r')
            print("Loading config for: ", fconfig.readline()) # Cuidado, que hay que leer la primera linea del archivo
            json_str = fconfig.readline()
            cfgdict = json.loads(json_str)
            # fconfig.close()
        return cfgdict
    except (UnboundLocalError, RuntimeError, FileNotFoundError):
        message = 'Oops! It sheems there is an invalid config file. No config loaded'

def saveconfig(cfgfile, cfgdict):  # Save the configuration file
    fconfig = open(cfgfile, 'w+')
    fconfig.write( "dhconfig{}:\n")
    jsondict = json.dumps( cfgdict )
    fconfig.write(jsondict)
    fconfig.close()

""" ================================================================================================================================
    Define the packet format functions to handle the config
"""

def format_sysfeat(hpackets):
    """Format the packets received (HomeAddr(), HomeCmd()) containing System Features to a readable format:
        Model, Hw version, Fw versions, Name, and Serial Naumber """
    hdevfeat = {}
    for devs in hpackets:
        netaddr = str(hpackets[devs][0])
        FeatCmd = hpackets[devs][1]
        numargs = len(FeatCmd.args)
        if numargs < 3:
            print("@format_sysfeat :: Error no args received from:", netaddr)
            netfeat = 'No device answered @' + netaddr
            # raise ValueError("Number of arguments must be less or equal to 16")
        else:
            netfeat =  'Model: {:s}, '.format(DN_MODELS[FeatCmd.args[0]])
            netfeat += 'Hw ver: 0x{:02x}, '.format(FeatCmd.args[1])
            netfeat += 'Fw ver: 0x{:02x}, '.format(FeatCmd.args[2])
            if numargs > 15:
                name = ''.join(chr(FeatCmd.args[c]) for c in range(3,11))
                netfeat += 'Name: ' + name + ', '
                netfeat += 'S/N: 0x{:02x}{:02x}{:02x}{:02x}, '.format(FeatCmd.args[14], FeatCmd.args[13], FeatCmd.args[12], FeatCmd.args[11])
            else:
                netfeat += 'Old version device'
        hdevfeat[netaddr] = [netaddr, netfeat]
    return hdevfeat

def format_pktargs_tostring(hpackets):
    """Format the packets received (HomeAddr(), HomeCmd()) in a readable format:
        net, node, haddrkey, devname
    """
    hdevfeat = {}
    for devs in hpackets:
        haddrkey = str(hpackets[devs][0])
        hnet = hpackets[devs][0].net
        hnode = hpackets[devs][0].node
        numargs = hpackets[devs][1].numargs
        args = hpackets[devs][1].args
        if numargs > 16:
            raise ValueError("Number of arguments must be less or equal to 16")
        if (args is not None) and (numargs != len(args)):
            #raise ValueError("len(args) must me equal to numargs")
            print('@format_pktargs_tostring :: ValueError("Error between the number of args and the args really availables")')
            outstring = '????'
        else:
            outstring = ''.join(chr(c) for c in args if(c>=0x20) and (c<0x80))     #It's ok, it's a string
            #ZZZZZ Only standar ASCII characters including punctuation marks.
        hdevfeat[haddrkey] = [hnet, hnode, haddrkey, outstring]
    return hdevfeat

def scan_net(hobj, hvar, numbytes):
    """ Scan the network sending a broadcast request for the names of the HomeNet devices
    Does a double scan to avoid missing devices due to collisions in the network

    Returns a dictionary with:
    - key:  the str representation of the address of the devices discovered
    - data: The net, node, key (again) , name of the device
    """
    allnet = HomeAddr( 0xff, 0xff, hobj)
    packets = dh_getpackets(allnet, DN_GET, hvar, numbytes)     # Scan all the alive devices and wait for response
    hdevscan = format_pktargs_tostring(packets)
    packets = dh_getpackets(allnet, DN_GET, hvar, numbytes)     # Rescan to incorporate missed devices by packet collisions
    hdevscan.update(format_pktargs_tostring(packets))   # Being a dictionay it will not appear duplicates
    print("hdevscan@scan_net: ", hdevscan)
    return hdevscan

# ================================================================================================================================
# Define the WebServer with Flask functions

# @app.route("/")
# def index():
#     pass

@app.route("/home")
def home():
    global topmenu

    topmenu = rootmenu
    return redirect('/home/select/locations/alive')

# The function below is executed when someone requests a URL with the pin number and option in it:
@app.route("/home/topmenu/<option>")
def menu(option):
    global topmenu
    try:
        if option == "home":
            topmenu = rootmenu
            return redirect('/home/select/locations/alive')
        elif option == "action":
            topmenu = actionmenu
            return redirect('/home/select/locations/alive')
        elif option == 'setupdb':
            topmenu = setupdbmenu
            return redirect('/home/setup/listlocations')
        elif option == "misc":
            topmenu = miscmenu
            return redirect('/home/setup/scannet')
        else:
            message = 'Oops! It sheems there is an invalid menu option'

    except (UnboundLocalError, RuntimeError):
        message = 'Oops! Catacrock : It sheems there is an invalid menu option'

    # Common return for error options
    templateData = {
        'topmenu' : topmenu,
        'message' : message
    }
    return render_template('maindhome.html', **templateData)

# The function below is executed when someone select a setup action:
@app.route("/home/select/<action>/<selitem>")
def select(action, selitem):
    global hdevscan
    global appliances, devices, devlocations, applbylocation
    global selappliances

    try:
        if action == 'locations':
            # devlocations : {LocID: (0 ZoneID, 1 ZoneTag, 2 LocTag, 3 LocOrder)}
            header = [False,  False, ('40%', 'Location')]
            if selitem == "all":
                oddev = devlocations
                message = 'Locations in database'
            else:   # Just the alive (by now)
                oddev = OrderedDict()
                message = 'Locations with alive Devices'
                hdevscan = scan_net( SIST_ID, NODENAME_ID, 8)
                for appldb in applbylocation: # Looking for appliances orderer by locations. 1st this dictionary to keep the order
                    # applbylocation = {ApplID : (0 ZoneID, 1 ZoneTag, 2 LocID, 3 LocTag, 4 DevID, 5 DevTag, 6 ApplID, 7 ApplTag, 8 DevNet, 9 DevNode, 10 ApplObj, 11 ObjTypeID, 12 ObjTypeTag, 13 SubTypeID, 14 SubTypeTag)
                    devnet = applbylocation[appldb][8]
                    devnode = applbylocation[appldb][9]
                    for hdev in hdevscan:
                        hnet = hdevscan[hdev][0]
                        hnode = hdevscan[hdev][1]
                        if (devnet == hnet) and (devnode == hnode):
                            oddev[applbylocation[appldb][2]] = devlocations[applbylocation[appldb][2]] # Takes the data form the "devlocations" Dictionary
                            break   # Skip to verify next appliance

            templateData = {
                'topmenu'   : topmenu, #actionmenu
                'message'   : message,
                'tblw'      : '35%',
                'numcol'    : len(header),
                'header'    : header,
                'keycol'    : 2,
                'odict'     : oddev,
                'handlerid' : 'select/appliances'
            }
            # Pass the template data into the template maindhome.html and return it to the user
            return render_template('select.html', **templateData)

        elif action == 'appliances':
            # applbylocation = {ApplID : (0 ZoneID, 1 ZoneTag, 2 LocID, 3 LocTag, 4 DevID, 5 DevTag, 6 ApplID, 7 ApplTag, 8 DevNet, 9 DevNode, 10 ApplObj, 11 ObjTypeID, 12 ObjTypeTag, 13 SubTypeID, 14 SubTypeTag)}

            header = [False, False, False, False, False, False, False, ('40%', 'Appliance'), False, False, False, False, False, False, False]

            if selitem == 'all':
                message = 'All the Appliances'
                odappl = applbylocation
            else:
                itemid = int(selitem)
                selappliances = OrderedDict()
                for appl in applbylocation:
                    if applbylocation[appl][2] == itemid:
                        selappliances[appl] = applbylocation[appl]

                odappl = selappliances
                message = 'Appliances @ {} : {}'.format(devlocations[itemid][2], devlocations[itemid][1])

            for appliance in odappl: #ZZZZZ  Esta verificacion deberia hacerse cuando se carga applbylocation
                if odappl[appliance][7] == None:
                    print("Hay un error en la appliance: ", odappl[appliance], "no tiene nombre")

            templateData = {
                'topmenu'   : topmenu, #actionmenu,
                'message'   : message,
                'tblw'      : '40%',
                'numcol'    : len(header),
                'header'    : header,
                'keycol'    : 7,
                'odict'     : odappl,
                'handlerid' : 'do/applbylocation'
            }
            return render_template('setup.html', **templateData)
        else:
            message = 'Oops! It sheems there is an invalid setup action'

    except (UnboundLocalError, RuntimeError):
        message = 'Oops! Catacrock : It sheems there is an invalid setup action'

    # Common return for error options
    templateData = {
        'topmenu' : topmenu,
        'message' : message
    }
    return render_template('setup.html', **templateData)

# The function below is executed when someone select a setup action:
@app.route("/home/setup/<action>")
def setup(action):
    global dhconfig
    global packets, hdevscan
    global appliances, devices, devlocations, devzones, applbylocation

    try:
        if action == 'savedevs':
            saveconfig( 'dhconfig.json', dhconfig)
            message = 'Devices saved OK'
            templateData = {
                'topmenu' : miscmenu,
                'message' : message
            }
            return render_template('setup.html', **templateData)

        elif action == 'loaddevs':
            dhconfig = loadconfig( 'dhconfig.json' )
            if dhconfig == None:
                message = 'Oops! It sheems there is an invalid config file. No config loaded'
            else:
                message = 'Devices loaded OK'
            templateData = {
                'topmenu' : miscmenu,
                'message' : message
            }
            return render_template('setup.html', **templateData)

        elif action == 'scannet':
            allnet = HomeAddr( 0xff, 0xff, SIST_ID)
            packets = dh_getpackets(allnet, DN_GET, MODEL_ID, 0x10)
            hfeatscan = format_sysfeat(packets)

            header = [('10%', 'Address (0x)'), ('50%', 'Device features')]
            templateData = {
                'topmenu'   : topmenu, #miscmenu,
                'message'   : 'Detected {} devices'.format(len(hfeatscan)),
                'tblw'      : '80%',
                'numcol'    : len(header),
                'header'    : header,
                'keycol'    : 0,
                'odict'     : hfeatscan,
                'handlerid' : 'setupdev'
            }
            return render_template('setup.html', **templateData)

        elif action == 'scandevices':
            hdevscan = scan_net( SIST_ID, NODENAME_ID, 8)

            header = [False, False, ('10%', 'Address (0x)'), ('20%', 'Name')]
            templateData = {
                'topmenu'   : topmenu, #miscmenu,
                'message'   : 'Detected {} devices'.format(len(hdevscan)),
                'tblw'      : '30%',
                'numcol'    : len(header),
                'header'    : header,
                'keycol'    : 2,
                'odict'     : hdevscan,
                'handlerid' : 'setupdev'
            }
            return render_template('setup.html', **templateData)

        elif action == 'listzones':
            # return redirect('/home/select/locations/all')
            # devzones : {ZoneID: (0 Home ID, 0 HomeTag, 1 ZoneTag, 2 ZoneOrder)}

            header = [False, False, ('60%', 'Zone'), False]
            templateData = {
                'topmenu'   : topmenu, #actionmenu
                'message'   : 'Zones in database',
                'tblw'      : '60%',
                'numcol'    : len(header),
                'header'    : header,
                'blockcol'  : 1,
                'keycol'    : 2,
                'odict'     : devzones,
                'handlerid' : 'doinput/devzones'
            }
            # Pass the template data into the template maindhome.html and return it to the user
            return render_template('inpselect_dragg.html', **templateData)

        elif action == 'listlocations':
            # return redirect('/home/select/locations/all')
            # devlocations : {LocID: (0 ZoneID, 1 ZoneTag, 2 LocTag, 3 LocOrder)}

            header = [False,  False, ('60%', 'Location'), False]
            templateData = {
                'topmenu'   : topmenu, #actionmenu
                'message'   : 'Locations in database',
                'tblw'      : '60%',
                'tbllft'    : '20%',
                'numcol'    : len(header),
                'header'    : header,
                'blockcol'  : 1,
                'keycol'    : 2,
                'odict'     : devlocations,
                'handlerid' : 'doinput/devlocations'
                # 'handlerid' : 'select/appliances'
            }
            # Pass the template data into the template maindhome.html and return it to the user
            return render_template('inpselect.html', **templateData)

        elif action == 'listappliances':
            # appliances {ApplID : ( 0 ApplTag, 1 ApplOrder, 2 ApplIconIdx, 3 ApplNet, 4 ApplNode, 5 ApplObj, 6 LocID_Ap, 7 DevID_Ap, 8 SubTypeID_Ap)}

            header = [('40%', 'Appliance'), False, ('10%', 'AppIcon'), ('5%', 'Net'), ('5%','Node'), ('5%', 'Obj'), False, ('10%','DevID'), False]
            templateData = {
                'topmenu'   : topmenu, #setupdbmenu,
                'message'   : 'Appliances in Database',
                'tblw'      : '75%',
                'numcol'    : len(header),
                'header'    : header,
                'keycol'    : 0,
                'odict'     : appliances,
                'handlerid' : 'do/applbylocation' #ZZZZZZCCCCC Pte cambio a manejador de DB de appliances
            }
            return render_template('setup.html', **templateData)

        elif action == 'listdevices':
            # devices = {DevID : 0 DevTag, 1 DevNotes, 2 DevOrder, 3 DevIconIdx, 4 DevNet, 5 DevNode, 6 LocID_Dev, 7 DevModelID_CP)}
            header = [('40%', 'Device'), False, False, False, ('5%', 'Net'), ('5%','Node'), False, ('5%', 'Model')]

            templateData = {
                'topmenu'   : topmenu, #setupdbmenu,
                'message'   : 'Devices in Database',
                'tblw'      : '55%',
                'numcol'    : len(header),
                'header'    : header,
                'keycol'    : 0,
                'odict'     : devices,
                'handlerid' : 'do/devices'
            }
            return render_template('setup.html', **templateData)

        elif action == 'listZUCA':
            # applbylocation = {ApplID : (0 ZoneID, 1 ZoneTag, 2 LocID, 3 LocTag, 4 DevID, 5 DevTag, 6 ApplID, 7 ApplTag, 8 DevNet, 9 DevNode, 10 ApplObj, 11 ObjTypeID, 12 ObjTypeTag, 13 SubTypeID, 14 SubTypeTag)}
            header = [False, ('15%', 'Zone'), False, ('15%', 'Location'), False, ('15%', 'Device'), False, ('40%', 'Appliance'), ('5%', 'Net'), ('5%','Node'), ('5%','Obj'), False, ('5%', 'Type'), False, ('5%', 'Model')]

            templateData = {
                'topmenu'   : topmenu, #setupdbmenu,
                'message'   : 'Devices by locations in Database',
                'tblw'      : '100%',
                'numcol'    : len(header),
                'header'    : header,
                'keycol'    : 7,
                'odict'     : applbylocation,
                'handlerid' : 'do/applbylocation'   # Pendiente de cambio a gestion DB de appliances
            }
            return render_template('setup.html', **templateData)
        else:
            message = 'Oops! It sheems there is an invalid setup action'

    except (UnboundLocalError, RuntimeError):
        message = 'Oops! Catacrock : It sheems there is an invalid setup action @/home/setup/' + action

    # Common return for error options
    templateData = {
        'topmenu' : topmenu,
        'message' : message
    }
    return render_template('setup.html', **templateData)

@app.route("/home/doinput/<queryid>/<int:itemid>", methods=['GET','POST'])
def input_post(queryid, itemid):
    global packets, hdevscan
    global dbhome, appliances, devices, devlocations, devzones, applbylocation

    info = ''
    try:
        if queryid == 'devlocations':
            if request.method == 'POST':
                location = request.form['inputbox']
                botonpress = request.form['button']
                # print( "location: ", location )
                # print( "itemid: ", itemid )
                # print( "boton:", botonpress )
                if botonpress == 'Ok':
                    conn = sqlite3.connect(dbhome)
                    conn.execute('UPDATE Location SET LocTag =? WHERE LocID =?', (location, itemid))
                    conn.commit()
                    devlocations = sql2orddict(conn, SQLLocations)
                    conn.close()
                    keyrow = None
                    info = 'Correctly updated Location: ' + location
                elif botonpress == '^':
                    locindex = list(devlocations.keys()).index(itemid)    # Get the position of the location
                    regnow = list(devlocations.items())[locindex]         # Get the whole register in that position
                    noworder = regnow[1][3]
                    upindex = locindex-1
                    #  print( "now:", locindex, regnow, itemid, noworder )
                    if upindex >= 0:                                # Checks no up before the first one
                        regup = list(devlocations.items())[upindex]
                        # print( "Zone:", regnow[1][0], regup[1][0] )
                        if (regnow[1][0] == regup[1][0]):           # Checks same Zones
                            upid = regup[0]
                            uporder = regup[1][3]
                            # print( "up:", upindex, regup, upid, uporder )
                            conn = sqlite3.connect(dbhome)
                            conn.execute('UPDATE Location SET LocOrder =? WHERE LocID =?', (uporder, itemid))
                            conn.execute('UPDATE Location SET LocOrder =? WHERE LocID =?', (noworder, upid))
                            conn.commit()
                            devlocations = sql2orddict(conn, SQLLocations)
                            conn.close()
                    keyrow = itemid
                elif botonpress == 'v':
                    locindex = list(devlocations.keys()).index(itemid)
                    regnow = list(devlocations.items())[locindex]
                    noworder = regnow[1][3]
                    # print( "now:", locindex, regnow, itemid, noworder )
                    downindex = locindex + 1
                    if (downindex < len(devlocations)):             # Checks no down past the last one
                        regdown = list(devlocations.items())[downindex]
                        # print( "Zone:", regnow[1][0], regdown[1][0] )
                        if (regnow[1][0] == regdown[1][0]):         # Checks same Zones
                            downid = regdown[0]
                            downorder = regdown[1][3]
                            # print( "down:", downindex, regdown, downid, downorder )
                            conn = sqlite3.connect(dbhome)
                            conn.execute('UPDATE Location SET LocOrder =? WHERE LocID =?', (downorder, itemid))
                            conn.execute('UPDATE Location SET LocOrder =? WHERE LocID =?', (noworder, downid))
                            conn.commit()
                            devlocations = sql2orddict(conn, SQLLocations)
                            conn.close
                    keyrow = itemid

                elif botonpress == 'x':
                    info = 'At work... here will handle de Locations deletion'
                    keyrow = None
                else:
                    pass
            else:
                print("Get----")
                keyrow = itemid

            header = [False,  False, ('60%', 'Location'), False]
            templateData = {
                'topmenu'   : topmenu, #actionmenu
                'message'   : 'Editing Locations in database',
                'info'      : info,
                'tblw'      : '60%',
                'numcol'    : len(header),
                'header'    : header,
                'blockcol'  : 1,
                'keycol'    : 2,
                'keyrow'    : keyrow,
                'odict'     : devlocations,
                'handlerid' : 'doinput/devlocations'
                # 'handlerid' : 'select/appliances'
            }
            # Pass the template data into the template maindhome.html and return it to the user
            return render_template('inpselect.html', **templateData)

        elif queryid == 'devzones':

            if request.method == 'POST':
                zone = request.form['inputbox']
                botonpress = request.form['button']
                if botonpress == 'Ok':
                    conn = sqlite3.connect(dbhome)
                    conn.execute('UPDATE Zone SET ZoneTag =? WHERE ZoneID =?', (zone, itemid))
                    conn.commit()
                    devzones = sql2orddict(conn, SQLZones)
                    conn.close()
                    keyrow = None
                    info = 'Correctly updated Zone: ' + zone
                elif botonpress == '^':
                    zoneindex = list(devzones.keys()).index(itemid)    # Get the position of the location
                    regnow = list(devzones.items())[zoneindex]         # Get the whole register in that position
                    noworder = regnow[1][3]
                    upindex = zoneindex-1
                    #  print( "now:", zoneindex, regnow, itemid, noworder )
                    if upindex >= 0:                                # Checks no up before the first one
                        regup = list(devzones.items())[upindex]
                        # print( "Zone:", regnow[1][0], regup[1][0] )
                        if (regnow[1][0] == regup[1][0]):           # Checks same Zones
                            upid = regup[0]
                            uporder = regup[1][3]
                            # print( "up:", upindex, regup, upid, uporder )
                            conn = sqlite3.connect(dbhome)
                            conn.execute('UPDATE Zone SET ZoneOrder =? WHERE ZoneID =?', (uporder, itemid))
                            conn.execute('UPDATE Zone SET ZoneOrder =? WHERE ZoneID =?', (noworder, upid))
                            conn.commit()
                            devzones = sql2orddict(conn, SQLZones)
                            conn.close()
                    keyrow = itemid

                elif botonpress == 'v':
                    zoneindex = list(devzones.keys()).index(itemid)
                    regnow = list(devzones.items())[zoneindex]
                    noworder = regnow[1][3]
                    # print( "now:", zoneindex, regnow, itemid, noworder )
                    downindex = zoneindex + 1
                    if (downindex < len(devzones)):             # Checks no down past the last one
                        regdown = list(devzones.items())[downindex]
                        # print( "Zone:", regnow[1][0], regdown[1][0] )
                        if (regnow[1][0] == regdown[1][0]):         # Checks same Zones
                            downid = regdown[0]
                            downorder = regdown[1][3]
                            # print( "down:", downindex, regdown, downid, downorder )
                            conn = sqlite3.connect(dbhome)
                            conn.execute('UPDATE Zone SET ZoneOrder =? WHERE ZoneID =?', (downorder, itemid))
                            conn.execute('UPDATE Zone SET ZoneOrder =? WHERE ZoneID =?', (noworder, downid))
                            conn.commit()
                            devzones = sql2orddict(conn, SQLZones)
                            conn.close
                    keyrow = itemid

                elif botonpress == 'x':
                    info = 'At work... here will handle de zones deletion'
                    keyrow = None
                else:
                    pass
            else:
                print("Get----")
                keyrow = itemid

            header = [False,  False, ('60%', 'Zone'), False]
            templateData = {
                'topmenu'   : topmenu, #actionmenu
                'message'   : 'Editing Zones in database',
                'info'      : info,
                'tblw'      : '60%',
                'numcol'    : len(header),
                'header'    : header,
                'blockcol'  : 1,
                'keycol'    : 2,
                'keyrow'    : keyrow,
                'odict'     : devzones,
                'handlerid' : 'doinput/devzones'
                # 'handlerid' : 'select/appliances'
            }
            # Pass the template data into the template maindhome.html and return it to the user
            return render_template('inpselect.html', **templateData)

        #ZZZZZZZZZ

        # elif action == 'listappliances':
        #     # record = {ApplID : ('0 LocID', '1 Appliance', '2 AppIcon', '3 AppOrder', '4 DevID', '5 Net', '6 Node', '7Obj', '8 Subtype')}
        #     header = [False, ('40%', 'Appliance'), ('10%', 'AppIcon'), False, ('10%','DevID'), ('5%', 'Net'), ('5%','Node'), ('5%', 'Obj'), False]
        #     templateData = {
        #         'topmenu'   : topmenu, #setupdbmenu,
        #         'message'   : 'Appliances in Database',
        #         'tblw'      : '100%',
        #         'numcol'    : len(header),
        #         'header'    : header,
        #         'keycol'    : 1,
        #         'odict'     : appliances,
        #         'handlerid' : 'do/appliances'
        #     }
        #     return render_template('setup.html', **templateData)

        # elif action == 'listdevices':
        #     # record = {DevID : ('0 LocID_CP' '1 Device Tag', '2 Order', '3 AppIcon', '4 Net', '5 Node', '6 DevModelID')}
        #     header = [False, ('40%', 'Device'), False, False, ('5%', 'Net'), ('5%','Node'), ('5%', 'Model')]

        #     templateData = {
        #         'topmenu'   : topmenu, #setupdbmenu,
        #         'message'   : 'Devices in Database',
        #         'tblw'      : '80%',
        #         'numcol'    : len(header),
        #         'header'    : header,
        #         'keycol'    : 1,
        #         'odict'     : devices,
        #         'handlerid' : 'do/devices'
        #     }
        #     return render_template('setup.html', **templateData)

        # elif action == 'listZUCA':
        #     # record = {ApplID : (ZoneID, ZoneTag, LocID, LocTag, DevID, LocID_CP, DevTag, DevOrder,DevIconIdx,DevNet,DevNode,DevModelID_CP,ApplID,LocID_Ap,ApplTag,ApplIconIdx,ApplOrder,DevID_Ap,ApplNet,ApplNode,ApplObj,SubTypeID_Ap)}
        #     header = [False, ('15%', 'Zone'), False, ('15%', 'Location'), False, False, ('40%', 'Device'), False, False, False, False, False, False, False, ('40%', 'Appliance'), False, False, False, ('5%', 'Net'), ('5%','Node'), ('5%','Obj'), ('5%', 'Model')]

        #     templateData = {
        #         'topmenu'   : topmenu, #setupdbmenu,
        #         'message'   : 'Devices by locations in Database',
        #         'tblw'      : '100%',
        #         'numcol'    : len(header),
        #         'header'    : header,
        #         'keycol'    : 14,
        #         'odict'     : applbylocation,
        #         'handlerid' : 'do/applbylocation'
        #     }
        #     return render_template('setup.html', **templateData)
        else:
            message = 'Oops! It sheems there is an invalid setup action'

    except (UnboundLocalError, RuntimeError):
        message = 'Oops! Catacrock : It sheems there is an invalid setup action'

    # Common return for error options
    templateData = {
        'topmenu' : topmenu,
        'message' : message
    }
    return render_template('setup.html', **templateData)

# The function below is executed when someone select a dbase setup action:
@app.route("/home/do/<queryid>/<int:itemid>")
def setupdbappl(queryid, itemid):
    global appliances, devices, devlocations, applbylocation

    # applchosen = [appl for appl in appliances if str(appl[0]) == itemid]
    if queryid == 'appliances':
        appl = appliances[itemid]
        HAappl = HomeAddr(appl[6], appl[7], appl[8])
        try:
            message = 'Appliance #: {}'.format(itemid)

        #   ZZZZZZZZCCCCCCC
            print()
            print('v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^')
            print()
            print()
            print()
            print('v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^')
            print()

            devstat = []
            devstat.append(('Description', '{:s}'.format(appl[1])))
            devstat.append(('Address', '{:s}'.format(HAappl)))
            lamplevel = dh_getvar( HAappl, LampXIntActID, 1)
            devstat.append(('Level', "{:3.0f}% [0x{:02x}]".format(lamplevel[0] / 2.55, lamplevel[0])))
            lampstat = dh_getvar( HAappl, LampXStatID, 1)
            devstat.append(('Stat', "[0x{:02x}]".format(lampstat[0])))
            lampmode = dh_getvar( HAappl, LampXModeID, 1)
            devstat.append(('Mode', "[0x{:02x}]".format(lampmode[0])))
            lampchlvl = dh_getvar( HAappl, LampXLvlChID, 1)
            devstat.append(('Ch Lvl', "[0x{:02x}]".format(lampchlvl[0])))
        except (UnboundLocalError, RuntimeError):
            message = 'Oops! Catacrock : It sheems there is an invalid setup action'

    elif queryid == 'applbylocation':
        return redirect('/home/actions/stat/' + str(itemid))

    elif queryid == 'devices':
        message = "Devices"
        devstat = []
    elif queryid == 'devlocations':
        message = 'Appliances at {} in {}'.format(devlocations[itemid][3], devlocations[itemid][1])
        devstat = []
    else:
        message = "No valid option"

    # Common return for load, save and error options
    templateData = {
        'topmenu'   : topmenu, #actionmenu,
        'message'   : message,
        'devstat'   : devstat,
        'dev'       : itemid,
        'queryid'   : queryid,
        'actions'   : actions
    }
    return render_template('setup_dev.html', **templateData)

# The function below is executed when someone select a setup action:
@app.route("/home/setupdev/<dev>")
def setupdev(dev):
    HAdev = HomeAddr(int(dev[:2], 16), int(dev[2:4], 16), int(dev[4:], 16))
    try:
        message = 'Device: {}'.format(dev)
        devstat = []
        devstat.append(('Device', '{:s}'.format(HAdev)))
        model = dh_getvar( HAdev, MODEL_ID, 1)
        devstat.append(('Model', DN_MODELS[model[0] & 0x07]))
        HWver = dh_getvar( HAdev, HWVER_ID, 1)
        devstat.append(('HW ver', '0x{:02x}'.format(HWver[0])))
        FWver = dh_getvar( HAdev, FWVER_ID, 1)
        devstat.append(('FW ver', '0x{:02x}'.format(FWver[0])))
        if FWver[0] > 0x30:
            name = dh_getvar( HAdev, NODENAME_ID, 8)
            devstat.append(('Dev Name', ''.join(chr(name[c]) for c in range(8))))
            serno = dh_getvar( HAdev, SERNUM_ID, 4)
            devsn = '{:02x}{:02x}{:02x}{:02x}'.format(serno[0], serno[1], serno[2], serno[3])
            devstat.append(('s/n', devsn))
        else:
            devstat.append(('Dev Name', '- (Old dev)'))
            devstat.append(('s/n', '- (Old dev)'))
    except (UnboundLocalError, RuntimeError):
        message = 'Oops! Catacrock : It sheems there is an invalid setup action'

    # Common return for load, save and error options
    templateData = {
        'topmenu'   : topmenu, #miscmenu,
        'message'   : message,
        'devstat'   : devstat,
        'dev'       : dev,
        'actions'   : actions
    }
    return render_template('setup_dev.html', **templateData)

@app.route("/home/actions/<action>/<int:applid>")
def actionhomedev(action, applid):
    # If the action part of the URL is "on" or "off" execute the code indented below:
    global appliances, applbylocation
    try:
        # applbylocation = {ApplID : (0 ZoneID, 1 ZoneTag, 2 LocID, 3 LocTag, 4 DevID, 5 DevTag, 6 ApplID, 7 ApplTag, 8 DevNet, 9 DevNode, 10 ApplObj, 11 ObjTypeID, 12 ObjTypeTag, 13 SubTypeID, 14 SubTypeTag)
        appl = applbylocation[applid]
        HAappl = HomeAddr(appl[8], appl[9], appl[10])
        message = '{} : {} : {}'.format(appl[7], appl[3], appl[1])
        feedback = ''
        appltype = appl[11]
        devstat = []
        devstat.append(('Description', '{:s}'.format(appl[7])))
        devstat.append(('Type', '{:s}'.format(appl[14])))
        devstat.append(('Address (0x)', str(HAappl)))

        #ZZZZZCCCCC

        domenu = statdomenu         # By default
        if( dh_getvar( HAappl, 0, 1)):                               # Test if the Dhomonet device is alive
            feedback = "Device seems to be alive"
            cmdresult = None

            if appltype == 9:       # LAMPS
                if action == 'on':
                    cmdresult = dh_do( HAappl, LAMP_ON )
                elif action == 'off':
                    cmdresult = dh_do( HAappl, LAMP_OFF )
                elif action == 'stat':
                    pass
                    # Not needed, next block will get the status of the lamp
                else:
                    feedback = "Oops!... Command not supported for this device"

                # Check the results of the previous actions
                if cmdresult:
                    feedback = "Command done"
                elif cmdresult is not None:
                    feedback = "Command error"

                # Always get the status of the lamp
                lamplevel = dh_getvar( HAappl, LampXIntActID, 1)    # Get the lamp level
                lampstat  = dh_getvar( HAappl, LampXStatID, 1)      # Get the lamp stat
                lampmode  = dh_getvar( HAappl, LampXModeID, 1)      # Get the lamp mode of work
                if(lamplevel and lampstat and lampmode):
                    devstat.append(('Level', "{:3.0f}% [0x{:02x}]".format(lamplevel[0] / 2.55, lamplevel[0])))
                    devstat.append(('Stat', "[0x{:02x}]".format(lampstat[0])))
                    devstat.append(('Mode', "[0x{:02x}]".format(lampmode[0])))
                    domenu = lampdomenu
                else:
                    feedback = "Something went wrong getting info from the lamp"

            elif appltype == 8:     # BLINDS
                if action == 'top':
                    cmdresult = dh_do( HAappl, PersXTabTopPID )
                elif action == 'up':
                    cmdresult = dh_do( HAappl, PersXNextTabUpPID )
                elif action == 'down':
                    cmdresult = dh_do( HAappl, PersXNextTabDnPID )
                elif action == 'bottom':
                    cmdresult = dh_do( HAappl, PersXTabBtmPID )
                elif action == 'stop':
                    cmdresult = dh_do( HAappl, PersXStopPID )
                elif action == 'stat':
                    pass
                    # blindpos = dh_getvar( HAappl, PersXPosActID, 1)
                else:
                    feedback = "Oops!... Command not supported for this device"

                # Check the results of the previous actions
                if cmdresult:
                    feedback = "Command done"
                elif cmdresult is not None:
                    feedback = "Command error"

                # Always get the position of the blind
                blindpos = dh_getvar( HAappl, PersXPosActID, 1)
                if(blindpos):
                    devstat.append(('Level', "{:3.0f} cm".format(blindpos[0] / 1.0)))
                    domenu = blinddomenu
                else:
                    feedback = "Something went wrong getting info from the blind"

            elif appltype == 3:     # Sensor digital de temperatura
                if action == 'stat':
                    pass
                rawtemp = dh_getvar( HAappl, TmpAvgID, 1)
                if rawtemp[0] < 0x80:
                    devstat.append(('Temp', "{:3.1f} ºC".format(rawtemp[0] / 2.0)))
                elif rawtemp[0] > 0x80:
                    devstat.append(('Temp', "{:3.1f} ºC".format((~rawtemp[0]+1) / -2.0)))
                else: #Just 0x80
                    devstat.append(('Temp', 'No device present'))
                domenu = statdomenu

            else:                   # Resto de dispositivos
                xxlevel = dh_getvar( HAappl, LampXIntActID, 1)
                devstat.append(('Level', "[0x{:02x}]".format(xxlevel[0])))
                domenu = statdomenu
        else:
            devstat.append(('Error', 'No DhomoNet device'))
            domenu = statdomenu
            feedback = "No DhomoNet device answering"
    except (UnboundLocalError, RuntimeError):
        feedback = 'Oops! Catacrock : It sheems there is an invalid appliance action'

    # Common return
    templateData = {
        'topmenu'   : topmenu, #actionmenu,
        'message'   : message,
        'feedback'  : feedback,
        'devstat'   : devstat,
        'dev'       : applid,
        'actions'   : domenu
    }
    return render_template('setup_dev.html', **templateData)

# etcpins functions for historical purposes --------------------------------------
@app.route("/etcpins")
def pinshome():
    global pinname, pinstate

    # For each pin, read the pin state and store it in the pins dictionary:
    for pin in pins:
        pins[pin][pinstate] = GPIO.input(pin)

    # Read the DS18B20 Temp sensor
    temp = str( read_temp())

    # Put the pin dictionary into the template data dictionary:
    templateData = {
        'topmenu' : topmenu,
        'message' : 'Wait for action',
        'pins' : pins,
        'temperature' : temp
        }
    # Pass the template data into the template maindhome.html and return it to the user
    return render_template('pinshome.html', **templateData)

# The function below is executed when someone requests a URL with the pin number and action in it:
@app.route("/pins/<changePin>/<action>")
def action(changePin, action):
    global pinname, pinstate
    # Convert the pin from the URL into an integer:
    changePin = int(changePin)
    # Get the device name for the pin being changed:
    deviceName = pins[changePin][pinname]
    # If the action part of the URL is "on," execute the code indented below:
    if action == "on":         # Set the pin high:
        GPIO.output(changePin, GPIO.HIGH)
        message = "Turned " + deviceName + " on."   # Save the status message to be passed into the template:
    if action == "off":
        GPIO.output(changePin, GPIO.LOW)
        message = "Turned " + deviceName + " off."
    if action == "toggle":      # Read the pin and set it to whatever it isn't (that is, toggle it):
        GPIO.output(changePin, not GPIO.input(changePin))
        message = "Toggled " + deviceName + "."

    # For each pin, read the pin state and store it in the pins dictionary:
    for pin in pins:
        pins[pin][pinstate] = GPIO.input(pin)

    # Read the DS18B20 Temp sensor
    temp = str( read_temp())

    # Along with the pin dictionary, put the message into the template data dictionary:
    templateData = {
        'topmenu' : topmenu,
        'message' : message,
        'pins' : pins,
        'temperature' : temp,
    }
    return render_template('pinshome.html', **templateData)

@app.route("/reorder", methods=['GET', 'POST'])
def saveorder():
    json = request.json
    print('>>>> Retornado draggable: ', json)

    return

# ================================================================================================================================
# main program

#Initialize the environment
initglobal()            # Create the global dictionaries for interface
init_dhcomms(port)      # Initialize the dhomonet protocol environment and open the serial port and send a Welcome message
initpins()              # Initialize the pins
# initds1820()            # Initialize the DS1820 Temperature sensor

#test_parse()          # Test the serial port with several patterns

# Load the configuration file
# dhconfig = loadconfig( 'dhconfig.json' )

# Initialize the Web server
if __name__ == "__main__":
    try:
        app.run(host='0.0.0.0', port=80, debug=True)

    except KeyboardInterrupt:
        # User pressed CTRL-C
        GPIO.cleanup()      # Reset GPIO settings
        close_dhcomms()     # Closes the serial port


from bs4 import BeautifulSoup
from selenium import webdriver
import time ##페이지가 열릴 때까지 기다려 주는 명령을 위해
import sys

query_txt = input('구글에 검색할 키워드는 무엇입니까?: ')
f_name = input('검색 결과를 저장할 파일경로와 이름을 지정하세요(예:c:\\data\\test.txt): ')

print(type(query_txt))
path = "C:\PythonSkill_Training\PythonSkill_Training\Crawling\chromedriver_win32\chromedriver.exe" # 셀레늄path
driver = webdriver.Chrome(path)
driver.get("https://www.google.co.kr")
time.sleep(2)
element = driver.find_element_by_name("q")
element.send_keys(query_txt)
time.sleep(2)
driver.find_element_by_xpath('//*[@id="tsf"]/div[2]/div[1]/div[2]/div[2]/div[2]/center/input[1]').click()

#######분석
time.sleep(1)
full_html = driver.page_source
soup = BeautifulSoup(full_html, 'html.parser')
content_list = soup.find('div',class_='srg')
#######
for i in content_list:
    print(i.text.strip())
    print("\n")

orig_stdout = sys.stdout
f = open(f_name , 'a' , encoding='UTF-8')
sys.stdout = f ##출력 방향을 윗줄로 바꿈
time.sleep(1)

html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
content_list = soup.find('div',class_='srg')

for i in content_list:
    print(i.text.strip())
    print("\n")

sys.stdout = orig_stdout
f.close()

print(" 요청하신 데이터 수집 작업이 정상적으로 완료되었습니다")


# -*- coding: utf-8 -*-
"""
Created on Sun Oct  8 05:52:26 2017

@author: Everton

    Monta análise estatística sobre um dataset
"""

import pandas as pd
import numpy as np
import util as util
import graficos as graficos
import algoritmos as algoritmos

from sklearn import preprocessing

import matplotlib.pyplot as plt
from scipy import stats, integrate
import seaborn as sns

#Importando e configurando classificador (DecisionTree)
from sklearn.tree import DecisionTreeClassifier
#Importando gerador de parametros otimizados
from sklearn.model_selection import GridSearchCV

pd.options.mode.chained_assignment = None

#--------------------------------------------------------------

disciplinas = {50404: 'Fund. Proc. Administrativo',
               60463: 'Ofic. Raciocínio Lógico',
               60465: 'Matemática Administração',
               60500: 'Lógica'}

"""
Configuração de filtros para o dataset
"""
disciplina = 60500
modulo = 6 #0 = ignora o módulo. Lembrando que só existem os módulos 3 e 6
#periodo_letivo = [20120101,20120201,20130101]
periodo_letivo = [20130201,20140101]

s_periodo = '[2012/01 a 2014/01]' if len(periodo_letivo) == 0 else str(periodo_letivo)
"""
"""

df = pd.read_csv('../dataset_m3_m6.csv', sep=';')

df = df.loc[:, (df != 0).any(axis=0)]

print('Total registros geral: ' + str(len(df)))

print('Análise disciplina: ' + disciplinas[disciplina] + ' / Módulo: ' + ('Todos' if modulo == '0' else str(modulo)))
print('Período: ' + s_periodo)

df_f = df

#Filta registros conforme os parâmetros
if (modulo == 0):
    df_f = df_f.loc[df_f['CodigoDisciplina'] == disciplina]

if (disciplina > 0):
    df_f = df_f.loc[(df_f['CodigoDisciplina'] == disciplina)]

if (len(periodo_letivo) > 0):
    df_f = df_f.loc[(df_f['PeriodoLetivo'].isin(periodo_letivo))]

df_f = df_f.reset_index(drop=True)

df_filter = util.clean_data(df_f, standardize=True, plot_cov=True, title='Matriz de Covariância - ' + disciplinas[disciplina] + ' / ' + s_periodo)

total_regs = len(df_filter)
total_sucesso = len(df_filter.loc[df_filter['Evadido'] == 1])
total_insucesso = len(df_filter.loc[df_filter['Evadido'] == 0])

print('\tTotal registros: ' + str(total_regs))
print('\tSucesso: %d / %.2f%%' % (total_sucesso, total_sucesso / total_regs * 100))
print('\tInsucesso: %d / %.2f%%' % (total_insucesso, total_insucesso / total_regs * 100))

target = df_filter.Evadido
features = df_filter[df_filter.columns.difference(['CodigoDisciplina','CodigoTurma','PeriodoLetivo','NumeroModulo','Evadido'])]

clf = DecisionTreeClassifier()
#ft = algoritmos.fit_features(clf, features, target)#, group_fold_column='CodigoTurma')

graficos.feature_importance(features, target, clf)

sns.distplot(df_filter.Evadido)


__author__ = 'sam.diefenbacher'

# CS - 125
# PigLatin.py
#
# This program converts english to pig latin

# Declare Magic Numbers and Constants

vowels = "aeiou"

# Write program code here

wordInput = input("Enter any English word to convert to PigLatin: ")
# Input word to convert
first = wordInput

first[0:1]
#defines what the first letter is
if first in vowels :
#checks to see if first letter is vowel
        print (wordInput + "yay")
else :
#if first letter is not vowel, then goes to here.
    print (wordInput.upper()[1] + wordInput[2:] + wordInput.lower()[0] + "ay")

# Input
#Enter any English word to convert to PigLatin: hello

#process
#Looks to see if word has vowel as fisrt letter, if not then converts

# Output
#ellohay


import json
import os
import math
import librosa

DATASET_PATH = "D:\Music_dataset\Genres"
JSON_PATH = "MusicData.json"
SAMPLE_RATE = 22050  # in hertz
TRACK_DURATION = 30  # measured in seconds
SAMPLES_PER_TRACK = SAMPLE_RATE * TRACK_DURATION

def save_mfcc(dataset_path, json_path, n_mfcc=13, n_fft=2048, hop_length=512, num_segments=5):

    """Extracts MFCCs from music dataset and saves them into a json file along with Genre labels.
        :param dataset_path (str): Path to dataset
        :param json_path (str): Path to json file used to save MFCCs
        :param n_mfcc (int): Number of coefficients to extract
        :param n_fft (int): Interval we consider to apply FFT(Fast Fourier Transform). Measured in #(number) of samples
        :param hop_length (int): Sliding window for FFT. Measured in # of samples
        :param num_segments (int): Number of segments we want to divide sample tracks into so that we have more data to train on
     """

    # dictionary to store Genre mapping, labels, and MFCCs
    data = {
        "genres": [],
        "labels": [],
        "mfcc": []
    }

    samples_per_segment = int(SAMPLES_PER_TRACK / num_segments)
    n_mfcc_vectors_per_segment = math.ceil(samples_per_segment / hop_length)

    # loop through all genre sub-folders
    for i, (dirpath, dirnames, filenames) in enumerate(os.walk(dataset_path)):

        if dirpath is not dataset_path:

            # save genre label (i.e., sub-folder name) in the Genre mapping
            semantic_label = dirpath.split("\\")[-1]
            data["genres"].append(semantic_label)
            print("\nProcessing: {}".format(semantic_label))

            # process all audio files in Genres sub-dir
            for f in filenames:

                # load audio file
                file_path = os.path.join(dirpath, f)
                signal, sample_rate = librosa.load(file_path, sr=SAMPLE_RATE)

                # process all segments of audio file
                for d in range(num_segments):

                    # calculate start and finish sample for current segment
                    start = samples_per_segment * d
                    finish = start + samples_per_segment

                    # extract mfcc
                    mfcc = librosa.feature.mfcc(signal[start:finish], sample_rate, n_mfcc=n_mfcc, n_fft=n_fft,
                                                hop_length=hop_length)
                    mfcc = mfcc.T # taking transpose of mfcc

                    # store only mfcc feature with expected number of vectors
                    if len(mfcc) == n_mfcc_vectors_per_segment:
                        data["mfcc"].append(mfcc.tolist())
                        data["labels"].append(i - 1)
                        print("{}, segment:{}".format(file_path, d + 1))

    # save MFCCs to json file
    with open(json_path, "w") as fp:
        json.dump(data, fp, indent=4)

if __name__ == "__main__":
    save_mfcc(DATASET_PATH, JSON_PATH, num_segments=10)


'''
3- Desenvolva uma lógica que leia o peso e a altura de uma pessoa, calcule seu Índice de Massa Corporal (IMC)
e mostre seu status de acordo com a tabela abaixo:
- IMC abaixo de 18,5: Abaixo do Peso
- IMC 18,5 até 25: Peso Ideal
- IMC 25 até 30: Sobrepeso
- IMC 30 até 40: Obesidade
- IMC acima de 40: Obesidade Mórbida

OBS: IMC = PESO/(ALTURA*ALTURA)
'''

from os import system

kg = float(input('Digite seu peso em Kg: '))
alt = float(input('Digite sua altura em metros: '))
imc = kg/(alt*alt)

system('cls')

print('Peso: {:.2f} Kg.\nAltura: {:.2f} m.\nSeu IMC é de: {:.2f}'.format(kg, alt, imc))

if imc<18.5:
	print('STATUS: Abaixo do Peso!')

elif imc>=18.5 and imc<25:
	print('STATUS: Peso Ideal!')

elif imc>=25 and imc<30:
	print('STATUS: Sobrepeso!')

elif imc>=30 and imc<40:
	print('STATUS: Obesidade!')

else:
	print('STATUS: Obesidade Mórbida!')


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

class shoe_data():

	def __init__(self):

		temp_data = pd.read_excel("2019 Winter Data Science Intern Challenge Data Set.xlsx")
		temp_data[["order_id", "shop_id", "user_id", "order_amount", "total_items"]] = temp_data[["order_id", "shop_id", "user_id", "order_amount", "total_items"]].apply(pd.to_numeric)
		temp_data["created_at"] = temp_data["created_at"].apply(pd.to_datetime)

		self.data = temp_data

	def get_data(self):
		return self.data

	def poor_aov(self):

		order_sum = self.data["order_amount"].sum()
		order_len = self.data.shape[0]

		aov = order_sum / order_len
		return round(aov, 2)

	def good_aov(self):

		order_sum = self.data["order_amount"].sum()
		item_sum = self.data["total_items"].sum()

		aov = order_sum / item_sum
		return round(aov, 2)

	def average_daily_items_sold(self):

		item_sum = self.data["total_items"].sum()
		start_date = self.data["created_at"].min()
		end_date = self.data["created_at"].max()
		date_range = (end_date - start_date).round("1d").days

		adt = item_sum / date_range
		return round(adt, 2)

	def average_daily_revenue(self):

		aov = self.good_aov()
		adt = self.average_daily_items_sold()

		adr = aov * adt
		return round(adr, 2)

	def plot_daily_items_sold(self):

		temp_data = self.data.copy()
		temp_data["created_at"] = temp_data["created_at"].dt.day

		daily_data = temp_data.groupby(["created_at"]).agg({"total_items": "sum"})
		adt = self.average_daily_items_sold()

		plt.plot(daily_data)
		plt.axhline(y=adt, color="r")
		plt.xlabel("Days during March, 2017")
		plt.ylabel("Number of Items Sold")
		plt.title("Daily Items Sold during March, 2017")
		plt.show()

	def plot_daily_revenue(self):

		temp_data = self.data.copy()
		temp_data["created_at"] = temp_data["created_at"].dt.day

		daily_data = temp_data.groupby(["created_at"]).agg({"order_amount": "sum"})
		adr = self.average_daily_revenue()

		plt.plot(daily_data)
		plt.axhline(y=adr, color="r")
		plt.xlabel("Days during March, 2017")
		plt.ylabel("Revenue ($)")
		plt.title("Revenue per Day during March, 2017")
		plt.show()

	def pivot_data(self):

		start_date = self.data["created_at"].min()
		end_date = self.data["created_at"].max()
		date_range = (end_date - start_date).round("1d").days

		new_data = self.data.groupby(["shop_id"], as_index=False).agg({"order_amount": "sum", "total_items": "sum", "user_id": "nunique"})
		new_data.rename(columns={"user_id": "user_count"}, inplace=True)

		new_data["AOV"] = new_data.apply(lambda row: round(row["order_amount"] / row["total_items"], 2), axis=1)
		new_data["ADT"] = new_data.apply(lambda row: round(row["total_items"] / date_range, 2), axis=1)
		new_data["ADR"] = new_data.apply(lambda row: round(row["AOV"] * row["ADT"], 2), axis=1)

		new_data.to_excel("2019 Winter Data Science Intern Challenge Data Set (Per Shop).xlsx", header=True, index=False)

def main():
	data = shoe_data()
	print(data.poor_aov())
	print(data.good_aov())
	print(data.average_daily_items_sold())
	print(data.average_daily_revenue())
	data.pivot_data()
	data.plot_daily_items_sold()
	data.plot_daily_revenue()

if __name__ == "__main__":
	main()


import json
import datetime

from MqttPublisher import MqttPublisher
from Log import Log
from LogRepository import LogRepository

mqtt_publisher = MqttPublisher("publisher")
mqtt_publisher.connect(1888)

class MqttMsgProcessing(object):

    @staticmethod
    def process_message(message, counter):
        tag_id = None
        msg_type = None
        msg_text = None
        try:
            print("Processing message...")
            msg_text = str(message.payload.decode("utf-8"))
            topic = message.topic.split('/')
            tag_id = topic[2]
            msg_type = topic[4]

            json_msg = json.loads(msg_text)
            json_msg['timestamp'] = datetime.datetime.now()
            json_msg['counter'] = counter

            if msg_type == "config":
                json_msg["zoneId"] = "zoneId"
                json_msg["panId"] = "panId"
                json_msg["active"] = True

            mqtt_publisher.publish(tag_id, topic[4], json.dumps(json_msg, default=str))
            f = open("backlog.txt", "a")
            f.write(tag_id + "," + topic[4] + "," +json.dumps(json_msg, default=str))
            f.write('\n')
            f.close()

            print("Processed.")
        except Exception as e:
            print("
Error: %s
" % str(e))
            try:
                log = Log(None, tag_id, msg_type, msg_text, e)
                repository = LogRepository()
                repository.create(log)
            except Exception as ex:
                print("
Error: %s
" % str(ex))


import feedparser
from models.models import Feed, Entry
from app import db

def entryPolling():
    feeds = Feed.query.all()

    for feed in feeds:
        d = feedparser.parse(feed.url)
        for entry in d.entries:
            checkEntryExistence(entry, feed)

    db.session.commit()

def checkEntryExistence(entry, feed):

    new_entry = Entry.query.filter(Entry.title.ilike(entry['title'])).first()

    if new_entry == None:
        addEntry(entry, feed)
    else:
        return True

def addEntry(entry, feed):

    new_entry = Entry(entry['title'], entry['link'], entry['description'], feed)
    db.session.add(new_entry)


import Nowack_Lab.Utilities.save
from importlib import reload
from Nowack_Lab.Utilities.save import Measurement
import matplotlib.pyplot as plt
import numpy as np
import scipy.optimize

plt.ion()
plt.show()

filenameprefix = r'/labshare/data/spruce/experiments/2017-06-10_10mk_scans/2017-06-15/'
#thisfile = r'2017-06-15_041403_VibrationTest'
firstfile  = r'2017-06-15_031930_VibrationTest'
secondfile = r'2017-06-15_034641_VibrationTest'
filename1  = filenameprefix + firstfile
filename2  = filenameprefix + secondfile

vb = Measurement.load(filename1)
vb2 = Measurement.load(filename2)

PU_LOOP_SIZE = 30 # volts, 6 um / (.2 um/V)

PU_LOOP_POS = {
        'on feature'    : 216,
        'off feature'   : 116,
        'falling edge'  : 190,
        'rising edge'   : 242
        }
PU_PLOT_HEIGHT = {
        'on feature'    : -6,
        'off feature'   : 3,
        'falling edge'  : 2,
        'rising edge'   : 2
        }
F_LIN = lambda x, m, b: x*m + b

PHI0_PER_V_MED = 1/1.44;
V_PER_UM_PIEZO = 5;
V_PER_UM_Z     = .14
GAIN           = 25

PHI0_PER_UM_Z  = {};

## DC plot
fig_dc,ax_dc = plt.subplots()

ax_dc.plot(vb.X[1]/V_PER_UM_PIEZO, vb.V['dc'][1]*PHI0_PER_V_MED/GAIN,
        marker='o', markersize=1, linestyle='',
        label='dc')

ax_dc.plot(vb.X[1]/V_PER_UM_PIEZO, vb2.V['dc'][1]*PHI0_PER_V_MED/GAIN,
        marker='o', markersize=1, linestyle='',
        label='dc 2')

ax_dc.plot(vb.X[1]/V_PER_UM_PIEZO,
        (vb2.V['dc'][1] - vb.V['dc'][1])*PHI0_PER_V_MED/GAIN,
        marker='o', markersize=1, linestyle='',
        label='dc 2 - dc')

plt.legend(loc='lower right', prop={'size':6})

dz = np.mean(vb2.Z[1] - vb.Z[1])

for key in PU_LOOP_POS.keys():
    x_range = np.linspace(PU_LOOP_POS[key] - PU_LOOP_SIZE/2,
                          PU_LOOP_POS[key] + PU_LOOP_SIZE/2,
                          100)
    index_s = np.argmin(np.abs(x_range[ 0]-vb.X[1]))
    index_f = np.argmin(np.abs(x_range[-1]-vb.X[1]))
    xs      =  vb.X[1]      [index_s:index_f+1]/V_PER_UM_PIEZO
    ys      =  vb.V['dc'][1][index_s:index_f+1]*PHI0_PER_V_MED/GAIN
    ys2     = vb2.V['dc'][1][index_s:index_f+1]*PHI0_PER_V_MED/GAIN
    dphi     = ys2-ys
    PHI0_PER_UM_Z[key] = dphi/dz

## original spectrum plots

fig_orig, ax_orig = plt.subplots(4,1,sharex=True, sharey=True)
ax_orig[0].semilogy(vb.spectrum_off_f,
        vb.spectrum_off_psdave*PHI0_PER_V_MED,
        marker='o', markersize=1, linestyle='')
ax_orig[0].semilogy(vb2.spectrum_off_f,
        vb2.spectrum_off_psdave*PHI0_PER_V_MED,
        marker='o', markersize=1, linestyle='')
ax_orig[0].annotate('Off feature', xy=(.02,.9),
             xycoords='axes fraction', fontsize=8, ha='left', va='top',
             family='monospace')
ax_orig[1].semilogy(vb.spectrum_onf_f,
        vb.spectrum_onf_psdave*PHI0_PER_V_MED,
        marker='o', markersize=1, linestyle='')
ax_orig[1].semilogy(vb2.spectrum_onf_f,
        vb2.spectrum_onf_psdave*PHI0_PER_V_MED,
        marker='o', markersize=1, linestyle='')
ax_orig[1].annotate('On feature', xy=(.02,.9),
             xycoords='axes fraction', fontsize=8, ha='left', va='top',
             family='monospace')
ax_orig[2].semilogy(vb.spectrum_red_f,
        vb.spectrum_red_psdave*PHI0_PER_V_MED,
        marker='o', markersize=1, linestyle='')
ax_orig[2].semilogy(vb2.spectrum_red_f,
        vb2.spectrum_red_psdave*PHI0_PER_V_MED,
        marker='o', markersize=1, linestyle='')
ax_orig[2].annotate('Rising edge', xy=(.02,.9),
             xycoords='axes fraction', fontsize=8, ha='left', va='top',
             family='monospace')
ax_orig[3].semilogy(vb.spectrum_fed_f,
        vb.spectrum_fed_psdave*PHI0_PER_V_MED,
        marker='o', markersize=1, linestyle='')
ax_orig[3].semilogy(vb2.spectrum_fed_f,
        vb2.spectrum_fed_psdave*PHI0_PER_V_MED,
        marker='o', markersize=1, linestyle='')
ax_orig[3].annotate('Falling edge', xy=(.02,.9),
             xycoords='axes fraction', fontsize=8, ha='left', va='top',
             family='monospace')
ax_orig[0].set_xlim([0,1e3])
ax_orig[0].set_ylim([1e-6,1e-3])

for ax in ax_orig:
    ax.set_xlabel(r'$f$ (Hz)')
    ax.set_ylabel(r'PSD ($\phi_0$)')

## vibration original spectra in um

fig_orig_vib, ax_orig_vib = plt.subplots(4,1,sharex=True)
ax_orig_vib[0].semilogy(
        vb.spectrum_off_f,
        vb.spectrum_off_psdave*PHI0_PER_V_MED/
            abs(PHI0_PER_UM_Z['off feature'][0]),
        marker='o', markersize=1, linestyle='')
ax_orig_vib[0].annotate(
            r'Off feature, $\phi_0$/um={0:2.2e}'.format(
                abs(PHI0_PER_UM_Z['off feature'][0]),
            ),
            xy=(.02,.9),
             xycoords='axes fraction', fontsize=8, ha='left', va='top',
             family='monospace')
ax_orig_vib[1].semilogy(
        vb.spectrum_onf_f,
        vb.spectrum_onf_psdave*PHI0_PER_V_MED/
            abs(PHI0_PER_UM_Z['on feature'][0]),
        marker='o', markersize=1, linestyle='')
ax_orig_vib[1].annotate(
            r'On feature, $\phi_0$/um={0:2.2e}'.format(
                abs(PHI0_PER_UM_Z['on feature'][0]),
            ),
            xy=(.02,.9),
             xycoords='axes fraction', fontsize=8, ha='left', va='top',
             family='monospace')
ax_orig_vib[2].semilogy(vb.spectrum_red_f,
        vb.spectrum_red_psdave*PHI0_PER_V_MED/
            abs(PHI0_PER_UM_Z['rising edge'][0]),
        marker='o', markersize=1, linestyle='')
ax_orig_vib[2].annotate(
            r'Rising Edge, $\phi_0$/um={0:2.2e}'.format(
                abs(PHI0_PER_UM_Z['rising edge'][0]),
            ),
            xy=(.02,.9),
             xycoords='axes fraction', fontsize=8, ha='left', va='top',
             family='monospace')
ax_orig_vib[3].semilogy(vb.spectrum_fed_f,
        vb.spectrum_fed_psdave*PHI0_PER_V_MED/
            abs(PHI0_PER_UM_Z['falling edge'][0]),
        marker='o', markersize=1, linestyle='')
ax_orig_vib[3].annotate(
            r'Falling edge, $\phi_0$/um={0:2.2e}'.format(
                abs(PHI0_PER_UM_Z['falling edge'][0]),
            ),
            xy=(.02,.9),
             xycoords='axes fraction', fontsize=8, ha='left', va='top',
             family='monospace')
ax_orig_vib[0].set_xlim([0,1e3])

ax_orig_vib[3].set_xlabel(r'$f$ (Hz)')
for ax in ax_orig_vib:
    ax.set_ylabel(r'PSD ($\mu m$)')


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

from scipy.stats import norm

inp_dict = {}
with open('../Data/ASSimilarityFileRiskMetricincrease_risk.json') as f:
    inp_dict = json.load(f)

rep_ASes = list(inp_dict.keys())

#extract values to plot
values = []
for AS in rep_ASes:
    values.append(list(inp_dict[AS].values()))

f = plt.figure()

for i,value in enumerate(values):
    sorted_values = sorted(value)
    cum_sum = np.cumsum(sorted_values)
    cum_sum = cum_sum/max(cum_sum)
    legend_title = "Cluster " + str(i+1)
    plt.plot(sorted_values,cum_sum, label = legend_title)

# plt.legend(loc='upper left')
plt.xlabel('Risk')
plt.ylabel('Cumulative Distribution')
plt.title('Cumulative distribution of risk within each cluster')
plt.show()
f.savefig("../Plots/risk_CDF_plot_09012019.png", bbox_inches='tight')


# Given two integers n and k, return all possible combinations of k numbers out of 1 ... n.

# Example:

# Input: n = 4, k = 2
# Output:
# [
#   [2,4],
#   [3,4],
#   [2,3],
#   [1,2],
#   [1,3],
#   [1,4],
# ]

# The number of k-combinations from a given set S of n elements is often denoted by C(n,k) -> C(n choose k)
# time complexity = O(C(n,k) * k) = O((n!/(k! * (n - k)!)) * k)
# Since, each time when we get a combination, we need copy patht to result, which is O(k), there is C(n, k) * k.
def combinations(n, k):
	result = []
	arr = []
	for i in range(1, n + 1):
		arr.append(i)

	dfs(0, arr, [], k, result)
	return result

def dfs(start, arr, path, k, result):
	if k == 0:
		result.append(path[:])
		return

	elif k > 0:
		for i in range(start, len(arr)):
			path.append(arr[i])
			dfs(i + 1, arr, path, k - 1, result)
			path.pop()

print(combinations(4, 2))


import os
import unittest

import torch
import torch.distributed as dist
from torch.multiprocessing import Process
import torch.nn as nn

from machina.optims import DistributedSGD

def init_processes(rank, world_size,
                   function, backend='tcp'):
    os.environ['MASTER_ADDR'] = '127.0.0.1'
    os.environ['MASTER_PORT'] = '29500'
    dist.init_process_group(backend, rank=rank,
                            world_size=world_size)
    function(rank, world_size)

class TestDistributedSGD(unittest.TestCase):

    def test_step(self):

        def _run(rank, world_size):
            model = nn.Linear(10, 1)
            optimizer = DistributedSGD(
                model.parameters())

            optimizer.zero_grad()
            loss = model(torch.ones(10).float())
            loss.backward()
            optimizer.step()

        processes = []
        world_size = 4
        for rank in range(world_size):
            p = Process(target=init_processes,
                        args=(rank,
                              world_size,
                              _run))
            p.start()
            processes.append(p)
        for p in processes:
            p.join()


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

# Copyright (c) 2014, Joshua Stone
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

__all__ = [
    "sort"
]

class Sort(object):
    def __init__(self):
        for method in self.methods:
            setattr(self, method.upper(), method)

    @property
    def methods(self):
        sorting_methods = {
            "created_at",
            "updated_at",
            "first_seen_at",
            "score",
            "wilson",
            "relevance",
            "height",
            "width",
            "comments",
            "tag_count",
            "random"
        }

        return sorting_methods

sort = Sort()


from ControlParameters import *
from CommandIndex import *
from collections import deque

# =============================================================================
# === Dequeue and ML Functions ================================================
# =============================================================================

def extractQueue(queue):
    modelInput = []
    for moment in queue:
        modelInput += moment
    return(modelInput)

def feedModel(modelInput):
    # feeds list of features to model and returns decision
    return()

def outputUI(result):
    # sort provide ordered UI list to model
    return()

def extractOrderlist(queue):
    modelInput = extractQueue(queue)
    result = feedModel(modelInput)
    outputUI(result)
    return()

# =============================================================================
# === Read ExoDataScript ======================================================
# =============================================================================

EXODATA_RATE = 100      # seconds to discrete time = 100 samples a second
FIRST_DELAY = 10        # seconds: first exit transition state delay
STATIONARY_DELAY = 5    # seconds: loop in stationary intent  delay
#TRANSITION_DELAY = 3   # if we need to optimise computation

tick = 0
firstDelay = (10 - RECORD_TIME)*EXODATA_RATE
stationaryDelay = (5 - RECORD_TIME)*EXODATA_RATE

MAX_Q_LENGTH = RECORD_TIME*100*SAMPLE_RATE/100
queue = deque(maxlen=MAX_Q_LENGTH)
exoReading = [0,0,0]
inStationary = False

while(True):
    # queue automatically pops data
    # investigate how to do sampling (i.e. ignore certain features)
    queue.appendleft(exoReading)

    # left transition state
    if ~inStationary and exoReading[ID_CURRSTATE] in STATIONARY_STATES:
        extractOrderlist(queue)
        inStationary = True
        tick = 0
        while tick < FIRST_DELAY:
            tick += 1

    # loop readings in stationary
    if inStationary:
        tick +=1
        if tick >= STATIONARY_DELAY:
            extractOrderlist(queue)
            tick = 0

    if exoReading[ID_CURRSTATE] in TRANSITION_STATES:
        inStationary = False


#!/usr/bin/env python3.7

"""
    could be expanded
    and robustified to include
    more connection options
    such as https
"""

import argparse
from io import BytesIO
import pycurl

def pycurl_get():

    """
        just a simple pycurl get
        to aide in troubleshooting
        basic RDS (or potentially
        other AWS service) instances
    """

    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--target',
                        help='curl host or address target',
                        type=str, required=True)
    parser.add_argument('-p', '--port',
                        help="target host's port",
                        type=str, required=True)
    args = parser.parse_args()

    host_target_url_and_port = f"{args.target}:{args.port}"
    buffer = BytesIO()
    c = pycurl.Curl()
    c.setopt(c.VERBOSE, True)
    c.setopt(c.URL, host_target_url_and_port)
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()

    body = buffer.getvalue()

    # from pycurl docs:
    # Body is a byte string.
    # We have to know the encoding in order to print it to a text file
    # such as standard output.

    print(body.decode('iso-8859-1'))

pycurl_get()


import torch
import torch.nn as nn
import torchvision.transforms as transforms
from torch.utils.data import DataLoader, Dataset

class ImgDataset(Dataset):

    def __init__(self, x, y=None, transform=None):
        self.x = x
        # label is required to be a LongTensor
        self.y = y
        if y is not None:
            self.y = torch.LongTensor(y)
        self.transform = transform

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

    def __getitem__(self, index):
        X = self.x[index]
        if self.transform is not None:
            X = self.transform(X)
        if self.y is not None:
            Y = self.y[index]
            return X, Y
        else:
            return X


#
# Copyright (C) 2020 Pico Technology Ltd. See LICENSE file for terms.
#
# PS6000 A STREAMING MODE EXAMPLE
# This example opens a 6000a driver device, sets up one channel then collects a streamed set of data.
# This data is then plotted as mV against time in ns.

import ctypes
# import numpy as np
from picosdk.ps6000a import ps6000a as ps
from picosdk.PicoDeviceEnums import picoEnum as enums
from picosdk.PicoDeviceStructs import picoStruct as structs
import matplotlib.pyplot as plt
from picosdk.functions import adc2mV, assert_pico_ok
from picosdk.constants import PICO_STATUS
import time

# Create chandle and status ready for use
chandle = ctypes.c_int16()
status = {}

# Open 6000 A series PicoScope
# returns handle to chandle for use in future API functions
resolution = enums.PICO_DEVICE_RESOLUTION["PICO_DR_8BIT"]
status["openunit"] = ps.ps6000aOpenUnit(ctypes.byref(chandle), None, resolution)
assert_pico_ok(status["openunit"])

# Set channel A on
# handle = chandle
channelA = enums.PICO_CHANNEL["PICO_CHANNEL_A"]
coupling = enums.PICO_COUPLING["PICO_DC"]
channelRange = 7
# analogueOffset = 0 V
bandwidth = enums.PICO_BANDWIDTH_LIMITER["PICO_BW_FULL"]
status["setChannelA"] = ps.ps6000aSetChannelOn(chandle, channelA, coupling, channelRange, 0, bandwidth)
assert_pico_ok(status["setChannelA"])

# set channel B-H off
for x in range(1, 7, 1):
    channel = x
    status["setChannel", x] = ps.ps6000aSetChannelOff(chandle, channel)
    assert_pico_ok(status["setChannel", x])

# Set number of samples to be collected
noOfPreTriggerSamples = 100000
noOfPostTriggerSamples = 900000
nSamples = noOfPostTriggerSamples + noOfPreTriggerSamples

# Set simple trigger on channel A, 1 V rising with 1 s autotrigger
# handle = chandle
# enable = 1
source = channelA
# threshold = 1000 mV
direction = enums.PICO_THRESHOLD_DIRECTION["PICO_RISING"]
# delay = 0 s
# autoTriggerMicroSeconds = 1000000 us
status["setSimpleTrigger"] = ps.ps6000aSetSimpleTrigger(chandle, 1, source, 1000, direction, 0, 1000000)
assert_pico_ok(status["setSimpleTrigger"])

# create buffers
maxBuffers = 10

bufferA = ((ctypes.c_int16 * nSamples) * 10)()

print(bufferA)
# Set data buffers
# handle = chandle
# channel = channelA
# bufferMax = bufferAMax
# bufferMin = bufferAMin
# nSamples = nSamples
dataType = enums.PICO_DATA_TYPE["PICO_INT16_T"]
waveform = 0
downSampleMode = enums.PICO_RATIO_MODE["PICO_RATIO_MODE_RAW"]
clear = enums.PICO_ACTION["PICO_CLEAR_ALL"]
add = enums.PICO_ACTION["PICO_ADD"]
action = clear | add  # PICO_ACTION["PICO_CLEAR_WAVEFORM_CLEAR_ALL"] | PICO_ACTION["PICO_ADD"]
status["setDataBuffers"] = ps.ps6000aSetDataBuffer(chandle, channelA, ctypes.byref(bufferA[0]), nSamples, dataType,
                                                   waveform, downSampleMode, action)
assert_pico_ok(status["setDataBuffers"])

# Run streaming
sampleInterval = ctypes.c_double(1)
sampleIntervalTimeUnits = enums.PICO_TIME_UNITS["PICO_US"]
autoStop = 0
downSampleRatio = 1

status["runStreaming"] = ps.ps6000aRunStreaming(chandle, ctypes.byref(sampleInterval), sampleIntervalTimeUnits,
                                                noOfPreTriggerSamples, noOfPostTriggerSamples, autoStop,
                                                downSampleRatio, downSampleMode)
assert_pico_ok(status["runStreaming"])

streamData = structs.PICO_STREAMING_DATA_INFO(channelA, downSampleRatio, dataType, 0, 0, 0, 0)

streamTrigger = structs.PICO_STREAMING_DATA_TRIGGER_INFO(0, 0, 0)

count = 1

actionB = add

picoOk = PICO_STATUS["PICO_OK"]

while count <= maxBuffers:

    status["getStreamingLatestValues"] = ps.ps6000aGetStreamingLatestValues(chandle, ctypes.byref(streamData), 1,
                                                                            ctypes.byref(streamTrigger))

    if status["getStreamingLatestValues"] == picoOk:
        # do nothing
        time.sleep(0.01)
    else:
        count = count + 1
        if count <= maxBuffers:
            status["setDataBuffer"] = ps.ps6000aSetDataBuffer(chandle, channelA, ctypes.byref(bufferA[count - 1]),
                                                              nSamples, dataType, waveform, downSampleMode, actionB)
            assert_pico_ok(status["setDataBuffer"])
            print(count)

print("streaming finished")

# get max ADC value
# handle = chandle
minADC = ctypes.c_int16()
maxADC = ctypes.c_int16()
status["getAdcLimits"] = ps.ps6000aGetAdcLimits(chandle, resolution, ctypes.byref(minADC), ctypes.byref(maxADC))
assert_pico_ok(status["getAdcLimits"])

# convert ADC counts data to mV
bufferAmV = ((ctypes.c_int16 * nSamples) * 10)()
for j in range(0, 9):
    A = bufferA[j]
    bufferAmV[j] = adc2mV(A, channelRange, maxADC)

# Close the scope
status["closeunit"] = ps.ps6000aCloseUnit(chandle)
assert_pico_ok(status["closeunit"])

print(status)


# Lab Exercise 6
'''
We want the user to input their gender, however if it doesn’t follow the correct format then ask them to
try again, and show the input option again.
'''

gender = " "

while gender != "m" or gender != "M" or gender != "f" or gender != "F":
    gender = input("\nPlease enter your gender in this format (m, M, f, F): ")
    if gender == "m" or gender == "M":
        print("you're male.")
        break
    elif gender == "f" or gender == "F":
        print("You're a Female")
        break
input("\npress the enter key to exit.")


from django.shortcuts import render
from .models import Product
from .models import AAA
# Create your views here.
from django.http import HttpResponseRedirect
from django.urls import reverse

def index(request):
    object_list = Product.objects.all()
    if("busca" in request.GET):
        object_list = object_list.filter(name__icontains=request.GET["busca"])
    return render(request, 'product/product.html', {'objetos':object_list})

def add(request):
    if request.POST:
        logo = request.FILES['image']
        description = request.POST['description']
        name = request.POST['name']
        value = request.POST['value']
        athletic = AAA.objects.get(id=1)
        product = Product.objects.create(name = name, image = logo, value= value, description = description,athletic= athletic )
        product.save()
        return HttpResponseRedirect(reverse('product:index'))
    return render(request, 'product/add.html')

def edit(request, id):
    if request.POST:
        description = request.POST['description']
        name = request.POST['name']
        value = request.POST['value']
        product = Product.objects.get(id =id)
        product.name = name
        product.description = description
        product.value = value
        product.save()
        return HttpResponseRedirect(reverse('product:index'))
    return render(request, 'product/edit.html', {'objeto':Product.objects.get(id=id)} )

def delete(request, id):
    product = Product.objects.get(id=id)
    product.delete()
    return HttpResponseRedirect(reverse('product:index'))

def views_product(request,id):
    product = Product.objects.get(id=id)
    res = {
        'objeto':product
    }
    return render(request,'product/product_detail.html',res)


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

# In[ ]:

import pandas as pd
df = pd.read_csv("C:/Users/PC/Downloads/archivos_base_python_data_science_big_data_esencial/base_datos_2008.csv",nrows=1e6)

#Un millon de elementos

# In[ ]:

dfduplicate = df.append(df)

# In[ ]:

dfduplicate = dfduplicate.sample(frac = 1)

# In[ ]:

dfclean = dfduplicate.drop_duplicates()

# In[ ]:

len(dfclean) == len(df)

# In[ ]:

dfclean.drop_duplicates(subset = "DayOfMonth")

# In[ ]:

df.dropna()

# In[ ]:

df.dropna(thresh = 25)

# In[ ]:

df.dropna(thresh = len(df.columns)-2)

# In[ ]:

df.dropna(subset = ["CancellationCode"])

# In[ ]:


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

import pyaudio
import wave
import matplotlib.pyplot as plt
import numpy as np

def read_wav(file_name):
    ''' Read one channel wav file as float data (-1~1) '''

    wf = wave.open(file_name, 'rb')
    params = wf.getparams()
    nchannels, sampwidth, framerate, nframes = params[:4]
    raw = wf.readframes(nframes)
    speech = np.frombuffer(raw, dtype=np.short)/32768

    print('[Info]')
    print('Sampling rate:', framerate, 'Hz')
    print('Duration:', len(speech)/framerate, 'sec')
    print('Channel:', nchannels)

    return speech.astype(np.float32), framerate

def play_raw(speech, fs):
    ''' Play audio raw data '''

    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paFloat32, channels=1, rate=fs, output=True)
    stream.write(speech.tostring())
    stream.stop_stream()
    stream.close()
    p.terminate()

''' Main '''

# 讀取音檔
file_name = 'sample2.wav'
speech, fs = read_wav(file_name)

# 後處理

speech = speech*3     # 變大聲
#speech = speech*0.2   # 變小聲
#fs = 8000             # 變慢
#fs = 16000            # 變快
fs = 128000
# 繪製波型
plt.figure(figsize=(10, 5))
plt.plot(speech)
plt.title(file_name)
plt.xlabel('samples')
plt.ylabel('amplitude')
plt.show()

# 播放音檔
play_raw(speech, fs)


#!/usr/bin/python3
import argparse
from argparse import RawTextHelpFormatter
from routines.data_loader_uuv import dataLoader, testDataLoader
from routines.icad import ICAD
import os
from routines.martingales import RPM, SMM, PIM
import matplotlib.pyplot as plt
from routines.ICP import ICP

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Choose different modes for inductive anomaly detection.', formatter_class=RawTextHelpFormatter)
    parser.add_argument("-t","--trajectory",help="anomaly detection based on the time trajectories", action="store_true")
    parser.add_argument("-o","--obstacle",help="choose the obstacle avoidance dataset", action="store_true")
    parser.add_argument("-p","--path", help="test data path")

    args = parser.parse_args()
    data_loader = dataLoader(args.trajectory, args.obstacle)
    (X_train, Y_train), (X_calibration, Y_calibration) = data_loader.load()
    icp = ICP(X_train, Y_train, X_calibration, Y_calibration, 20)
    data = testDataLoader(os.path.abspath(args.path), args.obstacle)
    cw_heading_list = []
    cw_speed_list = []
    for i in range(len(data)):
        if data[i][0] == None:
            cw_heading_list.append(None)
            cw_speed_list.append(None)
        else:
            action_normalized90, _, _, _ = icp.evaluate(data[i])
            cw_heading_list.append(1.0/action_normalized90[0])
            cw_speed_list.append(1.0/action_normalized90[1])

    g3 = plt.figure(3)
    plt.plot(cw_heading_list,'g')
    plt.ylim([0,30])
    plt.xlabel("Time(S)")
    plt.ylabel("1/Confidence Width for Heading Change (Obstacle)")
    g4 = plt.figure(4)
    plt.plot(cw_speed_list, 'g')
    plt.ylim([0,110])
    plt.xlabel("Time(S)")
    plt.ylabel("1/Confidence Width for Speed (Obstacle)")
    plt.show()


# This is a plugin created by iouonegirl(@gmail.com)
# Copyright (c) 2016 iouonegirl
# https://github.com/dsverdlo/minqlx-plugins
#
# You are free to modify this plugin to your custom,
# except for the version command related code.
#
# Original idea from <roasticle>, but edited to support
# a list of sounds which will be played one by one after each match.
#
# Place the sounds files in a PK3 file and upload it to a workshop.
#
# If you have trouble hearing the music, I heard Mino's
# workshop.py plugin helps.

import minqlx
import time
import requests

VERSION = "v0.10"

# These songs will be looped one by one. Don't forget to remove the #'s if you want to use songs
SONGS = [
    #"sound/songname/songtitle.ogg",
    #"sound/songname/songtitle.ogg",
    #"sound/songname/songtitle.ogg",
]

class intermission(minqlx.Plugin):
    def __init__(self):
        self.index = 0

        self.add_hook("game_end", self.handle_game_end)
        self.add_hook("player_connect", self.handle_player_connect)
        self.add_command("v_intermission", self.cmd_version)

    @minqlx.delay(0.3)
    def handle_game_end(self, *args, **kwargs):

        # If there are no songs defined, return
        if not SONGS: return

        # If last time the index was incremented too high, loop around
        if self.index == len(SONGS):
            self.index = 0

        # Try to play sound file
        try:
            self.play_sound(SONGS[self.index])
        except Exception as e:
            self.msg("^1Error: ^7{}".format(e))

        # Increase the counter so next round the next sound will be played
        self.index += 1

    def handle_player_connect(self, player):
        if self.db.has_permission(player, 5):
            self.check_version(player=player)

    def cmd_version(self, player, msg, channel):
        self.check_version(channel=channel)

    @minqlx.thread
    def check_version(self, player=None, channel=None):
        url = "https://raw.githubusercontent.com/dsverdlo/minqlx-plugins/master/{}.py".format(self.__class__.__name__)
        res = requests.get(url)
        last_status = res.status_code
        if res.status_code != requests.codes.ok: return
        for line in res.iter_lines():
            if line.startswith(b'VERSION'):
                line = line.replace(b'VERSION = ', b'')
                line = line.replace(b'"', b'')
                # If called manually and outdated
                if channel and VERSION.encode() != line:
                    channel.reply("^7Currently using ^3iou^7one^4girl^7's ^6{}^7 plugin ^1outdated^7 version ^6{}^7.".format(self.__class__.__name__, VERSION))
                # If called manually and alright
                elif channel and VERSION.encode() == line:
                    channel.reply("^7Currently using ^3iou^7one^4girl^7's latest ^6{}^7 plugin version ^6{}^7.".format(self.__class__.__name__, VERSION))
                # If routine check and it's not alright.
                elif player and VERSION.encode() != line:
                    time.sleep(15)
                    try:
                        player.tell("^3Plugin update alert^7:^6 {}^7's latest version is ^6{}^7 and you're using ^6{}^7!".format(self.__class__.__name__, line.decode(), VERSION))
                    except Exception as e: minqlx.console_command("echo {}".format(e))
                return