#!/usr/bin/python
import os
import re
import math
import matplotlib.pyplot as plt
import numpy
from numpy import sin, pi, arange
import astropy.io
from astropy.io import fits
from PIL import Image

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# This script contrasts photon index and luminosity for various observations. #
# In order to reduce error, the data is binned together                       #
#                                                                             #
# Usage: The script was strictly developed for the 13 galaxies avaliable at   #
# the time of development, and thus is more of a script to be used for       #
# reference.
#                                                                             #
# Author: April Walker                                                        #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

def main():
    fits_file = []

    #set to the directory containing all data you wish to plot
    fits_dir = os.listdir(os.environ["RESEARCH_DATA_PATH"] + "/Final-fits/")

    #specify the path each data file
    for i in range(len(fits_dir)):
        fits_file.append(os.environ["RESEARCH_DATA_PATH"] + "/Final-fits/" + fits_dir[i])

    fig = plt.figure(figsize=(20, 10))
    ax1 = fig.add_subplot(111)

    x = []
    x_error = []
    x_error_mean = []
    y = []

    for iterator, value in enumerate(fits_file):
        hdu_list = fits.open(value)

        #our data is now put into columns
        data = hdu_list[1].data
        cols = hdu_list[1].columns
        hdu_list.close()

        #take the values you need. If you need a new field, use print(cols) and use
        gamma = data.field('gamma')
        gamma_error = data.field('gamma_err')
        lh8 = data.field('lh8')

        #gamma of value 1.7 is an error as is NaN, so we only append indexes wihtout
        #those values
        gamma_indices = numpy.where(gamma != 1.7)

        for i, value in enumerate(gamma_indices[0]):
            if (gamma[value] == gamma[value] and lh8[value] == lh8[value] and gamma_error[value] > 0):
                x.append(gamma[value])
                x_error.append(gamma_error[value])
                y.append(lh8[value])

        #this guy holds our data set sorted by luminosity
        data_set = []
        for i in range(len(x)):
            temp = [y[i],x[i],x_error[i]]
            data_set.append(temp)

        #sort it
        data_set.sort(key=lambda x: x[0])

        Ay = []
        Ax = []
        Ax_error = []

        for i in range(len(x)):
            Ay.append(data_set[i][0])
            Ax.append(data_set[i][1])
            Ax_error.append(data_set[i][2])

        bin_minimum = Ay[0]
        #Set this in case you're binning too many values

        if iterator == 4:
            bin_upper_limit = 16
            bin_lower_limit = 8

        if iterator == 5 or 6 or 7 or 10:
            bin_upper_limit = 14
            bin_lower_limit = 6

        if iterator == 9:
            bin_lower_limit = 4
            bin_upper_limit = 10

        if iterator == 8:
            bin_upper_limit = 25
            bin_lower_limit = 10

        else:
            bin_upper_limit = 15
            bin_lower_limit = 10

        y_binned = []
        x_binned = []
        x_error_binned = []

        y_unbinned = []
        x_unbinned = []
        x_error_unbinned = []

        counter = []

        # THE BELOW CODE AUTOBINS NORMALLY #
        j = 0
        for i in range(len(Ay)):
            # if(Ax_error[i] < 0.17):
            #     y_unbinned.append(Ay[i])
            #     x_unbinned.append(Ax[i])
            #     x_error_unbinned.append(Ax_error[i])
            if(j == len(x_error_binned) - 1):
                if((numpy.sqrt(x_error_binned[j])/(counter[j]) < 0.13) and (counter[j] >= bin_lower_limit)):
                    j += 1
                elif(counter[j] >= bin_upper_limit):
                    j += 1
                else:
                    counter[j] += 1
                    y_binned[j] += Ay[i]
                    x_binned[j] += Ax[i]
                    x_error_binned[j] += Ax_error[i]**2
            else:
                y_binned.append(0)
                x_binned.append(0)
                x_error_binned.append(0)
                counter.append(0)

                counter[j] += 1
                y_binned[j] += Ay[i]
                x_binned[j] += Ax[i]
                x_error_binned[j] += Ax_error[i]**2

        #calculates the mean error as sqrt(sum(errors^2))/sqrt(n)
        for j in range(len(y_binned)):
            if value == value:
                y_binned[j] = y_binned[j]/counter[j]
                x_binned[j] = x_binned[j]/counter[j]
                x_error_binned[j] = numpy.sqrt(x_error_binned[j])/(counter[j])

        no = '_nolegend_'

        if iterator == 0 or iterator == 5 or iterator == 10:
            if iterator == 0:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#231193', fmt = 'o', marker = "s", zorder = 4)
            elif iterator == 5:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#231193', fmt = 'o', marker = "o", zorder = 4)
            elif iterator == 8:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#231193', fmt = 'o', marker = "^", zorder = 4)
            ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#3219cd', fmt = 'o', zorder = 3, label = no, ms=3)

            # The following lines can be uncommented (and the above commented) to develop graphs for individual galaxies
            # ax1.scatter(x, y, color = '#aabaff', zorder = 2, label = no, s=5)
            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC4382')
            # legend_labels = ["NGC4382"]

            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of M63')
            # legend_labels = ["M63"]

            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC3184')
            # legend_labels = ["NGC3184"]

            # The following ignores this galaxy
            # ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            # ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#e6e6e6', fmt = '.', marker = "s", zorder = 1, label = no)
            # ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#e6e6e6', fmt = '.', zorder = 1, label = no)

            dummy_variable = 1
        if iterator == 1 or iterator == 6 or iterator == 11:
            if iterator == 1:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#096612', fmt = 'o', marker = "s", zorder = 4)
            elif iterator == 6:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#096612', fmt = 'o', marker = "o", zorder = 4)
            elif iterator == 11:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#096612', fmt = 'o', marker = "^", zorder = 4)
            ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#0c8718', fmt = 'o', zorder = 3, label = no, ms=3)

            # The following lines can be uncommented (and the above commented) to develop graphs for individual galaxies
            # ax1.scatter(x, y, color = '#90e097', zorder = 2, label = no, s=5)
            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC0628')
            # legend_labels.append(["NGC0628"])

            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of M94')
            # legend_labels = ["M94"]

            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC3198')
            # legend_labels = ["NGC3198"]

            # The following ignores this galaxy
            # ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            # ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#e6e6e6', fmt = '.', marker = "s", zorder = 1, label = no)
            # ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#e6e6e6', fmt = '.', zorder = 1, label = no)

            dummy_variable = 1
        if iterator == 2 or iterator ==  7 or iterator == 12:
            if iterator == 2:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#6a0a7a', fmt = 'o', marker = "s", zorder = 4)
            elif iterator == 7:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#6a0a7a', fmt = 'o', marker = "o", zorder = 4)
            elif iterator == 12:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#6a0a7a', fmt = 'o', marker = "^", zorder = 4)
            ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#880d9d', fmt = 'o', zorder = 3, label = no, ms=3)

            # The following lines can be uncommented (and the above commented) to develop graphs for individual galaxies
            # ax1.scatter(x, y, color = '#edddff', zorder = 2, label = no, s=5)
            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC2403')
            # legend_labels = ["NGC2403"]

            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of M95')
            # legend_labels = ["M95"]

            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC4559')
            # legend_labels = ["NGC4559"]

            # The following lines ignore this galaxy
            # ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            # ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#e6e6e6', fmt = '.', marker = "s", zorder = 1, label = no)
            # ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#e6e6e6', fmt = '.', zorder = 1, label = no)

            dummy_variable = 1
        if iterator == 3 or iterator == 8:
            if iterator == 3:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#b50636', fmt = 'o', marker = "s", zorder = 4)
            elif iterator == 8:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#b50636', fmt = 'o', marker = "o", zorder = 4)
            ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#ec0040', fmt = 'o', zorder = 3, label = no, ms=3)

            # The following lines can be uncommented (and the above commented) to develop graphs for individual galaxies
            # ax1.scatter(x, y, color = '#f2bcc5', zorder = 2, label = no, s=5)
            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC6946')
            # legend_labels = ["NGC6946"]

            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of M100')
            # legend_labels = ["M100"]

            # The following lines ignore this galaxy
            # ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            # ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#e6e6e6', fmt = '.', marker = "s", zorder = 1, label = no)
            # ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#e6e6e6', fmt = '.', zorder = 1, label = no)

            dummy_variable = 1
        if iterator == 4 or iterator == 9:
            if iterator == 4:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#bb9407', fmt = 'o', marker = "s", zorder = 4)
            elif iterator == 9:
                ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#bb9407', fmt = 'o', marker = "*", zorder = 4)
            ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#f1bc00', fmt = 'o', zorder = 3, label = no, ms=3)

            # The following lines can be uncommented (and the above commented) to develop graphs for individual galaxies
            # ax1.scatter(x, y, color = '#f1d9ac', zorder = 2, label = no, s=5)
            # legend_labels = ["NGC7793"]
            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC7793')

            # legend_labels = ["NGC2841"]
            # ax1.set_title(r'Luminosity vs Photon Index ($\Gamma$) of NGC2841')

            # The following lines ignore this galaxy
            # ax1.scatter(x, y, color = '#e6e6e6', zorder = 1, label = no, s=5)
            # ax1.errorbar(x_binned, y_binned, xerr = x_error_binned, color = '#e6e6e6', fmt = '.', marker = "s", zorder = 1, label = no)
            # ax1.errorbar(x_unbinned, y_unbinned, xerr = x_error_unbinned, color = '#e6e6e6', fmt = '.', zorder = 1, label = no)

            dummy_variable = 1

    plt.yscale('log');
    ax1.set_xlabel("Photon Index")
    ax1.set_ylabel("Luminosity")
    ax1.set_title('Comparitive Chart')

    legend_labels = []
    for i in range(len(fits_dir)):
        legend_labels.append("".join(fits_dir[i].rsplit("-final-sample.fits")))

    ax1.legend(legend_labels)

    plt.grid(True)
    plt.draw()
    ax1.apply_aspect()
    fig.savefig('comparitive_auto.eps', dpi=fig.dpi)
    Image.open('comparitive_auto.eps').save('comparitive_auto.png','png')

    # The following lines can be uncommented (and the above commented) to develop graphs for individual galaxies

    # if (legend_labels == ["NGC4382", "NGC0628", "NGC2403", "NGC6946", "NGC7793", "M63", "M94", "M95", "M100", "NGC2841", "NGC3184", "NGC3198", "NGC4559"]):
    #     fig.savefig('comparitive_auto_update.eps', dpi=fig.dpi)
    #     Image.open('comparitive_auto_update.eps').save('comparitive_auto_update.png','png')
    #
    # elif (legend_labels == ["NGC4382"]):
    #     fig.savefig('NGC4382.eps', dpi=fig.dpi)
    #     Image.open('NGC4382.eps').save('NGC4382.png','png')
    #
    # elif (legend_labels == ["NGC0628"]):
    #     fig.savefig('NGC0628.eps', dpi=fig.dpi)
    #     Image.open('NGC0628.eps').save('NGC0628.png','png')
    #
    # elif (legend_labels == ["NGC2403"]):
    #     fig.savefig('NGC2403.eps', dpi=fig.dpi)
    #     Image.open('NGC2403.eps').save('NGC2403.png','png')
    #
    # elif (legend_labels == ["NGC6946"]):
    #     fig.savefig('NGC6946.eps', dpi=fig.dpi)
    #     Image.open('NGC6946.eps').save('NGC6946.png','png')
    #
    # elif (legend_labels == ["NGC7793"]):
    #     fig.savefig('NGC7793.eps', dpi=fig.dpi)
    #     Image.open('NGC7793.eps').save('NGC7793.png','png')
    #
    # if (legend_labels == ["M63"]):
    #     fig.savefig('M63.eps', dpi=fig.dpi)
    #     Image.open('M63.eps').save('M63.png','png')
    #
    # elif (legend_labels == ["M94"]):
    #     fig.savefig('M94.eps', dpi=fig.dpi)
    #     Image.open('M94.eps').save('M94.png','png')
    #
    # elif (legend_labels == ["M95"]):
    #     fig.savefig('M95.eps', dpi=fig.dpi)
    #     Image.open('M95.eps').save('M95.png','png')
    #
    # elif (legend_labels == ["M100"]):
    #     fig.savefig('M100.eps', dpi=fig.dpi)
    #     Image.open('M100.eps').save('M100.png','png')
    #
    # elif (legend_labels == ["NGC2841"]):
    #     fig.savefig('NGC2841.eps', dpi=fig.dpi)
    #     Image.open('NGC2841.eps').save('NGC2841.png','png')
    #
    # elif (legend_labels == ["NGC3184"]):
    #     fig.savefig('NGC3184.eps', dpi=fig.dpi)
    #     Image.open('NGC3184.eps').save('NGC3184.png','png')
    #
    # elif (legend_labels == ["NGC3198"]):
    #     fig.savefig('NGC3198.eps', dpi=fig.dpi)
    #     Image.open('NGC3198.eps').save('NGC3198.png','png')
    #
    # elif (legend_labels == ["NGC4559"]):
    #     fig.savefig('NGC4559.eps', dpi=fig.dpi)
    #     Image.open('NGC4559.eps').save('NGC4559.png','png')

    plt.show()
    return 0
main()


import re
#dictionary for rule mapping such that each rule by id maps to class label
rule_dict={}
rule_dict[0]=1 #location , key is rule ID and value is Label id. here it means rule 1 labels example as location
rule_dict[1]=5 #Cuisine
rule_dict[2]=1 #Location
rule_dict[3]=4 #Price
rule_dict[4]=8 #Rating
rule_dict[5]=2 #Hours
rule_dict[6]=2 #Hours
rule_dict[7]=3 #Amenity
rule_dict[8]=2 #Hours
rule_dict[9]=7 #Restaurant_Name
rule_dict[10]=6 #Dish
rule_dict[11]=4 #Price
rule_dict[12]=8 #Rating
rule_dict[13]=3 #Amenity
rule_dict[14]=7 #Restaurant Name

#all rules functions

#ex: any kid friendly restaurants around here
def rule0(sentence,sent_dict,rule_firing):
  label=rule_dict[0]
  s=sentence.lower()
  pattern= re.compile("( |^)[^\w]*(within|near|next|close|nearby|around|around)[^\w]*([^\s]+ ){0,2}(here|city|miles|mile)*[^\w]*( |$)")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(rule_firing[sent_dict[key]]==0):
          rule_firing[sent_dict[key]]=label
  return rule_firing

#ex: can you find me some chinese food
def rule1(sentence,sent_dict,rule_firing):
  label=rule_dict[1]
  s=sentence.lower()
  #print("sentence : ",sentence)
  #print("sentence in lowercase",s)
  words=s.strip().split(" ")
  #rule_firing=[0]*len(words)

  cuisine1a=['italian','american','japanese','spanish','mexican','chinese','vietnamese','vegan']
  cuisine1b=['bistro','delis']
  cuisine2=['barbecue','halal','vegetarian','bakery']
  #cuisine3=[('italian','bistro'),('japanese','delis')]

  for i in range(0,len(words)):
    if rule_firing[i]==0 : #rule not fired yet
      if words[i] in cuisine2:
        rule_firing[i]=label
      elif words[i] in cuisine1a:
        rule_firing[i]=label
        if i<len(words)-1:
          if words[i+1] in cuisine1b:
            rule_firing[i+1]=label

  #print(rule_firing)
  return rule_firing

#rule2 done in the area location
#ex: im looking for a 5 star restaurant in the area that serves wine
def rule2(sentence,sent_dict,firing_rule):
  label=rule_dict[2]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("in the area")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex: i need a family restaurant with meals under 10 dollars and kids eat
def rule3(sentence,sent_dict,firing_rule):
  label=rule_dict[3]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile(" ([0-9]+|few|under [0-9]+) dollar")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex: where can i get the highest rated burger within ten miles
def rule4(sentence,sent_dict,firing_rule):
  label=rule_dict[4]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("( (high|highly|good|best|top|well|highest|zagat) (rate|rating|rated))|((rated|rate|rating) [0-9]* star)|([0-9]+ star)")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex: where is the nearest italian restaurant that is still open
def rule5(sentence,sent_dict,firing_rule):
  label=rule_dict[5]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("((open|opened) (now|late))|(still (open|opened|closed|close))|(((open|close|opened|closed) \w+([\s]| \w* | \w* \w* ))*[0-9]+ (am|pm|((a|p) m)|hours|hour))")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex: find a vegan cuisine which is open until 2 pm
def rule6(sentence,sent_dict,firing_rule):
  label=rule_dict[6]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("(open|close) (\w* ){0,3}until (\w* ){0,2}(([0-9]* (am|pm|((a|p) m)|hour|hours))|(late (night|hour))|(midnight))")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex: i want to go to a restaurant within 20 miles that got a high rating and is considered fine dining
def rule7(sentence,sent_dict,firing_rule):
  label=rule_dict[7]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("(outdoor|indoor|group|romantic|family|outside|inside|fine|waterfront|outside|private|business|formal|casual|rooftop|(special occasion))([\s]| \w+ | \w+ \w+ )dining")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex:i need some late night chinese food within 4 miles of here
def rule8(sentence,sent_dict,firing_rule):
  label=rule_dict[8]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("(open |this |very ){0,2}late( night| dinner| lunch| dinning|( at night)){0,2}")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

# ex : is passims kitchen open at 2 am
def rule9(sentence,sent_dict,firing_rule):
  label=rule_dict[9]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("[\w+ ]{0,2}(palace|cafe|bar|kitchen|outback|dominoes)")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if sent_dict[key] != 'restaurants' and (firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex: please find me a pub that serves burgers
def rule10(sentence,sent_dict,firing_rule):
  label=rule_dict[10]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("wine|sandwich|pasta|burger|peroggis|burrito|(chicken tikka masala)|appetizer|pizza|winec|upcake|(onion ring)|tapas")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex: im looking for an inexpensive mexican restaurant
def rule11(sentence,sent_dict,firing_rule):
  label=rule_dict[11]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("(affordable|cheap|expensive|inexpensive)")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label

  bad_words=['the','a','an','has','have','that','this','beef','for','with','if','at']
  good_words=['price','prices','pricing','priced']
  words=s.strip().split(" ")
  for i in range(1,len(words)):
    if firing_rule[i-1]==0:
      if words[i] in good_words :
        if words[i-1] not in bad_words:
          firing_rule[i-1]=label
  return firing_rule

#ex: which moderately priced mexican restaurants within 10 miles have the best reviews
def rule12(sentence,sent_dict,firing_rule):
  label=rule_dict[12]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("(([0-9]*)|very|most)* (good|great|best|bad|excellent|negative|star) (\w* ){0,2}(review|reviews|rating|rated)")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

# ex: is there a pet friendly restaurant within 10 miles from here
def rule13(sentence,sent_dict,firing_rule):
  label=rule_dict[7]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("(pet|kid|)(friendly|indoor|outdoor|date|dining|buffet|great|fine|good|friend|group|birthday|anniversary|family|historical|family friendly|friendly)([\s]| \w+ | \w+ \w+ )(spot|dining|parking|dinne|style|eatries|catering|drive throughs|allow|amenity|amenity)*")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if(firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

#ex: where is the next mcdonalds
def rule14(sentence,sent_dict,firing_rule):
  label=rule_dict[9]
  #firing_rule=[0]*len(sent_dict.keys())
  s=sentence.lower()
  pattern=re.compile("(burger king|mcdonalds|taco bells|Mcdills|denneys|dennys|Mcdills)")
  r=re.finditer(pattern,s)
  for match in r:
    start=match.start()
    end=match.end()
    for key in sent_dict.keys():
      if key in range(start,end):
        if sent_dict[key] != 'restaurants' and (firing_rule[sent_dict[key]]==0):
          firing_rule[sent_dict[key]]=label
  return firing_rule

rule_list=[rule0,rule1,rule2,rule3,rule4,rule5,rule6,rule7,rule8,rule9,rule10,rule11,rule12,rule13,rule14]
num_rules=len(rule_list)


import copy
import os
import shlex
import sys
import textwrap
from functools import wraps

def bash_quote(w, quote):
    '''
    Quote word *w* with quote character *quote* which may be empty, single quote or double quote.
    '''
    assert quote in ('', '"', "'")
    if quote == "'":
        w = w.replace("'", quote + '"\'"' + quote)
    else:
        # some characters are special and cannot be escaped unless we use a single quote:
        # ! - get rid of history expansion
        # \x01 - breaks escaping in bash: echo "\\$" -> \\$
        # \n - when only using escapes
        special_characters = '!\x01'
        if quote == '':
            special_characters += '\n'
        for special in special_characters:
            if special in w:
                return ("'" + special + "'").join(bash_quote(s, quote) for s in w.split(special))

        # escape characters
        escaped_chars = set()
        if quote == '':
            escaped_chars |= set(os.environ.get("COMP_WORDBREAKS", " \t\"'@><=;|&(:."))
            escaped_chars |= set("`$\"'\t ~&;?|#()*{><[")
        elif quote == '"':
            escaped_chars |= set("`$\"")
        escaped = ''
        last = ''
        for i, c in enumerate(w):
            if last == '\\' and (c in escaped_chars | set('\n\\') or quote == ''):
                escaped += '\\'
            if (c == '\\' and i == len(w) - 1) or (c in escaped_chars):
                escaped += '\\'
            escaped += c
            last = c
        w = escaped
    return quote + w + quote

class Namespace(dict):
    def __getattr__(self, key):
        return self[key]

    def __setattr__(self, key, value):
        self[key] = value

    def __deepcopy__(self, memo):
        return copy.deepcopy(dict(self), memo)

class Parser(object):
    def __init__(self, tokens, complete_token=None):
        '''
        :param complete_token: the token to be completed; `None` disables completion
        '''
        self.tokens = tokens
        self.complete_token = complete_token
        # internal state
        self.long = {}
        self.short = {}
        self.pos = 0
        # results
        self._completions = []
        self.values = Namespace()
        self.errors = []
        self.subcommands = []

    def get_state(self):
        return dict([(attr, copy.copy(getattr(self, attr)))
                     for attr in ('long', 'short', 'pos', '_completions', 'errors', 'subcommands')] +
                    [('values', Namespace(copy.deepcopy(self.values)))])

    def set_state(self, state):
        for attr, val in state.items():
            setattr(self, attr, val)

    def add_options(self, options):
        for opt in options:
            if opt.short:
                self.short[opt.short] = opt
            if opt.long:
                self.long[opt.long] = opt

    def error(self, error):
        self.errors.append(error)

    def __repr__(self):
        return "<Parser values=%r, errors=%r, subcommands=%r>" % (self.values, self.errors, self.subcommands)

    @property
    def token(self):
        return self.tokens[self.pos] if self.pos < len(self.tokens) else None

    @property
    def last_token(self):
        return self.tokens[self.pos - 1] if self.pos - 1 >= 0 else None

    def token_is_option(self):
        return self.token.startswith('-')

    def eat_token(self):
        token = self.token
        self.pos += 1
        return token

    def barf_token(self):
        self.pos -= 1

    def parse_options(self):
        while self.token and self.token_is_option():
            option = None
            token = self.eat_token()
            if token.startswith('--'):
                if token[2:] in self.long:
                    option = self.long[token[2:]]
            elif token[1:] in self.short:
                option = self.short[token[1:]]
            if option is None:
                self.error('Unknown option %s' % token)
                return
            else:
                option.parse(self)
        if self._completing_option:
            self._add_completions('-' + k for k in list(self.short.keys()))
            self._add_completions('--' + k for k in list(self.long.keys()))

    def parse_arguments(self, arguments):
        for arg in arguments:
            if arg.nargs not in (None, '?', '*', '+'):
                raise Exception('Invalid nargs %s' % arg.nargs)
            self._add_arg_completions(arg)
            self.parse_options()
            if arg.nargs in (None, '+'):
                arg.parse(self)
                self.parse_options()
            if arg.nargs in ('?', '*', '+'):
                rewind_state = None
                while self.token and (not arg.choices or self.token in arg.choices):
                    if type(arg.stop_at) != list and self.token == arg.stop_at:
                        rewind_state = self.get_state()
                    elif type(arg.stop_at) == list and self.token in arg.stop_at:
                        rewind_state = self.get_state()
                    arg.parse(self)
                    self.parse_options()
                    if arg.nargs == '?':
                        break
                if rewind_state:
                    self.set_state(rewind_state)
                if arg.nargs in ('*', '+'):
                    # Even if the token doesn't match the set of choices, it
                    # might still yield valid completions for the current arg
                    self._add_arg_completions(arg)
            if self.errors:
                return
        self.parse_options()

    @property
    def completing(self):
        return not self.errors and self.token is None and self.complete_token is not None

    @property
    def _completing_option(self):
        return self.completing and len(self.complete_token) > 0 and self.complete_token[0] == '-'

    @property
    def _completing_argument(self):
        return self.completing and (len(self.complete_token) == 0 or self.complete_token[0] != '-')

    def _add_completions(self, completions):
        self._completions.extend(c for c in completions if c.startswith(self.complete_token))

    def _add_arg_completions(self, arg):
        if self._completing_argument:
            self._add_completions(arg.completions(self.complete_token, self))

class Option(object):
    def __init__(self, short, long, action='store_true', dest=None, help=None, default=None):
        '''
        The number of additional tokens needed for an Option is determined by
        *action*:

        - ``store_true`` requires 0 tokens and stores True in *dest*
        - ``store`` requires 1 token and stores it in *dest**
        '''
        self.short = short
        self.long = long
        self.dest = dest if dest else long
        self.help = help
        self.action = action
        self.default = default

    def __repr__(self):
        return '-%s/--%s' % (self.short, self.long)

    def set_default(self, parser):
        parser.values[self.dest] = self.default

    def parse(self, parser):
        if self.action == 'store_true':
            parser.values[self.dest] = True
        elif self.action == 'store':
            if parser.token is None or parser.token_is_option():
                parser.error("%s expects an argument" % parser.last_token)
            else:
                value = parser.eat_token()
                parser.values[self.dest] = value

class ArgMixin(object):
    def usage(self):
        if self.nargs is None:
            return self.metavar
        elif self.nargs == '?':
            return '[%s]' % self.metavar
        elif self.nargs == '*':
            return '[%s]...' % self.metavar
        elif self.nargs == '+':
            return '%s...' % self.metavar
        else:
            raise Exception('Invalid nargs %s' % self.nargs)

    def __repr__(self):
        return self.metavar

    def set_default(self, parser):
        '''
        Sets the default value for the curent argument. Called as soon as the argument's command is seen.
        '''
        pass

    def completions(self, complete_token, parser):
        '''
        Returns the completions matching `complete_token` for the current state from `parser`.
        '''
        pass

    def parse(self, parser):
        '''
        Uses the state from `parser` to consume the tokens for the current arg
        (only one instance, even if nargs says otherwise).  Called only if at
        least a token is required for the current argument.
        '''
        pass

class Argument(ArgMixin):
    def __init__(self, name, dest=None, metavar=None, nargs=None, action='store', choices=None,
                 default=None, completions=None, stop_at=None):
        self.name = name
        self.dest = dest if dest else name
        if metavar:
            self.metavar = metavar
        elif choices:
            self.metavar = '|'.join(choices)
        else:
            self.metavar = name.upper()
        self.nargs = nargs
        self.action = action
        self.choices = choices
        self.completion_fn = completions
        self.default = default
        # stop_at is an ugly hack to resolve grammar ambiguity
        # The parser will revert to the state for the last instance of this token
        self.stop_at = stop_at

    def set_default(self, parser):
        if self.action in ('append', 'append_unique') or self.nargs in ('*', '+'):
            parser.values.setdefault(self.dest, [])
        elif self.action == 'store':
            parser.values.setdefault(self.dest, self.default)
        else:
            pass

    def completions(self, complete_token, parser):
        if self.choices:
            if self.action == 'append_unique':
                return set(self.choices) - set(parser.values[self.dest])
            else:
                return self.choices
        elif hasattr(self, 'completion_fn') and callable(self.completion_fn):
            comps = self.completion_fn(complete_token, parser)
            if self.action == 'append_unique':
                return set(comps) - set(parser.values[self.dest])
            return comps
        else:
            return []

    def parse(self, parser):
        token = parser.eat_token()
        if token is None:
            parser.error("A value is required for %s" % self.metavar)
            return
        if self.choices and token not in self.choices:
            parser.error("%s must be one of: %s" % (self.metavar, ' '.join(self.choices)))
            return

        if self.action == 'append' or self.nargs in ('*', '+'):
            parser.values[self.dest].append(token)
        elif self.action == 'store':
            parser.values[self.dest] = token
        elif self.action == 'append_unique':
            pv = parser.values[self.dest]
            if token in pv:
                parser.error('%s cannot be specified twice' % token)
            else:
                pv.append(token)
        elif self.action is None:
            pass
        else:
            raise Exception('Invalid action %s' % self.action)

class Token(Argument):
    def __init__(self, name, dest=None, nargs=None, action=None):
        super(Token, self).__init__(name, metavar=name, choices=(name, ), action=action, nargs=nargs)
        if dest is None:
            self.dest = None

class Group(ArgMixin):
    '''
    If the group has nargs='?' or nargs='*' and it's not followed by eof it must
    start with a static set of choices (otherwise the grammar would be
    ambiguous).
    '''
    def __init__(self, *args, **kwargs):
        self.nargs = kwargs.pop('nargs', None)
        self.stop_at = kwargs.pop('stop_at', None)
        self.arguments = args

    @property
    def metavar(self):
        return ' '.join(a.usage() for a in self.arguments)

    @property
    def choices(self):
        return self.arguments[0].choices

    def completions(self, complete_token, parser):
        return self.arguments[0].completions(complete_token, parser)

    def parse(self, parser):
        parser.parse_arguments(self.arguments)

    def set_default(self, parser):
        for arg in self.arguments:
            arg.set_default(parser)

class Command(object):
    def __init__(self, name, *args, **kwargs):
        self.name = name
        self.options = []
        self.subcommands = []
        self.arguments = []
        for o in args:
            if isinstance(o, Option):
                self.options.append(o)
            elif isinstance(o, Command):
                self.subcommands.append(o)
            else:
                self.arguments.append(o)
        self.help = kwargs.pop('help', None)
        self.description = kwargs.pop('description', None)
        self.defaults = kwargs.pop('defaults', {})
        self.default_subcommand = kwargs.pop('default_subcommand', None)
        assert not kwargs

    def register(self, *args, **kwargs):
        def decorator(func):
            cmd, path = self._get_scmd_path(args[0])
            if 'description' not in kwargs and func.__doc__:
                kwargs['description'] = textwrap.dedent(func.__doc__).strip()
            kwargs.setdefault('defaults', {}).setdefault('run', func)
            cmd.subcommands.append(Command(path[-1], *(args[1:]), **kwargs))

            @wraps(func)
            def wrapper(*wargs, **wkwargs):
                func(*wargs, **wkwargs)
            return wrapper
        return decorator

    def alias(self, source_path, dest_path):
        scmd, spath = self._get_scmd_path(source_path)
        dcmd, dpath = self._get_scmd_path(dest_path)
        dest_cmd = copy.copy(scmd._get_subcommand(spath[-1]))
        dest_cmd.name = dpath[-1]
        dcmd.subcommands.append(dest_cmd)

    def set_default(self, parser):
        parser.values.update(self.defaults)
        for arg in self.arguments:
            arg.set_default(parser)
        for opt in self.options:
            opt.set_default(parser)

    def parse(self, tokens):
        parser = Parser(tokens)
        self._parse_command(parser)
        if parser.token:
            parser.error('Unparsed tokens: %s' % ' '.join(parser.tokens[parser.pos:]))
        return parser

    def complete(self, line, point):
        # ignore everything after point
        line = line[:point]
        # if the line ends in an incomplete escape sequence skip it
        if line[-1] == '\\' and line[-2] != '\\':
            line = line[:-1]
        quote_char = ''
        for attempt in range(2):
            try:
                lex = shlex.shlex(line, posix=True)
                lex.whitespace_split = True
                tokens = list(lex)
            except ValueError:
                if attempt == 0:
                    # close the quotes and try again
                    quote_char = lex.state
                    line += quote_char
                else:
                    raise
        tokens = tokens[1:]  # skip the program name
        if tokens and (line[-1] != ' ' or line[-2:] == '\ '):
            complete_token = tokens.pop()
        else:
            complete_token = ''
        parser = Parser(tokens, complete_token)
        self._parse_command(parser)
        return set(bash_quote(c, quote_char) for c in parser._completions)

    def handle_shell_completion(self):
        if 'COMP_LINE' in os.environ:
            for c in self.complete(os.environ['COMP_LINE'], int(os.environ['COMP_POINT'])):
                print(c)
            sys.exit()

    def usage(self):
        return ' '.join([self.name] + [a.usage() for a in self.arguments])

    def chain_usage(self, chain):
        return ' '.join(c.usage() for c in chain)

    def print_help(self, subcommands):
        '''Only works for the top-level command'''
        last = self
        chain = [self]
        for cmd_name in subcommands:
            last = last._get_subcommand(cmd_name)
            if last is None:
                print("Unknown subcommand: %s" % cmd_name)
                return
            chain.append(last)

        usage = self.chain_usage(chain)
        if last.subcommands:
            if last.default_subcommand:
                usage += ' [<subcommand>]'
            else:
                usage += ' <subcommand>'
        print("Usage: {}".format(usage))
        if last.description or last.help:
            print("\n", last.description or last.help)

        def _cmd_chains(cmd, stop_on_args=False):
            '''Follows subcommand chains until an argument can be specified'''
            if not cmd.subcommands or (cmd.arguments and stop_on_args):
                return {'': cmd}
            else:
                return dict(((s.name + ' ' + name).strip(), cmd)
                            for s in cmd.subcommands
                            for name, cmd in _cmd_chains(s, True).items())
        if last.subcommands:
            print("\nSubcommands:")
            if last.default_subcommand:
                cmd = last._get_subcommand(last.default_subcommand)
                print("  %-20s %s" % ('[%s]' % cmd.name, cmd.help or cmd.name))
            for name, cmd in sorted(_cmd_chains(last).items()):
                if not last.default_subcommand or last.default_subcommand != name:
                    print("  %-20s %s" % (name, cmd.help or name))

        for i, cmd in enumerate(reversed(chain)):
            if cmd.options:
                print("\nOptions for %s:" % ' '.join(c.name for c in chain[:len(chain) - i]))
                wrapper = textwrap.TextWrapper(width=80,
                                               initial_indent=' ' * 26,
                                               subsequent_indent=' ' * 26)
                for opt in sorted(cmd.options, key=lambda x: x.long or x.short):
                    print("  %-2s %-20s %s" % ('-' + opt.short if opt.short else '',
                                               '--' + opt.long if opt.long else '',
                                               wrapper.fill(opt.help or '').lstrip()))

    def _get_subcommand(self, subcommand):
        for cmd in self.subcommands:
            if cmd.name == subcommand:
                return cmd
        else:
            return None

    def _get_scmd_path(self, path_string):
        path = path_string.split()
        cmd = self
        for cname in path[:-1]:
            cmd = cmd._get_subcommand(cname)
            if cmd is None:
                raise Exception('Invalid command path: %s (%s not found)' % (path_string, cname))
        return cmd, path

    def _parse_command(self, parser):
        self.set_default(parser)
        parser.add_options(self.options)
        parser.parse_arguments(self.arguments)
        if self.subcommands:
            if parser._completing_argument:
                parser._add_completions(s.name for s in self.subcommands)
            token = parser.eat_token()
            if token is None:
                if self.default_subcommand:
                    self._get_subcommand(self.default_subcommand).set_default(parser)
                else:
                    parser.error("Subcommand expected")
            else:
                cmd = self._get_subcommand(token.lower())
                if cmd:
                    parser.subcommands.append(cmd.name)
                    cmd._parse_command(parser)
                elif self.default_subcommand:
                    parser.barf_token()
                    cmd = self._get_subcommand(self.default_subcommand)
                    cmd._parse_command(parser)
                else:
                    parser.error("Invalid subcommand %s" % token)


name_of_file = input("Введите имя файла для анализа")
name_of_file += '.txt'

amount = 0

with open(name_of_file, 'r') as file:
    lines = file.readlines()
    for line in lines:
        amount += int(line)
    print("Общая сумма у нас состоявляет", amount)
    print("Среднее у нас получается: ", amount/len(lines))


#!/usr/bin/python3
"""This is a function that prints stuffies"""

def say_my_name(first_name, last_name=""):
    """This functions does the printing
    Args:
        first_name (string)
        last_name (string)

    Raises:
        TypeError: when the names aren't a string
    """
    if not isinstance(first_name, str):
        TypeError ("first_name must be a string")
    if not isinstance(last_name, str):
        TypeError ("last_name must be a string")
    print("My name is {} {}".format(first_name, last_name))


# https://leetcode.com/problems/find-all-duplicates-in-an-array/description/

#Time: O(n), Space: O(N)
class Solution:
    def findDuplicates(self, nums: List[int]) -> List[int]:
        lst = []
        hashMap = {}
        for num in nums:
            if num not in hashMap:
                hashMap[num] = 0
            hashMap[num] += 1
            if hashMap[num] == 2:
                lst.append(num)
        return lst


import datetime
import logging

from concurrent import futures

from google.appengine.ext import ndb

from upvote.gae.bigquery import tables
from upvote.gae.datastore.models import exemption as exemption_models
from upvote.gae.datastore.models import host as host_models
from upvote.gae.datastore.models import policy as policy_models
from upvote.gae.lib.bit9 import api as bit9_api
from upvote.gae.lib.bit9 import utils as bit9_utils
from upvote.gae.lib.exemption import checks
from upvote.gae.lib.exemption import notify
from upvote.gae.lib.exemption import monitoring
from upvote.gae.utils import env_utils
from upvote.gae.utils import mail_utils
from upvote.gae.utils import template_utils
from upvote.shared import constants

# Done for brevity.
_STATE = constants.EXEMPTION_STATE

class Error(Exception):
  """Base error class for this module."""

class UnknownHostError(Error):
  """Raised when a particular host cannot be found."""

class InvalidEnforcementLevelError(Error):
  """Raised when an invalid Bit9 enforcement level is provided."""

class UnknownPolicyError(Error):
  """Raised if a Bit9 host has an unknown policy."""

class InvalidClientModeError(Error):
  """Raised when an invalid Santa client mode is provided."""

class UnsupportedPlatformError(Error):
  """Raised if an Exemption with an unsupported platform is encountered."""

class UnsupportedClientError(Error):
  """Raised when attempting to take an action for an unsupported client."""

class InvalidStateChangeError(Error):
  """Raised when attempting to change an Exemption to an invalid state."""

class InvalidReasonError(Error):
  """Raised when an invalid EXEMPTION_REASON is provided."""

class InvalidDurationError(Error):
  """Raised when an invalid EXEMPTION_DURATION is provided."""

class InvalidRenewalError(Error):
  """Raised when trying to make an invalid Exemption renewal."""

_POLICY_CHECKS = {
    constants.PLATFORM.MACOS: [],
    constants.PLATFORM.WINDOWS: [],
}

def _ChangeEnforcementInBit9(host_id, new_enforcement_level):
  """Changes enforcement level for a Bit9Host.

  Args:
    host_id: The ID of the Bit9Host.
    new_enforcement_level: The new enforcement level to set for the Bit9Host.

  Raises:
    UnknownHostError: if the host cannot be found in Datastore.
    InvalidEnforcementLevelError: if the provided enforcement level is invalid.
    UnknownPolicyError: if the host's Bit9 policy is unknown.
  """
  # Verify the host_id corresponds to an actual Bit9Host.
  if not host_models.Bit9Host.get_by_id(host_id):
    monitoring.enforcement_errors.Increment()
    raise UnknownHostError('Host %s is unknown' % host_id)

  # Verify the specified enforcement level is valid.
  if new_enforcement_level not in constants.BIT9_ENFORCEMENT_LEVEL.SET_ALL:
    monitoring.enforcement_errors.Increment()
    raise InvalidEnforcementLevelError(
        'Invalid Bit9 enforcement level: %s' % new_enforcement_level)

  # Retrieve the current Computer policy from Bit9.
  computer = bit9_api.Computer.get(int(host_id), bit9_utils.CONTEXT)
  current_policy_id = computer.policy_id

  # Determine the appropriate policy for the new enforcement level.
  policy_map = constants.BIT9_ENFORCEMENT_LEVEL.MAP_TO_POLICY_ID
  new_policy_id = policy_map.get(new_enforcement_level)

  # If there's not a valid policy, bail.
  if not new_policy_id:
    monitoring.enforcement_errors.Increment()
    raise UnknownPolicyError(
        'Host %s has an unknown policy ID: %s' % (host_id, current_policy_id))

  logging.info(
      'Changing policy from %s to %s', current_policy_id, new_policy_id)

  # Write the new policy back to Bit9.
  computer.policy_id = new_policy_id
  computer.put(bit9_utils.CONTEXT)

  # Change the policy Key on the entity itself.
  new_policy_key = ndb.Key(policy_models.Bit9Policy, new_policy_id)
  host_models.Bit9Host.ChangePolicyKey(host_id, new_policy_key)

  # Insert a row into BigQuery reflecting the change.
  host = host_models.Bit9Host.get_by_id(host_id)
  tables.HOST.InsertRow(
      device_id=host_id,
      timestamp=datetime.datetime.utcnow(),
      action=constants.HOST_ACTION.MODE_CHANGE,
      hostname=host.hostname,
      platform=constants.PLATFORM.WINDOWS,
      users=host.users,
      mode=new_enforcement_level)

def _ChangeEnforcementInSanta(host_id, new_client_mode):
  """Toggles between MONITOR and LOCKDOWN for a SantaHost.

  Args:
    host_id: The ID of the SantaHost.
    new_client_mode: The new client mode to set for the SantaHost.

  Raises:
    UnknownHostError: if the host cannot be found in Datastore.
    InvalidClientModeError: if the provided client mode is invalid.
  """
  # Verify the host_id corresponds to an actual SantaHost.
  host = host_models.SantaHost.get_by_id(host_id)
  if not host:
    monitoring.enforcement_errors.Increment()
    raise UnknownHostError('Host %s is unknown' % host_id)

  # Verify the specified client mode is valid.
  if new_client_mode not in constants.CLIENT_MODE.SET_ALL:
    monitoring.enforcement_errors.Increment()
    raise InvalidClientModeError(
        'Invalid Santa client mode: %s' % new_client_mode)

  host_models.SantaHost.ChangeClientMode(host_id, new_client_mode)

  # If changing to MONITOR mode and transitive whitelisting is enabled, disable
  # it.
  if (new_client_mode == constants.CLIENT_MODE.MONITOR and
      host.transitive_whitelisting_enabled):
    ChangeTransitiveWhitelisting(host_id, False)

  host = host_models.Host.get_by_id(host_id)
  tables.HOST.InsertRow(
      device_id=host_id,
      timestamp=datetime.datetime.utcnow(),
      action=constants.HOST_ACTION.MODE_CHANGE,
      hostname=host.hostname,
      platform=constants.PLATFORM.MACOS,
      users=[host.primary_user],
      mode=host.client_mode)

def _EnableLockdown(exm_key):
  """Enables LOCKDOWN mode for a given Exemption.

  Args:
    exm_key: The Key of the Exemption we're enabling LOCKDOWN for.

  Raises:
    UnsupportedPlatformError: if the platform of the corresponding Host is
        unsupported.
  """
  host_id = exm_key.parent().id()
  platform = exemption_models.Exemption.GetPlatform(exm_key)
  logging.info('Enabling LOCKDOWN mode for Host %s', host_id)

  if platform == constants.PLATFORM.WINDOWS:
    _ChangeEnforcementInBit9(host_id, constants.BIT9_ENFORCEMENT_LEVEL.LOCKDOWN)

  elif platform == constants.PLATFORM.MACOS:
    _ChangeEnforcementInSanta(host_id, constants.CLIENT_MODE.LOCKDOWN)

  else:
    monitoring.enforcement_errors.Increment()
    raise UnsupportedPlatformError(
        'Host %s has an unsupported platform: %s' % (host_id, platform))

def _DisableLockdown(exm_key):
  """Disables LOCKDOWN mode for a given Exemption.

  Args:
    exm_key: The Key of the Exemption we're disabling LOCKDOWN for.

  Raises:
    UnsupportedPlatformError: if the platform of the corresponding Host is
        unsupported.
  """
  host_id = exm_key.parent().id()
  platform = exemption_models.Exemption.GetPlatform(exm_key)
  logging.info('Disabling LOCKDOWN mode for Host %s', host_id)

  if platform == constants.PLATFORM.WINDOWS:
    _ChangeEnforcementInBit9(host_id, constants.BIT9_ENFORCEMENT_LEVEL.MONITOR)

  elif platform == constants.PLATFORM.MACOS:
    _ChangeEnforcementInSanta(host_id, constants.CLIENT_MODE.MONITOR)

  else:
    monitoring.enforcement_errors.Increment()
    raise UnsupportedPlatformError(
        'Host %s has an unsupported platform: %s' % (host_id, platform))

@ndb.transactional
def Request(host_id, reason, other_text, duration):
  """Creates a new Exemption, or reuses an existing one.

  If no corresponding Exemption exists, creates a new one in the REQUESTED
  state. Otherwise, if one exists in a terminal state
  (CANCELLED/REVOKED/EXPIRED), sets it back to REQUESTED with the new
  deactivation date.

  Args:
    host_id: (str) Host ID
    reason: (str) The reason for requesting an Exemption. Must be one of
        constants.EXEMPTION_REASON.
    other_text: (str) Additional text if the reason is OTHER
    duration: (str) The requested duration of the Exemption. Must be one of
        constants.EXEMPTION_DURATION.

  Raises:
    InvalidReasonError: if the provided reason is invalid.
    InvalidDurationError: if the provided duration is invalid.
    InvalidRenewalError: if the Exemption cannot currently be renewed.
  """
  logging.info('Requesting Exemption for host %s', host_id)

  # Validate the reason.
  if reason not in constants.EXEMPTION_REASON.SET_ALL:
    message = 'Invalid reason provided: %s' % reason
    logging.error(message)
    raise InvalidReasonError(message)

  # Validate the duration.
  if duration not in constants.EXEMPTION_DURATION.SET_ALL:
    message = 'Invalid exemption duration: %s' % duration
    logging.error(message)
    raise InvalidDurationError(message)

  duration_delta = datetime.timedelta(
      days=constants.EXEMPTION_DURATION.MAP_TO_DAYS[duration])
  deactivation_dt = datetime.datetime.utcnow() + duration_delta

  exm = exemption_models.Exemption.Get(host_id)

  # If an Exemption has never existed for this host_id, just create one.
  if exm is None:
    exm_key = exemption_models.Exemption.Insert(
        host_id, deactivation_dt, reason, other_text=other_text)
    notify.DeferUpdateEmail(exm_key, _STATE.REQUESTED, transactional=True)
    return

  # If we're dealing with an existing Exemption which can state change back to
  # REQUESTED, then make the change.
  if exm.CanChangeToState(_STATE.REQUESTED):
    exm_key = exemption_models.Exemption.CreateKey(host_id)
    details = [reason, other_text] if other_text else [reason]
    exemption_models.Exemption.ChangeState(
        exm_key, _STATE.REQUESTED, details=details)
    exm.deactivation_dt = deactivation_dt
    exm.put()
    notify.DeferUpdateEmail(exm_key, _STATE.REQUESTED, transactional=True)

  # Otherwise, we've received a request for an invalid renewal.
  else:
    message = 'Host %s already has a(n) %s Exemption' % (host_id, exm.state)
    logging.error(message)
    raise InvalidRenewalError(message)

def Process(exm_key):
  """Checks if a REQUESTED Exemption is compatible with all policies.

  Args:
    exm_key: The NDB Key of the Exemption entity.
  """
  host_id = exm_key.parent().id()
  logging.info('Processing Exemption for host %s', host_id)

  # Change state from REQUESTED to PENDING.
  try:
    exemption_models.Exemption.ChangeState(exm_key, _STATE.PENDING)

  # Process() shouldn't be transactional due to all the potential calls out made
  # below. Because of this, it's entirely possible that the calls to Process()
  # in RequestExemptionHandler and ProcessExemptions could both end up trying to
  # transition this Exemption to PENDING at the same time. It's a benign race
  # condition, so we should just note it and move on.
  except exemption_models.InvalidStateChangeError:
    logging.warning(
        'Error encountered while processing Exemption for host %s', host_id)
    return

  # Any other Exceptions should make noise.
  except Exception:  # pylint: disable=broad-except
    monitoring.processing_errors.Increment()
    logging.exception(
        'Error encountered while processing Exemption for host %s', host_id)
    return

  try:

    # If no platform can be determined, auto-deny, because it means there's a
    # bug. Otherwise this request will just endlessly bounce between REQUESTED
    # and PENDING.
    try:
      platform = exemption_models.Exemption.GetPlatform(exm_key)
    except exemption_models.UnknownPlatformError:
      message = 'Host %s has an unknown platform' % host_id
      logging.error(message)
      monitoring.processing_errors.Increment()
      Deny(exm_key, details=[message])
      return

    # If no policy has been defined for the platform, auto-deny, because it
    # means there's a bug. Otherwise this request will just endlessly bounce
    # between REQUESTED and PENDING.
    if platform not in _POLICY_CHECKS:
      message = 'Platform "%s" is unsupported' % platform
      logging.error(message)
      monitoring.processing_errors.Increment()
      Deny(exm_key, details=[message])
      return

    # An empty policy should fail open, otherwise it would require a no-op check
    # which always returns APPROVED. An empty policy that fails closed would be
    # better suited by simply disabling the exemption system altogether.
    policy_checks = _POLICY_CHECKS[platform]
    if not policy_checks:
      logging.info('Empty policy defined for platform "%s"', platform)
      Approve(exm_key)
      return

    # Create a ThreadPoolExecutor and run the individual policy checks.
    logging.info(
        'Executing %d policy check(s) against host %s', len(policy_checks),
        host_id)
    with futures.ThreadPoolExecutor(max_workers=len(policy_checks)) as executor:
      running_futures = [
          executor.submit(check, exm_key) for check in policy_checks]
      done_futures = futures.wait(running_futures).done
      results = [done_future.result() for done_future in done_futures]

    # If any of the checks return a non-'outcome' state, auto-deny, because it
    # means there's a bug. Otherwise this request will just endlessly bounce
    # between REQUESTED and PENDING.
    for result in results:
      if result.state not in _STATE.SET_OUTCOME:
        message = '%s returned an invalid state: %s' % (
            result.name, result.state)
        logging.error(message)
        monitoring.processing_errors.Increment()
        Deny(exm_key, details=[message])
        return

    details = [result.detail for result in results if result.detail]

    # Outcome precedence is: any(DENIED) > any(ESCALATED) > any(APPROVED).
    if any(result.state == _STATE.DENIED for result in results):
      Deny(exm_key, details=details)
    elif any(result.state == _STATE.ESCALATED for result in results):
      Escalate(exm_key, details=details)
    else:
      Approve(exm_key, details=details)

  except Exception as e:  # pylint: disable=broad-except

    logging.exception(
        'Error encountered while processing Exemption for host %s', host_id)
    monitoring.processing_errors.Increment()

    # If something breaks, revert back to REQUESTED so the cron can retry.
    exemption_models.Exemption.ChangeState(
        exm_key, _STATE.REQUESTED,
        details=['Error while processing: ' + str(e)])

@ndb.transactional(xg=True)  # xg due to Windows (Bit9Host & Bit9ApiAuth)
def Approve(exm_key, details=None):
  """Transitions an Exemption to the APPROVED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.
    details: Optional list of strings describing the rationale.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Approving Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.APPROVED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.APPROVED))

  _DisableLockdown(exm_key)
  exemption_models.Exemption.ChangeState(
      exm_key, _STATE.APPROVED, details=details)
  notify.DeferUpdateEmail(
      exm_key, _STATE.APPROVED, details=details, transactional=True)

@ndb.transactional
def Deny(exm_key, details=None):
  """Transitions an Exemption to the DENIED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.
    details: Optional list of strings describing the rationale.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Denying Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.DENIED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.DENIED))

  exemption_models.Exemption.ChangeState(
      exm_key, _STATE.DENIED, details=details)
  notify.DeferUpdateEmail(
      exm_key, _STATE.DENIED, details=details, transactional=True)

@ndb.transactional
def Escalate(exm_key, details=None):
  """Transitions an Exemption to the ESCALATED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.
    details: Optional list of strings describing the rationale.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Escalating Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.ESCALATED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.ESCALATED))

  exemption_models.Exemption.ChangeState(
      exm_key, _STATE.ESCALATED, details=details)

@ndb.transactional(xg=True)  # xg due to Windows (Bit9Host & Bit9ApiAuth)
def Expire(exm_key):
  """Transitions an Exemption to the EXPIRED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Expiring Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.EXPIRED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.EXPIRED))

  _EnableLockdown(exm_key)
  exemption_models.Exemption.ChangeState(exm_key, _STATE.EXPIRED)
  notify.DeferUpdateEmail(exm_key, _STATE.EXPIRED, transactional=True)

@ndb.transactional(xg=True)  # xg due to Windows (Bit9Host & Bit9ApiAuth)
def Revoke(exm_key, details):
  """Transitions an Exemption to the REVOKED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.
    details: List of strings describing the rationale.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Revoking Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.REVOKED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.REVOKED))

  _EnableLockdown(exm_key)
  exemption_models.Exemption.ChangeState(
      exm_key, _STATE.REVOKED, details=details)
  notify.DeferUpdateEmail(
      exm_key, _STATE.REVOKED, details=details, transactional=True)

@ndb.transactional(xg=True)  # xg due to Windows (Bit9Host & Bit9ApiAuth)
def Cancel(exm_key):
  """Transitions an Exemption to the CANCELLED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Cancelling Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.CANCELLED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.CANCELLED))

  _EnableLockdown(exm_key)
  exemption_models.Exemption.ChangeState(exm_key, _STATE.CANCELLED)
  notify.DeferUpdateEmail(exm_key, _STATE.CANCELLED, transactional=True)

@ndb.transactional
def ChangeTransitiveWhitelisting(host_id, enable):
  """Changes the transitive whitelisting state for a SantaHost.

  Args:
    host_id: The ID of the SantaHost.
    enable: Whether to enable or disable transitive whitelisting.

  Raises:
    UnsupportedClientError: if called against anything other than a SantaHost.
  """
  # Only Santa clients are supported.
  host = host_models.Host.get_by_id(host_models.Host.NormalizeId(host_id))
  if host.GetClientName() != constants.CLIENT.SANTA:
    raise UnsupportedClientError(
        'Only Santa clients support transitive whitelisting')

  # If this is a no-op, just bail now.
  if host.transitive_whitelisting_enabled == enable:
    logging.warning(
        'Transitive whitelisting is already %s for %s',
        'enabled' if enable else 'disabled', host.hostname)
    return

  # Make the change.
  host.transitive_whitelisting_enabled = enable
  host.put()
  modification = 'enabled' if enable else 'disabled'
  logging.info('Transitive whitelisting %s for %s', modification, host.hostname)

  # If enabling transitive whitelisting and the SantaHost has an APPROVED
  # Exemption, cancel it.
  exm_key = exemption_models.Exemption.CreateKey(host_id)
  exm = exm_key.get()
  if enable and exm and exm.state == constants.EXEMPTION_STATE.APPROVED:
    Cancel(exm_key)

  # Notify the user of the mode change.
  body = template_utils.RenderEmailTemplate(
      'transitive_modified.html', modification=modification,
      device_hostname=host.hostname, upvote_hostname=env_utils.ENV.HOSTNAME)
  subject = 'Developer mode changed: %s' % host.hostname
  mail_utils.Send(subject, body, to=[host.primary_user], html=True)

  # Note the state change in BigQuery.
  comment = 'Transitive whitelisting %s' % modification
  tables.HOST.InsertRow(
      device_id=host_id,
      timestamp=datetime.datetime.utcnow(),
      action=constants.HOST_ACTION.COMMENT,
      hostname=host.hostname,
      platform=constants.PLATFORM.MACOS,
      users=[host.primary_user],
      mode=host.client_mode,
      comment=comment)


#sets não permitem valores duplicados
numeros = set([1,2,1,3,3,4,5,2,6]) #valido somente 1,2,3,4,5,6

carros = set(('palio','gol','celta','palio'))#valido somente palio,gol,celta

print(numeros)
print(carros)

#Unindo conjuntos com union
conjunto_a = {1,2}
conjunto_b = {3,4}

print(conjunto_a.union(conjunto_b))

#Adicionar itens a um conjunto
adicionar = {11,22,33}
adicionar.add(24)#24 foi adicionado
print(adicionar)

#Remover um número de um conjunto

remover = {101,102,103}
remover.discard(101)#101 foi eliminado
print(remover)


import pygame

# Initialize pygame
pygame.init()

# Set up window
size = (400, 400)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Circle Line")

# Set up colors
WHITE = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
click_sound = pygame.mixer.Sound("clicked_sound.mp3")

# Set up circles
circle_radius = 10
circle_distance = 100
circle_x1 = (size[0] // 2) - (circle_distance // 2) - circle_radius
circle_x2 = (size[0] // 2) + (circle_distance // 2) - circle_radius
circle_y = size[1] // 2
circle_color1 = RED
circle_color2 = RED
circle1_active = False
circle2_active = False

# Set up line
line_thickness = 5
line_color = GREEN
line_rect = pygame.Rect(0, 0, 0, line_thickness)
line_active = False

# Main game loop
done = False
while not done:
    # Handle events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_pos = pygame.mouse.get_pos()
            # Toggle circle 1 on/off
            if not circle1_active and abs(mouse_pos[0] - (circle_x1 + circle_radius)) <= circle_radius and abs(mouse_pos[1] - (circle_y + circle_radius)) <= circle_radius:
                circle1_active = True
                circle_color1 = GREEN
            # Toggle circle 2 on/off and draw line if both circles are active
            elif not circle2_active and abs(mouse_pos[0] - (circle_x2 + circle_radius)) <= circle_radius and abs(mouse_pos[1] - (circle_y + circle_radius)) <= circle_radius:
                circle2_active = True
                circle_color2 = GREEN
                if circle1_active:
                    line_rect = pygame.Rect(circle_x1 + circle_radius, circle_y + (line_thickness // 2), circle_distance, line_thickness)
                    line_active = True
                    click_sound.play()

    # Draw everything
    screen.fill(WHITE)
    pygame.draw.circle(screen, circle_color1, (circle_x1 + circle_radius, circle_y + circle_radius), circle_radius)
    pygame.draw.circle(screen, circle_color2, (circle_x2 + circle_radius, circle_y + circle_radius), circle_radius)
    if line_active:
        pygame.draw.rect(screen, line_color, line_rect)
    pygame.display.update()

# Quit pygame properly
pygame.quit()


# -*- coding: utf-8 -*-
"""
Created on Tue May 24 18:36:51 2022

@author: User
"""
# -*- coding: utf-8 -*-
"""
Created on Thu May 19 20:12:51 2022

@author: User
"""
import urllib.request

# pretty-print python data structures
from pprint import pprint
from nsetools import Nse
from nsepy import get_history
from html_table_parser.parser import HTMLTableParser

# for converting the parsed data in a
# pandas dataframe
import pandas as pd

# Opens a website and read its
# binary contents (HTTP Response Body)
def url_get_contents(url):

    # Opens a website and read its
    # binary contents (HTTP Response Body)

    #making request to the website
    req = urllib.request.Request(url=url)
    f = urllib.request.urlopen(req)

    #reading contents of the website
    return f.read()

# defining the html contents of a URL.
nse = Nse()
d = {}
#q = nse.get_quote('infy')
all_stock_codes = nse.get_stock_codes()

def comma(val):
    if ',' in val:
        return val.replace(',','')
    else:
        return val

for stock in list(all_stock_codes.keys())[1]:
    print(stock)
    xhtml = url_get_contents('https://www.screener.in/company/'+ 'SUNCLAYLTD' +'/consolidated/').decode('utf-8')

# Defining the HTMLTableParser object
    p = HTMLTableParser()

    # feeding the html contents in the
    # HTMLTableParser object
    p.feed(xhtml)
    l= []
    for idx1 in range(0,len(p.tables)):
        for idx2 in range(0,len(p.tables[idx1])):
            print(p.tables[idx1][idx2])
            if idx1 == 0:
                if p.tables[idx1][idx2][0] == 'Sales +':
                    p_qtr = float(comma(p.tables[idx1][idx2][-2]))
                    c_qtr = float(comma(p.tables[idx1][idx2][-1]))
                    qtr_sal = (c_qtr - p_qtr)/p_qtr *100
                    l.append(p_qtr)
                    l.append(c_qtr)
                    l.append(qtr_sal)

                if p.tables[idx1][idx2][0] == 'Operating Profit':
                    p_opr_prf = float(comma(p.tables[idx1][idx2][-2]))
                    c_opr_prf= float(comma(p.tables[idx1][idx2][-1]))
                    qtr_opr_prf = (c_opr_prf - p_opr_prf)/p_opr_prf *100
                    l.append(p_opr_prf)
                    l.append(c_opr_prf)
                    l.append(qtr_opr_prf)

                if p.tables[idx1][idx2][0] == 'Net Profit':
                    p_net_prf = float(comma(p.tables[idx1][idx2][-2]))
                    c_net_prf= float(comma(p.tables[idx1][idx2][-1]))
                    qtr_net_prf = (c_net_prf - p_net_prf)/p_net_prf *100
                    l.append(p_net_prf)
                    l.append(c_net_prf)
                    l.append(qtr_net_prf)

            if idx1 == 1:

                 if p.tables[idx1][0][-1] != 'TTM':
                     if p.tables[idx1][idx2][0] == 'Sales +':
                         p_anl = float(comma(p.tables[idx1][idx2][-2]))
                         c_anl = float(comma(p.tables[idx1][idx2][-1]))
                         anl_sal = (c_anl - p_anl)/p_anl *100
                         l.append(p_anl)
                         l.append(c_anl)
                         l.append(anl_sal)
                     if p.tables[idx1][idx2][0] == 'Operating Profit':
                         p_opr_prf_a = float(comma(p.tables[idx1][idx2][-2]))
                         c_opr_prf_a= float(comma(p.tables[idx1][idx2][-1]))
                         opr_prf_a = (c_opr_prf_a - p_opr_prf_a)/p_opr_prf_a * 100
                         l.append(p_opr_prf_a)
                         l.append(c_opr_prf_a)
                         l.append(opr_prf_a)
                     if p.tables[idx1][idx2][0] == 'Net Profit':
                         p_net_prf_a = float(comma(p.tables[idx1][idx2][-2]))
                         c_net_prf_a= float(comma(p.tables[idx1][idx2][-1]))
                         net_prf_a = (c_net_prf_a - p_net_prf_a)/p_net_prf_a * 100
                         l.append(p_net_prf_a)
                         l.append(c_net_prf_a)
                         l.append(net_prf_a)

                 else:
                     if p.tables[idx1][idx2][0] == 'Sales +':
                         p_anl = float(comma(p.tables[idx1][idx2][-2]))
                         c_anl = sum([float(comma(x)) for x in p.tables[idx1-1][idx2][-3:]]) + float(comma(p.tables[idx1][idx2][-1]))
                         anl_sal = (c_anl - p_anl)/p_anl *100
                         l.append(p_anl)
                         l.append(c_anl)
                         l.append(anl_sal)

                     if p.tables[idx1][idx2][0] == 'Operating Profit':
                         p_opr_prf_a = float(comma(p.tables[idx1][idx2][-2]))
                         c_opr_prf_a= sum([float(comma(x)) for x in p.tables[idx1-1][idx2][-3:]] )+ float(comma(p.tables[idx1][idx2][-1]))
                         opr_prf_a = (c_opr_prf_a - p_opr_prf_a)/p_opr_prf_a *100
                         l.append(p_opr_prf_a)
                         l.append(c_opr_prf_a)
                         l.append(opr_prf_a)

                     if p.tables[idx1][idx2][0] == 'Net Profit':
                         p_net_prf_a = float(comma(p.tables[idx1][idx2][-2]))
                         c_net_prf_a = sum([float(comma(x)) for x in p.tables[idx1-1][idx2][-3:]]) + float(comma(p.tables[idx1][idx2][-1]))
                         net_prf_a = (c_net_prf_a - p_net_prf_a)/p_net_prf_a *100
                         l.append(p_net_prf_a)
                         l.append(c_net_prf_a)
                         l.append(net_prf_a)

            if p.tables[idx1][idx2][0] == 'Public +':
                public_holders = p.tables[idx1][idx2][-1]
                l.append(public_holders)

    d[stock] = l

df_screener = pd.DataFrame.from_dict(d, orient = 'index')
df_screener.columns = ['prev_qtr_sales','curr_qtr_sales','perc_imp_sales','prev_qtr_oprPro','curr_qtr_oprPro','perc_imp_oprPro','prev_qtr_NetPro','curr_qtr_NetPro','perc_imp_NetPro','prev_anl_sales','curr_anl_sales','perc_imp_sales_anl','prev_anl_oprPro','curr_anl_oprPro','perc_imp_oprPro_anl','prev_anl_NetPro','curr_anl_NetPro','perc_imp_NetPro_anl','public_holding']
df_screener.to_excel("E:\Trade\Analysis\\screener_data.xlsx")


def solution(start, length):
    checksum = 0
    l = length
    while l:
        checksum^=xor_sum(start)^xor_sum(start+l)
        start+=length
        l-=1
    return checksum

def xor_sum(n):
    if n == 0:
        return 0
    elif (n-1) % 4 == 0:
        return n-1
    elif (n-1) % 4 == 1:
        return 1
    elif (n-1) % 4 == 2:
        return n
    else:
        return 0


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

from .core import *
from .. import _logging as logging
import tensorflow as tf

__all__ = [
    'StackLayer',
    'UnStackLayer',
]

class StackLayer(Layer):
    """
    The :class:`StackLayer` class is layer for stacking a list of rank-R tensors into one rank-(R+1) tensor, see `tf.stack() <https://www.tensorflow.org/api_docs/python/tf/stack>`__.

    Parameters
    ----------
    layers : list of :class:`Layer`
        Previous layers to stack.
    axis : int
        Dimension along which to concatenate.
    name : str
        A unique layer name.

    Examples
    ---------
    >>> x = tf.placeholder(tf.float32, shape=[None, 30])
    >>> net = tl.layers.InputLayer(x, name='input')
    >>> net1 = tl.layers.DenseLayer(net, 10, name='dense1')
    >>> net2 = tl.layers.DenseLayer(net, 10, name='dense2')
    >>> net3 = tl.layers.DenseLayer(net, 10, name='dense3')
    >>> net = tl.layers.StackLayer([net1, net2, net3], axis=1, name='stack')
    ... (?, 3, 10)

    """

    def __init__(
            self,
            layers,
            axis=1,
            name='stack',
    ):
        Layer.__init__(self, prev_layer=layers, name=name)
        self.inputs = []
        for l in layers:
            self.inputs.append(l.outputs)

        self.outputs = tf.stack(self.inputs, axis=axis, name=name)

        logging.info("StackLayer %s: axis: %d" % (self.name, axis))

        # self.all_layers = list(layers[0].all_layers)
        # self.all_params = list(layers[0].all_params)
        # self.all_drop = dict(layers[0].all_drop)
        #
        # for i in range(1, len(layers)):
        #     self.all_layers.extend(list(layers[i].all_layers))
        #     self.all_params.extend(list(layers[i].all_params))
        #     self.all_drop.update(dict(layers[i].all_drop))
        #
        # self.all_layers = list_remove_repeat(self.all_layers)
        # self.all_params = list_remove_repeat(self.all_params)

        self.all_layers.append(self.outputs)

def unstack_layer(layer, num=None, axis=0, name='unstack'):
    """
    It is layer for unstacking the given dimension of a rank-R tensor into rank-(R-1) tensors., see `tf.unstack() <https://www.tensorflow.org/api_docs/python/tf/unstack>`__.

    Parameters
    ----------
    layer : :class:`Layer`
        Previous layer
    num : int or None
        The length of the dimension axis. Automatically inferred if None (the default).
    axis : int
        Dimension along which axis to concatenate.
    name : str
        A unique layer name.

    Returns
    -------
    list of :class:`Layer`
        The list of layer objects unstacked from the input.

    """
    inputs = layer.outputs
    with tf.variable_scope(name):
        outputs = tf.unstack(inputs, num=num, axis=axis)

    logging.info("UnStackLayer %s: num: %s axis: %d, n_outputs: %d" % (name, num, axis, len(outputs)))

    net_new = []
    scope_name = tf.get_variable_scope().name
    if scope_name:
        full_name = scope_name + '/' + name
    else:
        full_name = name

    for i, _v in enumerate(outputs):
        n = Layer(prev_layer=layer, name=full_name + str(i))
        n.outputs = outputs[i]
        # n.all_layers = list(layer.all_layers)
        # n.all_params = list(layer.all_params)
        # n.all_drop = dict(layer.all_drop)
        # n.all_layers.append(inputs)

        net_new.append(n)

    return net_new

# Alias
UnStackLayer = unstack_layer


import os
from twisted.internet import reactor, defer

def read_mail(mailitems):
    print(mailitems)
    return "Junk Mail... Sending to shredder: " + mailitems

def shred_mail(mailitems):
    print('buzzzzz: ' + mailitems)
    os.remove('mail')
    reactor.stop()

def create_mail(msg):
    with open("mail","w") as f:
        f.write(msg)

def wait_for_mail(d=None):
    if not d:
        d = defer.Deferred()
    if not os.path.isfile('mail'):
        reactor.callLater(1, wait_for_mail, d)
    else:
        with open("mail") as f:
            contents = f.readlines()
        d.callback(contents[0])
    return d

deferred = wait_for_mail()
deferred.addCallback(read_mail)
deferred.addCallback(shred_mail)
reactor.callLater(2, create_mail, "Look at this new letter!")
reactor.callLater(20, reactor.stop)
reactor.run()


import re
from collections import defaultdict

def parse_rule_container(rule):
    regex = re.compile(r'(.*) bags contain(.*)')
    matches = regex.match(rule)
    return matches.group(1), matches.group(2)

def parse_contained_rule(rule):
    regex = re.compile(r'((\d+) ([a-z ]+) bag)+')
    all_matches = regex.findall(rule)
    return [(lambda x: (x[1], x[2]))(match) for match in all_matches]

def contains_bag(contained_bags_arr, expected_color):
    for (count, color) in contained_bags_arr:
        if color == expected_color:
            return True
    return False

def main():
    f = open("input.txt", "r")
    inp = f.read().split('\n')
    inp = list(filter(lambda inp_line: len(inp_line) != 0, inp))
    rules = [parse_rule_container(inp_line) for inp_line in inp]

    fwd_map = defaultdict(lambda: [])
    rev_map = defaultdict(lambda: [])

    for rule in rules:
        container, contained_rule = rule
        contained_bags_arr = parse_contained_rule(contained_rule)

        fwd_map[container] = contained_bags_arr
        for contained_bags in contained_bags_arr:
            contained_bags_count, contained_bags_color= contained_bags
            rev_map[contained_bags_color].append(container)

    ans = set()
    possible_container = set(rev_map['shiny gold'])
    while len(possible_container) != 0:
        for possible_bag in possible_container.copy():
            possible_container.remove(possible_bag)
            if possible_bag in ans:
                continue
            ans.add(possible_bag)
            for bag in rev_map[possible_bag]:
                possible_container.add(bag)

    print(ans)
    print(len(ans))

if __name__ == '__main__':
    main()


import numpy as np
import torch
import torch.nn as nn
from lib.datasets.utils import class2angle
from utils import box_ops
import math

padsize = np.array([28.,11.],dtype=np.float32)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
def affine_transform(pt, t):

    new_pt = np.array([pt[0], pt[1], 1.], dtype=np.float32).T
    #new_pt = torch.cat((pt, torch.ones(1).to(device=device)), dim=0)
    #new_pt = new_pt.unsqueeze(-1)
        # expand project points as [N, 3, 1]
    #new_pt=torch.matmul(t, new_pt)
    new_pt = np.dot(t, new_pt)
    return new_pt[:2]

def softget(weighted_depth,outputs_coord):
        h,w = weighted_depth.shape[-2], weighted_depth.shape[-1] # 32 58
        pts_x =outputs_coord [0]
        pts_y = outputs_coord[ 1]

        pts_x_low = math.floor(pts_x )
        pts_x_high =math.ceil(pts_x )
        pts_y_low = math.floor(pts_y )
        pts_y_high =math.ceil(pts_y)
        pts_x_low = np.clip(pts_x_low, a_min=0,a_max = w-1)
        pts_x_high = np.clip(pts_x_high, a_min=0,a_max = w-1)
        pts_y_low = np.clip(pts_y_low, a_min=0,a_max = h-1)
        pts_y_high =np.clip(pts_y_high, a_min=0,a_max = h-1)

        rop_lt = weighted_depth[..., pts_y_low, pts_x_low]
        rop_rt = weighted_depth[..., pts_y_low, pts_x_high]
        rop_ld = weighted_depth[..., pts_y_high, pts_x_low]
        rop_rd = weighted_depth[..., pts_y_high, pts_x_high]

        rop_t = (1 - pts_x + pts_x_low) * rop_lt + (1 - pts_x_high + pts_x) * rop_rt
        rop_d = (1 - pts_x + pts_x_low) * rop_ld + (1 - pts_x_high + pts_x) * rop_rd
        rop = (1 - pts_y + pts_y_low) * rop_t + (1 - pts_y_high + pts_y) * rop_d
        return rop

def decode_detections(dets, info, calibs, cls_mean_size, threshold,trans_inv,depthmaps,pre_denorm,weighted_depth):
    '''
    NOTE: THIS IS A NUMPY FUNCTION
    input: dets, numpy array, shape in [batch x max_dets x dim]
    input: img_info, dict, necessary information of input images
    input: calibs, corresponding calibs for the input batch
    output:
    '''
    results = {}
    for i in range(dets.shape[0]):  # batch
        preds = []
        for j in range(dets.shape[1]):  # max_dets
            cls_id = int(dets[i, j, 0])
            score = dets[i, j, 1]
            if score < threshold:
                continue

            # 2d bboxs decoding
            x = dets[i, j, 2] * 928
            y = dets[i, j, 3] *  512
            w = dets[i, j, 4] * 928
            h = dets[i, j, 5] * 512
            #x = dets[i, j, 2] * info['img_size'][i][0]
            #y = dets[i, j, 3] * info['img_size'][i][1]
            #w = dets[i, j, 4] * info['img_size'][i][0]
            #h = dets[i, j, 5] * info['img_size'][i][1]
            bbox = np.array([x-w/2, y-h/2, x+w/2, y+h/2])
            bbox[:2] = bbox[:2]-padsize
            bbox[2:] =bbox[2:] -padsize

            bbox[:2] = bbox[:2]*2.2#affine_transform(bbox[:2], trans_inv[i])
            bbox[2:] = bbox[2:]*2.2#affine_transform(bbox[2:], trans_inv[i])

            # 3d bboxs decoding
            # depth decoding
            depth_p = dets[i, j, 6]

            # dimensions decoding
            dimensions = dets[i, j, 31:34]
            dimensions += cls_mean_size[int(cls_id)]

            # positions decoding
            #x3d = dets[i, j, 34]
            #y3d = dets[i, j, 35]
            size = np.array([928,512])
            #size = torch.tensor(size).to(device)
            pad = np.array([28,11])
            #pad =torch.tensor(pad).to( device)
            pad2 = np.array([2,1])
            #pad2 =torch.tensor(pad2).to(device)
            #coord =(dets[i, j, 34:36]*size-pad)/16+[2,1]
            coord =(dets[i, j, 34:36]*size-pad)/16 # 本来图像的除以35.2 x,y
            pts = np.array(coord)
            w = 56
            h = 31
            pts_x = pts[0]
            pts_x  = np.clip(pts_x, a_min=0,a_max =w-1)
            pts_y = pts[1]
            pts_y  = np.clip(pts_y , a_min=0,a_max = h-1)

            denorm = pre_denorm[i] # 32,58,4
            P =  calibs[i].P2
            #coord = np.array([i+2,j+1])
            '''
            d  = denorm[int(pts_y)+1,int(pts_x)+2] #[16.69273   5.326345]
            W =torch.tensor([[P[0,0]/35.2,0,P[0,2]/35.2-coord[0]],[0,P[1,1]/35.2,P[1,2]/35.2-coord[1]],[d[0],d[1],d[2]]])
            result = torch.tensor([0,0,-d[3]]).reshape(-1,1)
            W_inv = torch.inverse(W)
            vvxyz = torch.mm(W_inv,result)
            depth=vvxyz[2,0]
            '''
            '''
            #print(coord.shape)
            #weighteddepth = depthmaps[i]
            coord = np.array([pts_x+2,pts_y+1])
            weighteddepth = weighted_depth[i]
            #weighteddepth = weighteddepth.transpose(1,0) #
            weighteddepth = weighted_depth.cpu().numpy() # 32,58
            depth = softget(weighteddepth,coord)
            '''

            x3d = dets[i, j, 34] * 928
            y3d = dets[i, j, 35] * 512

            x3d = x3d - padsize[0] # -28
            y3d = y3d - padsize[1] #-11
            xy = np.array([x3d, y3d])

            xy= xy *2.2 #affine_transform(xy , trans_inv[i])
            #xy= affine_transform(xy , trans_inv[i])
            x3d = xy[0]
            y3d =  xy[1]
            #x3d = dets[i, j, 34] * info['img_size'][i][0]
            #y3d = dets[i, j, 35] * info['img_size'][i][1]
            #locations = calibs[i].img_to_rect(x3d, y3d, depth).reshape(-1)
            locations = calibs[i].img_to_rect(x3d, y3d, depth_p).reshape(-1)
            #locations[1] += dimensions[0] / 2

            # heading angle decoding
            alpha = get_heading_angle(dets[i, j, 7:31])
            ry = calibs[i].alpha2ry(alpha, x)

            score = score * dets[i, j, -1]
            preds.append([cls_id, alpha] + bbox.tolist() + dimensions.tolist() + locations.tolist() + [ry, score])
        results[info['img_id'][i]] = preds
    return results

def extract_dets_from_outputs(outputs, K=50, topk=50):
    # get src outputs

    # b, q, c
    out_logits = outputs['pred_logits']
    out_bbox = outputs['pred_boxes']

    prob = out_logits.sigmoid()
    topk_values, topk_indexes = torch.topk(prob.view(out_logits.shape[0], -1), topk, dim=1)

    # final scores
    scores = topk_values
    # final indexes
    topk_boxes = (topk_indexes // out_logits.shape[2]).unsqueeze(-1)
    # final labels
    labels = topk_indexes % out_logits.shape[2]

    heading = outputs['pred_angle']
    size_3d = outputs['pred_3d_dim']
    depth = outputs['pred_depth'][:, :, 0: 1]
    sigma = outputs['pred_depth'][:, :, 1: 2]
    sigma = torch.exp(-sigma)

    # decode
    boxes = torch.gather(out_bbox, 1, topk_boxes.repeat(1, 1, 6))  # b, q', 4

    xs3d = boxes[:, :, 0: 1]
    ys3d = boxes[:, :, 1: 2]

    heading = torch.gather(heading, 1, topk_boxes.repeat(1, 1, 24))
    depth = torch.gather(depth, 1, topk_boxes)
    sigma = torch.gather(sigma, 1, topk_boxes)
    size_3d = torch.gather(size_3d, 1, topk_boxes.repeat(1, 1, 3))

    corner_2d = box_ops.box_cxcylrtb_to_xyxy(boxes)

    xywh_2d = box_ops.box_xyxy_to_cxcywh(corner_2d)
    size_2d = xywh_2d[:, :, 2: 4]

    xs2d = xywh_2d[:, :, 0: 1]
    ys2d = xywh_2d[:, :, 1: 2]

    batch = out_logits.shape[0]
    labels = labels.view(batch, -1, 1)
    scores = scores.view(batch, -1, 1)
    xs2d = xs2d.view(batch, -1, 1)
    ys2d = ys2d.view(batch, -1, 1)
    xs3d = xs3d.view(batch, -1, 1)
    ys3d = ys3d.view(batch, -1, 1)

    detections = torch.cat([labels.float(), scores, xs2d, ys2d, size_2d, depth, heading, size_3d, xs3d, ys3d, sigma], dim=2)
    #detections = torch.cat([labels.float(), scores, xs2d, ys2d, size_2d,  heading, size_3d, xs3d, ys3d ], dim=2)

    return detections

############### auxiliary function ############

def _nms(heatmap, kernel=3):
    padding = (kernel - 1) // 2
    heatmapmax = nn.functional.max_pool2d(heatmap, (kernel, kernel), stride=1, padding=padding)
    keep = (heatmapmax == heatmap).float()
    return heatmap * keep

def _topk(heatmap, K=50):
    batch, cat, height, width = heatmap.size()

    # batch * cls_ids * 50
    topk_scores, topk_inds = torch.topk(heatmap.view(batch, cat, -1), K)

    topk_inds = topk_inds % (height * width)
    topk_ys = (topk_inds / width).int().float()
    topk_xs = (topk_inds % width).int().float()

    # batch * cls_ids * 50
    topk_score, topk_ind = torch.topk(topk_scores.view(batch, -1), K)
    topk_cls_ids = (topk_ind / K).int()
    topk_inds = _gather_feat(topk_inds.view(batch, -1, 1), topk_ind).view(batch, K)
    topk_ys = _gather_feat(topk_ys.view(batch, -1, 1), topk_ind).view(batch, K)
    topk_xs = _gather_feat(topk_xs.view(batch, -1, 1), topk_ind).view(batch, K)

    return topk_score, topk_inds, topk_cls_ids, topk_xs, topk_ys

def _gather_feat(feat, ind, mask=None):
    '''
    Args:
        feat: tensor shaped in B * (H*W) * C
        ind:  tensor shaped in B * K (default: 50)
        mask: tensor shaped in B * K (default: 50)

    Returns: tensor shaped in B * K or B * sum(mask)
    '''
    dim  = feat.size(2)  # get channel dim
    ind  = ind.unsqueeze(2).expand(ind.size(0), ind.size(1), dim)  # B*len(ind) --> B*len(ind)*1 --> B*len(ind)*C
    feat = feat.gather(1, ind)  # B*(HW)*C ---> B*K*C
    if mask is not None:
        mask = mask.unsqueeze(2).expand_as(feat)  # B*50 ---> B*K*1 --> B*K*C
        feat = feat[mask]
        feat = feat.view(-1, dim)
    return feat

def _transpose_and_gather_feat(feat, ind):
    '''
    Args:
        feat: feature maps shaped in B * C * H * W
        ind: indices tensor shaped in B * K
    Returns:
    '''
    feat = feat.permute(0, 2, 3, 1).contiguous()   # B * C * H * W ---> B * H * W * C
    feat = feat.view(feat.size(0), -1, feat.size(3))   # B * H * W * C ---> B * (H*W) * C
    feat = _gather_feat(feat, ind)     # B * len(ind) * C
    return feat

def get_heading_angle(heading):
    heading_bin, heading_res = heading[0:12], heading[12:24]
    cls = np.argmax(heading_bin)
    res = heading_res[cls]
    return class2angle(cls, res, to_label_format=True)


import numpy
import os

numpy.seterr('ignore')
luz = int(300000000)

while True:

	inicio = input("¿que deseas?(entrar, salir o limpiar): \n>")
	print ("")

	if inicio == "entrar" or inicio == "enter":

		opcion = input("elige la magnitud(energia, fuerza o recorrido): \n>")

		if opcion == "energia" or opcion == "energy" or opcion == "energi":

				try:
					print(" ")
					masa_en_reposo = float(input("ingresa la masa (kg): \n>"))

					print(" ")
					aceleracion = float(input("ingresa la aceleracion (m/s): \n>"))

					if aceleracion > (luz):
							print ("las ecuaciones de einstein impiden velocidades superluminicas por lo que intentarlo conlleva numeros “rotos” aun así, si te interesa ver el resultado, elimina esta condicion del codigo y veras un “nan”.")
							print("")

					else:

						relatividad = (masa_en_reposo/(numpy.sqrt(1-(aceleracion**2)/luz**2)))

						energia = (0.5*(relatividad * (aceleracion**2)))

						print ("la energia usada son:", energia,"J\n")

				except:

						print("")
						print(" ")

		elif opcion == "fuerza" or opcion == "momento lineal" or opcion == "momentum" or opcion == "impetú":

				try:

					print("")
					masa_en_reposo = float(input("ingresa la masa (kg): \n>"))

					print(" ")
					aceleracion = float(input("ingresa la aceleracion (m/s): \n>"))

					print(" ")

					if (aceleracion) > (luz):
						print ("las ecuaciones de einstein impiden velocidades superluminicas por lo que intentarlo conlleva numeros “rotos” aun así, si te interesa ver el resultado, elimina esta condicion del codigo y veras un “nan”.")
						print("")

					else:

						relatividad = (masa_en_reposo/(numpy.sqrt(1-(aceleracion**2)/luz**2)))

						fuerza = (relatividad * aceleracion)

						peso = (fuerza/9.81)

						print ("la fuerza (newtons) es:",fuerza,"N")

						print (" ")

						print("la fuerza (kilogramos) es:", peso, "kg/f\n")

						print(" ")

				except:

					print("")
					print(" ")
		elif opcion == "recorrido":
			try:

				print(" ")
				espacio = float(input("ingresa la distancia a recorrer(m):\n>"))
				print(" ")

				velocidad = float(input("ingresa la velocidad (m/s): \n>"))
				print("")

				if velocidad > (luz):
					print ("las ecuaciones de einstein impiden velocidades superluminicas por lo que intentarlo conlleva numeros “rotos” aun así, si te interesa ver el resultado, elimina esta condicion del codigo y veras un “nan”.")

					print("")

				else:
					relatividad = (espacio *(numpy.sqrt(1-(velocidad**2)/(luz**2))))

					dilatacion = (1*(numpy.sqrt(1-(velocidad**2)/(luz**2))))

					tiempo = (relatividad/velocidad)

					total= (tiempo/dilatacion)

					print ("recorrer la distancia de", espacio,"metros", "toma", tiempo, "segundos")
					print(" ")

			except:
				print("")

		else:

				print("")

	elif inicio == "salir" or inicio == "exit":
		break
	elif inicio == "limpiar" or inicio == "clean":
		if os.name == "posix":

			os.system ("clear")

		elif os.name == "ce" or os.name == "nt" or os.name == "dos":

			os.system ("cls")

	else:
		print("ingresa opcion valida")
		print(" ")


import json
import serial
import numpy as np

class CameraMLX90640(serial.Serial):
    """
    Implements communications camera_mlx90640_firmware
    """

    FRAME_HEIGHT = 24
    FRAME_WIDTH = 32

    def __init__(self, port):
        self.port_param = {'port': port, 'baudrate': 115200, 'timeout': 2.0}
        super().__init__(**self.port_param)
        self.num_throw_away = 10
        self.throw_away_lines()

    def throw_away_lines(self):
        """
        Throw away first few lines. Deals with case where user has updated the
        firmware which writes a bunch text to the serial port.
        """
        self.timeout = 0.1
        for i in range(self.num_throw_away):
            line = self.readline()
        self.timeout = self.port_param['timeout']

    def send_and_receive(self, msg_dict):
        """
        Send and receive message from the device.
        """
        msg_json = f'{json.dumps(msg_dict)}\n'
        self.write(msg_json.encode())
        rsp_json = self.read_until()
        rsp_json = rsp_json.strip()
        rsp_dict = {}
        try:
            rsp_dict = json.loads(rsp_json.decode('utf-8'))
        except json.decoder.JSONDecodeError as e:
            print(f'Error decoding json message: {e}')
        return rsp_dict

    def grab_frame(self):
        """
        Grab from from camera and convert it to a numpy array
        """
        cmd = {'cmd': 'frame'}
        rsp = self.send_and_receive(cmd)
        try:
            frame = np.array(rsp['frame'])
        except KeyError:
            frame = np.zeros((self.FRAME_HEIGHT,self.FRAME_WIDTH))
            ok = False
        else:
            frame = np.array(frame)
            frame = np.reshape(frame, (self.FRAME_HEIGHT,self.FRAME_WIDTH))
            frame = np.flipud(frame)
            frame = np.fliplr(frame)
            ok = True
        return ok, frame


from .base import Shape

class Circle(Shape):

    def __init__(self, radius, **kwargs):
        super().__init__(**kwargs)
        self.radius = radius

    def draw(self, turtle):
        turtle.penup()
        turtle.goto(self.center_x, self.center_y - self.radius)  # From docs: The center is radius units left of the turtle;
        turtle.pendown()
        turtle.color(self.color)
        turtle.circle(self.radius)

06 Python OOP/01 Shape Extension/Shapes/circle.py