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

def column_nan_ratios(data):
    '''
    Function takes in DataFrame and displays bar graph of percentage of NaNs per column

    Args:
    -----
    DataFrame
    '''
    nan_per_col_percentage=[]
    nan_per_col_percentage = data.isnull().sum().values/data.shape[0]
    col_names = data.columns
    df = pd.DataFrame({'Percentage missing': nan_per_col_percentage}, index=col_names)
    ax = df.plot.bar(rot=0,figsize=(20,4))
    plt.xticks(rotation=90)
    plt.title('Percentage missing in each column')
    plt.xlabel('Column Name')
    plt.ylabel('Percentage')
    plt.grid(color='g', linestyle='-', linewidth=.5)
    plt.show()

def bar_booktable(df):
    '''
    plots bar graph for counts of unique values in book table column

    '''

    book_table = df.groupby('book_table').count()['online_order']
    #calculating rartio of yes/no for book tables
    book_table = book_table/df.shape[0]

    #x,y for the text in the plot + the string for the output
    y = book_table.get_values().tolist()
    x = [x for x in range(len(y))]
    #zipping x,y cordinates and string value for yes/no online book option
    zip_x_y_str = zip(x,[y1 - .03 for y1 in y] ,y)

    df.groupby('book_table').count()
    #ploting graph to show ratio of online order options
    ax = book_table.plot(kind='bar', color=['palegreen','limegreen'], grid=True, title='Book Table Yes/No - count, percentage' )
    ax.set_xlabel('Book Table Option on Zomato')
    ax.set_ylabel('Percentage')
    #print the text(ratio) on the bar
    for x,y,s in zip_x_y_str:
        #print(x,y,s)
        #rounding the ratio to 3 decimal point
        s = round(s,3)
        #aligning text for the ratio on the bars
        ax.text(x,y,str(s), horizontalalignment='center',verticalalignment='center')

def bar_onlineorder(df):
    '''
    plots bar graph for counts of unique values in online order column

    '''

    online_order = df.groupby('online_order').count()['book_table']
    #calculating the ratio of yes/no for online ordering
    online_order = online_order/df.shape[0]

    #x,y for the text in the plot + the string for the output
    y = online_order.get_values().tolist()
    x = [x for x in range(len(y))]
    #zipping x,y cordinates and string value for yes/no online delivery option
    zip_x_y_str = zip(x,[y1 - .02 for y1 in y] ,y)

    ax = online_order.plot(kind='bar', color=['palegreen','limegreen'], grid=True, title='Online Order Yes/No - count, percentage' )
    ax.set_xlabel('Online Delivery Options on Zomato')
    ax.set_ylabel('Percentage')
    #print the text(ratio) on the bar
    for x,y,s in zip_x_y_str:
        #print(x,y,s)
        s = round(s,3)
        ax.text(x,y,str(s), horizontalalignment='center',verticalalignment='center')

def rating_curve(df):
    '''
    plots bar graph for counts of unique values in rate column

    '''

    #return the numerical value of ratings from string
    rate = df.apply(lambda x: x.rate.replace(" ","") if type(x.rate) == str else x.rate, axis=1).value_counts().sort_index()
    #Ratio of the ratings, total number of ratios = total number rows - sum of missing values)
    rate = rate/(df.shape[0] - df['rate'].isnull().sum())

    #x,y position of the text(ratio) for the bar graph
    y = rate.get_values().tolist()
    x = [x for x in range(len(y))]
    zip_x_y_str = zip(x,[y1 + .0008 for y1 in y] ,y)

    colors_list = ['grey'] + ['orangered'] + ['gold']*5  + ['yellow']*5 + ['yellowgreen']*5 + ['limegreen']*5 + ['green']*5 + ['darkgreen']*5 +['grey']

    fig, ax = plt.subplots(figsize=(20, 10))
    ax = rate.plot(kind='bar', color=colors_list, grid=True, title='Distribution of Ratings' )
    ax.set_xlabel('Ratings')
    ax.set_ylabel('Percentage')
    #text on bar plots
    for x,y,s in zip_x_y_str:
        #print(x,y,s)
        s = round(s,3)
        ax.text(x,y,str(s), horizontalalignment='center',verticalalignment='center')

def rates_to_color_code(rating):
    '''
    returns color bin in string form

    '''

    #print(rating)
    #print(type(rating))
    if type(rating) == str and rating != '-' and rating != 'NEW':
        #print("in if")
        rating = rating.replace(" ","").split('/')[0]
        if float(rating) <= 5 and float(rating) >= 4.5:
            return "4.5-5 dark green"
        elif float(rating) < 4.5 and  float(rating) >=4:
            return "4.0-4.4 green"
        elif float(rating) < 4 and float(rating) >= 3.5:
            return "3.5-3.9 light green"
        elif float(rating) < 3.5 and float(rating) >= 3:
            return "3.0-3.4 green yellow"
        elif float(rating) < 3 and float(rating) >= 2.5:
            return "2.5-2.9 yellow"
        elif float(rating) < 2.5 and float(rating) >= 2:
            return "2.0-2.4 yellow orange"
        elif float(rating) < 2 and float(rating) >= 1.5:
            return "1.5-1.9 red orange"
        elif float(rating) <1.5 and float(rating) >= 1:
            return "1.0-1.4 red"

    else:
        return rating

def color_bins(df):
    '''
    plots bar graph for different rating bins

    '''

    #ratios for the color bins
    #rates_to_color_code function returns the color of the rating
    rate_colors = df.apply(lambda x: rates_to_color_code(x.rate), axis=1).value_counts().sort_index()
    rate_colors = rate_colors/df.shape[0]

    #x,y and string(ratio)
    y = np.round(rate_colors.get_values(),4).tolist()
    x = [x for x in range(len(y))]
    zip_x_y_str = zip(x,[y1 + .008 for y1 in y] ,y)

    colors_list = ['grey','orangered','gold','yellow','yellowgreen','limegreen','green','darkgreen','grey']
    fig, ax = plt.subplots(figsize=(10, 6))
    ax = rate_colors.plot(kind='bar', color=colors_list, grid=True, title='Rating Color Category Bins' )
    ax.set_xlabel('Rating Bins and color Category')
    ax.set_ylabel('Percentage')
    for x,y,s in zip_x_y_str:
        #print(x,y,s)
        s = round(s,4)
        ax.text(x,y,str(s), horizontalalignment='center',verticalalignment='center')

def listed_in_city(df):
    '''
    plots bar graph for counts with unique values in listed in city

    '''

    location_count = df['listed_in(city)'].value_counts()
            #print("30 Main Locations Listed on Zomato for quick searches:"df['listed_in(city)'].value_counts().shape[0],df['listed_in(city)'].value_counts().keys())
    fig, ax = plt.subplots(figsize=(7, 5))
    ax.bar(location_count.keys()[:],location_count.values[:],color = 'green')
    ax.grid(color='g', linestyle='-', linewidth=.5)
    ax.set_xlabel('Locations')
    ax.set_ylabel('Counts')
    plt.title('Locations and Respective Restaurant Counts')
    plt.xticks(rotation=90)
    plt.show()

def location(df):
    '''
    plots bar graph for counts with unique values in location column

    '''

    location_count = df['location'].value_counts()
    print("Total Locations:",df['location'].value_counts().shape[0],"\nLocations:",df['location'].value_counts().keys())
    print("\n Top 50 Locations with restaurant Counts")
    fig, ax = plt.subplots(figsize=(12, 5))
    ax.bar(location_count.keys()[0:50],location_count.values[0:50])
    ax.grid(color='g', linestyle='-', linewidth=.5)
    ax.set_xlabel('Locations')
    ax.set_ylabel('Count')
    plt.title('Top 10 locations with highest number of Restaurants')
    plt.xticks(rotation=90)
    plt.show()

    return

def rest_type_listedin(df):
    '''
    plots bar graph for counts with unique values in rest_type column

    '''

    location_count = df['listed_in(type)'].value_counts()
    #print(df['listed_in(type)'].value_counts().shape[0])
    fig, ax = plt.subplots(figsize=(8, 5))
    ax.bar(location_count.keys()[0:10],location_count.values[0:10]/df.shape[0])
    ax.grid(color='g', linestyle='-', linewidth=.5)
    ax.set_xlabel('Restaurant Types')
    ax.set_ylabel('Percentage')
    plt.title('7 Restaurant Types listed on Restaurant \n and their percentage out of 51,717 Restautrants ')
    plt.xticks(rotation=90)
    plt.show()

def rest_mixed_type(df):
    '''
    plots bar graph for counts with unique values in rest_type column

    returns:
    -------
    (list) unique restaurants as listed by the restaurants

    '''
    #Restraunt types are comma separated i.e each restaurant can have multiple restraunt types
    #finding unique restaurant types
    unique_rest = {}
    rest_max_row = {1:0,2:0,3:0}
    for i in range(51717):
        if type(df.loc[i]['rest_type']) == str:
            rest_type =  df.loc[i]['rest_type'].replace(" ", "").lower()
            list_rest = rest_type.split(',')
        #print(len(list_rest))
            rest_max_row[len(list_rest)] += 1
            for rest_typ in list_rest:
                if rest_typ not in unique_rest:
                    unique_rest[rest_typ] = 1
                else:
                    unique_rest[rest_typ] +=1
    rest_max_row[0] = df['rest_type'].isnull().sum()
    print("types counts: restaurant counts", rest_max_row)
    df_rest  = pd.Series(rest_max_row, index=rest_max_row.keys())

    ax = df_rest.plot(kind='bar', color='green', grid=True, title='Number of Restaurants types listed by Restaurants' )
    ax.set_xlabel('Restauraunts Labels')
    ax.set_ylabel('Count')

    return unique_rest

def unique_rest_types(df, unique_rest):
    '''
    plots bar graph

    returns:
    -------
    (list) unique restaurants as listed by the restaurants

    '''

    fig, ax = plt.subplots(figsize=(8, 6))
    ax.bar(unique_rest.keys(),np.array(list(unique_rest.values())))
    ax.grid(color='g', linestyle='-', linewidth=.5)
    ax.set_xlabel('Restaurants Type')
    ax.set_ylabel('Count')
    plt.title('Restaurant Type listed by Restaurant')
    plt.xticks(rotation=90)
    plt.show()

def unique_cuisines(df):

    unique_cuisines = {}
    cuisine_max_row = {1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0} #stores the maximum number of restaurant types mentioned in the column "rest_type"
    for i in range(51717):
        if type(df.loc[i]['cuisines']) == str:
            cuisines_type =  df.loc[i]['cuisines'].replace(" ", "").lower()
            list_cuisines = cuisines_type.split(',')
            cuisine_max_row[len(list_cuisines)] += 1
            for cuisines_typ in list_cuisines:
                if cuisines_typ not in unique_cuisines:
                    unique_cuisines[cuisines_typ] = 1
                else:
                    unique_cuisines[cuisines_typ] +=1
    cuisine_max_row[0] = df['cuisines'].isnull().sum()
    df_c  = pd.Series(cuisine_max_row, index=cuisine_max_row.keys())

    ax = df_c.plot(kind='bar', color='green', grid=True, title='Cuisines Count' )
    ax.set_xlabel('Number of Cuisines listed per Restaurant')
    ax.set_ylabel('Count')

    return unique_cuisines

def unique_cuisines_top30(df,unique_cuisines):

    cuisines_series  = pd.Series(unique_cuisines, index=unique_cuisines.keys()).sort_values(ascending = False)
    fig, ax = plt.subplots(figsize=(4, 8))
    print("Total Number of Unique cuisines:",len(unique_cuisines.keys()))
    ax.barh(list(cuisines_series.keys())[:30],list(cuisines_series.values[:30]))
    ax.grid(color='g', linestyle='-', linewidth=.5)
    ax.set_xlabel('Count')
    ax.set_ylabel('Cuisines')
    plt.title('Restaurant Counts for top 30 served cuisines')
    #plt.xticks(fontsize = 9,rotation=90)
    plt.show()

def unique_cuisines_lowest30(df,unique_cuisines):

    cuisines_series  = pd.Series(unique_cuisines, index=unique_cuisines.keys()).sort_values(ascending = False)
    fig, ax = plt.subplots(figsize=(4, 8))
    #print("Total Number of Unique cuisines:",len(unique_cuisines.keys()))
    ax.barh(list(cuisines_series.keys())[-30:-1],list(cuisines_series.values[-30:-1]))
    ax.grid(color='g', linestyle='-', linewidth=.5)
    ax.set_xlabel('Count')
    ax.set_ylabel('Cuisines')
    plt.title('Restaurant counts for lowest 30 served cuisines')
    #plt.xticks(fontsize = 9,rotation=90)
    plt.show()


# Flask
from flask import Flask, request, abort, make_response, jsonify
from flask_restful import Api, Resource, reqparse, fields, marshal
# Custom modules
from html_processor import JobData
from postgres_handler import PGHandler
from postgres_config import pg_config

app = Flask(__name__)
api = Api(app)

# Define the fields to be yielded during GET requests
job_fields = {
    'id': fields.Integer,
    'url': fields.String,
    'title': fields.String,
    'company': fields.String,
    'location': fields.String,
    'seniority': fields.String,
    'employment_type': fields.String,
    'industries': fields.List(fields.String),
    'functions': fields.List(fields.String),
    'posting_text': fields.String,
    'uri': fields.Url('job')
}

# Initialize a connection pool to the Postgres database
# NOTE: Connection parameters must be specified in the .env file
PGHandler.init_connection_pool()
print("API is ready to accept requests!")

def attempt_connection():
    """
    Attempts to connect to the postgres database if the connection has not been established already
    """
    if PGHandler.connection_status == False:
        try:
            PGHandler.init_connection_pool()
        except Exception as error:
            print(str(error))
            abort(504)

@app.route("/")
def hello():
    return "Hello World from Flask inside Docker!"

@app.route("/jobdataextractor/api/v1.0/checkconnection/", methods=['GET'])
def checkconnect():
    return "Current connection status to database is: " + str(PGHandler.connection_status)

@app.route("/jobdataextractor/api/v1.0/tryconnection/", methods=['GET'])
def tryconnect():
    PGHandler.init_connection_pool()
    return "Current connection status to database is: " + str(PGHandler.connection_status)

class JobListAPI(Resource):

    # Validation arguments for '/jobs' endpoint
    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('id', type=int, required=True,
                                   help='No job id provided',
                                   location='json')
        self.reqparse.add_argument('HTML', type=str, required=True,
                                   help='No HTML provided',
                                   location='json')
        super(JobListAPI, self).__init__()

    def get(self):
        # Verify connection, exit if failed
        attempt_connection()

        # Select data for all jobs (no id passed) from the Postgres database and store to appropriate dict
        job_list = PGHandler.select_job()

        if job_list == False:
            abort(504)
        elif job_list is None:
            abort(404)
        else:
            return {'job_list': [marshal(job, job_fields) for job in job_list]}, 200

    def post(self):
        # Verify connection, exit if failed
        attempt_connection()

        # Assign the id and HTML received from the Chrome Extension into a JobData object
        args = self.reqparse.parse_args()
        job_args = {
            'id': args['id'],
            'html': args['HTML']
        }
        current_job = JobData(job_input_data=job_args)

        # Have the JobData object extract the relevant data fields from the raw HTML
        current_job.extract_job_data()

        # Commit extracted data to the Postgres database and return HTML code
        if PGHandler.insert_job(current_job.data):
            return {'job': marshal(current_job.data, job_fields)}, 201
        else:
            abort(409)

class JobAPI(Resource):

    # Validation arguments for '/jobs/<id>' endpoint
    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument('id', type=int, required=True,
                                   help='No job id provided',
                                   location='json')
        #self.reqparse.add_argument('HTML', type=str, location='json')
        super(JobAPI, self).__init__()

    def get(self, id):
        # Verify connection, exit if failed
        attempt_connection()

        # Select data for the specific job id from the Postgres database and store to appropriate dict
        selected_job = PGHandler.select_job(id)

        if selected_job == "Connection Failed":
            abort(504)
        elif selected_job is None:
            abort(404)
        else:
            return {'job': marshal(selected_job, job_fields)}, 200

api.add_resource(JobListAPI, '/jobdataextractor/api/v1.0/jobs/', endpoint = 'jobs')
api.add_resource(JobAPI, '/jobdataextractor/api/v1.0/jobs/<int:id>', endpoint = 'job')

if __name__ == '__main__':
    app.run(debug=True)

# TODO:
# Update documentation and push to repo


from flask import Flask, request, render_template
import os
import cv2 as cv
import numpy as np
from werkzeug.utils import secure_filename

app = Flask(__name__)

# folder where the images are stored
image_folder = os.path.join('static', 'images')
app.config['UPLOAD_FOLDER'] = image_folder

@app.route('/')
def detect():
    return render_template('home.html')

@app.route('/detect', methods=['POST'])
def detect_post():
    img = request.files['image']
    # Extracting uploaded data file name
    img_filename = secure_filename(img.filename)
    image = os.path.join(app.config['UPLOAD_FOLDER'], img_filename)
    result_image = crosswalk_detection(image)
    IMG_LIST = [image, result_image]

    return render_template('show_image.html', imagelist=IMG_LIST)

def crosswalk_detection(image):
    # loading yolo config file and yolo trained model
    net = cv.dnn.readNetFromDarknet("yolo-files\custom_yolov3_10000.cfg","yolo-files\custom_yolov3_10000.weights")
    # classes for trained model
    classes = []
    with open('yolo-files\classes.names','r') as f:
        classes = [line.strip() for line in f.readlines()]

    # image to be detected
    test_img = cv.imread(image)
    height,width,_ = test_img.shape

    # convert the image to yolo format
    blob = cv.dnn.blobFromImage(test_img, 1/255,(416,416),(0,0,0),swapRB = True,crop= False)
    net.setInput(blob)
    last_layer = net.getUnconnectedOutLayersNames()
    layer_output = net.forward(last_layer)

    boxes =[]
    confidences = []
    class_ids = []

    for output in layer_output:
        for detection in output:
            score = detection[5:]
            class_id = np.argmax(score)
            confidence = score[class_id]
            if confidence > 0.6:
                center_x = int(detection[0] * width)
                center_y = int(detection[1] * height)
                w = int(detection[2] * width)
                h = int(detection[3]* height)

                x = int(center_x - w/2)
                y = int(center_y - h/2)

                boxes.append([x,y,w,h])
                confidences.append((float(confidence)))
                class_ids.append(class_id)

    # find the bounding box
    indexes = cv.dnn.NMSBoxes(boxes,confidences,.6,.4)
    font = cv.FONT_HERSHEY_PLAIN
    if  len(indexes)>0:
        for i in indexes.flatten():
            x,y,w,h = boxes[i]
            label = str(classes[class_ids[i]])
            confidence = str(round(confidences[i],2))
            cv.rectangle(test_img,(x,y),(x+w,y+h),(255,0,0),2)
            cv.putText(test_img,label + " " + confidence, (x,y),font,2,(255,255,255),2)

    # save the resulting image
    result_path = os.path.join(app.config['UPLOAD_FOLDER'], 'result.jpg')
    cv.imwrite(result_path, test_img)

    return result_path

if __name__ == '__main__':
    port = int(os.environ.get('PORT', 5000))
    app.run(debug=True, host='0.0.0.0', port=port)


import threading
import json

lock = threading.Lock()

iplist = set()

def addtoiplist(ip):
	iplist.add(ip)

def getiplist():
	return iplist

tnxlist = {}

current_tnxid = 0

def performtnx(name, qty):

	if name in itemlist.keys():
		if qty <= itemlist[name]['qty']:
			itemlist[name]['qty'] = itemlist[name]['qty'] - qty

			if itemlist[name]['qty'] == 0:
				del itemlist[name]
		else:
			return False
	else:
		print("Parser Error: Invalid Transaction")
		return False

	return True

def createtnx(name, qty):
	global current_tnxid

	if performtnx(name, qty):
		print("Transaction Successful!")
	else:
		print("Parser Error: Transaction failed!")
		return False

	current_tnxid = current_tnxid + 1

	tnxlist[current_tnxid] = {'tnxid':current_tnxid,
					  'name': name,
					  'qty': qty}
	return createRequest('ADDTNX', tnxlist[current_tnxid])

def gettnxlist():
	return tnxlist

itemlist = {}

current_itemid = 0

def createitem(name, qty, price):
	global current_itemid
	current_itemid = current_itemid + 1

	if name in itemlist.keys():
		return False

	itemlist[name] = {'itemid':current_itemid,
					  'name': name,
					  'qty': qty,
					  'price': price}
	return createRequest('ADDITM', itemlist[name])

def getitemlist():
	return itemlist

""" Data is processed as JSON format.
HEADERs for the data is created over here """
# Item List and Transactions. TNX should cange the amount of qtys in other nodes. TNX to be generated on a buy or a sell
# {HEAD: "SNDALL" | "SNDTNX", DATA: {"txid" : 123, "item" : "iphone", "qty" : 10,  "price" : 1000 }}

# Instructions:
# parseHeader return val: Parse Result -> True/False, Send To individual thread -> True/False, Data
# Anything created in the Parser will return as a request

def createDictonary(HEAD, DATA):
	dicti = {}
	dicti['HEAD'] = HEAD
	dicti['DATA'] = DATA
	return dicti

def createInitDictonary(HEAD, IPLIST, ITEMLIST):
	dicti = {}
	dicti['HEAD'] = HEAD
	dicti['IPLIST'] = IPLIST
	dicti['ITEMLIST'] = ITEMLIST
	return dicti

def createRequest(HEAD, DATA = {}):

	if(HEAD == 'INITCN' or HEAD == 'rINITCN'):
		return json.dumps(createInitDictonary(HEAD, repr(iplist), itemlist))

	elif((HEAD == 'ADDTNX' or HEAD == 'ADDITM') and DATA):
		return json.dumps(createDictonary(HEAD, DATA))

class parser:

	def __init__(self, jsonString):
		# self.jsonString = jsonString
		self.d = json.loads(jsonString)
		self.HEAD = self.d['HEAD']

		try:
			self.DATA = self.d['DATA']
		except:
			self.IPLIST = self.d['IPLIST']
			self.ITEMLIST = self.d['ITEMLIST']

	def parseHeader(self):

		global lock

		if(self.HEAD == 'ADDTNX'):
			global current_tnxid
			print("DEBUG: Received ADDTNX Packet")
			# ADDTNX - ADD a Transaction. Tnx is present in DATA field
			# Place to Modify the Transaction Protocol
			if self.DATA['tnxid'] not in tnxlist.keys():

				lock.acquire()

				if performtnx(self.DATA['name'], self.DATA['qty']):

					print("Transaction Successful!")

					current_tnxid = self.DATA['tnxid']
					tnxlist[self.DATA['tnxid']] = self.DATA

					lock.release()

					return True, False, createRequest('ADDTNX',self.DATA)

				else:
					print("Parser Error: Transaction failed!")

				lock.release()
			else:
				return True, False, None

		elif(self.HEAD == 'ADDITM'):
			global current_itemid
			# ADDITM - Add Item to ItemList. Item details is present in Data field
			# Rebroadcast ADDITM

			if self.DATA['name'] not in itemlist.keys():

				lock.acquire()

				current_itemid = self.DATA['itemid']
				itemlist[self.DATA['name']] = self.DATA

				lock.release()

				return True, False, createRequest('ADDITM', self.DATA)
			else:
				# Item Already received
				print("Ignore ADDITM")
				return True, False, None

		elif(self.HEAD == 'INITCN'):
			# INIT - New Initial connection. Send the Ip list

			lock.acquire()

			iplist.update(eval(self.IPLIST))
			itemlist.update(self.ITEMLIST)

			lock.release()

			return True, True, createRequest('rINITCN')

		elif(self.HEAD == 'rINITCN'):
			# rINITIP - reply Initial connection. Receive the IP list and update

			lock.acquire()

			iplist.update(eval(self.IPLIST))
			itemlist.update(self.ITEMLIST)

			lock.release()

			return True, False, None

		else:
			return False, False, None


import pygame
from pygame.locals import *

from scene import Scene
from scenes import EyesCalibration
from screen import boundary, Screen

class Verify(Scene):
    def __init__(self, surface, fontname, parent=None, screen=None):
        super(Verify, self).__init__(surface, fontname, parent)
        with open('screen.conf') as f:
            screen = eval(f.read())
        self.screen = screen
        s = Screen()
        s.ppl = screen['ppl']
        s.wpl = screen['wpl']
        self.sub_surf = surface.subsurface(pygame.Rect((480, 540), (960, 540)))
        self.sub_window = EyesCalibration(self.sub_surf, fontname, self, s, (480, 540))

    def process_event(self, event):
        if event.type == KEYUP and event.key in self.keys:
            self.process_key_event(event)
        else:
            self.sub_window.process_event(event)

    def draw(self):
        self.surface.fill(0)
        begin = int((self.sub_window.position[0] - self.screen['offset'])
                / self.screen['period'] % 1. * self.screen['ppl'])
        for x in boundary(self.screen['ppl'], 1120, 800):
            for i in range(begin, begin + self.screen['wpl']):
                pygame.draw.line(self.surface, (0, 255, 0), (x + i, 100), (x + i, 980))
            # for i in range(self.screen.offset + self.screen.wpl, self.screen.offset + self.screen.wpl * 2):
            #     pygame.draw.line(self.surface, (0, 0, 255), (x + i, 100), (x + i, 980))
        self.sub_window.draw()

    def esc(self, _):
        exit()

    keys = {K_ESCAPE: esc, K_SPACE: esc}


'''
Newton solver from commit d084cd00d9e9d884002527ef581d957d94433647
Date:   Thu Dec 11 09:06:24 2014
'''

import traceback, time
import FreeCAD
from assembly2.solvers.common import *
from assembly2.core import QtGui
from .variableManager import VariableManager
from assembly2.constraints import *
import numpy

def solve_via_simplex( constraintEqs, x0, bounds ):
    import scipy.optimize
    algName = 'scipy.optimize.fmin (simplex, nelder mead solver)'
    errorNorm = lambda x: numpy.linalg.norm(constraintEqs(x))
    R = scipy.optimize.fmin( errorNorm, x0, disp=False, full_output=True)
    optResults = dict( zip(['xOpt', 'fOpt' , 'iter', 'funCalls', 'warnInt'], R ) ) # see scipy.optimize.fmin_bfgs docs for info
    if optResults['warnInt'] == 0:
        warningMsg = ''
    else:
        warningMsg = { 1: 'Maximum number of function evaluations made.',
                       2: 'Maximum number of iterations reached.' }[optResults['warnInt']]
    return algName, warningMsg, optResults

def solve_via_bfgs( constraintEqs, x0, bounds ):
    import scipy.optimize
    algName = 'scipy.optimize.fmin_bfgs'
    errorNorm = lambda x: numpy.linalg.norm(constraintEqs(x))
    R = scipy.optimize.fmin_bfgs( errorNorm, x0 , disp=False, full_output=True)
    optResults = dict( zip(['xOpt', 'fOpt' , 'gOpt', 'BOpt', 'func_calls', 'grad_calls', 'warnInt'], R ) ) # see scipy.optimize.fmin_bfgs docs for info
    if optResults['warnInt'] == 0:
        warningMsg = ''
    else:
        warningMsg = { 1: 'Maximum number of iterations exceeded.',
                       2: 'Gradient and/or function calls not changing.' }[optResults['warnInt']]
    return algName, warningMsg, optResults

def solve_via_slsqp( constraintEqs, x0, bounds , iterations=160 ):
    import scipy.optimize
    algName = 'scipy.optimize.fmin_slsqp (Sequential Least SQuares Programming)'
    errorNorm = lambda x: numpy.linalg.norm(constraintEqs(x))
    R = scipy.optimize.fmin_slsqp( errorNorm, x0, bounds=bounds, disp=False, full_output=True, iter=iterations)
    optResults = dict( zip(['xOpt', 'fOpt' , 'iter', 'imode', 'smode'], R ) ) # see scipy.optimize.fmin_bfgs docs for info
    if optResults['imode'] == 0:
        warningMsg = ''
    else:
        warningMsg = optResults['smode']
    return algName, warningMsg, optResults

#def solve_via_fsolve( constraintEqs, x0, bounds ):
#    import scipy
#    Does not work as number of constraint equations does not equal number of variables.
#    algName = 'scipy.optimize.fsolve'
#    xOpt, infodict , solvedInt, warningMsg = scipy.optimize.fsolve( constraintEqs, x0, full_output=False)
#    infodict['xOpt'] = xOpt
#    return algName, warningMsg, infodict

def objects_violating_constraints( constraints ):
    violatedConstraints = [c for c in constraints if not c.satisfied() ]
    vNames = [ vc.constraintObj.Name for vc in violatedConstraints ]
    debugPrint( 3, "violated constraints: " + ', '.join(vNames) )
    vObjects = sum( [ vc.objectNames() for vc in violatedConstraints ], [] )
    debugPrint( 3, "objects associated to these constraints: " + ', '.join( list(set(vObjects))))
    return vObjects

def solveConstraints(
        doc,
        showFailureErrorDialog=True,
        printErrors=True,
        use_cache=False,
        solver=solve_via_slsqp,
        random_restart_attempts=1
):
    assert not use_cache, "cache not implemented for Newton solver"
    T_start = time.time()
    variableManager = VariableManager( doc )
    constraints = []
    mapper = {
        'axial':AxialConstraint,
        'plane':PlaneConstraint,
        'circularEdge':CircularEdgeConstraint,
        'angle_between_planes':AngleConstraint,
        'sphericalSurface':SphericalSurfaceConstraint
        }
    for obj in doc.Objects:
        if 'ConstraintInfo' in obj.Content:
            debugPrint(3, "assembly2solver parsing %s" % obj.Name )
            #try:
            constraints.append( mapper[obj.Type]( doc, obj, variableManager) )
            #except AttributeError, msg:
            #    if str(msg).strip() == "'NoneType' object has no attribute 'Placement'":
            #        flags = QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.Abort
            #        message = "%s is refering to an object no longer in the assembly. Delete constraint? otherwise abort solving." % obj.Name
            #        response = QtGui.QMessageBox.critical(QtGui.qApp.activeWindow(), "Broken Constraint", message, flags )
            #        if response == QtGui.QMessageBox.Yes:
            #            FreeCAD.Console.PrintError("removing constraint %s" % obj.Name)
            #            doc.removeObject(obj.Name)
            #        else:
            #            FreeCAD.Console.PrintError("aborted solving constraints due to %s refering a non-existent object" % obj.Name)
            #            return
            #    else:
            #        raise AttributeError(msg)

    violatedConstraints = [c for c in constraints if not c.satisfied() ]
    vNames = [ vc.constraintObj.Name for vc in violatedConstraints ]
    debugPrint( 3, "violated constraints: " + ', '.join(vNames) )
    vObjects = sum( [ vc.objectNames() for vc in violatedConstraints ], [] )
    debugPrint( 3, "objects associated to these constraints: " + ', '.join( list(set(vObjects))))
    vObjects_connectivety = [ sum( obj in c.objectNames() for c in constraints ) for obj in vObjects ]
    debugPrint( 3, "repective connectivety %s " %  vObjects_connectivety)
    if len(violatedConstraints) == 1 and len(vObjects_connectivety) == 2 and sum(vObjects_connectivety) > 2:
        if not variableManager.objFixed(vObjects[0]) and not variableManager.objFixed(vObjects[1]):
            for obj, conn in zip(vObjects, vObjects_connectivety):
                if conn == 1: # makes vObjects_connectivety[0] == 1 or vObjects_connectivety[1] == 1 unnessary
                    variableManager.fixEveryObjectExcept( obj )
                    debugPrint( 3, "moving %s as to satisfy %s, everything else fixed" % ( obj, vNames[0]) )
                    constraints = violatedConstraints

    def constraintEqs(x): #equations which need to solved inorder to assemble parts
        variableManager.setValues(x)
        errors = sum( [c.errors() for c in constraints], [] )
        debugPrint( 4, "constraint errors %s" % errors )
        return errors

    x0 = variableManager.getValues()
    debugPrint(3, "variableManager.getValues() %s" % x0)

    algName, warningMsg, optResults = solver(constraintEqs, x0, variableManager.bounds() )
    debugPrint(3, str(optResults))
    if warningMsg !=  '' or optResults['fOpt'] > 10**-4 and random_restart_attempts > 0:
        for i in range(random_restart_attempts):
            variableManager.setValues(x0)
            xN = variableManager.peturbValues( vObjects )
            algName, warningMsg, optResults = solver(constraintEqs, xN, variableManager.bounds() )
            debugPrint(3, str(optResults))
            if warningMsg == '' and optResults['fOpt'] < 10**-4:
                break

    if warningMsg == '' and optResults['fOpt'] < 10**-4: #then constraints satisfied
        variableManager.setValues( optResults['xOpt'] )
        variableManager.updateFreeCADValues( )
        return  optResults['xOpt']
    elif showFailureErrorDialog and QtGui.qApp != None:
        FreeCAD.Console.PrintError("UNABLE TO SOLVE ASSEMBLY CONSTRAINTS. Info:\n")
        FreeCAD.Console.PrintError("  optimization algorithm could not minimize the norm of constraint errors\n" )
        FreeCAD.Console.PrintError("    optimization algorithm used  : %s\n" % algName )
        FreeCAD.Console.PrintError("    optimization warning message : %s\n" %  warningMsg)
        for k,v in optResults.iteritems():
            FreeCAD.Console.PrintError("    %s: %s\n" % (k,v))
        FreeCAD.Console.PrintError("UNABLE TO SOLVE ASSEMBLY CONSTRAINTS. refer to the Report View window for info\n")
        # http://www.blog.pythonlibrary.org/2013/04/16/pyside-standard-dialogs-and-message-boxes/
        flags = QtGui.QMessageBox.StandardButton.Yes
        flags |= QtGui.QMessageBox.StandardButton.No
        message = """The Assembly 2 Netwon solver failed to find a solution to the specified constraints.
This is due to either
  - the contraint problem being too difficult for the solver, or
  - impossible/contridictorary constraints have be specified.

Either way, the solution is most likely to delete the problematic constraints, and try again using a different constraint scheme.
Delete constraints [%s]?
 """ % ', '.join(vNames)
        response = QtGui.QMessageBox.critical(
            QtGui.qApp.activeWindow(),
            "Solver Failure!",
            message,
            flags
        )
        if response == QtGui.QMessageBox.Yes:
            for name in vNames:
                doc.removeObject(name)
                FreeCAD.Console.PrintError("removed constraint %s" % name)
        return None


import unittest, sys
from unittest.mock import patch
from io import StringIO
import student

class Tests(unittest.TestCase):
	inputs = "Some input\n"
	@patch('sys.stdin', StringIO(inputs))
	@patch('sys.stdout', new_callable = StringIO)
	def test01_part_1(self, stdout):
		correct = "Enter a sentence or phrase:\nYou entered: Some input\n"
		student.main()
		result = stdout.getvalue()[:len(correct)]
		self.assertEqual(result, correct)

	def test02_part_2(self):
		input = "Some input"
		correct = 9
		try:
			result = student.num_letters(input)
			self.assertEqual(result, correct)
		except AttributeError:
			self.fail('Message: num_letters() function is missing')
		except TypeError:
			self.fail('Message: num_letters() function has incorrect parameters')

	inputs = "May the force be with you!\n"
	@patch('sys.stdin', StringIO(inputs))
	@patch('sys.stdout', new_callable = StringIO)
	def test03_part_3(self, stdout):
		correct = "Enter a sentence or phrase:\nYou entered: May the force be with you!\nNumber of letters: 20\n"
		try:
			student.main()
			result = stdout.getvalue()[:len(correct)]
			self.assertEqual(result, correct)
		except AttributeError:
			self.fail('Message: num_letters() function is missing')
		except TypeError:
			self.fail('Message: num_letters() function has incorrect parameters')

	@patch('sys.stdout', new_callable = StringIO)
	def test04_part_4(self, stdout):
		input = " lots  \nof \tspa\tc\tes\n\n"
		correct = "String with no whitespace: lotsofspaces\n"
		try:
			student.output_without_whitespace(input)
			result = stdout.getvalue()
			self.assertEqual(result, correct)
		except AttributeError:
			self.fail('Message: output_without_whitespace() function is missing')
		except TypeError:
			self.fail('Message: output_without_whitespace() function has incorrect parameters')

	inputs = "Do. Or do not. There is no try.\n"
	@patch('sys.stdin', StringIO(inputs))
	@patch('sys.stdout', new_callable = StringIO)
	def test05_part_5(self, stdout):
		correct = "Enter a sentence or phrase:\nYou entered: Do. Or do not. There is no try.\nNumber of letters: 21\nString with no whitespace: Do.Ordonot.Thereisnotry.\n"
		try:
			student.main()
			result = stdout.getvalue()
			self.assertEqual(result, correct)
		except AttributeError:
			self.fail('Message: output_without_whitespace() function is missing')
		except TypeError:
			self.fail('Message: output_without_whitespace() function has incorrect parameters')

def main(simple):
	suite = unittest.defaultTestLoader
	runner = unittest.TextTestRunner(stream=StringIO(), descriptions=False)
	result = runner.run(suite.loadTestsFromTestCase(Tests))
	total = result.testsRun
	if result.wasSuccessful():
		score = 10
		passed = total
	else:
		passed = total - len(result.failures) - len(result.errors)
		score = round(passed/total*10,2)
	report = f"Passed: {passed}/{total}\nScore: {score}\n"
	if not simple:
		failed = []
		for i in result.failures:
			failed.append(f"Fail: {i[0].id()[15:]}")
		for i in result.errors:
			failed.append(f"Error: {i[0].id()[15:]}")
		report += "Failed:\n"
		for i in failed:
			report += f"\t{i}\n"
	return score, report

if __name__ == '__main__':
	score, report = main(sys.argv[1]=='True')
	with open('score.txt','w') as f:
		f.write(str(score))
		f.write('\n'+report)


from flask import Flask
from flask_ngrok import run_with_ngrok
from flask import jsonify, request

from firebase_admin import credentials, firestore, initialize_app

app = Flask(__name__)
app.config['JSONIFY_PRETTYPRINT_REGULAR'] = False
run_with_ngrok(app)  # Start ngrok when app is run

cred = credentials.Certificate('./fs.json')
app_fs = initialize_app(cred)
db = firestore.client()

sensor = db.collection('sensor')

@app.route("/", methods=['GET'])
def index():
  return 'Welcome to FLASK'

# /create_sensor
@app.route("/create_sensor", methods=['POST'])
def create_sensor():
  try:
    print(request)

    sensor_id = request.form['id']
    sensor.document(sensor_id).set(request.form)
    return jsonify({
        "status": "CREATED",
        "data": request.form
    })
  except Exception as e:
    return jsonify({
        "status": "ERROR",
        "details": e
    })

@app.route("/get_sensor", methods=['GET'])
def get_sensor():
  try:
    sensor_id = request.args.get('id')
    print("sensor_id", sensor_id)

    if sensor_id:
      sensor_data = sensor.document(sensor_id).get()
      return jsonify({
          "status": "SUCCESS",
          "data": sensor_data.to_dict()
      })
    else:
      all_sensor = [doc.to_dict() for doc in sensor.stream()]
      return jsonify({
          "status": "SUCCESS",
          "data": all_sensor
      })
  except Exception as e:
    return jsonify({
        "status": "ERROR",
        "details": e
    })

# /update_sensor
@app.route("/update_sensor", methods=['POST', 'PUT'])
def update_sensor():
  try:
    sensor_id = request.form['id']
    sensor.document(sensor_id).update(request.form)
    sensor_data = sensor.document(sensor_id).get()
    return jsonify({
          "status": "UPDATED",
          "data": sensor_data.to_dict()
    })
  except Exception as e:
    return jsonify({
        "status": "ERROR",
        "details": e
    })

@app.route("/delete_sensor", methods=['GET', 'DELETE'])
def delete_sensor():
  try:
    sensor_id = request.args.get('id')
    sensor_data = sensor.document(sensor_id).delete()
    return jsonify({
          "status": "DELETED",
          "id": sensor_id
      })
  except Exception as e:
    return jsonify({
        "status": "ERROR",
        "details": e
    })

if __name__ == '__main__':
    app.run()


from typing import List

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        left, right = 0, 1
        current_sum, best_sum = nums[0], nums[0]
        while left < len(nums):
            while right < len(nums) and current_sum >= 0:
                current_sum += nums[right]
                best_sum = max(best_sum, current_sum)
                right += 1
            while (left < right) and (current_sum < 0 or right == len(nums)):
                current_sum -= nums[left]
                left += 1
                if left < right:
                    best_sum = max(best_sum, current_sum)
        return best_sum

class SolutionDivideAndConquer:
    def maxSubArray(self, nums: List[int]) -> int:
        if len(nums) == 1:
            return nums[0]

        base = 0
        def helper(left, right):
            if right - left <= 2:
                m = max(nums[left:right])
                l = max(base, nums[left])
                f = sum(nums[left:right])
                c = max(nums[left:right])
                r = max(base, nums[right-1])
                return m, l, f, c, r

            mid = left + int((right - left) / 2)
            amax, al, af, ac, ar = helper(left, mid)
            bmax, bl, bf, bc, br = helper(mid, right)
            m, l, f, c, r = (
                max(amax, bmax),               # max
                max(al, af, af + bl, af + bf), # left
                af + bf,                       # full
                max(ac, ar + bl, bc),          # center
                max(br, bf, ar + bf, af + bf), # right
            )
            return m, l, f, c, r

        m, l, f, c, r = helper(0, len(nums))
        result = max(l, f, c, r)
        # if all numbers were negative, set result to the max negative number
        if m < 0 and m < result:
            result = m
        return result

def assert_eq(actual, expected):
    if actual != expected:
        raise AssertionError('expected: %s, actual: %s' % (expected, actual))

def test(input_, output):
    #assert_eq(Solution().maxSubArray(input_), output)
    assert_eq(SolutionDivideAndConquer().maxSubArray(input_), output)

if __name__ == '__main__':
    test([-2, -2, -3, 0, -3, 1, -3], 1)
    test([1, 2, 3, -10, 1, 2, 4], 7)

    test([-2, 1, -3, 4, -1, 2, 1, -5, 4], 6)
    test([1, 2, 3], 6)
    test([1], 1)
    test([-3], -3)
    test([-1, 0, -3], 0)
    test([-1, 1, -3], 1)
    test([-1, -3], -1)
    test([1, 2, 3, -10, 1, 2, 4], 7)
    test([1, 2, 4, -10, 1, 2, 3], 7)
    test([2, -1, -3], 2)
    test([-1, -3, 2], 2)


import glob
import inspect
import os
import sys
import time
import traceback
from functools import partial

import numpy as np
from PyQt4 import QtCore, QtGui

import makeFilters as mF
import processData as pD

reload(pD)

class WorkerSignals(QtCore.QObject):
    '''
    Defines the signals available from a running worker thread.

    Supported signals are:

    finished
        `tuple` (integer for dataset, timing info, bool for killed or not, percent complete)

    error
        `tuple` (exctype, value, traceback.format_exc() )

    result
        `object` data returned from processing, anything

    progress
        `tuple`  (float indicating % progress, index for dataset)

    '''
    finished = QtCore.pyqtSignal(tuple)
    error = QtCore.pyqtSignal(tuple)
    result = QtCore.pyqtSignal(object)
    progress = QtCore.pyqtSignal(tuple)
    interrupt=QtCore.pyqtSignal(bool)

class Worker(QtCore.QRunnable):
    '''
    Worker thread

    Inherits from QRunnable to handler worker thread setup, signals and wrap-up.

    :param callback: The function callback to run on this worker thread. Supplied args and
                     kwargs will be passed through to the runner.
    :type callback: function
    :param args: Arguments to pass to the callback function
    :param kwargs: Keywords to pass to the callback function

    '''

    def __init__(self, fn, *args, **kwargs):
        super(Worker, self).__init__()
        # Store constructor arguments (re-used for processing)
        self.fn = fn
        self.args = args
        self.kwargs = kwargs
        self.signals = WorkerSignals()

        # Add the callback to our kwargs
        kwargs['progress_callback'] = self.signals.progress

    @QtCore.pyqtSlot()
    def run(self):
        '''
        Initialise the runner function with passed args, kwargs.
        '''

        # Retrieve args/kwargs here; and fire processing using them
        try:
            result = self.fn(*self.args, **self.kwargs)
            worked=True
        except:
            #traceback.print_exc()
            exctype, value = sys.exc_info()[:2]
            self.signals.error.emit((self.kwargs['dataset'], value,exctype, traceback.format_exc()))
            worked=False
        else:
            pass
            #self.signals.result.emit(result)  # Return the result of the processing
        finally:
            if worked:
                self.signals.finished.emit((result,worked))  # Done
            else:
                self.signals.finished.emit(((self.kwargs['dataset'], 0, False, 0),worked))

class MainWindow(QtGui.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        #make the folder finder button, display, filter type and plotting tool
        self.btn = QtGui.QPushButton('Find Folder', self)
        self.btn.clicked.connect(self.getDirectory)
        self.btn.setAutoDefault(False)

        self.file_display=QtGui.QLineEdit(self)
        self.file_display.setReadOnly(True)

        self.comboBox=QtGui.QComboBox(self)
        self.filterTypes=zip(*inspect.getmembers(mF, inspect.isfunction))
        index0=0
        for ind, filterType in enumerate(self.filterTypes[0]):
            self.comboBox.addItem(filterType)
            try:
                smalldoc=self.filterTypes[1][ind].__doc__.split('\n')
                smalldoc=map(str.strip,smalldoc[1:])
                smalldoc='\n'.join(smalldoc)
                smalldoc=smalldoc.split('\n\n')[0]
                self.comboBox.setItemData(ind,smalldoc,QtCore.Qt.ToolTipRole)
            except: pass
            if filterType=='wienerFilter':
                index0=ind
        self.filterFunction=self.filterTypes[1][index0]
        self.filterName=self.filterTypes[0][index0]
        self.comboBox.setCurrentIndex(index0)
        self.comboBox.currentIndexChanged.connect(self.change_filter)

        #plotting tool button
        self.btn2=QtGui.QPushButton('Open Plotting Tool',self)
        self.btn2.clicked.connect(self.openPlotting)
        self.btn.setAutoDefault(False)

        #define filebar panel geometry
        self.filebar = QtGui.QHBoxLayout()
        self.filebar.addWidget(self.btn)
        self.filebar.addWidget(self.file_display)
        self.filebar.addWidget(self.comboBox)
        self.filebar.addWidget(self.btn2)

        #define control panel geometry
        spacer=QtGui.QSpacerItem(350, 0)

        self.control=QtGui.QVBoxLayout()
        self.control.addItem(spacer)

        # set the layout
        grid = QtGui.QGridLayout()
        grid.addLayout(self.filebar,1,1,1,2)
        grid.addLayout(self.control,2,1,3,2)

        w=QtGui.QWidget()
        w.setLayout(grid)
        self.setCentralWidget(w)

        self.setGeometry(300, 30, 800, 400)
        self.setWindowTitle('Optimal Filter GUI')

        self.show()

        self.threadpool = QtCore.QThreadPool()
        print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())

    def getDirectory(self):
        #remove previous kill files if changing directories
        if hasattr(self,'directory'):
            for f in glob.glob(os.path.join(self.directory,'kill_processes*.txt')):
                os.remove(f)

        #get directory
        self.directory = str(QtGui.QFileDialog.getExistingDirectory(self, 'Select a folder:',
                '/mnt/data0/Darkness',QtGui.QFileDialog.ShowDirsOnly))
        self.file_display.setText(self.directory)

        #update control pannel with directories
        self.subdirectories=[d for d in os.listdir(self.directory) if os.path.isdir(os.path.join(self.directory,d))]

        if len(self.subdirectories)>25:
            raise(ValueError('Too many directories in chosen folder'))

        #remove any previously created rows
        if hasattr(self,'row'):
            self.clearLayout(self.control)
        #initialize row, label, check, run_button, kill_button, and progress
        self.row=[]
        self.row_label=[]
        self.check=[]
        self.run_button=[]
        self.kill_button=[]
        self.progress=[]

        #loop through folders
        for index, directory in enumerate(self.subdirectories):
            #make row elements
            self.row_label.append(QtGui.QLabel(directory+':'))

            self.check.append(QtGui.QCheckBox("Continuing?"))

            self.run_button.append(QtGui.QPushButton('Run', self))
            self.run_button[index].clicked.connect(partial(self.run_filter,index))
            self.run_button[index].setAutoDefault(False)

            self.kill_button.append(QtGui.QPushButton('Kill', self))
            self.kill_button[index].clicked.connect(partial(self.kill_filter,index))
            self.kill_button[index].setDisabled(True)

            self.progress.append(QtGui.QLineEdit(self))
            self.progress[index].setReadOnly(True)

            spacer=QtGui.QSpacerItem(50, 0)

            #add elements to row
            self.row.append(QtGui.QHBoxLayout())
            self.row[index].addWidget(self.row_label[index])
            self.row[index].addItem(spacer)
            self.row[index].addWidget(self.check[index])
            self.row[index].addWidget(self.run_button[index])
            self.row[index].addWidget(self.kill_button[index])
            self.row[index].addWidget(self.progress[index])

            #add row to control pannel
            self.control.addLayout(self.row[index])

            #set warning text if filters already exist
            if os.path.isfile(os.path.join(os.path.join(self.directory,directory),"log_file.txt")):
                self.progress[index].setText("WARNING: Filters already exist for this dataset")

            #create kill file for row
            filename=os.path.join(self.directory,'kill_processes'+str(index)+'.txt')
            np.savetxt(filename,np.array([0]))

        #add last row for running everything
        self.check_all=QtGui.QCheckBox("Check All")
        self.check_all.stateChanged.connect(self.check_all_boxes)

        self.run_all=QtGui.QPushButton("Run All",self)
        self.run_all.clicked.connect(self.run_all_filters)
        self.run_all.setAutoDefault(False)

        self.kill_all=QtGui.QPushButton("Kill All",self)
        self.kill_all.clicked.connect(self.kill_all_filters)
        self.kill_all.setAutoDefault(False)

        self.recalculate_filters=QtGui.QPushButton("Recalculate Filters Only")
        self.recalculate_filters.clicked.connect(self.run_all_recalculations)
        self.recalculate_filters.setAutoDefault(False)

        self.last_row=QtGui.QHBoxLayout()
        self.last_row.addStretch()
        self.last_row.addWidget(self.check_all)
        self.last_row.addWidget(self.run_all)
        self.last_row.addWidget(self.kill_all)
        self.last_row.addWidget(self.recalculate_filters)
        self.last_row.addStretch()

        self.control.addLayout(self.last_row)

        #add final stretch
        self.control.addStretch()

        #create is running attribute
        self.isrunning=np.zeros(len(self.row),dtype=bool)

    def kill_filter(self,index):
        filename=os.path.join(self.directory,'kill_processes'+str(index)+'.txt')
        working=False
        while not working:
            try:
                np.savetxt(filename,np.array([1]))
                working=True
            except:
                time.sleep(0.1)

    def progress_fn(self, n):
        self.progress[n[1]].setText("{0}% done".format(round(n[0],1)))

    def error_fn(self,n):
        self.progress[n[0]].setText('error: ' + str(n[1]))

    def thread_complete(self,results):
        worked=results[1]
        results=results[0]

        #unlock run button
        self.run_button[results[0]].setEnabled(True)
        #lock kill button
        self.kill_button[results[0]].setDisabled(True)

        #print completion status
        if results[2] and worked:
            self.progress[results[0]].setText("Filters Complete after {0} minutes!".format(round(results[1]/60.0,1)))
        elif worked and not results[2]:
            self.progress[results[0]].setText("Calculation Stopped at {0}% after {1} minutes!".format(round(results[3],1),round(results[1]/60.0,1)))

        #remove kill setting
        filename=os.path.join(self.directory,'kill_processes'+str(results[0])+'.txt')
        working=False
        while not working:
            try:
                np.savetxt(filename,np.array([0]))
                working=True
            except:
                time.sleep(0.1)

        self.isrunning[results[0]]=False
        time.sleep(0.1)

    def run_filter(self,index,isAll=False):
        #check if files exist
        if (not isAll) and os.path.isfile(os.path.join(self.directory,self.subdirectories[index],self.filterName +'_coefficients.txt')) and (not self.check[index].isChecked()):
            question="Filters of type '" + self.filterName + "' have already been calculated. Are you sure you would like to delete and restart?"
            answer=self.query_yes_no(question)
            if not answer:
                return

        #clear text box
        self.progress[index].setText('')
        #grey out run button and make unresponsive
        self.run_button[index].setDisabled(True)
        #unlock kill button
        self.kill_button[index].setEnabled(True)

        #set as running
        self.isrunning[index]=True

        # Pass the function to execute
        path=os.path.join(self.directory,self.subdirectories[index])
        worker = Worker(execute_filter_calcs,dataset=index, mainDirectory=self.directory, continuing=self.check[index].isChecked(), directory=path,filterMethod=self.filterFunction)
        worker.signals.finished.connect(self.thread_complete)
        worker.signals.progress.connect(self.progress_fn)

        # Execute
        self.threadpool.start(worker)

    def run_recalculation(self,index):
        #clear text box
        self.progress[index].setText('')
        #grey out run button and make unresponsive
        self.run_button[index].setDisabled(True)
        #unlock kill button
        self.kill_button[index].setEnabled(True)

        #set as running
        self.isrunning[index]=True

        # Pass the function to execute
        path=os.path.join(self.directory,self.subdirectories[index])
        worker = Worker(execute_filters_only,dataset=index, mainDirectory=self.directory, directory=path,filterMethod=self.filterFunction)
        worker.signals.finished.connect(self.thread_complete)
        worker.signals.progress.connect(self.progress_fn)
        worker.signals.error.connect(self.error_fn)

        # Execute
        self.threadpool.start(worker)

    def run_all_recalculations(self):
        for index, row in enumerate(self.row):
            if not self.isrunning[index]:
                self.run_recalculation(index)

    def run_all_filters(self):
        #check if files exist
        logic=False
        for index,subdirectory in enumerate(self.subdirectories):
            logic=logic or (os.path.isfile(os.path.join(self.directory,subdirectory,self.filterName +'_coefficients.txt')) and (not self.check[index].isChecked()))
        if logic:
            question="Filters of type '" + self.filterName + "' have already been calculated for some folders. Are you sure you would like to delete and restart?"
            answer=self.query_yes_no(question)
            if not answer:
                return
        for index, row in enumerate(self.row):
            if not self.isrunning[index]:
                self.run_filter(index, isAll=True)

    def check_all_boxes(self):
        for index, row in enumerate(self.row):
            if self.check_all.checkState():
                self.check[index].setChecked(True)
            else:
                self.check[index].setChecked(False)

    def kill_all_filters(self):
        for index, row in enumerate(self.row):
            if self.isrunning[index]:
                self.kill_filter(index)
                time.sleep(0.1)

    def closeEvent(self,event):
        if hasattr(self,'directory'):
            for f in glob.glob(os.path.join(self.directory,'kill_processes*.txt')):
                os.remove(f)

    def clearLayout(self, layout):
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()
                else:
                    self.clearLayout(item.layout())
    def openPlotting(self):
        os.system("python plotFiltersGUI.py &")
    def change_filter(self,index):
        self.filterFunction=self.filterTypes[1][index]
        self.filterName=self.filterTypes[0][index]
    def query_yes_no(self,question):
        choice = QtGui.QMessageBox.question(self, 'Answer before continuing',
                                            question,
                                            QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
        if choice == QtGui.QMessageBox.Yes:
            return True
        else:
            return False

def execute_filter_calcs(progress_callback=[],dataset=[],mainDirectory=[],directory=[],continuing=False,filterMethod=mF.wienerFilter):
    defaultTemplate=np.loadtxt('template200_15us.txt') #change default template here
    result=pD.processData(directory,defaultTemplate,GUI=True, progress_callback=progress_callback, dataset=dataset, mainDirectory=mainDirectory, continuing=continuing,filterMethod=filterMethod)
    return result

def execute_filters_only(filterCode=[],progress_callback=[],dataset=[],mainDirectory=[],directory=[],filterMethod=mF.wienerFilter):
    result=pD.recalculate_filters(directory,filterMethod,GUI=True, progress_callback=progress_callback, dataset=dataset, mainDirectory=mainDirectory)
    return result

app = QtGui.QApplication([])
window = MainWindow()
app.exec_()


#!/bin/env python
import RPi.GPIO as GPIO
import Adafruit_DHT
import time
from datetime import datetime
from flask import Flask, render_template, jsonify, request

heater_status = {"power": False, 'heat': False, 'temp':0, 'hum':0}
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def main_page():
    update_temp_hum()
    if request.method == 'POST':
        return get_heater_status()
    else:
        curr_time = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
        return render_template('app.html', heater_status=heater_status, curr_time=curr_time)

def update_temp_hum():
    sensor = Adafruit_DHT.DHT22
    pin = 22
    hum, temp = Adafruit_DHT.read_retry(sensor, pin)
    heater_status['temp'] = round(temp, 2)
    heater_status['hum'] = round(hum, 2)

@app.route('/toggle_power')
def toggle_power():
    press_power_button()
    heater_status['power'] = not heater_status['power']
    if not heater_status['power']:
        heater_status['heat'] = False
    return get_heater_status()

@app.route('/toggle_heat')
def toggle_heat():
    if not heater_status['power']:
        return get_heater_status()
    else:
        press_heat_button()
        heater_status['heat'] = not heater_status['heat']
        return get_heater_status()

def get_heater_status():
    curr_time = datetime.now()
    return jsonify({"heater_status": heater_status, "time": curr_time.strftime("%Y/%m/%d %H:%M:%S")})

def press_power_button():
    duty_cycle = 7.5
    power_servo_pin = 17
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(power_servo_pin, GPIO.OUT)
    pwm_servo = GPIO.PWM(power_servo_pin, 50)
    pwm_servo.start(duty_cycle)
    pwm_servo.ChangeDutyCycle(duty_cycle)
    time.sleep(0.2)
    pwm_servo.ChangeDutyCycle(5)
    time.sleep(0.3)
    pwm_servo.ChangeDutyCycle(duty_cycle)
    time.sleep(0.2)
    GPIO.cleanup()

def press_heat_button():
    duty_cycle = 7.5
    warm_servo_pin = 27
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(warm_servo_pin, GPIO.OUT)
    pwm_servo = GPIO.PWM(warm_servo_pin, 50)
    pwm_servo.start(duty_cycle)
    pwm_servo.ChangeDutyCycle(duty_cycle)
    time.sleep(0.2)
    pwm_servo.ChangeDutyCycle(8.5)
    time.sleep(0.3)
    pwm_servo.ChangeDutyCycle(duty_cycle)
    time.sleep(0.2)
    GPIO.cleanup()

if __name__ == '__main__':
    app.run(threaded=True, debug=True, port=80, host='0.0.0.0')


from Bio import Entrez, SeqIO

import os
import sys
import multiprocessing
import datetime

import re
import math
import random

from email_validator import validate_email, EmailNotValidError

sys.setrecursionlimit(10000)    #再起深度の上限

import collections
Result = collections.namedtuple("Result", "i1, i2, alignment, distance")
Matrices = collections.namedtuple("Matrices", "alignment, distance")
MS = collections.namedtuple("MS", "score, direction")

## 一致を+3pt、不一致を-1pt、ギャップを-2ptとする ##
SC = lambda nucleotide1, nucleotide2: 3 if nucleotide1==nucleotide2 else -1
GP = -2

def main():
    Entrez.email = input_email()

    show_help()
    rrn16S=[]
    descriptions_list=[]
    matrices = Matrices([],[])
    clustering=None
    while True:
        term_input_list=[]
        while True:
            print('')
            term_input = input("input: ")
            if re.search(r'(\w+\([\d\s,]*\))', term_input):
                end = handle_command(term_input, descriptions_list, matrices, clustering)
                if end: break
                continue
            term_input_list.append(term_input)

        for term_input in term_input_list:
            gbids=[]
            gbids = search_gbids(term_input)

            random.shuffle(gbids)

            if len(gbids)==0: continue

            for gbid in gbids:
                record = fetch_record(gbid)
                seq = extract_16SrRNA(record)
                if seq: break

            if seq == None:
                print('')
                print(term_input+" doesn't heve 16S-rRNA data.")
                continue

            description = record.description.replace(', complete genome','')
            descriptions_list.append(description)
            rrn16S.append(seq)

            print('')
            print(str(len(rrn16S)-1)+'. '+description)
            print("ID: "+gbid)
            print("16S rRNA sequence: ")
            print(seq)

        if len(rrn16S)>1:
            matrices, clustering = add_alignment(matrices, rrn16S, len(matrices.alignment)+1)
            show_clustering(matrices.distance, clustering)

#################
# Handle inputs #
#################

def input_email():
    while True:
        print('')
        email = input("Input your email: ")
        try:
            v = validate_email(email)
            return v["email"]
        except EmailNotValidError as e:
            print(str(e))
            continue

def handle_command(term_input, descriptions_list, matrices, clustering):
    command=re.findall(r'(\w+)', term_input)[0]
    arguments=re.findall(r'(\d+)', (re.findall(r'(\([\d\s,]*\))', term_input)[0]))
    try:
        if   command=='nametable':
            show_nametable(descriptions_list)
        elif command=='sequence':
            show_sequence(rrn16S, int(arguments[0]))
        elif command=='alignment':
            show_alignment(matrices, int(arguments[0]), int(arguments[1]))
        elif command=='cluster':
            show_clustering(matrices.distance, clustering)
        elif command=='end':
            return True
        elif command=='save':
            save_text(descriptions_list, matrices.distance)
        elif command=='exit':
            sys.exit()
        else:
            show_help()
        return False
    except:
        show_help()
        return False

############################
# Fetch 16S-rRNA sequences #
############################

def search_gbids(term_input):
    term_ = correct_spell(term_input)

    handle = Entrez.esearch(db="nucleotide", term=term_+"[orgn] AND complete genome[title]", idtype="acc", retMax='1000')
    record = Entrez.read(handle)
    gbids = record["IdList"]

    if len(gbids)==0:
        print('')
        print("\""+term_+"\" does not exist")
    return gbids

def correct_spell(term_):
    handle = Entrez.espell(term=term_)
    record = Entrez.read(handle)

    if record["CorrectedQuery"]!='':
        term_=record["CorrectedQuery"]
        print('')
        print("Showing results for \""+term_+"\"")

    return term_

def fetch_record(id_):
    handle = Entrez.efetch(db="nucleotide", id=id_, rettype="gb", retmode="text")
    record = SeqIO.read(handle, "genbank")
    handle.close()
    return record

def extract_16SrRNA(record):
    for feature in record.features:
        if feature.type != 'rRNA': continue
        if feature.qualifiers['product']==['16S ribosomal RNA']:
            seq=feature.location.extract(record.seq)
            return seq
    return None

#####################
# Execute alignment #
#####################

def add_alignment(matrices, seqs, len_seqs_b):
    len_seqs = len(seqs)
    canceled = False
    jobs = multiprocessing.JoinableQueue()
    results = multiprocessing.Queue()
    concurrency=multiprocessing.cpu_count()
    create_processes(seqs, jobs, results, concurrency)
    add_jobs(len_seqs, len_seqs_b, jobs)

    try:
        jobs.join()
    except KeyboardInterrupt:
        canceled = True

    for i in range(len_seqs_b-1):
        for _ in range(len_seqs - len_seqs_b):
            matrices.alignment[i].append(None)
            matrices.distance[i].append(None)
    for _ in range(len_seqs - len_seqs_b):
        matrices.alignment.append([None for _ in range(len_seqs-1)])
        matrices.distance.append([None for _ in range(len_seqs-1)])

    while not results.empty():
        result=results.get_nowait()
        matrices.alignment[result.i1][result.i2-1]  = result.alignment
        matrices.distance[result.i1][result.i2-1]   = result.distance

    clustering = neighbor_joining(matrices.distance)

    return matrices, clustering

def create_processes(seqs, jobs, results, concurrency):
    for _ in range(concurrency):
        process = multiprocessing.Process(target=worker, args=(seqs, jobs, results))
        process.daemon = True
        process.start()

def worker(seqs, jobs, results):
    while True:
        try:
            si1, si2 = jobs.get()
            try:
                alignment, distance = align(seqs[si1], seqs[si2])
                result = Result(si1, si2, alignment, distance)
                results.put(result)
            except:
                 pass
        finally:
            jobs.task_done()

def add_jobs(len_seqs, len_seqs_b, jobs):
    for i2 in range(len_seqs - len_seqs_b):
        for i1 in range(len_seqs_b + i2):
            jobs.put((i1, len_seqs_b + i2))

def align(seq1, seq2):
    memo = [[None for _ in range(len(seq2)+1)] for __ in range(len(seq1)+1)]
    memo[0][0] = MS(0, 'S')
    for si1 in range(len(seq1)): memo[si1+1][0] = MS((si1+1)*GP, 'H')
    for si2 in range(len(seq2)): memo[0][si2+1] = MS((si2+1)*GP, 'V')

    alignment=['' for _ in range(3)]
    si1=len(seq1)
    si2=len(seq2)
    length_of_alignment=0
    noMatch=0
    while si1!=0 or si2!=0:
        length_of_alignment+=1
        if   maxScore(si1, si2, seq1, seq2, memo).direction=='D':
            alignment[0] += seq1[si1-1]
            alignment[1] += '|' if seq1[si1-1]==seq2[si2-1] else ' '
            alignment[2] += seq2[si2-1]
            si1-=1
            si2-=1
        elif maxScore(si1, si2, seq1, seq2, memo).direction=='V':
            alignment[0] += '-'
            alignment[1] += ' '
            alignment[2] += seq2[si2-1]
            si2-=1
            noMatch+=1
        elif maxScore(si1, si2, seq1, seq2, memo).direction=='H':
            alignment[0] += seq1[si1-1]
            alignment[1] += ' '
            alignment[2] += '-'
            si1-=1
            noMatch+=1
    for i in range(3):
        alignment[i]=alignment[i][::-1]

    f = noMatch/length_of_alignment
    distance = abs(3/4*math.log(1-4*f/3))

    return alignment, distance

def maxScore(mi1, mi2, seq1, seq2, memo):
    if memo[mi1][mi2]: return memo[mi1][mi2]

    scoreList=[]
    scoreList.append(maxScore(mi1-1, mi2-1, seq1, seq2, memo).score + SC(seq1[mi1-1], seq2[mi2-1]))
    scoreList.append(maxScore(mi1  , mi2-1, seq1, seq2, memo).score + GP)
    scoreList.append(maxScore(mi1-1, mi2  , seq1, seq2, memo).score + GP)

    direction = scoreList.index(max(scoreList))
    if   direction == 0: direction = 'D'
    elif direction == 1: direction = 'V'
    elif direction == 2: direction = 'H'

    memo[mi1][mi2] = MS(max(scoreList), direction)
    return memo[mi1][mi2]

################
# Make cluster #
################

def neighbor_joining(distance_matrix):
    dm = [dr[:] for dr in distance_matrix]
    node_list=[i for i in range(len(distance_matrix)+1)]
    while len(node_list)>2:
        r=[]
        for node1 in range(len(node_list)):
            r_i = 0
            for node2 in range(len(node_list)):
                if   node1<node2: r_i += dm[node1][node2-1]
                elif node1>node2: r_i += dm[node2][node1-1]
            r_i /= len(node_list)-2
            r.append(r_i)
        min_drr=None
        min_drr_i1=None
        min_drr_i2=None
        for di1, dr in enumerate(dm):
            node1 = di1
            for di2, d in enumerate(dr[di1:]):
                node2 = di1+di2+1
                drr = d - r[node1]- r[node2]
                if min_drr==None or drr < min_drr:
                    min_drr = drr
                    min_drr_i1 = di1
                    min_drr_i2 = di1+di2+1

        node_list.append((node_list[min_drr_i1], node_list[min_drr_i2]))
        node_list.pop(min_drr_i2)
        node_list.pop(min_drr_i1)

        dm.append([None for _ in range(len(dm))])
        for dri, dr in enumerate(dm):
            if dri in {min_drr_i1, min_drr_i2}: continue
            d_mi1 = dr[min_drr_i1-1] if dri<min_drr_i1 else dm[min_drr_i1][dri-1]
            d_mi2 = dr[min_drr_i2-1] if dri<min_drr_i2 else dm[min_drr_i2][dri-1]
            d_mk = (d_mi1 + d_mi2 - dm[min_drr_i1][min_drr_i2-1])/2
            dr.append(d_mk)
        dm.pop(min_drr_i2)
        dm.pop(min_drr_i1)
        for dr in dm:
            dr.pop(min_drr_i2-1)
            dr.pop(min_drr_i1-1) if min_drr_i1>0 else dr.pop(min_drr_i1-0)

    clustering = (node_list[0],node_list[1])
    return clustering

#######################
# Output informations #
#######################

def show_clustering(matrix, clustering):
    print('')
    print('{:>3}'.format('') + '|' +
              '|'.join('{:>6}'.format(str(mi2+1)) for mi2 in range(len(matrix))))
    for mi1 in range(len(matrix)):
        print('{:>3}'.format(str(mi1)) + '|' +
              '|'.join('{:>6}'.format(str('{:.3f}'.format(matrix[mi1][mi2])) if matrix[mi1][mi2]!=None else '')
                       for mi2 in range(len(matrix))))

    print('')
    print(clustering)

def show_nametable(descriptions_list):
    print('')
    for di, description in enumerate(descriptions_list):
        print('{:>3}'.format(str(di)) + '. ' + description)

def show_sequence(seqs, si):
    print('')
    print(seqs[si])

def show_alignment(matrices, si1, si2):
    print('')
    WIDTH=os.get_terminal_size().columns
    alignment = matrices.alignment[si1][si2-1]
    sai=0
    while sai<len(alignment[0]):
        length = min(len(alignment[0])-sai, WIDTH)
        for i in range(3):
            print(alignment[i][sai:sai+length])
        print('')
        sai+=length

    similarity = 1 - math.tanh(matrices.distance[si1][si2-1]*4/3)
    print('Similarity: '+str(similarity))

def show_help():
    print("""
Usage:
    1. input: <academic name>
    2. input: <command(arg)>

Commands:
    nametable()             Show nametable
    sequence(int)           Show DNA-sequence
    alignment(int, int)     Show alignment result
    cluster()               Show clustering result
    end()                   Stop inputting and start analizing
    save()                  Save to text file(same directory)
    exit()                  Exit this application""")

#####################
# Save to text file #
#####################

def save_text(descriptions_list, matrix):
    text=[]
    for di, description in enumerate(descriptions_list):
        text.append('{:>3}'.format(str(di)) + '. ' + description)
    text.append('')

    for mi1 in range(len(matrix)):
        for mi2 in range(len(matrix)):
            if matrix[mi1][mi2]==None: continue
            similarity = 1 - math.tanh(matrix[mi1][mi2]*4/3)
            text.append(str(similarity)+', '+str(mi1)+'-'+str(mi2+1))

    filename=datetime.datetime.now().strftime('%y%m%d%H%M%S')+'.txt'
    with open(os.getcwd()+'/'+filename,'w') as f:
        f.write('\n'.join(text))

if __name__ == "__main__":
    main()


import os
import discord
import random
import socket
import wikipedia
import requests
from pytrends.request import TrendReq
from discord.ext import commands
from forex_python.converter import CurrencyRates
from forex_python.bitcoin import BtcConverter

bot = commands.Bot('!')

@bot.event
async def on_ready():
    print('bom dia')

@bot.command(name='oi')
async def send_hi(ctx):
  await ctx.send('oii, espero que esteja bem')

@bot.command(name='manga')
async def Manga(ctx):
  await ctx.send('qual obra deseja procurar?')
  obra = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
  obra = str(obra.content)
  obra = obra.split()

  if obra[0] == 'chobits':
    link = ('https://mangalivre.net/manga/chobits/4954')
    await ctx.send(link)
  else:
    link = ('https://mangayabu.top/manga/')
    n = len(obra)
    for i in range (n):
      link = (link + obra[i] + '-')
    await ctx.send(link[:-1])

@bot.command(name='webtoon')
async def Webtoon(ctx):
  await ctx.send('qual obra deseja procurar?')
  obra = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
  obra = str(obra.content)
  obra = obra.split()
  link = ('https://yabutoons.com/webtoon/')
  n = len(obra)
  for i in range (n):
    link = (link + obra[i] + '-')
  await ctx.send(link[:-1])

@bot.command(name='pesquisa')
async def check_on_wikipedia(ctx):

  await ctx.send('qual a sua duvida?')
  query = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
  query = str(query.content)
  try:
    query = query.lower()
    query = query.replace("quem foi", "")
    query = query.replace("quem é", "")
    query = query.replace("o que é", "")
    query = query.replace("você sabe o que é", "")
    query = query.replace("me diga o que é", "")
    wikipedia.set_lang("pt")
    resumo = wikipedia.summary(query, sentences=3)
    await ctx.send(resumo)
  except:
    await ctx.send("desculpa, mas não foi possivel encontrar sobre ", query)

@bot.command(name='gato')
async def cat_fact(ctx):
  try:
    requisicao_gato = requests.get('https://cat-fact.herokuapp.com/facts/random?animal_type=cat&amount=2').json()
    await ctx.send(requisicao_gato[1]['text'])
  except:
    await ctx.send("a api está com excesso de requisições no momento, peço desculpas por isso, tente mais tarde")

@bot.command(name='cachorro')
async def dog_fact(ctx):
  try:
    requisicao_cachorro = requests.get('https://dog-facts-api.herokuapp.com/api/v1/resources/dogs?number=1')
    curiosidade = requisicao_cachorro.json()
    await ctx.send(curiosidade[0]['fact'])
  except:
    await ctx.send("a api está com excesso de requisições no momento, peço desculpas por isso, tente mais tarde")

@bot.command(name='tendencia')
async def tendencia(ctx):
  pytrends = TrendReq(hl='en-US', tz=360)
  data = pytrends.trending_searches(pn='brazil')
  await ctx.send(data)

@bot.command(name='anime')
async def anime(ctx):
  try:
     computer_choice = random.randint(1, 9000)
     computer_url = 'https://api.jikan.moe/v3/anime/{}/'.format(computer_choice)
     computer_response = requests.get(computer_url)
     a = computer_response.json()['title']
     await ctx.send(a)
  except:
    await ctx.send("a api está com excesso de requisições no momento, peço desculpas por isso, tente mais tarde")

@bot.command(name='cotação')
async def moedas(ctx):
  try:
    await ctx.send("insira o código da moeda que deseja ver a conversão")
    moeda = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
    moeda = str(moeda.content)
    if (moeda == 'BTC'):
      b = BtcConverter()
      b = b.get_latest_price('BRL')
      await ctx.send ('R$ {:.3}'.format(b))
    else:
      c = CurrencyRates()
      await ctx.send ('R$ {:.3}'.format(c.convert(moeda, 'BRL', 1)))
  except(KeyError):
    await ctx.send("chii:código inserido não é invalido, tente de novo")
  except:
    await ctx.send("a api atingiu o limite de requisições, por favor tente novamente quando renovar as requisições")

@bot.command(name='dado')
async def dado(ctx):
  await ctx.send("insira o numero maximo que se pode tirar no dado")
  n = await bot.wait_for('message', check=lambda message: message.author == ctx.author)
  n = int(str(n.content))
  dado = random.randint(1, n)
  await ctx.send("que a sorte esteja com você")
  await ctx.send("o numero sorteado foi {}".format(dado))

bot.run(os.environ['TOKEN'])


from scipy.stats import ttest_rel
import numpy as np
from ssl_main.const import LINE_WIDTH, FONT_DICT
from figures.PaperFigures import save_fig, load_da_data, results_dict_to_pd, format_axis
import matplotlib.pyplot as plt
from matplotlib import rc
from matplotlib.patches import Patch
from tab_2 import task_names
import sys

def init_fig():
    fig = plt.figure(figsize=(6, 4))
    return fig

def draw_box_pair(result_df, i_box_pair):
    with_ssl_ = result_df[result_df['use_ssl'] == True][metric].values
    no_ssl_ = result_df[result_df['use_ssl'] == False][metric].values
    boxes_ = []
    for i_cond, data_ in enumerate([with_ssl_, no_ssl_]):
        meanpointprops = dict(marker='D', markeredgecolor='none', markerfacecolor='white', markersize=7)
        box_ = plt.boxplot(data_, positions=[i_cond + 4 * i_box_pair], widths=[0.8], patch_artist=True,
                           meanprops=meanpointprops, showmeans=True)
        for field in ['medians', 'whiskers', 'caps', 'boxes']:
            [box_[field][i].set(linewidth=LINE_WIDTH, color=colors[i_cond]) for i in range(len(box_[field]))]
        [box_['fliers'][i].set(marker='o', markeredgecolor=colors[i_cond], markerfacecolor=colors[i_cond],
                               markersize=2.5) for i in range(len(box_['fliers']))]
        box_['medians'][0].set(linewidth=LINE_WIDTH, color=[1, 1, 1])
        boxes_.append(box_['whiskers'])

    p_val = ttest_rel(with_ssl_, no_ssl_).pvalue
    top_line_y = 1.04
    if p_val < 0.05:
        plt.plot([4 * i_box_pair, 4 * i_box_pair, 4 * i_box_pair + 1, 4 * i_box_pair + 1],
                 [max(with_ssl_) + 0.04, top_line_y, top_line_y, max(no_ssl_) + 0.04], linewidth=LINE_WIDTH, color='black')
        plt.text(4 * i_box_pair + 0.3, top_line_y + 0.01, '*', fontdict={'fontname': 'Times New Roman'}, size=20, zorder=20)

def finalize_fig():
    def format_ticks():
        ax.set_ylabel('Correlation Coefficient - {}'.format(fig_config[i_fig]['ylabel']), fontdict=FONT_DICT)
        x_range = (-1, 10)
        ax.set_xlim(x_range[0], x_range[1])
        ax.tick_params(bottom=False)

        ax.set_xticks(np.arange(0.5, x_range[1], 4))
        ax.set_xticklabels(['Task 1 -\nRunning VALR', 'Task 2 -\nWalking vGRF',
                            'Task 3 -\nWalking KFM'], fontdict=FONT_DICT)

        ylim_up = 1.2
        if np.min(ylim_ori[0]) < 0.4:
            ylim_down = 0.2
            ticks = [.2, .4, .6, .8, 1., 1.2]
        else:
            ylim_down = 0.4
            ticks = [.4, .6, .8, 1., 1.2]
        ax.set_ylim(ylim_down, ylim_up)
        ax.set_yticks(ticks)     # [.4, .5, .6, .7, .8, .9, 1., 1.1]
        ax.set_yticklabels(ticks, fontdict=FONT_DICT)

    ax = plt.gca()
    ylim_ori = ax.get_ylim()
    format_ticks()
    format_axis()
    legend_elements = [Patch(facecolor=colors[0], label='Color Patch'),
                       Patch(facecolor=colors[1], label='Color Patch')]
    plt.legend(legend_elements, ['Self-Supervised Encoders', 'Initial Encoders'], bbox_to_anchor=(0.65, 1.22 - 0.2 * (ylim_ori[0])),
               ncol=1, fontsize=FONT_DICT['fontsize'], frameon=False)
    plt.tight_layout(rect=[0., 0., 1., 1.01])
    save_fig(fig_name)

data_path = sys.path[0] + '/results/0_contrastive_on_MoVi'
colors = [np.array([125, 172, 80]) / 255, np.array([130, 130, 130]) / 255]
rc('font', family='Arial')
fig_config = [
    {'ylabel': 'Fine-Tuning'},
    {'ylabel': 'Linear'},
]

if __name__ == "__main__":
    metric = 'correlation'
    for i_fig, (only_linear, fig_name) in enumerate(zip([False, True], ['f2', 'f3'])):
        init_fig()
        for i_task, task_name in enumerate(task_names):
            results_task = load_da_data(data_path + task_name + '.h5')
            result_df = results_dict_to_pd(results_task)
            result_df = result_df[(result_df['ratio'] == 1.) & (result_df['only_linear'] == only_linear)]
            draw_box_pair(result_df, i_task)
        finalize_fig()
    plt.show()


from PIL import Image, ImageDraw, ImageFont

def save_image():
    img = Image.new('RGB', (200, 200), (255, 0, 0))
    img.save('D:\\test.png', 'png')

def write_text_to_image():
    # 载入图片
    img = Image.open('D:\\test.png')
    # 载入字体及大小
    font = ImageFont.truetype('data/神韵哈天随性体.ttf', 30)
    # 获取图片宽度和高度
    w, h = img.size
    # 创建图像
    draw = ImageDraw.Draw(img)
    # 写入文字
    draw.text((0.5 * w, 0.2 * h), '中文', font=font, fill=(0, 0, 255))
    # 保存图像
    img.save('D:\\deal.png', 'png')

def show_image_in_plt():
    # 载入图片
    img = Image.open('E:\\我的图片\\QQ图片20170914200717.jpg')
    # 载入字体及大小
    font = ImageFont.truetype('data/神韵哈天随性体.ttf', 100)
    # 获取图片宽度和高度
    w, h = img.size
    # 创建图像
    draw = ImageDraw.Draw(img)
    # 写入文字
    draw.text((0.5 * w, 0.2 * h), '程序猿', font=font, fill=(255, 0, 0))
    # 显示图像
    # plt.imshow(img)
    # plt.axis('off')
    # plt.show()
    img.show()

show_image_in_plt()