"""Upload the contents of your Downloads folder to Dropbox.

This is an example app for API v2.
"""

#test comment here

from __future__ import print_function

import argparse
import contextlib
import datetime
import os
import six
import sys
import time
import unicodedata
import zipfile
import datetime
import string
import filecmp
import exifread
import json

if sys.version.startswith('2'):
    input = raw_input

parser = argparse.ArgumentParser(description='Compare two directories to see which files are common and which are missing')
parser.add_argument('sourcedir', nargs='?', default='~/',
                    help='Local directory to compare from')

parser.add_argument('destdir', nargs='?', default='~/',
                    help='Local directory to compare to')

def main():
    """Main program.
    """
    args = parser.parse_args()
    sourcedir = os.path.expanduser(args.sourcedir)
    destdir = os.path.expanduser(args.destdir)

    if not os.path.exists(sourcedir):
        print(sourcedir, 'does not exist on your filesystem')
        sys.exit(1)
    elif not os.path.isdir(sourcedir):
        print(sourcedir, 'is not a foldder on your filesystem')
        sys.exit(1)

    if not os.path.exists(destdir):
        print(destdir, 'does not exist on your filesystem')
        sys.exit(1)
    elif not os.path.isdir(destdir):
        print(destdir, 'is not a foldder on your filesystem')
        sys.exit(1)

    print('*************************************************************')

    #    sourcedir='/dataf/Pictures/'
    #    destdir='/datag/Takeout/'
    print('Local source directory:', sourcedir)
    print('Local dest   directory:', destdir)

    print('*************************************************************')

    #    dictionary_of_name_to_time_from_sourcedir = create_dictionary_of_jpg_fullfilename_and_time(sourcedir)
    #    keylist=dictionary_of_name_to_time_from_sourcedir.keys()
    #    keylist.sort()
    #    for x in keylist:
    #        print(x +" => " + dictionary_of_name_to_time_from_sourcedir[x])

#    dict1 = read_dictionary_from_json_file('rnlist.json')
#    dict2 = read_dictionary_from_json_file('gdlist.json')
#    dict3 = read_dictionary_from_json_file('tolist.json')

    lista = create_list_of_all_file_and_foldernames(sourcedir)
    list1 = create_list_of_all_filenames(sourcedir)
    list2 = create_list_of_all_nonfilenames(sourcedir)
    list3 = create_list_of_all_non_jpg_filenames(sourcedir)
    list4 = create_list_of_all_jpg_filenames(sourcedir)

    list3.sort()

    count_filetypes_in_list_of_files(list3)

#    for fname in list3:
#        print(fname)
        #print('-----------------------')

    missing_file_list=[]
    time_match_only_file_dictionary={}

    quit()

    keylist=dict1.keys()
    keylist.sort()
    for x in keylist:
        #print(x +" => " + dict1[x])
        if not find_match_for_file_xyz_in_dict_xyz(x,dict1[x],dict2):
            missing_file_list.append(x)

        # find file in dict1 in dict2

#    for dn, dirs, files in os.walk(sourcedir):
        # dn is directory name we are inside of (inside root directory)
        # subfolder= the dn we are in now, striped of rootdir prefactor
        # files is a list of file in dn
#        subfolder = dn[len(sourcedir):].strip(os.path.sep)
#        if not subfolder.startswith('.'):# First do all the files. Only if subfolder is not prefaced by a dot.
#            for name in sorted(files): # files = all files in dn; fullname, name - file we are working on now
#                if not name.startswith('.'):
#                    fullname = os.path.join(dn, name)
#                    if is_this_file_a_jpg_image(fullname): # only proceed if its an image file
#                        if not find_match_for_file_xyz_in_dir_abc(fullname,destdir,time_match_only_file_dictionary): # call compare for this file
#                            missing_file_list.append(fullname)

    print('DONE DONE DONE')

#    print('Missing files:')

#    missing_file_list.sort()

#    for missing_file in missing_file_list:
#        print(missing_file)

    print('Number of missing files = ',len(missing_file_list))

#    print('time_match_only_file_dictionary:')

    #    for this_key in time_match_only_file_dictionary.keys()
    #        print time_match_only_file_dictionary[this_key]

#    klist=time_match_only_file_dictionary.keys()
 #   klist.sort()

  #  for entry in klist:
   #     print(entry,time_match_only_file_dictionary[entry])

#   print(str(time_match_only_file_dictionary))

#    print('lenght of time_match_only_file_dictionary',len(time_match_only_file_dictionary))

    print('generated by ', __file__, ' on ',str(datetime.datetime.now()))

def find_match_for_file_xyz_in_dir_abc(filename_to_search,dir_to_search,time_match_only_file_dictionary):

    print('----------------------------------------------------------------')
    print('Searching for ',filename_to_search,' inside of ',dir_to_search)

    match=False
    for dn, dirs, files in os.walk(dir_to_search):
        if match==True:
            break
        # dn is directory name we are inside of (inside root directory)
        # subfolder= the dn we are in now, striped of rootdir prefactor
        # files is a list of file in dn
        subfolder = dn[len(dir_to_search):].strip(os.path.sep)
        # print('Descending into', dn, '...')

        for name in files: # files = all files in dn; fullname, name - file we are working on now
            if not (name.startswith('.') and match==True): # First do all the files. Only if subfolder is not prefaced by a dot.
                fullname = os.path.join(dn, name)

                # trying to compare two files: fullname to filename_to_search

                #print('calling comparepix on ',fullname,' to ', filename_to_search)
                # if fullname is a picture, compare date of picture:
                if is_this_file_a_jpg_image(fullname):
                    if are_these_the_same_picture(fullname,filename_to_search):
                        #print("they are the same by time")
                        if not filecmp.cmp(fullname,filename_to_search):
                            print('Time match only! between ',fullname, ' and ', filename_to_search)
                            time_match_only_file_dictionary[fullname]=filename_to_search
                            match=True

                #print('calling filecmp.cmp on ',fullname,' to ', filename_to_search)
                if filecmp.cmp(fullname,filename_to_search):
                    print('Match! between ',name, ' and ', filename_to_search)
                    match=True
                    #break

                # print(fullname,' is NOT EQUAL to ', filename_to_search)

    #if match==False:
     #   print('no match found for ',filename_to_search )
    # print('-------------------------------------------------------')

    return match

def find_match_for_file_xyz_in_dict_xyz(filename_to_search,filetime_to_search,dict_to_search):
    # PB 6/3/2016 Searches in dictionary to see if (filename,filetime) combo exists with same time.

    #print('----------------------------------------------------------------')
    #print('Searching for ',filename_to_search,' inside of dictionary')

    match=False
    # loop through all the files in dictionary to search
    keylist=dict_to_search.keys()
    keylist.sort()
    for dict_to_search_filename in keylist:
        dict_to_search_time=dict_to_search[dict_to_search_filename]
        if dict_to_search_time == filetime_to_search:
            #print('Match: ', filename_to_search,filetime_to_search,dict_to_search_filename,dict_to_search_time)
            match=True

    if match==False:
        print('no match found for ',filename_to_search )
    #print('-------------------------------------------------------')

    return match

def is_this_file_a_jpg_image(filename):

    result = False

#    print("Is this a jpg image?")
#    print(filename,len(filename))
    if ( filename.endswith('.jpg') or filename.endswith('.JPG') ):
        result=True
        #print("yes!")

#    print(filename,filename[len(filename)-3,len(filename)])

#    if filename[len(filename)-3,len(filename)]=='jpg':
#        result=True

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

    #if match==False:
     #   print('no match found for ',filename_to_search )
    # print('-------------------------------------------------------')

    return result

def are_these_the_same_picture(picturefilename1,picturefilename2):

    result = False

    #imagedatetimetag='Image DateTime'
    imagedatetimetag='EXIF DateTimeOriginal'
    imagesubsectag='EXIF SubSecTimeOriginal'

    #print("getting datetime for file ", picturefilename1)
    f1 = open(picturefilename1, 'rb') # Open image file for reading (binary mode)
    tags1 = exifread.process_file(f1) # Return Exif tags
    f1.close()

    if imagedatetimetag in tags1.keys():
        f1datetime=tags1[imagedatetimetag]
    else:
        return False

#    print(tags1.keys())

    if imagesubsectag in tags1.keys():
        f1subsectime=tags1[imagesubsectag]
    else:
        f1subsectime=0

    #print("f1datetime = ",f1datetime)

    #print("getting datetime for file ", picturefilename2)
    f2 = open(picturefilename2, 'rb') # Open image file for reading (binary mode)
    tags2 = exifread.process_file(f2) # Return Exif tags
    f2.close()

    if imagedatetimetag in tags2.keys():
        f2datetime=tags2[imagedatetimetag]
    else:
        return False

    if imagesubsectag in tags2.keys():
        f2subsectime=tags2[imagesubsectag]
    else:
        f2subsectime=0

    #print("f2datetime = ",f2datetime)

    if (imagedatetimetag in tags1.keys()) & (imagedatetimetag in tags2.keys()) : # subsec present
        if (str(f1datetime) == str(f2datetime)) & (str(f1subsectime)==str(f2subsectime)):
            result=True
    else:
        if str(f1datetime) == str(f2datetime):
            result=True
        #print("f1datetime==f2datetime")

    return result

def dump_exif_date(filename_to_dump):

    print('+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')
    # Open image file for reading (binary mode)
    f = open(filename_to_dump, 'rb')

    # Return Exif tags
    tags = exifread.process_file(f)

    for tag in tags.keys():
        if tag not in ('JPEGThumbnail', 'TIFFThumbnail', 'Filename', 'EXIF MakerNote'):
            print("Key: %s, value %s" % (tag, tags[tag]))

    f.close()
    print('+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++')

def create_dictionary_of_jpg_fullfilename_and_time(dir_to_search):
    # PJB 6/1/2016 Creates dictionary of all files in directory that are jpg images.
    # Full filename is key
    # Entry is the time the image was taken.
    startTime = time.time()
    jpg_fullfilename_to_time_dict ={}

    print('----------------------------------------------------------------')
    print('Searching inside of ',dir_to_search)

    match=False
    for dn, dirs, files in os.walk(dir_to_search):
        # dn is directory name we are inside of (inside root directory)
        timestamp = time.time()
        value = datetime.datetime.fromtimestamp(timestamp)
        # print('We are inside of directory ', dn,' at time ',value.strftime('%Y-%m-%d %H:%M:%S'))

        # subfolder= the dn we are in now, striped of rootdir prefactor
        # files is a list of file in dn
        subfolder = dn[len(dir_to_search):].strip(os.path.sep)
        # print('Descending into', dn, '...')
        for name in files: # files = all files in dn; fullname, name - file we are working on now
            if not (name.startswith('.') and match==True): # First do all the files. Only if subfolder is not prefaced by a dot.
                fullname = os.path.join(dn, name)
                if is_this_file_a_jpg_image(fullname):
                    jpg_fullfilename_to_time_dict[fullname]=time_of_picture_from_fullname(fullname)
                    #print(fullname, jpg_fullfilename_to_time_dict[fullname])

    elapsedTime = time.time() - startTime
    print('Elapsed time = ',elapsedTime)

    print('-------------------------------------------------------')

    return jpg_fullfilename_to_time_dict

def create_list_of_all_filenames(dir_to_list):
    # PJB 6/4/2016 Creates list of ALL files in a directory

    startTime = time.time()

    full_file_list=[]

    print('----------------------------------------------------------------')
    print('Creating list of files inside ',dir_to_list)

    for dn, dirs, files in os.walk(dir_to_list):
        # dn is directory name we are inside of (inside root directory)
        timestamp = time.time()
        value = datetime.datetime.fromtimestamp(timestamp)
        #print('We are inside of directory ', dn,' at time ',value.strftime('%Y-%m-%d %H:%M:%S'))

        # subfolder= the dn we are in now, striped of rootdir prefactor
        # files is a list of file in dn
        subfolder = dn[len(dir_to_list):].strip(os.path.sep)
        #full_file_list.append(subfolder)
        # print('Descending into', dn, '...')
        for name in files: # files = all files in dn; fullname, name - file we are working on now
                fullname = os.path.join(dn, name)
                full_file_list.append(fullname)

    elapsedTime = time.time() - startTime
    print('Elapsed time = ',elapsedTime)

    print('Created file list of size ',len(full_file_list))

    print('-------------------------------------------------------')

    return full_file_list

def create_list_of_all_file_and_foldernames(dir_to_list):
    # PJB 6/4/2016 Creates list of ALL files in a directory

    startTime = time.time()

    full_file_list=[]

    print('----------------------------------------------------------------')
    print('Creating list of files and folders inside ',dir_to_list)

    for dn, dirs, files in os.walk(dir_to_list):
        # dn is directory name we are inside of (inside root directory)
        timestamp = time.time()
        value = datetime.datetime.fromtimestamp(timestamp)
        #print('We are inside of directory ', dn,' at time ',value.strftime('%Y-%m-%d %H:%M:%S'))

        # subfolder= the dn we are in now, striped of rootdir prefactor
        # files is a list of file in dn
        subfolder = dn[len(dir_to_list):].strip(os.path.sep)
        full_file_list.append(subfolder)
        # print('Descending into', dn, '...')
        for name in files: # files = all files in dn; fullname, name - file we are working on now
                fullname = os.path.join(dn, name)
                full_file_list.append(fullname)

    elapsedTime = time.time() - startTime
    print('Elapsed time = ',elapsedTime)

    print('Created file and folder list of size ',len(full_file_list))

    print('-------------------------------------------------------')

    return full_file_list

def create_list_of_all_nonfilenames(dir_to_list):
    # PJB 6/4/2016 Creates list of ALL files in a directory

    startTime = time.time()

    full_file_list=[]

    print('----------------------------------------------------------------')
    print('Creating list of non files inside ',dir_to_list)

    for dn, dirs, files in os.walk(dir_to_list):
        # dn is directory name we are inside of (inside root directory)
        timestamp = time.time()
        value = datetime.datetime.fromtimestamp(timestamp)
        #print('We are inside of directory ', dn,' at time ',value.strftime('%Y-%m-%d %H:%M:%S'))

        # subfolder= the dn we are in now, striped of rootdir prefactor
        # files is a list of file in dn
        subfolder = dn[len(dir_to_list):].strip(os.path.sep)
        full_file_list.append(subfolder)
        # print('Descending into', dn, '...')
        for name in files: # files = all files in dn; fullname, name - file we are working on now
                fullname = os.path.join(dn, name)
                #full_file_list.append(fullname)

    elapsedTime = time.time() - startTime
    print('Elapsed time = ',elapsedTime)

    print('Created non file list of size ',len(full_file_list))

    print('-------------------------------------------------------')

    return full_file_list

def create_list_of_all_non_jpg_filenames(dir_to_list):
    # PJB 6/4/2016 Creates list of ALL files in a directory

    startTime = time.time()

    full_file_list=[]

    print('----------------------------------------------------------------')
    print('Creating list of non jpg files inside ',dir_to_list)

    for dn, dirs, files in os.walk(dir_to_list):
        # dn is directory name we are inside of (inside root directory)
        timestamp = time.time()
        value = datetime.datetime.fromtimestamp(timestamp)
        #print('We are inside of directory ', dn,' at time ',value.strftime('%Y-%m-%d %H:%M:%S'))

        # subfolder= the dn we are in now, striped of rootdir prefactor
        # files is a list of file in dn
        subfolder = dn[len(dir_to_list):].strip(os.path.sep)
        #full_file_list.append(subfolder)
        # print('Descending into', dn, '...')
        for name in files: # files = all files in dn; fullname, name - file we are working on now
                fullname = os.path.join(dn, name)
                if not is_this_file_a_jpg_image(fullname):
                    full_file_list.append(fullname)

    elapsedTime = time.time() - startTime
    print('Elapsed time = ',elapsedTime)

    print('Created non jpg file list of size ',len(full_file_list))

    print('-------------------------------------------------------')

    return full_file_list

def create_list_of_all_jpg_filenames(dir_to_list):
    # PJB 6/4/2016 Creates list of ALL files in a directory

    startTime = time.time()

    full_file_list=[]

    print('----------------------------------------------------------------')
    print('Creating list of jpg files inside ',dir_to_list)

    for dn, dirs, files in os.walk(dir_to_list):
        # dn is directory name we are inside of (inside root directory)
        timestamp = time.time()
        value = datetime.datetime.fromtimestamp(timestamp)
        #print('We are inside of directory ', dn,' at time ',value.strftime('%Y-%m-%d %H:%M:%S'))

        # subfolder= the dn we are in now, striped of rootdir prefactor
        # files is a list of file in dn
        subfolder = dn[len(dir_to_list):].strip(os.path.sep)
        #full_file_list.append(subfolder)
        # print('Descending into', dn, '...')
        for name in files: # files = all files in dn; fullname, name - file we are working on now
                fullname = os.path.join(dn, name)
                if is_this_file_a_jpg_image(fullname):
                    full_file_list.append(fullname)

    elapsedTime = time.time() - startTime
    print('Elapsed time = ',elapsedTime)

    print('Created jpg file list of size ',len(full_file_list))

    print('-------------------------------------------------------')

    return full_file_list

def count_filetypes_in_list_of_files(list_of_files):

    filetypelist=[]
    filetypelist.append('avi') # 0
    filetypelist.append('mpg') # 1
    filetypelist.append('gif') # 2
    filetypelist.append('peg') # 3
    filetypelist.append('mp4') # 4
    filetypelist.append('wmv') # 5
    filetypelist.append('png') # 6
    filetypelist.append('mov') # 7
    filetypelist.append('m4v') # 8
    filetypelist.append('bmp') # 9
    filetypelist.append('thm') # 10
    filetypelist.append('.db') # 11
    filetypelist.append('ata') # 12
    filetypelist.append('tif') #
    filetypelist.append('doc') #
    filetypelist.append('psd') #
    filetypelist.append('ini') #
    filetypelist.append('tmp') #
    filetypelist.append('m4p') #
    filetypelist.append('exe')
    filetypelist.append('pdf')
    filetypelist.append('txt')
    filetypelist.append('ngs')
    filetypelist.append('nfo')
    filetypelist.append('ppt')
    filetypelist.append('htm')
    filetypelist.append('bat')
    filetypelist.append('lnk')
    filetypelist.append('pps')
    filetypelist.append('srf')
    filetypelist.append('inf')
    filetypelist.append('ist')
    filetypelist.append('orv')
    filetypelist.append('wav')

    filenumberlist=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

    startTime = time.time()

    full_file_list=[]

    print('----------------------------------------------------------------')
    print('Counting file types inside list')

    for fn in list_of_files:

        startindex=len(fn)-3
        endindex=len(fn)
        fnsuffix=fn[startindex:endindex]
        fnsuffixcap=fnsuffix.upper()
        match=False

        for x in range(0, len(filetypelist)):
            #print('filetypelist[' , x,'] = ', filetypelist[x])
            if filetypelist[x]==fnsuffix or filetypelist[x].upper()==fnsuffix:
                #print('match', x,filetypelist[x],fn)
                filenumberlist[x]=filenumberlist[x]+1
                match=True
#        if match==False:
#            print('no match for ',fn, ' with suffix ', fnsuffix)

    elapsedTime = time.time() - startTime
    print('Elapsed time = ',elapsedTime)

    print('Counted file types inside list')

    total_matched=0
    for x in range(0, len(filetypelist)):
        #print('We re on time ' , x)
        print( filetypelist[x],' has ', filenumberlist[x])
        total_matched=total_matched+filenumberlist[x]

    print('total matched = ',total_matched,' of ', len(list_of_files))
    print('total unmatched = ',len(list_of_files)-total_matched)

    print('-------------------------------------------------------')

    return

def write_dictionary_to_json_file(dictionary_name_to_write,json_filename):
    # PJB 6/1/2016 Writes a dictionary to a json file

    print('----------------------------------------------------------------')
    print('Writing dictionary to file ', json_filename)
    print('Length of dictionary is', len(dictionary_name_to_write) )

    with open(json_filename, 'w') as fp:
        json.dump(dictionary_name_to_write, fp)

    print('Done writing dictionary to file ', json_filename)
    print('-------------------------------------------------------')

    return

def read_dictionary_from_json_file(json_filename):
    # PJB 6/1/2016 Reads a dictionary from a json file

    print('----------------------------------------------------------------')
    print('Reading dictionary from file ', json_filename)

    dictionary_name_to_read = {}

    with open(json_filename, 'r') as fp:
        #json.load(dictionary_name_to_read, fp)
        dictionary_name_to_read = json.load(fp)

    print('Done reading dictionary to file ', json_filename)
    print('Length of dictionary is', len(dictionary_name_to_read) )
    print('-------------------------------------------------------')

    return dictionary_name_to_read

def time_of_picture_from_fullname(fullname):

    #imagedatetimetag='Image DateTime'
    imagedatetimetag='EXIF DateTimeOriginal'
    imagesubsectag='EXIF SubSecTimeOriginal'

    #print("getting datetime for file ", picturefilename1)
    f1 = open(fullname, 'rb') # Open image file for reading (binary mode)
    tags1 = exifread.process_file(f1) # Return Exif tags
    f1.close()

    if imagedatetimetag in tags1.keys():
        f1datetime=tags1[imagedatetimetag]
    else:
        f1datetime=0

#    print(tags1.keys())

    if imagesubsectag in tags1.keys():
        f1subsectime=tags1[imagesubsectag]
    else:
        f1subsectime=0

    #print("f1datetime = ",f1datetime)

    time_of_picture=str(f1datetime)+':'+str(f1subsectime)

    return time_of_picture

if __name__ == '__main__':
    main()


import time
import board
import busio
import pulseio
from adafruit_motor import servo

pwm1 = pulseio.PWMOut(board.A2, duty_cycle=10, frequency=50)
servo1 = servo.Servo(pwm1)

pwm2 = pulseio.PWMOut(board.A3, duty_cycle=10, frequency=50)
servo2 = servo.Servo(pwm2)

uart = busio.UART(board.TX, board.RX, baudrate=9600)

while True:
    data = uart.read(8)
    # Allows uart to read 8 bytes at a time
    if data is not None:
        data = data.decode("utf-8")
        # Decodes the data
        dataArray = data.split(",")
        # Splits the data into two lines
        servo1.angle = int(dataArray[0])
        print(servo1.angle)
        servo2.angle = int(dataArray[1])
        print(servo2.angle)
        # Values are already in 0 - 180 degrees
        time.sleep(0.02)
        # time.sleep should be fast


#!/usr/bin/python3
from random import randint
import dice
import sys
from subprocess import call
from os import name as osname
from time import sleep
'''Chad's Ongoing RPG Game'''

# import call method from subprocess module

# define clear function
def clear():
    # check and make call for specific operating system
    _ = call('clear' if osname =='posix' else 'cls')

bestiary = [{'name' : 'goblin', 'health' : 10, 'damage' : '1d5'},
            {'name' : 'orc', 'health' : 15, 'damage' : '1d8'},
            {'name' : 'ogre', 'health' : 20, 'damage' : '1d12'}]
armory = {'sword': {'damage': '1d12'}}
spell_lookup = {'fireball': {'damage': '4d6'}}
player_health = 20
inventory = []
spellbook = []

def combat():
    monster_ID= randint(0,2)

    global player_health, inventory, armory, bestiary
    round = 1
    monster_health = bestiary[monster_ID]['health']

    print(f"A ferocious {bestiary[monster_ID]['name']} approaches! COMBAT HAS BEGUN!\n")
    while True:
        print(f"ROUND {round}")
        print("Player Health: [" + str(player_health) + "]")
        print("Monster Health: [" + str(monster_health) + "]")

        print("Type: RUN, CAST [spell], or USE [weapon]") # gotta write code for cast
        move = input().lower().split(" ", 1) # converts move into a lower-case list to deal with each item in list separately
        monster_damage = sum(dice.roll(bestiary[monster_ID]['damage']))
        print("\n=========================")

        if move[0] == 'use': #
            if move[1] in inventory: # checks if weapon is in your inventory
                player_damage = dice.roll(armory[move[1]]['damage'])
                print(f"You hit a {bestiary[monster_ID]['name']} for {player_damage} damage!")
            if move[1] not in inventory:
                print(f"There is no {move[1]} in your inventory!")

        if move[0] == 'cast': #
            if move[1] in spellbook: # checks if spell is in your spellbook
                if move[1].lower() == 'fireball':
                    player_damage = sum(dice.roll(spell_lookup[move[1]]['damage']))
                    print(f"Summoning eldritch forces, you scorch the {bestiary[monster_ID]['name']} for {player_damage} damage!")
            if move[1] not in spellbook:
                print(f"You don't know the {move[1]} spell!")

        if move[0] == 'run': #
            escape_chance= randint(1,10) #+ player_speed # if I set this variable later, here's where it would work

            if escape_chance >= 10:
                print("You make a flawless escape!")
                break
            if escape_chance >= 5:
                print("You expose your back as you turn and flee- the monster takes advantage.")
                print(f"A {bestiary[monster_ID]['name']} hits you for {monster_damage} damage!")
                player_health -= int(monster_damage)
                if player_health >= 1:
                    print("You managed to escape.")
                    break
                if player_health < 1:
                    print("You have been slain.")
                    print("\nGAME OVER")
                    sys.exit()
            if escape_chance >= 0:
                print("The monster out-maneuvers you and attacks! You do not escape.")

        try:
            monster_health -= int(player_damage)
        except:
            pass
        if monster_health <= 0:
            print(f"The {bestiary[monster_ID]['name']} lies dead. You are victorious!\n")
            break

        print(f"A {bestiary[monster_ID]['name']} hits you for {monster_damage} damage!")
        print ("=========================\n")
        round += 1
        player_health -= int(monster_damage)

        if player_health <= 0:
            print("You have been vanquished! You are dead.")
            sys.exit()

def showInstructions():
    print('''
CHAD'S RPG GAME
OBJECTIVE: Collect spells and weapons- fight and survive!
--------
Actions:
    GO [north, south, east, west, up, down]
    GET [item, spell]
    USE [item, spell]
    LOOK
    INV/INVENTORY

Type 'help' at any time! Type 'q' to quit!''')

def dammit():
#    print('')
#    print('YOU ARE IN THE ' + currentRoom + '.')
    print('=================================')
    print('Inventory :', str(inventory))
    print('Spells :', str(spellbook))
    print('=================================')

def showStatus(): # display the player's status
 #   if 'desc' in rooms[currentRoom]:
 #       print(rooms[currentRoom]['desc'])
    if 'item' in rooms[currentRoom]:
        print('You see a ' + rooms[currentRoom]['item'] + rooms[currentRoom]['item_status'] + '.')
    if 'spell' in rooms[currentRoom]:
        print('You see a magic scroll. On the ribbon it says "' + rooms[currentRoom]['spell'] + '".')
#    print('=================')

def spellreceive(incantation):
 #   print("You received a new spell scroll. Be careful... magic is dangerous!")
 #   incantation = input("Create the magic word to summon your spell! >")
 #   if incantation not in spells:
        print("\nA pentagram illuminates beneath your feet as an unnatural wind sweeps your hair.")
        print("The spell has been successfully added to your spellbook. Be careful... magic is dangerous!")

def random_encounter():
    if ((int(rooms[currentRoom]['randenc'])) + 5) >= 10:
        combat()

rooms = {
        'HALL' : {
            'south' : 'KITCHEN',
            'east' : 'DINING ROOM',
            'item' : 'sword',
            'item_status' : ' inside of a display case. It is unlocked',
            'randenc' : '0',
            'desc' : 'You are in the hall of a large, decrepit house. The walls are blackened from some ancient fire. You get the feeling you are being watched. To the east is a dusty dining room. South is the kitchen... something is moving there.'
            },
        'KITCHEN' : {
            'north' : 'HALL',
            'randenc' : '0',
            'down' : 'BASEMENT',
            'desc' : 'You are in what was once a kitchen. Nests made of human bones are draped across every countertop. There is a large hole in the floor. Where it leads you have no idea.'
            },
        'BASEMENT' : {
            'up' : 'KITCHEN',
            'desc' : 'You are in a stinking basement with an earthen floor. You can\'t even see your hand in front of your face. You are likely to be eaten by a grue.',
            'randenc' : '10',
            },
        'DINING ROOM' : {
            'west' : 'HALL',
            'south' : 'GARDEN',
            'north' : 'PANTRY',
            'desc' : 'You are in the dining room. The table is set for an elegant party but is covered a blanket of dust. Sleeping bats cling to the chandelier. North is a dark pantry. South lies the garden. West returns to the hall.',
            'randenc' : '0',
            'item' : 'potion',
            'item_status' : ' hiding among the bottles of wine. It is cherry red in color'
            },
        'GARDEN' : {
            'north' : 'DINING ROOM',
            'spell' : 'fireball',
            'randenc' : '0',
            },
        'PANTRY' : {
            'south' : 'DINING ROOM',
            'randenc' : '0',
            'item' : 'cookie',
            'item_status' : ' collecting dust. It appears to be oatmeal raisin... yuck.'
            }
        }

currentRoom = 'HALL'   # player start location

showInstructions()     # show instructions to the player

while True:   # MAIN INFINITE LOOP
    showStatus()
    # ask the player what they want to do
    move = ''
    while move == '':
        move = input('>') # so long as the move does not
        # have a value. Ask the user for input

    move = move.lower().split(" ", 1) # make everything lower case because directions and items require it, then split into a list

    try:
        if move[0].lower() == 'q':
            print("Are you sure you want to quit? Progress will be lost.")
            quit_query= input("> ")
            if quit_query.lower() == "yes":
                sys.exit(4)
        if move[0].lower() == 'clear':
            clear()
        if move[0].lower() == 'go':
            if move[1] in rooms[currentRoom]:
                currentRoom = rooms[currentRoom][move[1]]
                if 'desc' in rooms[currentRoom]:
                    print(rooms[currentRoom]['desc'])
                random_encounter()
                # if YES that direction exists, then assign your new current room to the VALUE of the key the user entered
            else:
                print("YOU CAN'T GO THAT WAY!")
        if move[0].lower() == 'use':
            if move[1].lower() == 'potion' and 'potion' in inventory:
                print("You drink from the potion. Your health has been restored!")
                print("Your potion magically refills itself! Handy!")
                player_health = 20
        if move[0] == 'get':
            if 'item' in rooms[currentRoom] and move[1] in rooms[currentRoom]['item']:
                inventory += [move[1]] # add item to inv
                print(move[1].capitalize() + ' received!') # msg saying you received the item
                del rooms[currentRoom]['item'] # deletes that item from the dictionary
            elif 'spell' in rooms[currentRoom] and move[1] in rooms[currentRoom]['spell']:
                    spellreceive('spell')
                    spellbook += [move[1]]  # add spell to spells
                    del rooms[currentRoom]['spell']

            else:
                print('YOU CANNOT GET ' + (move[1].upper()) + '!')

        if move[0] == 'look':
            if 'desc' in rooms[currentRoom]:
                print(rooms[currentRoom]['desc']) # print the look description
            else:
                print('You can\'t see anything.')

        elif move[0] == 'help':
            showInstructions()

        elif move[0] in ['q', 'quit]']:
            print("Are you sure you want to quit? Yes/No")
            quit_query = input('>')
            if quit_query.lower() in ['y', 'yes']:
                print("Thanks for playing!")
                sys.exit()
            else:
                pass
        elif move[0] in ['inv', 'inventory', 'spells', 'status', 'spell', 'help']:
            dammit()
    except:
        pass


from flask import Flask
import json
import os

# set the project root directory as the static folder, you can set others.
app = Flask(__name__, static_url_path='', static_folder='build')

@app.route('/')
def root():
    return app.send_static_file('index.html')

# retrieve config file
with open(os.getcwd() + '/config/config.json') as json_data_file:
    config = json.load(json_data_file)

if __name__ == "__main__":
    app.run(port=config['app']['port'], host='0.0.0.0', debug=True)


# 如果needle 包含在 haystack 中，返回在haystack 的序數

class Solution(object):
    def strStr(self, haystack: str, needle: str) -> int:

        if needle in haystack:
            return haystack.find(needle)
        else:
            return -1

sol = Solution()
haystack = "hello"
needle = "ll"

print(sol.strStr(haystack,needle))


# -*- coding: utf8 -*-

"""
Encriptació i desencriptació amb AES.
La clau es guarda en un fitxer.
"""

import base64
import hashlib
import os

from Crypto.Cipher import AES
from Crypto import Random

from .constants import APP_CHARSET

class AESCipher(object):
    """
    Classe principal.
    """
    def __init__(self):
        """Captura la clau del fitxer (pot ser de qualsevol longitut)."""
        if 'AES_KEY' in os.environ:
            pth = os.environ['AES_KEY']
            key = open(pth).read()
        else:
            key = 'testkey'
        self.key = hashlib.sha256(AESCipher.str_to_bytes(key)).digest()
        self.bs = 32

    @staticmethod
    def str_to_bytes(data):
        """Converteix unicode a bytes."""
        u_type = type(b''.decode(APP_CHARSET))
        if isinstance(data, u_type):
            return data.encode(APP_CHARSET)
        return data

    def _pad(self, s):
        return s + (self.bs - len(s) % self.bs) * \
               AESCipher.str_to_bytes(chr(self.bs - len(s) % self.bs))

    @staticmethod
    def _unpad(s):
        return s[:-ord(s[len(s)-1:])]

    def encrypt(self, raw):
        """
        Funció per encriptar.
        Pot rebre unicode o bytes, i retorna unicode.
        """
        raw = self._pad(AESCipher.str_to_bytes(raw))
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return base64.b64encode(iv + cipher.encrypt(raw)).decode(APP_CHARSET)

    def decrypt(self, enc):
        """
        Funció per desencriptar.
        Rep unicode (el que retorna encrypt) i retorna unicode.
        """
        enc = base64.b64decode(enc)
        iv = enc[:AES.block_size]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        decrypted = cipher.decrypt(enc[AES.block_size:])
        return self._unpad(decrypted).decode(APP_CHARSET)


"""
Time complexity:
Worst Case:   O(n^2)
Best Case:    O(n)
Average Case: O(n^2)
Bubble sort, sometimes referred to as sinking sort, is a simple sorting
algorithm that repeatedly steps through the list to be sorted, compares each
pair of adjacent items and swaps them if they are in the wrong order. The pass
through the list is repeated until no swaps are needed, which indicates that the
list is sorted. The algorithm, which is a comparison sort, is named for the way
smaller or larger elements "bubble" to the top of the list. Although the
algorithm is simple, it is too slow and impractical for most problems even when
compared to insertion sort. It can be practical if the input is usually in
sorted order but may occasionally have some out-of-order elements nearly in
position.

- Wikipedia
"""

def bubblesort(a):
    swapped = True
    while swapped:
        swapped = False
        for idx in range(1, len(a)):
            if a[idx - 1] > a[idx]:
                a[idx], a[idx - 1] = a[idx - 1], a[idx]
                swapped = True
        if not swapped:
            return a


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

import sys
import os

sys.path.append( os.path.join(sys.path[0], 'system/networks') )
sys.path.append( os.path.join(sys.path[0], 'system/devices') )

from deviceConstants import *
import deviceObject

from networkConstants import *

from modbusConstants import *
# import modbusConstants

import copy
from collections import OrderedDict

import logsystem
log = logsystem.getLogger()

deviceType = "LAE AT1-5BS2U-BG"
deviceTypeName = "LAE AT1-5BS2U-BG"
executionType = deviceNetworkExecution
executionTypeName = deviceNetworkExecutionText

valueDescriptions = OrderedDict()

# OUTPUTS - Dedicated Register value
valueDescriptions["T1 TEMP"] = {"displayName": "T1-Air Probe", "dataType": dataTypeFloat, "unitType": unitTypeTemperature, "valueType": valueTypeOutput, "significantDigits": 1, "defaultLog":"true"}
valueDescriptions["T2 TEMP"] = {"displayName": "T2-Evap Probe", "dataType": dataTypeFloat, "unitType": unitTypeTemperature, "valueType": valueTypeOutput, "significantDigits": 1, "defaultLog":"true"}

# OUTPUT - Address 100 Status Flag bits
valueDescriptions["ALARM"] = {"displayName": "General Alarm", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"} }
valueDescriptions["MUTE"] = {"displayName": "Alarm Mute", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"} }
valueDescriptions["DEFROST"] = {"displayName": "Defrost Status", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"}, "defaultLog":"true" }
valueDescriptions["DOOR"] = {"displayName": "Door Status", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "Open", "false": "Closed"}, "defaultLog":"true" }

# OUTPUT - Address 101 Alarm Flag bits
valueDescriptions["T1FAILUREALARM"] = {"displayName": "T1 Probe FAILUREALARM", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"} }
valueDescriptions["T2FAILUREALARM"] = {"displayName": "T2 Probe FAILUREALARM", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"} }
valueDescriptions["HIGHTEMPALARM"] = {"displayName": "High Temp Alarm", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"} }
valueDescriptions["LOWTEMPALARM"] = {"displayName": "Low Temp Alarm", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"} }
valueDescriptions["CONDCLEANALARM"] = {"displayName": "Dirty Condenser", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"} }
valueDescriptions["DOOROPENALARM"] = {"displayName": "Door Open Alarm", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"} }

# OUTPUT - Address 102 Output Flag bits
valueDescriptions["COMP RLY"] = {"displayName": "Compressor", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"}, "defaultLog":"true"}
valueDescriptions["AUX RLY"] = {"displayName": "AUX", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "On", "false": "Off"}, "defaultLog":"true"}

# Virtual (function to load value)
# valueDescriptions["MDEF"] = {"dataType":dataTypeBool,"dataList":{"true":"On", "false": "Off"},"valueType":valueTypeConfig,"displayName":"MDEF","description":"Turn On Manual Defrost"}
valueDescriptions["STANDBY"] = {"displayName": "Standby Status", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeOutput, "dataList": {"true": "Standby", "false": "No"} }

# CONFIG
valueDescriptions["SCL"] = {"displayName": "SCL", "description": "Readout scale", "dataType": dataTypeList, "valueType": valueTypeConfig, "dataList": {"0": "1°C", "1": "2°C", "2": "°F"},"default":"0"}
valueDescriptions["SPL"] = {"displayName": "SPL", "description": "Minimum setpoint", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeTemperature, "significantDigits": 1,"default":"-25.0"}
valueDescriptions["SPH"] = {"displayName": "SPH", "description": "Maximum setpoint", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeTemperature, "significantDigits": 1,"default":"25.0"}
valueDescriptions["SP"] = {"displayName": "SP", "description": "Setpoint", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeTemperature, "significantDigits": 1,"default":"0.0"}
valueDescriptions["CHHEATCOOL"] = {"displayName": "C-H", "description": "Refrigerating or heating mode", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeConfig, "dataList": {"true": "Heating", "false": "Cooling"},"default":"true"}
valueDescriptions["HYS"] = {"displayName": "HYS", "description": "Hysteresis", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeDeltaTemperature, "significantDigits": 1,"default":"3.0"}
valueDescriptions["CRT"] = {"displayName": "CRT", "description": "Compressor rest time", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"1"}
valueDescriptions["CT1"] = {"displayName": "CT1", "description": "Compressor run with sensor T1 failure", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"3"}
valueDescriptions["CT2"] = {"displayName": "CT2", "description": "Compressor stop with T1 failure", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"6"}
valueDescriptions["CSD"] = {"displayName": "CSD", "description": "Compressor stop delay after door open", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"1"}
valueDescriptions["DFR"] = {"displayName": "DFR", "description": "Defrost frequency", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "2.5 minute increments","default":"0"}
valueDescriptions["DLI"] = {"displayName": "DLI", "description": "Defrost end temperature", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeTemperature, "significantDigits": 1,"default":"10.0"}
valueDescriptions["DTO"] = {"displayName": "DTO", "description": "Maximum defrost duration", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"30"}
valueDescriptions["DTY"] = {"displayName": "DTY", "description": "Defrost type", "dataType": dataTypeList, "valueType": valueTypeConfig, "dataList": {"14": "OFF", "15": "ELE", "16": "GAS"},"default":"14"}
valueDescriptions["DDY"] = {"displayName": "DDY", "description": "Display controls during defrost", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"0"}
valueDescriptions["ATM"] = {"displayName": "ATM", "description": "Alarm threshold management", "dataType": dataTypeList, "valueType": valueTypeConfig, "dataList": {"11": "NON", "12": "ABS", "13": "REL"},"default":"11"}
valueDescriptions["ALA"] = {"displayName": "ALA", "description": "Low temperature alarm", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeTemperature, "significantDigits": 1,"default":"-50.0"}
valueDescriptions["AHA"] = {"displayName": "AHA", "description": "High temperature alarm", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeTemperature, "significantDigits": 1,"default":"120.0"}
valueDescriptions["ALR"] = {"displayName": "ALR", "description": "Low alarm differential", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeDeltaTemperature, "significantDigits": 1,"default":"0.0"}
valueDescriptions["AHR"] = {"displayName": "AHR", "description": "High alarm differential", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeDeltaTemperature, "significantDigits": 1,"default":"0.0"}
valueDescriptions["ATD"] = {"displayName": "ATD", "description": "Temperature alarm delay", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"60"}
valueDescriptions["ADO"] = {"displayName": "ADO", "description": "Door alarm delay", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"5"}
valueDescriptions["ACC"] = {"displayName": "ACC", "description": "Condenser cleaning", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "weeks","default":"0"}
valueDescriptions["STANDBYBUTTONENABLE"] = {"displayName": "SB","description":"Standby button enable", "dataType": dataTypeBool, "valueType": valueTypeConfig, "dataList": {"true": "Yes", "false": "No"},"default":"true"}
valueDescriptions["DSDOORENABLE"] = {"displayName": "DS", "description": "Door Enable", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeConfig, "dataList": {"true": "Yes", "false": "No"},"default":"false"}
valueDescriptions["OAU"] = {"displayName": "OAU", "description": "Auxiliary output control mode", "dataType": dataTypeList, "valueType": valueTypeConfig, "dataList": {"17": "NON", "18": "O-I", "19": "DEF", "20": "LGT", "21": "ALR"},"default":"17"}
valueDescriptions["INP"] = {"displayName": "INP", "description": "Probe type selection", "dataType": dataTypeList, "valueType": valueTypeConfig, "dataList": {"3": "SN4", "4": "ST1"},"default":"3"}
valueDescriptions["OS1"] = {"displayName": "OS1", "description": "Probe T1 offset", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeDeltaTemperature, "significantDigits":1,"default":"0.0"}
valueDescriptions["ENABLET2"] = {"displayName": "T2", "description": "Probe T2 Enable", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeConfig, "dataList": {"true": "Yes", "false": "No"},"default":"false"}
valueDescriptions["OS2"] = {"displayName": "OS2", "description": "Probe T2 offset", "dataType": dataTypeFloat, "valueType": valueTypeConfig, "unitType": unitTypeDeltaTemperature, "significantDigits": 1,"default":"0.0"}
valueDescriptions["TLD"] = {"displayName": "TLD", "description": "Delay for min/max temperature storage", "dataType": dataTypeInt, "valueType": valueTypeConfig, "unitText": "minutes","default":"5"}
valueDescriptions["SIM"] = {"displayName": "SIM", "description": "Display slowdown", "dataType": dataTypeInt, "valueType": valueTypeConfig,"default":"3"}

# Cfg_1 Address 229
valueDescriptions["LOCKKEYBOARD"] = {"displayName": "LOC", "description": "Lock Keyboard", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeConfig, "dataList": {"true": "Yes", "false": "No"}}
valueDescriptions["STBY"] = {"displayName": "STBY", "description": "Standby", "dataType": dataTypeBool,"unitType":"OnOff", "valueType": valueTypeConfig, "dataList": {"true": "Standby", "false": "No"}}

# ALARMS
alarmDescriptions = OrderedDict()
alarmDescriptions["T1FAILUREALARM"] = {"description": "T1 Probe Failure" }
alarmDescriptions["T2FAILUREALARM"] = {"description": "T2 Probe Failure" }
alarmDescriptions["HIGHTEMPALARM"] = {"description": "High Temp" }
alarmDescriptions["LOWTEMPALARM"] = {"description": "Low Temp" }
alarmDescriptions["CONDCLEANALARM"] = {"description": "Dirty Condenser" }
alarmDescriptions["DOOROPENALARM"] = {"description": "Door Open Alarm" }

class Device(deviceObject.NetworkDeviceObject):
  def __init__(self, deviceManager, name, description, network, networkAddress, image, method = ""):
    deviceObject.NetworkDeviceObject.__init__(self, deviceManager, name, description, network, networkAddress, deviceType, deviceTypeName, image)

    self._valueDescriptions = valueDescriptions
    self._alarmDescriptions = alarmDescriptions

    self.loadValuesFromDatabase()
    self.loadAdvisoriesFromDatabase()

    self.configModbusList = [
                      ["1", "SCL", 200],
                      ["1", "SPL", 201],
                      ["1", "SPH", 202],
                      ["2", "SP",  203],
                      ["2", "HYS", 204],
                      ["2", "CRT", 205],
                      ["3", "CT1", 206],
                      ["3", "CT2", 207],
                      ["3", "CSD", 208],
                      ["4", "DFR", 209],
                      ["4", "DLI", 210],
                      ["4", "DTO", 211],
                      ["5", "DTY", 212],
                      ["5", "DDY", 213],
                      ["5", "ATM", 214],
                      ["6", "ALA", 215],
                      ["6", "AHA", 216],
                      ["6", "ALR", 217],
                      ["7", "AHR", 218],
                      ["7", "ATD", 219],
                      ["7", "ADO", 220],
                      ["8", "ACC", 221],
                      ["8", "OAU", 222],
                      ["8", "INP", 223],
                      ["9", "OS1", 224],
                      ["9", "OS2", 225],
                      ["9", "TLD", 226],
                      ["10", "SIM", 227],
                      ["11", "CFG_1", 229]
               #       ["12","CMD_1",100]
    ]

  def _prepareSetDeviceConfigurationTransactions(self):
    if self._newDeviceConfigurationValues is None:
      return None

    retval = []
    networkTransTag = ""
    networkTrans = None

    for configItem in self.configModbusList:
      # [0] = MessageGroup/Tag; [1] = actual parameter, [2] = register address
      if networkTransTag != configItem[0]:
        networkTransTag = configItem[0]
        networkTrans = NetworkTransaction("WriteConfig" + networkTransTag)
        retval.append(networkTrans)

      key = configItem[1]

   #   if len(self._newDeviceConfigurationValues) == 1:
   #     value = 0
   #     value = value | 0x04 if self._newDeviceConfigurationValues["MDEF"] else value
   #     networkTrans.transactions.append(NetworkMessage(writeHoldingRegister(100, 0x04), "MDEF"))
   #     break

   #   if key == "CMD_1":
   #     value = 0
   #     if "MDEF" in self._newDeviceConfigurationValues:
   #       value = value | 0x04 if self._newDeviceConfigurationValues["MDEF"] else value

      if key == "CFG_1":
        value = 0
        value = value | 0x01 if self._newDeviceConfigurationValues["DSDOORENABLE"] else value
        value = value | 0x02 if self._newDeviceConfigurationValues["CHHEATCOOL"] else value
        value = value | 0x04 if self._newDeviceConfigurationValues["ENABLET2"] else value
        value = value | 0x20 if self._newDeviceConfigurationValues["LOCKKEYBOARD"] else value
        value = value | 0x40 if self._newDeviceConfigurationValues["STBY"] else value
        value = value | 0x80 if self._newDeviceConfigurationValues["STANDBYBUTTONENABLE"] else value

      else:
        newConfigValue = self._newDeviceConfigurationValues[key]

     # LEO sending data to Device
        if self._valueDescriptions[key]["dataType"] == dataTypeFloat:
          if (self._newDeviceConfigurationValues["SCL"]) == "2" or (self._newDeviceConfigurationValues["SCL"]) == 2:
            if self._valueDescriptions[key]["unitType"] == unitTypeTemperature:
              newConfigValue = self._convertC2F(newConfigValue)
            elif self._valueDescriptions[key]["unitType"] == unitTypeDeltaTemperature:
              newConfigValue = self._convertDeltaC2F(newConfigValue)
          elif (self._newDeviceConfigurationValues["SCL"]) == "0" or (self._newDeviceConfigurationValues["SCL"]) == 0:
            newConfigValue = newConfigValue * 10.0
          value = self._convertFromFloatValue(newConfigValue)
        elif self._valueDescriptions[key]["dataType"] == dataTypeBool:
          value = 0 if newConfigValue == False else 1
        else:
          value = self._convertFromIntValue(newConfigValue)
      networkTrans.transactions.append(NetworkMessage(writeHoldingRegister(configItem[2], value), configItem[1]))
    return retval

  def _prepareUpdateDeviceConfigurationTransactions(self):
    retval = []
    networkTransTag = ""
    networkTrans = None

    for configItem in self.configModbusList:
      if networkTransTag != configItem[0]:
        networkTransTag = configItem[0]
        networkTrans = NetworkTransaction("ReadConfig" + networkTransTag)
        retval.append(networkTrans)
      networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(configItem[2], 1), configItem[1]))
    return retval

  def _prepareLoggingTransactions(self, valueToLog):
    if len(valueToLog) == 0:
      return None

    networkTrans = NetworkTransaction("Logging")

    if "T1 TEMP" in valueToLog:
      networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(0, 1), "T1 TEMP"))

    if "T2 TEMP" in valueToLog:
      networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(1, 1), "T2 TEMP"))

    setValueToLog = set(valueToLog)
    setStatusFlag = set(["ALARM", "MUTE", "DEFROST", "DOOR"])
    if len(setValueToLog & setStatusFlag) > 0:
      networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(100, 1), "StatusFlag"))

    # Alarm flag
    setAlarmFlag = set(["T1FAILUREALARM", "T2FAILUREALARM", "HIGHTEMPALARM", "LOWTEMPALARM", "CONDCLEANALARM", "DOOROPENALARM"])
    if len(setValueToLog & setAlarmFlag) > 0:
      networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(101, 1), "AlarmFlag"))

    # Output flag
    setOutputFlag = set(["COMP RLY", "AUX RLY"])
    if len(setValueToLog & setOutputFlag) > 0:
      networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(102, 1), "OutputFlag"))

    # Standby flag
    setStandbyFlag = set(["STANDBY"])
    if len(setValueToLog & setStandbyFlag) > 0:
      networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(229, 1), "StandbyFlag"))

    return [ networkTrans ]

  def _prepareUpdateStatusTransactions(self):
    networkTrans = NetworkTransaction("Status1")
    networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(0, 1), "T1 TEMP"))
    networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(1, 1), "T2 TEMP"))
    networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(203, 1), "SP"))
    networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(100, 1), "StatusFlag"))
    networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(102, 1), "OutputFlag"))
    networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(229, 1), "StandbyFlag"))
    return [ networkTrans ] + self._prepareUpdateAlarmsTransactions()

  def _prepareUpdateAlarmsTransactions(self):
    networkTrans = NetworkTransaction("Alarms")
    networkTrans.transactions.append(NetworkMessage(readHoldingRegisters(101, 1), "AlarmFlag")) # function 3
    return [ networkTrans ]

  def _executeTransaction(self, networkTrans):
    if not networkTrans.online:
      self._nullOutputValues()
    else:

      for transaction in networkTrans.transactions:
        with self.lock:
          if isinstance(transaction.response, readHoldingRegistersResponse):
            value = transaction.response.registers[0]

            if transaction.tag == "StatusFlag":
              self._values["ALARM"] = ((value & 0x01) > 0)
              self._alarm = self._values["ALARM"]
              self._values["MUTE"] = ((value & 0x02) > 0)
              self._values["DEFROST"] = ((value & 0x04) > 0)
              self._values["DOOR"] = ((value & 0x08) > 0)

            elif transaction.tag == "AlarmFlag":
              self._values["T1FAILUREALARM"] = ((value & 0x01) > 0)
              self.checkBooleanAdvisory("T1FAILUREALARM", self._values["T1FAILUREALARM"])
              self._values["T2FAILUREALARM"] = ((value & 0x02) > 0)
              self.checkBooleanAdvisory("T2FAILUREALARM", self._values["T2FAILUREALARM"])
              self._values["HIGHTEMPALARM"] = ((value & 0x04) > 0)
              self.checkBooleanAdvisory("HIGHTEMPALARM", self._values["HIGHTEMPALARM"])
              self._values["LOWTEMPALARM"] = ((value & 0x08) > 0)
              self.checkBooleanAdvisory("LOWTEMPALARM", self._values["LOWTEMPALARM"])
              self._values["CONDCLEANALARM"] = ((value & 0x10) > 0)
              self.checkBooleanAdvisory("CONDCLEANALARM", self._values["CONDCLEANALARM"])
              self._values["DOOROPENALARM"] = ((value & 0x20) > 0)
              self.checkBooleanAdvisory("DOOROPENALARM", self._values["DOOROPENALARM"])

            elif transaction.tag == "OutputFlag":
              self._values["COMP RLY"] = ((value & 0x01) > 0)
              self._values["AUX RLY"] = ((value & 0x02) > 0)

            elif transaction.tag == "StandbyFlag":
              self._values["STANDBY"] = ((value & 0x40) > 0)

            elif transaction.tag == "CFG_1":
              self._values["DSDOORENABLE"] = ((value & 0x01) > 0)
              self._values["CHHEATCOOL"] = ((value & 0x02) > 0)
              self._values["ENABLET2"] = ((value & 0x04) > 0)
              self._values["LOCKKEYBOARD"] = ((value & 0x20) > 0)
              self._values["STBY"] = ((value & 0x40) > 0)
              self._values["STANDBYBUTTONENABLE"] = ((value & 0x80) > 0)

        #    elif transaction.tag == "CMD_1":
        #      self._values["MDEF"] = ((value & 0x4) > 0)

            else:    # LEO reading up from Device
              key = transaction.tag
              if self._valueDescriptions[key]["dataType"] == dataTypeFloat:
                self._values[key] = self._convertToFloatValue(value)
                if self._values["SCL"] == 2:
                  if self._valueDescriptions[key]["unitType"] == unitTypeTemperature:
                    self._values[key] = self._convertF2C(self._values[key])
                  elif self._valueDescriptions[key]["unitType"] == unitTypeDeltaTemperature:
                    self._values[key] = self._convertDeltaF2C(self._values[key])
                elif self._values["SCL"] == 0:
                  self._values[key] = self._values[key] / 10.0
              elif self._valueDescriptions[key]["dataType"] == dataTypeBool:
                self._values[key] = False if value == 0 else True
              else:
                self._values[key] = self._convertToIntValue(value)

      if "ReadConfig" in networkTrans.tag:
        self.saveValuesToDatabase()
      elif "WriteConfig" in networkTrans.tag:
        self.updateDeviceConfiguration()

  def _convertF2C(self, value):
    return (value - 32) / 1.8

  def _convertC2F(self, value):
    return (value * 1.8) + 32

  def _convertDeltaF2C(self, value):
    return value / 1.8

  def _convertDeltaC2F(self, value):
    return value * 1.8

  def _convertToFloatValue(self, value):
    if value > 0x7fff:
      return float(value - 0x10000)
    return float(value)

  def _convertFromFloatValue(self, value):
    if value < 0:
      return int(round(value + 0x10000))
    return int(round(value))

  def _convertToIntValue(self, value):
    if value > 0x7fff:
      return int(value - 0x10000)
    return int(value)

  def _convertFromIntValue(self, value):
    if value < 0:
      return int(value + 0x10000)
    return int(value)


import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while True:

    ret, frame = cap.read()
    # Locate points of the documents or object which you want to transform
    pts1 = np.float32([[0, 260], [640, 260], [0, 400], [640, 400]])
    pts2 = np.float32([[0, 0], [400, 0], [0, 640], [400, 640]])

    # Apply Perspective Transform Algorithm
    matrix = cv2.getPerspectiveTransform(pts1, pts2)
    result = cv2.warpPerspective(frame, matrix, (500, 600))
    # Wrap the transformed image

    cv2.imshow('frame', frame) # Inital Capture
    cv2.imshow('frame1', result) # Transformed Capture

    if cv2.waitKey(24) == 27:
        break

cap.release()
cv2.destroyAllWindows()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
from Queue import Queue, Empty

class DelayedExecution(threading.Thread):#потоки

    def __init__(self, ):
        threading.Thread.__init__(self)
        self.q = Queue()#очередь
        self.daemon = True#демон
        self.executing = False#изменнеия
        self.start()#старат

    def restart(self, delay, action, *args):#перезапуск
        self.args = args
        self.action = action
        self.q.put(delay)

    def cancel(self):#закрытие
        delay = None#задержка
        self.q.put(delay)#добавить в очередь задержку

    def isExecuting(self):
        return self.executing#изменеие

    def run(self):#запуск
        delay = None#задержка
        '''
        пока справдливо условие попытаться вернуть задержку
        в противном случае вывести ее в значение None
        '''
        while True:
            try:
                delay = self.q.get(True, delay)
                self.executing = True
            except Empty as e:
                # print self.args
                self.action(self.args)
                self.executing = False
                delay = None


# I copied most of the code from assembler.py
# Note: The input file is assumed to be a directory with .vm files, and not a .vm file itself
# Note: @FRAME is set to @R14 while @RET is set to @R15

import re
import sys
import os

# This slaps some code at the beginning to set the SP to 256 and a function call to sys.init
def bootstrap():

    return '@256\nD=A\n@SP\nM=D\n' + functioncall('call', 'Sys.init', '0', 0, 'main')

# This function accepts the arithmetic operation and returns a string with the corresponding ASM code
def arithmeticOp(operation, conditionalNumber):

    twoVarHeader = '@SP\nAM=M-1\nD=M\nA=A-1\n'
    conditionEnd = '@SP\nA=M-1\nM=-1\n@CONTINUE' + str(conditionalNumber) + '\n0;JMP\n(FALSE' + str(conditionalNumber) \
                   + ')\n@SP\nA=M-1\nM=0\n(CONTINUE' + str(conditionalNumber) + ')\n'

    return {
        'add':    twoVarHeader + 'M=M+D\n',
        'sub':    twoVarHeader + 'M=M-D\n',
        'and':    twoVarHeader + 'M=M&D\n',
        'or':     twoVarHeader + 'M=M|D\n',
        'eq':     twoVarHeader + 'D=M-D\n@FALSE' + str(conditionalNumber) + '\nD;JNE\n' + conditionEnd,
        'gt':     twoVarHeader + 'D=M-D\n@FALSE' + str(conditionalNumber) + '\nD;JLE\n' + conditionEnd,
        'lt':     twoVarHeader + 'D=M-D\n@FALSE' + str(conditionalNumber) + '\nD;JGE\n' + conditionEnd,
        'neg':    'D=0\n@SP\nA=M-1\nM=D-M\n',
        'not':    '@SP\nA=M-1\nM=!M\n'
    }.get(operation, 'Match Error with arithmenticOp\n')

def restoreVirtual():

    compoundLine = ''

    compoundLine += '@LCL\nD=M\n@R14\nM=D\n'                                        # FRAME = lcl
    compoundLine += '@R14\nD=M\n@5\nA=D-A\nD=M\n@R15\nM=D\n'                        # RET = *(FRAME - 5)
    compoundLine += pushpop('pop', 'argument', '0', 'uselessStr')                   # *ARG = pop()
    compoundLine += '@ARG\nD=M\n@SP\nM=D+1\n'                                       # SP = ARG + 1
    compoundLine += '@R14\nD=M\n@1\nA=D-A\nD=M\n@THAT\nM=D\n'                       # THAT = *(FRAME - 1)
    compoundLine += '@R14\nD=M\n@2\nA=D-A\nD=M\n@THIS\nM=D\n'                       # THIS = *(FRAME - 2)
    compoundLine += '@R14\nD=M\n@3\nA=D-A\nD=M\n@ARG\nM=D\n'                        # ARG = *(FRAME - 3)
    compoundLine += '@R14\nD=M\n@4\nA=D-A\nD=M\n@LCL\nM=D\n'                        # LCL = *(FRAME - 4)
    compoundLine += '@R15\nD=M\nA=D\n0;JMP\n'                                       # go to RET
    return compoundLine

def functioncall(command, name, n, retNum, fileName):

    if command == 'function':
        retLine = '(' + name + ')\n'

        for i in range(int(n)):
            retLine += pushpop('push', 'constant', '0', fileName)

        return retLine

    elif command == 'call':
        compoundLine = ''
        returnLabel = 'RETURN_' + str(retNum)

        compoundLine += '@' + returnLabel + '\nD=A\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'    # Push ret-add
        compoundLine += '@LCL\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'                    # Push lcl
        compoundLine += '@ARG\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'                    # Push arg
        compoundLine += '@THIS\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'                   # Push this
        compoundLine += '@THAT\nD=M\n@SP\nA=M\nM=D\n@SP\nM=M+1\n'                   # Push that

        compoundLine += '@SP\nD=M\n@' + n + '\nD=D-A\n@5\nD=D-A\n@ARG\nM=D\n'       # arg = sp - n - 5
        compoundLine += '@SP\nD=M\n@LCL\nM=D\n'                                     # lcl = sp
        compoundLine += '@' + name + '\n0;JMP\n'                                    # jump to callee
        compoundLine += '(' + returnLabel + ')\n'                                   # create a return label

        return compoundLine

    else:
        return 'Match Error with functioncall\n'

# This function accepts a full push/pop string into 3 arguments and returns the corresponding ASM code
def pushpop(command, segment, i, fileName):

    pushTail = '@SP\nA=M\nM=D\n@SP\nM=M+1\n'
    popTail  = '@SP\nAM=M-1\nD=M\n@R13\nA=M\nM=D\n'

    return {
        'push':    pushSeg(segment, i, fileName) + pushTail,
        'pop':     popSeg(segment, i, fileName) + popTail
    }.get(command, 'Match Error with pushpop\n')

# This function accepts a segment and variable for a push command and returns its ASM code segment
def pushSeg(segment, i, fileName):

    ptrHeader = '@' + i + '\nA=D+A\nD=M\n'

    return {
        'constant': '@' + i + '\nD=A\n',
        'pointer':  '@3\nD=A\n' + ptrHeader,
        'temp':     '@5\nD=A\n' + ptrHeader,
        'static':   '@' + fileName + '.' + i + '\nD=M\n',
        'local':    '@LCL\nD=M\n' + ptrHeader,
        'argument': '@ARG\nD=M\n' + ptrHeader,
        'this':     '@THIS\nD=M\n' + ptrHeader,
        'that':     '@THAT\nD=M\n' + ptrHeader
    }.get(segment, 'Match Error with pushSeg\n')

# This function accepts a segment and variable for a pop command and returns its ASM code segment
def popSeg(segment, i, fileName):

    ptrHeader = '@' + i + '\nD=D+A\n@R13\nM=D\n'

    return {
        'constant': '@' + i + '\nD=A\n' + ptrHeader,
        'pointer':  '@3\nD=A\n' + ptrHeader,
        'temp':     '@5\nD=A\n' + ptrHeader,
        'static':   '@' + fileName + '.' + i + '\nD=A\n@R13\nM=D\n',
        'local':    '@LCL\nD=M\n' + ptrHeader,
        'argument': '@ARG\nD=M\n' + ptrHeader,
        'this':     '@THIS\nD=M\n' + ptrHeader,
        'that':     '@THAT\nD=M\n' + ptrHeader
    }.get(segment, 'Match Error with popSeg\n')

def ctrlFlow(command, label):

    return {
        'label':    '(' + label + ')\n',
        'goto':     '@' + label + '\n0;JMP\n',
        'if-goto':  '@SP\nAM=M-1\nD=M\n@' + label + '\nD;JNE\n'
    }.get(command, 'Match Error with ctrlFlow\n')

###############################
# MAIN LOOPING FUNCTION BLOCK #
###############################

def vmToAsm(fileName, inputFile, outputFile, conditionalNumber, returnCounter):

        # Loops through the lines to output the ASM code
        for line in inputFile:

            #################################
            # COMMENTS AND WHITESPACE BLOCK #
            #################################

            commentMatchObject = commentPat.search(line)

            if (commentMatchObject):
                line = line[:commentMatchObject.start()]

            # The following lines of code take off newlines if they are the only characters in that line
            commLine = line

            if (commLine == '\n'):
                commLine += ''

            # This line initializes the asmLines string
            asmLines = ''

            # Takes off all the newlines for lines that do have them
            commLine = commLine[:-1]

            commLineList = commLine.split()

            ###############################
            # ARITHMETIC OPERATIONS BLOCK #
            ###############################

            # If commLine is in the arithmeticList, it will get the asm code using arithmeticOp
            # The conditionalNumber is also incremented if there are asm lines that deal with conditional jumps

            if len(commLineList) == 1:
                operation = commLineList[0]

                if operation in arithmeticList:
                    if operation in condList:
                        conditionalNumber += 1
                    asmLines = arithmeticOp(operation, conditionalNumber)

            ################
            # RETURN BLOCK #
            ################

                elif operation == 'return':
                    asmLines = restoreVirtual()

            ######################
            # CONTROL FLOW BLOCK #
            ######################

            elif len(commLineList) == 2:
                command = commLineList[0]
                label = commLineList[1]
                asmLines = ctrlFlow(command, label)

            ###########################
            # MEMORY OPERATIONS BLOCK #
            ###########################

            # Else, it firstly splits the commLine and puts each token into commListList
            # If there are 3 tokens, it then passes those tokens into the pushpop function to get the asm code
            elif len(commLineList) == 3:
                    command = commLineList[0]
                    segment = commLineList[1]
                    var     = commLineList[2]

                    if command == 'push' or command == 'pop':
                        asmLines = pushpop(command, segment, var, fileName)

            #######################
            # FUNCTION CALL BLOCK #
            #######################

                    elif command == 'function':
                        asmLines = functioncall(command, segment, var, returnCounter, fileName)
                    elif command == 'call':
                        returnCounter += 1
                        asmLines = functioncall(command, segment, var, returnCounter, fileName)

            #########################
            # NOTHING MATCHES BLOCK #
            #########################

            # Otherwise, the final asmLines is just whatever was in the commLine, which can be an empty string
            else:
                asmLines = commLine

            #################
            # OUTPUT  BLOCK #
            #################

            # Finally, the modified output line is written in the output file
            outputFile.write(asmLines)

##############################
# MAIN FUNCTION STARTS HERE  #
##############################

# Gets the directory name and puts all of its files into fileList
# It then creates an outputFilePath with the same name as the directory in the same location
inputDirectory = sys.argv[1]
fileList = os.listdir(inputDirectory)
outputFilePath = inputDirectory
outputFilePath += '.asm'
outputFile = open(outputFilePath, 'w')

# Creates a pattern to match for comments
commentPat = re.compile('//')

# Creates a list of things to check for the grammar
arithmeticList = ['add', 'sub', 'eq', 'gt', 'lt', 'and', 'or', 'neg', 'not']
pushpopList = ['push', 'pop']
condList = ['eq', 'gt', 'lt']
controlFlowList = ['label', 'goto', 'if-goto']

# This variable is used for keeping track of the conditional naming
conditionalNumber = 0
returnCounter = 0

# This line right here writes out the bootstrap function
outputFile.write(bootstrap())

# Loops through the rest of the .vm files and appends the ASM output to outputFile
for file in fileList:
    filePath = inputDirectory + '/' + file
    if filePath.endswith('.vm'):
        inputFile = open(filePath, 'r')
        vmToAsm(file[:-3], inputFile, outputFile, conditionalNumber, returnCounter)
        inputFile.close()

# Closes the input and output files
outputFile.close()


#!/usr/bin/python2.7
# -*- coding: utf-8 -*-

"""config.py: Application's default settings."""

import os

# Paths:
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))

# Directories:
DIR_APPS = os.path.join(ROOT, 'apps')
DIR_DBS = os.path.join(ROOT, 'dbs')
DIR_VIEWS = os.path.join(ROOT, 'views')
DIR_STATIC = os.path.join(ROOT, 'static')
DIR_MEDIA = os.path.join(ROOT, 'media')
DIR_SESSIONS = os.path.join(ROOT, 'cache')
DIR_LOGS = os.path.join(ROOT, 'logs')

# Server:
SERVER_WSGI = 'wsgiref'
SERVER_HOST = 'localhost'
SERVER_PORT = 8080
SERVER_DEBUG = True
SERVER_RELOADER = True
SERVER_INTERVAL = 1
SERVER_QUIET = False

# Session:
SESSION_TYPE = 'file'
SESSION_AUTO = True

# Template:
TEMPLATE_RENDERER = 'mako'

# Database:
DB_FILE = 'db.sqlite3'
DB_DEST = '////'  # 4 slash: absolute, 3 slash: relative, 2 slash: non-SQLite
DB_TYPE = 'sqlite'

# Repo:
REPO_WOOJI_ALIAS = 'wooji'
REPO_WOOJI_ORIGIN = 'https://github.com/ejelome/wooji'
REPO_WOOJI_LIST = 'http://wooji.me/apps.json'

# Log:
LOG_FILE = '{date}.log'
LOG_FORMAT = ('[%(asctime)s][{db}]'
              '[%(name)s:{file}] '
              '%(levelname)s: %(message)s')
LOG_FORMAT_TIME_FILE = '%Y-%m-%d'
LOG_FORMAT_TIME_CONSOLE = '%Y-%m-%d %I:%M:%S %p'
LOG_LEVEL_FILE = 'INFO'
LOG_LEVEL_CONSOLE = 'DEBUG'
LOG_LEVEL_HANDLER = 'WARNING'


import numpy as np
import keras as ks
from Balerion import balerion
from keras.models import Sequential
from keras.layers import Dense
import matplotlib.pyplot as plt
#from scipy.ndimage.filters import gaussian_filter1d
from scipy.interpolate import spline
from docplex.mp.model import Model
from time import time

def createInstances( jobs, machines):
    sequences = []
    length = np.random.choice(machines, replace=True, size=jobs)
    n = 0
    for i in range(len(length)):
        if length[i] <= machines/2:
            length[i] = machines
        n = n + length[i]
    for i in range(jobs):
        array = np.random.choice(machines, replace=False, size=length[i])
        comp = np.random.randint(low = 1, high = jobs*10, size = machines)
        sequence = []
        for s, t in zip(array, comp):
            add = t
            if add < 1:
                add = 1
            sequence.append((s, add))
        sequences.append(sequence)
    print("JOBS: ", jobs)
    print("MACHINES: ", machines)
    for i in range(jobs):
        print("Job N°", i, " : ", sequences[i])
    return sequences, n

def createModel( layers, instance_dimension ):
    model = Sequential()

    tup = layers[0]
    model.add(Dense(tup[0], input_dim=instance_dimension, activation=tup[2],  kernel_initializer=tup[1]))
    for i in range(1, len(layers)):
        tup = layers[i]
        model.add(Dense( tup[0], activation=tup[2],  kernel_initializer=tup[1]))
    #optimizer =  ks.optimizers.SGD(lr=0.1, decay=1e-6, momentum=0.1, nesterov=True)
    optimizer = ks.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=None, decay=0.0)
    # w = model.get_weights()
    # w[0][0,1] = 10
    # model.set_weights(w)
    # outputTensor = model.output
    # listOfVariableTensors = model.trainable_weights
    # gradients = k.gradients(outputTensor, listOfVariableTensors)
    # print("gradients", gradients)
    # trainingExample = np.random.random((1, 8))
    # sess = tf.InteractiveSession()
    # sess.run(tf.initialize_all_variables())
    #

    #print("INPUT", model.input)

    #evaluated_gradients = sess.run(gradients, feed_dict={model.input: })
    #print("EVALUATED GRADIENTS",evaluated_gradients)
    #sess.close()

    #print("weigth",model.get_weights())
    return model, optimizer

def cplexmodel(jobs, machines, sequences):
    cplexmodel = Model(name = 'simple_job_shop')

    t = []

    for i in range(jobs):
        name = "t" + str(i)+"_"
        tj = cplexmodel.continuous_var_list(
            range(machines), lb = 0, name = name)
        t.append(tj)

    z = []
    for j in range(jobs):
        zj = []
        for k in range(jobs):
            name = "z"+str(j)+"_"+str(k)
            zjk = cplexmodel.binary_var_list(
                range(machines), name = name
            )
            zj.append(zjk)
        z.append(zj)
    m = cplexmodel.continuous_var(name = 'makespan')

    bigM = 0
    for seq in sequences:
        for s in seq:
            bigM = bigM + s[1]
    bigM = bigM*2
    #####CONSTRAINTS####
    for j in range(jobs):
        tj = t[j]
        seq = sequences[j]
        for i in range(1, len(seq)):
            ohj = seq[i][0]
            ohm1j = seq[i-1][0]
            pohm1j = seq[i-1][1]
            xohj = tj[ohj]
            xohm1j = tj[ohm1j]
            con = cplexmodel.add_constraint( xohj >= xohm1j + pohm1j)
            #print("CIAO",cplexmodel.pprint_as_string(con))
            if i == len(seq) -1:
                pohj = seq[i][1]
                cplexmodel.add_constraint( m >= xohj + pohj)

    for j in range(jobs):
        seqj = sequences[j]
        for k in range(jobs):
            if j != k:
                seqk = sequences[k]
                mach = machmerge(seqj, seqk)
                for machine in mach:
                    xij = t[j][machine]
                    #print(xij)
                    xik = t[k][machine]
                    #print(xik)
                    pij = 0
                    pik = 0
                    for s in seqj:
                        if s[0] == machine:
                            pij = s[1]
                            break
                    for s in seqk:
                        if s[0] == machine:
                            pik = s[1]
                            break

                    cplexmodel.add_constraint(xij >= xik + pik - bigM * z[j][k][machine])
                    cplexmodel.add_constraint(xik >= xij + pij - bigM + bigM * z[j][k][machine])

    #####Objective
    cplexmodel.minimize( m )
    #####Solution
    start = time()
    #print(cplexmodel.export_as_lp_string())

    solution = cplexmodel.solve(log_output = True)

    return (time() - start), solution, cplexmodel.objective_value

def machmerge( seqj, seqk):
    lista = []
    listb = []
    ##lista.append( seqj[i][0] for i in range(len(seqj)))
    for s in seqj:
        lista.append(s[0])
    lista = np.array(lista)
    #listb.append( seqk[i][0] for i in range(len(seqk)))
    for s in seqk:
        listb.append(s[0])
    listb = np.array(listb)
    intersection = np.intersect1d(lista, listb)
    #print("lista", lista,"\nlistb",listb,"\ninter", intersection)
    return intersection

def mainbalerion():
    seed = 300#70
    np.random.seed(seed)

    ############################################create instances###
    jobs = 2
    machines = 2
    sequences, n = createInstances(jobs = jobs, machines = machines)

    state_dimension = n + machines
    instance_dimension = n + machines + n + machines + machines
                     #jobs + machines + nextjobs + nextmachines + action
    print("State Dimension: ", state_dimension, "  Instance dimension: ", instance_dimension)

    ###############################################create model###
    innerlayers = [
        (instance_dimension*10+machines, 'uniform', 'relu'),
        #(2*state_dimension+machines, 'uniform', 'relu'),
        #(instance_dimension, 'uniform', 'relu'),
        (machines, 'uniform', 'sigmoid')
    ]

    outerlayers = [
        (instance_dimension+machines, 'uniform', 'relu'),
        (2*state_dimension, 'uniform', 'relu'),
        # (instance_dimension, 'uniform', 'relu'),
        (1, 'uniform', 'linear')
    ]
    #model, optimizer = createModel(  layers, instance_dimension ) #fi you need to check particular settings
                                                                 # for the optimizer please go deeper into the method

    #####################################Reinforcement Learning###

    min_experience = 1
    max_experience =  2
    min_gamma = 4
    max_gamma = 5

    M = 30

    record = []

    for experience in range(min_experience, max_experience):
        for gamma in range(min_gamma, max_gamma):

            seed = gamma*experience

            outermodel, outeroptimizer = createModel(outerlayers, instance_dimension+machines)  # fi you need to check particular settings

            innermodel, inneroptimizer = createModel(innerlayers, state_dimension+machines)  # fi you need to check particular settings

            # for the optimizer please go deeper into the method
            gamma = gamma/10
            trainer = balerion(
                innermodel,
                inneroptimizer,
                outermodel,
                outeroptimizer,
                jobs,
                machines,
                sequences,
                path=None,
                M=M,
                T=jobs * machines,
                peps=0.9,
                delta=0.75,
                gamma=gamma,
                experience=experience,
                size=10000000000,
                randomized=False,
                finalreward=200*2,#1e1,
                batch_size=5,
                verbose=True,
                npseed=seed)
            episode, reward, rewards, solution, elapsedtime, timings = trainer.solve()
            makespan = 0
            for timing in timings:
                makespan = makespan + timing
            print("Experience", experience," Gamma",gamma, " Best reward", reward," MAKESPAN", makespan, " Elapsed time", elapsedtime)

            record.append( ( experience, gamma, episode, reward, rewards, solution, elapsedtime, timings ) )
                            #   0          1       2       3        4         5          6          7

    ###show resuts###

    fig = plt.figure(1, figsize = (10,4.8))
    chart = fig.add_subplot(111)
    for i in record:
        name = str(i[0]) + "-"+ str(i[1])
        #y = gaussian_filter1d(i[4], sigma=1)
        x = np.array(range(len(i[4])))
        x_smooth = np.linspace(x.min(), x.max(), M)
        y_smooth = spline(x, np.array(i[4]), x_smooth)
        chart.plot( x_smooth, y_smooth, label = name)
    #chart.legend()
    plt.show()

    # episode, reward, rewards, solution, elapsedtime, timings = trainer.play()
    # makespan = 0
    # for timing in timings:
    #     makespan = makespan + timing
    # print("PLAY Experience", experience, " Gamma", gamma, " Best reward", reward, " MAKESPAN", makespan,
    #       " Elapsed time",
    #       elapsedtime)

    elaptime, sol, obj =cplexmodel(jobs, machines, sequences)

    print("CPLEX_SOL  Elapsed time", elaptime, " MAKESPAN", obj)

    return

mainbalerion()


"""empty message

Revision ID: b5f9c73b8cad
Revises: 162eff6dc9d5
Create Date: 2018-07-25 23:07:38.718941

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = 'b5f9c73b8cad'
down_revision = '162eff6dc9d5'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('customer', sa.Column('last_rec_time', sa.String(length=120), nullable=True))
    op.drop_column('customer', 'starred')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('customer', sa.Column('starred', mysql.TINYINT(display_width=1), server_default=sa.text("'0'"), autoincrement=False, nullable=True))
    op.drop_column('customer', 'last_rec_time')
    # ### end Alembic commands ###


""" Parts of the U-Net model """

import tensorflow as tf
from tensorflow import keras

class DoubleConv(keras.layers.Layer):
    """(convolution => [BN] => ReLU) * 2"""

    def __init__(self, in_channels, out_channels, mid_channels=None, first=False):
        super(DoubleConv, self).__init__()
        if not mid_channels:
            mid_channels = out_channels
        if first:
            self.double_conv = keras.models.Sequential([
                keras.layers.Conv2D(filters=mid_channels, kernel_size=3, activation="relu", padding="same"),
                keras.layers.BatchNormalization(),
                keras.layers.Conv2D(filters=mid_channels, kernel_size=3, activation="relu", padding="same")
            ])
        else:
            self.double_conv = keras.models.Sequential([
                keras.layers.Conv2D(filters=mid_channels, kernel_size=3, activation="relu", padding="same"),
                keras.layers.BatchNormalization(),
                keras.layers.Conv2D(filters=out_channels, kernel_size=3, activation="relu", padding="same")
            ])

    def call(self, x):
        return self.double_conv(x)

class Down(keras.layers.Layer):
    """Downscaling with maxpool then double conv"""

    def __init__(self, in_channels, out_channels):
        super(Down, self).__init__()
        self.maxpool_conv = keras.models.Sequential([
            keras.layers.MaxPool2D(2),
            DoubleConv(in_channels, out_channels)]
        )

    def call(self, x):
        return self.maxpool_conv(x)

class Up(keras.layers.Layer):
    """Upscaling then double conv"""

    def __init__(self, in_channels, out_channels, bilinear=False):
        super(Up, self).__init__()

        # if bilinear, use the normal convolutions to reduce the number of channels
        if bilinear:
            self.up = keras.layers.UpSampling2D(size=2, mode='bilinear')
            self.conv = DoubleConv(in_channels, out_channels, in_channels // 2)
        else:
            self.up = keras.layers.Conv2DTranspose(filters=in_channels//2, kernel_size=2, strides=2)
            self.conv = DoubleConv(in_channels, out_channels)

    def call(self, x1, x2):
        x1 = self.up(x1)

        # # input is CHW
        # diffY = x2.shape[2] - x1.shape[2]
        # diffX = x2.shape[3] - x1.shape[3]
        #
        # x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2,
        #                 diffY // 2, diffY - diffY // 2])
        # # if you have padding issues, see
        # # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a
        # # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd
        x = tf.concat([x2, x1], axis=3)
        return self.conv(x)

class OutConv(keras.layers.Layer):
    def __init__(self, in_channels, out_channels):
        super(OutConv, self).__init__()
        self.conv = keras.layers.Conv2D(out_channels, kernel_size=1)

    def call(self, x):
        return self.conv(x)


import os

from data import load_data
from sklearn.decomposition import FastICA
try:
    import cPickle as pickle
except:
    import pickle

# Factor Analysis

# ================================================================
# Apply independent component analysis on the tf-idf matrix and transform raw
# documents into intermediate representation.
docs_tfidf, vocab_tfidf, vocabulary = load_data(subset='all')
n_components = 40
ica = FastICA(n_components=n_components)
ica.fit(docs_tfidf.toarray())
ica_words = ica.transform(vocab_tfidf.toarray())

# Create a dict to hold the new pca words.
ica_dict = dict(zip(vocabulary, ica_words))

# Store the intermediate representation pca words on disk.
ica_dict_filename = 'ica_dict.pk'
if not os.path.exists(ica_dict_filename):
    ica_dict_file = open(ica_dict_filename, 'w')
    pickle.dump(ica_dict, ica_dict_file)

# Store estimator on dist for further usage.
ica_estimator_filename = 'ica_estimator.pk'
if not os.path.exists(ica_estimator_filename):
    ica_estimator_file = open(ica_estimator_filename, 'w')
    pickle.dump(ica, ica_estimator_file)
# ================================================================


import os
import torch.utils.data
import numpy as np
from PIL import Image
import json

from ssd.structures.container import Container

def get_valid_person(json_path):
    """Get the valid person object, which needs to satisfy the following conditions.
    *: The label of the object is pedestrian.
    *: The height of pedestrian is more than 50 pixel.
    *: The ridio of pedestrain is less than 0.35 (not sure)
    Args:
        json_path: the path of json file that will be decoded

    Retuens:
        valid_person: a dictionary and the keys of this dict is 'valid' and 'bbox'
        the value of 'valid' is a bool that valid == True means we get a valid person data
        the value of 'bbox_list' is a list that contains y_min, x_min, y_max, x_max
    """
    valid_person = dict()
    bbox_list = list()
    label_list = list()
    person_label = {'pedestrian': 1, 'rider': 2}
    with open(json_path, 'r') as label_json:
        annot = json.load(label_json)
    valid_index = 0
    for obj in annot['objects']:
        if obj['label'] == 'pedestrian':
            x, y, w, h = obj['bbox']
            if h > 60:
                x_vis, y_vis, w_vis, h_vis = obj['bboxVis']
                ratio = 1 - (w_vis * h_vis) / (w * h)
                if ratio < 0.35:
                    valid_index += 1
                    bbox = [y-1, x-1, y-1+h, x-1+w]
                    bbox_list.append(bbox)
                    label_list.append(person_label[obj['label']])
    if valid_index > 0:
        valid = True
    else:
        valid = False
    valid_person['valid'] = valid
    valid_person['bbox_list'] = bbox_list
    valid_person['label_list'] = label_list
    return valid_person

def get_data_list(img_path, json_path, split='train'):
    """Get the images and bbox labels lists, which contain people.
    Args:
        img_path: the path of images that contain people, actually the path is '/cityscape/leftImg8bit'
        label_path: the path of bbox labels that contain people, actually the path is '/cityscape/gtBboxCityPersons'

    Returns:
        valid image list and label list
    """

    img_list, json_list = list(), list()
    if split not in ['train', 'val']:
        return print("You should check the parameter of split!")
    else:
        i_dir = os.path.join(img_path, split)
        j_dir = os.path.join(json_path, split)
        city_list = sorted(os.listdir(j_dir))
        for city in city_list:
            i_city_dir = os.path.join(i_dir, city)
            j_city_dir = os.path.join(j_dir, city)
            js_list = sorted(os.listdir(j_city_dir))
            for js in js_list:
                label_json_path = os.path.join(j_city_dir, js)
                if get_valid_person(label_json_path)['valid'] == True:
                    json_name = label_json_path
                    img_name = os.path.join(i_city_dir, js).replace('gtBboxCityPersons.json', 'leftImg8bit.png')
                    img_list.append(img_name)
                    json_list.append(json_name)

        return img_list, json_list

class CitypersonDataset(torch.utils.data.Dataset):
    class_names = ('__background__',
                   'pedestrian')
    data_dir = '/home/szy/data/cityscape'
    #img_path = '/home/szy/data/cityscape/leftImg8bit'
    #json_path = '/home/szy/data/cityscape/gtBboxCityPersons'

    def __init__(self, data_dir, split, transform=None, target_transform=None, keep_difficult=False):
        self.data_dir = data_dir
        self.split = split
        self.transform = transform
        self.target_transform = target_transform
        self.keep_difficult = keep_difficult
        self.img_path = os.path.join(data_dir, 'leftImg8bit')
        self.json_path = os.path.join(data_dir, 'gtBboxCityPersons')
        self.img_list, self.json_list = get_data_list(self.img_path, self.json_path, split=split)

        self.class_dict = {class_name: i for i, class_name in enumerate(self.class_names)}

    def __getitem__(self, index):
        boxes, labels, is_difficult = self._get_annotation(index)
        if not self.keep_difficult:
            boxes = boxes[is_difficult == 0]
            labels = labels[is_difficult == 0]
        image = self._read_image(index)
        if self.transform:
            image, boxes, labels = self.transform(image, boxes, labels)
        if self.target_transform:
            boxes, labels = self.target_transform(boxes, labels)
        target = Container(
            boxes=boxes,
            labels=labels,
        )
        return image, target, index

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

    def _get_annotation(self, image_id):
        annotation_file = self.json_list[image_id]
        bbox_list = get_valid_person(annotation_file)['bbox_list']
        label_list = get_valid_person(annotation_file)['label_list']
        boxes = np.array(bbox_list, dtype=np.float32)
        labels = np.array(label_list, dtype=np.int64)
        is_difficult = np.zeros(labels.size, dtype=np.int8)
        return boxes, labels, is_difficult

    def _read_image(self, image_id):
        image_file = self.img_list[image_id]
        image = Image.open(image_file).convert("RGB")
        image = np.array(image)
        return image

if __name__ == '__main__':
    img_path = '/home/szy/data/cityscape/leftImg8bit'
    json_path = '/home/szy/data/cityscape/gtBboxCityPersons'
    img_list, json_list = get_data_list(img_path, json_path)
    print(img_list)
    data_dir = '/home/szy/data/cityscape'
    cityperson = CitypersonDataset(data_dir, split='train')
    image, target, index = cityperson.__getitem__(0)
    print('done')