from django.urls import include, path
from rest_framework import routers
from .views import PlanoComissoesViewSet, VendaViewSet, VendedorViewSet

router = routers.DefaultRouter()
router.register(r'planos-de-comissoes', PlanoComissoesViewSet)
router.register(r'vendedores', VendedorViewSet)
router.register(r'vendas', VendaViewSet)

urlpatterns = [
    path("", include(router.urls))
]


from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import cx_Oracle

#db = Database("Employee.db")
root = Tk()
root.title("Enterprise Application.")
root.geometry("1920x1080+0+0")
root.config(bg="#535c68")
root.state("zoomed")

#textbox for salesman table

cid = StringVar()
cname = StringVar()
ccity = StringVar()
cgrade = StringVar()

# Entries Frame Table 1 Salesman
eframe = Frame(root, bg="#535c68")
eframe.pack(side=TOP, fill=X)
title = Label(eframe, text="Enterprise Application.", font=("Calibri", 18, "bold"), bg="#535c68", fg="white")
title.grid(row=0, columnspan=2, padx=10, pady=20, sticky="w")

#widgets
lblstablename = Label(eframe, text="Customer Table", font=("Calibri", 16), bg="#535c68", fg="white")
lblstablename.grid(row=0, column=2, padx=10, pady=10, sticky="w")

lblcid= Label(eframe, text="Customer Id", font=("Calibri", 16), bg="#535c68", fg="white")
lblcid.grid(row=1 , column=0, padx=10, pady=10, sticky="w")
txtcid= Entry(eframe, textvariable=cid, font=("Calibri", 16), width=30)
txtcid.grid(row=1, column=1, padx=10, pady=10, sticky="w")

lblcname = Label(eframe, text="Customer Name", font=("Calibri", 16), bg="#535c68", fg="white")
lblcname.grid(row=1, column=2, padx=10, pady=10, sticky="w")
txtcname = Entry(eframe, textvariable=cname, font=("Calibri", 16), width=30)
txtcname.grid(row=1, column=3, padx=10, pady=10, sticky="w")

lblccity = Label(eframe, text="Customer City", font=("Calibri", 16), bg="#535c68", fg="white")
lblccity.grid(row=2, column=2, padx=10, pady=10, sticky="w")
txtccity = Entry(eframe, textvariable=ccity, font=("Calibri", 16), width=30)
txtccity.grid(row=2, column=3, padx=10, pady=10, sticky="w")

lblcgrade = Label(eframe, text="Grade", font=("Calibri", 16), bg="#535c68", fg="white")
lblcgrade.grid(row=2, column=0, padx=10, pady=10, sticky="w")
txtcgrade = Entry(eframe, textvariable=cgrade, font=("Calibri", 16), width=30)
txtcgrade.grid(row=2, column=1, padx=10, pady=10, sticky="w")

def insert():
    con = cx_Oracle.connect('system/balaji@localhost:1521/xe')
    csid=int(txtcid.get())
    csname=txtcname.get()
    cscity=txtccity.get()
    csgrade=int(txtcgrade.get())
    icsid=int(csid)
    icsgrade=int(csgrade)
    datai=[[icsid,csname,cscity,csgrade]]
    try:
        if con:
            print(con.version)
            cur = con.cursor()
            cur.executemany('insert into customers25 values(:1,:2,:3,:4)',datai)
    except cx_Oracle.DatabaseError as er:
        print('There is an error in Oracle database:', er)
    except Exception as er:
            print(er)
    else:
        # To commit the transaction manually
        con.commit()
        messagebox.showinfo("Inserted Dialogbox", "INSERTED SUCCESSFULLY!")
    finally:
        if cur:
            cur.close()
        if con:
            con.close()
    tab()
def update():
    con = cx_Oracle.connect('system/balaji@localhost:1521/xe')
    csid=int(txtcid.get())
    csname=txtcname.get()
    cscity=txtccity.get()
    csgrade=int(txtcgrade.get())
    icsid=int(csid)
    icsgrade=int(csgrade)
    datau=[[csname,cscity,icsgrade,icsid]]
    try:
        if con:
            print(con.version)
            cur = con.cursor()
            cur.executemany('update customers25 set customer_name=:1,city=:2,grade=:3 where customer_id=:4',datau)
    except cx_Oracle.DatabaseError as er:
        print('There is an error in Oracle database:', er)
    except Exception as er:
            print(er)
    else:
        # To commit the transaction manually
        con.commit()
        messagebox.showinfo("Updated Dialogbox", "UPDATED SUCCESSFULLY!")
    finally:
        if cur:
            cur.close()
        if con:
            con.close()
    tab()

def delete():
    con = cx_Oracle.connect('system/balaji@localhost:1521/xe')
    csid=int(txtcid.get())
    icsid=int(csid)
    datau=[[icsid]]
    try:
        if con:
            print(con.version)
            cur = con.cursor()
            cur.executemany('delete from customers25 where customer_id=:1',datau)
    except cx_Oracle.DatabaseError as er:
        print('There is an error in Oracle database:', er)
    except Exception as er:
            print(er)
    else:
        # To commit the transaction manually
        con.commit()
        messagebox.showinfo("Deleted Dialogbox", "DELETED SUCCESSFULLY!")
    finally:
        if cur:
            cur.close()
        if con:
            con.close()
    tab()

#insert rows in tables
def tab():
    con = cx_Oracle.connect('system/balaji@localhost:1521/xe')
    try:
        if con:
            print(con.version)
            cur = con.cursor()
            sql="select * from customers25"
            cur.execute(sql)
            rows=cur.fetchall()
            tv.delete(*tv.get_children())
            for ro in rows:
                tv.insert("",END,values=ro)
    except cx_Oracle.DatabaseError as er:
        print('IN TAB There is an error in Oracle database:', er)
    except Exception as er:
            print(er)
    else:
        # To commit the transaction manually
        con.commit()
        print("Table Created in GUI")
    finally:
        if cur:
            cur.close()
        if con:
            con.close()

def change():
    import order3
    print('changed')

#button for crud
btnframe1 = Frame(eframe, bg="#535c68")
btnframe1.grid(row=1, column=4, padx=10, pady=10, sticky="w")
insbtn = Button(btnframe1, command=insert, text="Insert", width=8, font=("Calibri", 16, "bold"), fg="white",
                bg="#535c68", bd=2).grid(row=1, column=5, padx=100, pady=10, sticky="w")

btnframe2 = Frame(eframe, bg="#535c68")
btnframe2.grid(row=2, column=4, padx=10, pady=10, sticky="w")
insbtn = Button(btnframe1, command=update, text="Update", width=8, font=("Calibri", 16, "bold"), fg="white",
                bg="#535c68", bd=2).grid(row=2, column=5, padx=100, pady=10, sticky="w")

btnframe3 = Frame(eframe, bg="#535c68")
btnframe3.grid(row=3, column=4, padx=10, pady=10, sticky="w")
insbtn = Button(btnframe1, command=delete, text="Delete", width=8, font=("Calibri", 16, "bold"), fg="white",
                bg="#535c68", bd=2).grid(row=3, column=5, padx=100, pady=10, sticky="w")

btnframe4 = Frame(eframe, bg="#535c68")
btnframe4.grid(row=4, column=4, padx=10, pady=10, sticky="w")
insbtn1 = Button(btnframe4, command=change, text="ORDER", width=8, font=("Calibri", 16, "bold"), fg="white",
                bg="#535c68", bd=2).grid(row=4, column=5, padx=100, pady=10, sticky="w")

#Display tables
tframe=Frame(root)
tframe.place(x=100,y=400,width=1000,height=250)
#style for table
style=ttk.Style()
style.configure("mystyle.Treeview",font=('Calibri',14),rowheight=40)
#table show
tv=ttk.Treeview(tframe,columns=(1,2,3,4),style="mystyle.Treeview")
tv.heading("1",text="CUSTOMER ID")
tv.heading("2",text="CUSTOMER NAME")
tv.heading("3",text="CUSTOMER CITY")
tv.heading("4",text="CUSTOMER GRADE")
tv['show']='headings'
tv.pack(fill=X)

tab()
root.mainloop()


from django.contrib import admin
from api.models import *

# Register your models here.
@admin.register(address)
class AddressAdmin(admin.ModelAdmin):
  list_display = (
    'address_id', 'address_line_1', 'address_line_2', 'city',
    'country', 'created_by', 'created_date', 'is_deleted',
    'modified_by', 'modified_date', 'postal_code', 'state'
  )

@admin.register(storage_type)
class StorageTypeAdmin(admin.ModelAdmin):
  list_display = (
    'created_by', 'created_date', 'is_deleted', 'modified_by',
    'modified_date', 'storage_type_id', 'type_name'
  )

@admin.register(resource_type)
class ResourceTypeAdmin(admin.ModelAdmin):
  list_display = (
    'created_by', 'created_date', 'is_deleted', 'modified_by',
    'modified_date', 'resource_type_id', 'type_name'
  )

@admin.register(contact)
class ContactAdmin(admin.ModelAdmin):
  list_display = (
    'contact_id', 'created_by', 'created_date', 'email_address',
    'first_name', 'middle_name', 'last_name', 'is_deleted',
    'modified_by', 'modified_date', 'phone_number'
  )

@admin.register(abc_client)
class AbcClientAdmin(admin.ModelAdmin):
  list_display = (
    'abc_client_id', 'client_name', 'company_address_id',
    'created_by', 'created_date', 'is_deleted', 'modified_by',
    'modified_date', 'phone_number'
  )

@admin.register(inventory)
class InventoryAdmin(admin.ModelAdmin):
  list_display = (
    'abc_client_id', 'address_id', 'created_by', 'created_date',
    'inventory_id', 'inventory_name', 'is_deleted',
    'max_item_capacity', 'modified_by', 'modified_date',
    'storage_type_id'
  )

@admin.register(abc_resource)
class ResourceAdmin(admin.ModelAdmin):
  list_display = (
    'abc_resource_id', 'created_by', 'created_date',
    'current_number_of_resources', 'inventory_id', 'is_deleted',
    'max_number_of_resources', 'modified_by', 'modified_date',
    'resource_name', 'resource_type_id'
  )

@admin.register(client_contacts)
class ClientContactAdmin(admin.ModelAdmin):
  list_display = (
    'abc_client_id', 'client_contacts_id', 'contact_id',
    'created_by', 'created_date', 'is_deleted', 'modified_by',
    'modified_date'
  )

@admin.register(access_log)
class AccessLogAdmin(admin.ModelAdmin):
  list_display = (
    'access_log_id', 'action', 'field_name', 'screen_name',
    'table_name', 'username'
  )


#!/usr/bin/env python
import sys, os
import numpy as np
import synergia
import pytest

# This test is similar to test_get_tunes2.py but with the Booster-like lattice.

# lattice_fixture is a lattice
@pytest.fixture
def lattice_fixture():
    # booster-like lattice
    booster_madx = """
ncells=24;
turn_voltage=1.0; ! 1 MV /turn
beam, particle=proton,energy=pmass+0.8;

f: sbend, l=2.0, angle=(pi/(2*ncells)), k1=1/16.2;
d: sbend, l=2.0, angle=(pi/(2*ncells)), k1=-1/16.7;
!f: quadrupole, l=2.0, k1=0.0625;
!d: quadrupole, l=2.0, k1=-0.0625;
rfc: rfcavity, l=0.0, volt=turn_voltage/ncells, harmon=96, lag=(1/120.0);

cell: sequence, l=20.0, refer=centre;
fodo_1: f, at=1.5;
fodo_2: d, at=8.5;
fodo_3: d, at=11.5;
fodo_4: f, at=18.5;
fodo_5: rfc, at=20.0;
endsequence;

booster: sequence, l=480.0, refer=entry;
cell, at=0.0;
cell, at=20.0;
cell, at=40.0;
cell, at=60.0;
cell, at=80.0;
cell, at=100.0;
cell, at=120.0;
cell, at=140.0;
cell, at=160.0;
cell, at=180.0;
cell, at=200.0;
cell, at=220.0;
cell, at=240.0;
cell, at=260.0;
cell, at=280.0;
cell, at=300.0;
cell, at=320.0;
cell, at=340.0;
cell, at=360.0;
cell, at=380.0;
cell, at=400.0;
cell, at=420.0;
cell, at=440.0;
cell, at=460.0;
endsequence;

"""

    reader = synergia.lattice.MadX_reader()
    reader.parse(booster_madx)
    lattice = reader.get_lattice('booster')
    lattice.set_all_string_attribute('extractor_type', 'libff')

    return lattice

def test_tunes(lattice_fixture):
    tunes = synergia.simulation.Lattice_simulator.calculate_tune_and_cdt(lattice_fixture)
    print('Tunes: x: ', tunes[0], ', y: ', tunes[1])
    assert tunes[0] == pytest.approx(0.16533417, rel=1.0e-4)
    assert tunes[1] == pytest.approx(0.436092762, rel=1.0e-4)

def test_chromaticities(lattice_fixture):
    beta = lattice_fixture.get_reference_particle().get_beta()
    chrom = synergia.simulation.Lattice_simulator.get_chromaticities(lattice_fixture)
    print('H chromaticitity: ', chrom.horizontal_chromaticity)
    print('V chromaticitity: ', chrom.vertical_chromaticity)
    # MADX chromaticiticity is with respect to PT
    #assert chrom.horizontal_chromaticity == pytest.approx(-65.68223681*beta)
    #assert chrom.vertical_chromaticity == pytest.approx(-25.5636675*beta)

def main():
    lf = lattice_fixture()
    test_tunes(lf)
    test_chromaticities(lf)

if __name__ == "__main__":
    main()


import discord
import util

from discord.ext import commands

class Commisioner(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.guild_only()
    @commands.has_any_role("Game Master")
    @commands.command(name="startcount", description="Start a counting game on a channel", usage="startcount #channel")
    async def startcount(self, ctx, channel : discord.TextChannel=None):
        if channel is None:
            embed = util.log_embed("Please ping a channel you want to start counting game on", "failed")
            await ctx.send(embed=embed)
            return

        cursor = self.bot.conn.cursor()
        query = "UPDATE servers SET count_game_channel_id = %s WHERE server_id = %s"
        cursor.execute(query,(channel.id, ctx.guild.id))
        self.bot.conn.commit()
        try:
            query_insert = "INSERT INTO count_game(server_id, count_game_channel_id, last_count_member_id, last_count_number, last_count_status, last_count_fee, total_fee, created_at, last_modified_at) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s)"
            data_insert = (ctx.guild.id, channel.id, 1, 0, 'good', 300, 0, datetime.datetime.now(), datetime.datetime.now())
            cursor.execute(query_insert,data_insert)
        except:
            self.bot.conn.commit()
            query_update = "UPDATE count_game SET count_game_channel_id = %s, last_count_member_id = 1, last_count_number = %s, last_count_status = %s, last_count_fee = 300, total_fee = 0, last_modified_at = current_timestamp WHERE server_id = %s"
            data_update = (channel.id, 0, "good", ctx.guild.id)
            cursor.execute(query_update, data_update)
        self.bot.conn.commit()
        log_embed = util.log_embed(f"Successfully started counting game on {channel.mention}", "success")
        await ctx.send(embed=log_embed)
        embed = discord.Embed(title="Apollo's Chain Counting Game", description="Alright! Let's start all over again!", color=discord.Color.teal())
        embed.set_thumbnail(url="https://i.imgur.com/DMvoEus.png")
        await channel.send(embed=embed)

    @commands.guild_only()
    @commands.has_any_role("Game Master")
    @commands.command(name="resetcount", description="Reset counting game number and fee", usage="resetcount <number> <fee>")
    async def resetcount(self, ctx, count_number:int=None, fee:int=None):
        if count_number is None or fee is None:
            embed = util.log_embed("Please input the count number and fee", "failed")
            await ctx.send(embed=embed)
            return

        cursor = self.bot.conn.cursor()
        try:
            query = "UPDATE count_game SET last_count_member_id = 1, last_count_number = %s, last_count_fee = %s, last_count_status = %s WHERE server_id = %s"
            cursor.execute(query,(count_number, fee, "good", ctx.guild.id))
            self.bot.conn.commit()
            self.bot.logger.info("Updated channel count (reset_count)")
            response = f"Number and fee have been reset to {count_number} and {fee:,}"
            embed = util.log_embed(response, "success")
        except:
            response = f"You haven't set a count channel"
            embed = util.log_embed(response, "failed")
        await ctx.send(embed=embed)

    @commands.guild_only()
    @commands.has_any_role("Game Master")
    @commands.command(name="stopcount", description="Stop counting game (need to restart it with startcount command)", usage="stopcount")
    async def stopcount(self, ctx):
        cursor = self.bot.conn.cursor()
        query = "UPDATE servers SET count_game_channel_id = %s WHERE server_id = %s"
        cursor.execute(query,(1, ctx.guild.id))
        self.bot.conn.commit()
        try:
            query_update = "UPDATE count_game SET count_game_channel_id = %s WHERE server_id = %s"
            data_update = (1, ctx.guild.id)
            cursor.execute(query_update, data_update)
            self.bot.conn.commit()
            self.bot.logger.info("Updated channel count (stop_count)")
            response = f"Counting game has been stopped"
            embed = util.log_embed(response, "success")
        except:
            response = f"You haven't set a count channel"
            embed = util.log_embed(response, "failed")
        await ctx.send(embed=embed)

    @commands.guild_only()
    @commands.has_any_role("Game Master")
    @commands.command(name="addcoins", description="Add coins to a player", usage="addcoins @user <amount>")
    async def addcoins(self, ctx, member:discord.Member=None, coins:int=None):
        if member is None or coins is None:
            embed = util.log_embed("Please ping a player and input coins amount", "failed")
            await ctx.send(embed=embed)
            return

        cursor = self.bot.conn.cursor()
        query_add_coins = "UPDATE players SET coins = coins + %s, last_modified_at = current_timestamp where player_id = %s"
        data_add_coins = (coins, member.id)
        cursor.execute(query_add_coins, data_add_coins)
        self.bot.conn.commit()
        await ctx.message.add_reaction("✅")
        response = f"{ctx.author.mention} has added {coins:,} coins to {member.mention}"
        embed = util.log_embed(response, "success")
        await ctx.send(embed=embed)

def setup(bot):
    bot.add_cog(Commisioner(bot))


from tokens import keys

import tweepy
from tweepy import OAuthHandler
from random import randint

consumer_key = keys['consumer_key']
consumer_secret = keys['consumer_secret']

auth = OAuthHandler(consumer_key, consumer_secret)

api = tweepy.API(auth)

class RandomTweet:

  def get_tweet(handle):
      fifty_tweets = api.user_timeline(screen_name=handle, count=50)
      for tweet in fifty_tweets:
	      with open('quotes.txt', 'a+') as f:
	        f.write(tweet.text + "\n")

  if __name__ == '__main__':
      get_tweet("sadguruwhispers")


from random import randint
from pickle import load
import numpy as np
from data_preparation import*
from keras.models import load_model
from keras_preprocessing.sequence import pad_sequences
from keras.utils import plot_model
import matplotlib.pyplot as plt

# load cleaned text sequences
in_filename = 'republic_sequences.txt'
doc = load_doc(in_filename)
lines = doc.split('\n') # list of sentences
seq_length = len(lines[0].split()) - 1 # equal to the no. of words in the first sentence minus one (right?)

# load the model
model = load_model('model.h5')
#print(model.summary())

# load the tokenizer
tokenizer = load(open('tokenizer.pkl', 'rb'))

def start_interactive_session(amount_of_predictions):
    """
    Allows the user to type words and returns the predictions until a keyboard interrupt occurs.

    Parameters
        amount_of_predictions: int
            The no. of words to be predicted.
    """
    print('\n\n\nInteractive session started\n===========================')
    while 1:
        print('Words predicted: ' + generate_seq(model, tokenizer, seq_length, input("Type a few words: "), amount_of_predictions) + '\n')

def generate_seq(model, tokenizer, seq_length, seed_text, n_words):
    """
    Returns a sequence of words generated by the model.

    Parameters
        model: Sequential
            The trained model that will perform the predictions.
        tokenizer: Tokenizer
            Will encode 'seed_text' into integers.
        seq_length: int
            The max no. of all sequences.
        seed_text: str
            A random sequence of 50 words.
        n_words: int
            The no. of words to predict.

    Returns
        :str
            A string made of the words predicted.
    """
    result = list()
    in_text = seed_text
    for _ in range(n_words):
        encoded = tokenizer.texts_to_sequences([in_text])[0] # encodes the text as integer
        encoded = pad_sequences([encoded], maxlen = seq_length, truncating = 'pre') # truncates sequences to a fixed length

        yhat = model.predict(encoded, verbose = 0) # numpy array of probabilities for each word
        index_of_word_with_max_probability = np.argmax(yhat, axis = 1) # https://stackoverflow.com/questions/68776790/model-predict-classes-is-deprecated-what-to-use-instead

        out_word = ''
        for word, index in tokenizer.word_index.items(): # map predicted word index to word
            if index == index_of_word_with_max_probability:
                out_word = word
                break
		# append to input
        in_text += ' ' + out_word
        result.append(out_word)
    return ' '.join(result)

def get_sentence_completion(user_input, words_per_phrase):
    """
    Returns multiple words (i.e., a phrase) in response to user input.

    Parameters
        user_input: str
            A word or a phrase/sentence.
        words_per_phrase: int
            The number of words returned.

    Returns
        :str
            A string made of the words predicted.
    """
    generated = generate_seq(model, tokenizer, seq_length, user_input, words_per_phrase) # the number denotes the amount of words to be generated by the prediction
    print(f'Generated response to "{user_input}": {generated}')
    return generated

def get_most_probable_next_words(user_input, amount_of_words):
    """
    Returns a list of the most probable next words.

    Parameters
        user_input: str
            A word or a phrase/sentence.
        amount_of_words: int
            The length of the list of words to predict.

    Returns
        : list
            The list of the most probable next words.
    """
    most_probable_words = list()
    encoded = tokenizer.texts_to_sequences([user_input])[0] # encodes the text as integer
    encoded = pad_sequences([encoded], maxlen = seq_length, truncating = 'pre') # truncates sequences to a fixed length
    yhat = model.predict(encoded, verbose = 0) # list of probabilities for each word

    # sort, flatten, and slice the indices with the highest probabilities from the end
    indices_of_most_probable_words = np.argsort(yhat, axis = 1).flatten()[-amount_of_words:] # use 'flatten' because 'yhat' is a 2D array

    for word, index in tokenizer.word_index.items(): # map predicted word index to word
        if index in indices_of_most_probable_words:
            most_probable_words.append(word)
    return most_probable_words

# does not work
#plt.plot(model.history['acc'])
#plt.plot(model.history['val_acc'])
#plt.show()


import json
from datetime import datetime
import calendar

class consumption_calc:
    def __init__(self,status_file, IDs, cost):
        with open(status_file) as file:
            self.statis = json.load(file)
        self._root = f"{IDs['farmID']}/{IDs['sectionID']}"

        self.cost = cost

    def selective_time(self, start, end):
        start_time = datetime.strptime(start,  "%d/%m/%Y %H:%M:%S")
        end_time = datetime.strptime(end, "%d/%m/%Y %H:%M:%S")
        # time_on_list = []
        time_on_seconds = 0
        first_status = None
        last_status = None
        f_state = None

        for _dict in self.statis['pump_status']:
            if _dict['r'] == self._root:
                _dict_t = datetime.strptime(_dict['t'], "%d/%m/%Y %H:%M:%S")

                if start_time <= _dict_t <= end_time:
                    if first_status == None:
                        first_status = _dict['status']
                        _first_t = _dict_t
                    last_status = _dict['status']

                    if f_state == None and _dict['status'] == 'on':
                        f_state = _dict['status']
                        time_s = _dict_t

                    elif f_state == 'on' and _dict['status'] == 'off':
                        time_on = _dict_t - time_s
                        # time_on_list.append(time_on)
                        time_on_seconds = time_on_seconds + time_on.total_seconds()
                        f_state = None
        if last_status == 'on':
            time_on = end_time - time_s
            time_on_seconds = time_on_seconds + time_on.total_seconds()

        if first_status == 'off':
            time_on = _first_t - start_time
            time_on_seconds = time_on_seconds + time_on.total_seconds()

        power_cons = round(time_on_seconds/3600 * self.cost,2)  # 1 KW/h * Elec_price (Euro)

        return time_on_seconds, power_cons

    def daily_usage(self, day):
        '''
            Day should be present as %d/%m/%Y
        '''

        start_time = day +" 00:00:00"
        end_time = day +" 23:59:59"
        on_sec, power_cons = self.selective_time(start_time,end_time)

        return on_sec, power_cons

    def monthly_usage(self, month_year = '01/2023'):
        mm = month_year.split('/')[0]
        if mm.isdigit() and len(mm) == 1:
            month_year = f"0{mm}/" + month_year.split("/")[1]

        if int(month_year.split('/')[0]) == datetime.now().month and int(month_year.split('/')[1]) == datetime.now().year:
            now_time = datetime.now()
            end_time = now_time.strftime('%d/%m/%Y %H:%M:%S')

        else:
            month = month_year.split('/')[0]
            if month == '02':
                end_day = '28'
            elif month == '04'or month == '06' or month == '09' or month == '11':
                end_day = '30'
            else:
                end_day = '31'

            end_time = f'{end_day}/{month_year} 23:59:59'

        start_time = f'01/{month_year} 00:00:00'
        on_sec, power_cons = self.selective_time(start_time,end_time)

        return on_sec, power_cons

    def yearly(self, year = '2023'):
        year_cost ={}
        for i in range(1,13):
            month_year = f'{i}/{year}'
            _, power_cons = self.monthly_usage(month_year)
            month_name = calendar.month_name[i]
            year_cost[month_name] = power_cons
        return year_cost

if __name__ == "__main__":

    IDs = {
    'farmID': 'Farm_2',
    'sectionID': 'Section1'
    }

    cost = 0.12 #cost per min

    cons = consumption_calc('./pump_status.json', IDs, cost)
    # on_sec, power_cons = cons.selective_time(start='25/03/2023 00:00:00',end='01/04/2023 23:59:59')

    # print(f'on_sec: {on_sec}\npower cons: {power_cons}')

    # on_sec, power_cons = cons.daily_usage('25/03/2023')
    # print(f'on_sec: {on_sec}\npower cons: {power_cons}')

    on_sec, power_cons = cons.monthly_usage(month_year = '5/2023')
    print(f'on_sec: {on_sec}\npower cons: {power_cons}')

    # _dict = cons.yearly(year = '2024')
    # print(_dict)


import voluptuous as v

class Base(object):
    formats = v.Any(
        u"none",
        u"short",
        u"percent",
        u"percentunit",
        u"humidity",
        u"ppm",
        u"dB",
        u"currencyUSD",
        u"currencyGBP",
        u"currencyEUR",
        u"currencyJPY",
        u"hertz",
        u"ns",
        u"µs",
        u"ms",
        u"s",
        u"m",
        u"h",
        u"d",
        u"bits",
        u"bytes",
        u"kbytes",
        u"mbytes",
        u"gbytes",
        u"decbits",
        u"decbytes",
        u"deckbytes",
        u"decmbytes",
        u"decgbytes",
        u"pps",
        u"bps",
        u"Bps",
        u"Kbits",
        u"KBs",
        u"Mbits",
        u"MBs",
        u"GBs",
        u"Gbits",
        u"ops",
        u"rps",
        u"wps",
        u"iops",
        u"opm",
        u"rpm",
        u"wpm",
        u"lengthmm",
        u"lengthm",
        u"lengthkm",
        u"lengthmi",
        u"velocityms",
        u"velocitykmh",
        u"velocitymph",
        u"velocityknot",
        u"mlitre",
        u"litre",
        u"m3",
        u"watt",
        u"kwatt",
        u"watth",
        u"kwatth",
        u"joule",
        u"ev",
        u"amp",
        u"volt",
        u"celsius",
        u"farenheit",
        u"kelvin",
        u"pressurembar",
        u"pressurehpa",
        u"pressurehg",
        u"pressurepsi",
        u"reqps",
        u"dtdurations",
    )

    def __init__(self):
        self.base = {
            v.Required("editable", default=True): v.All(bool),
            v.Required("error", default=False): v.All(bool),
            v.Required("span", default=12): v.All(int, v.Range(min=0, max=12)),
            v.Required("title"): v.All(str, v.Length(min=1)),
            v.Required("type"): v.Any(
                "dashlist",
                "graph",
                "logs",
                "singlestat",
                "text",
                "row",
                "stat",
                "table-old",
            ),
            v.Optional("id"): int,
            v.Optional("format"): v.Any(self.formats, v.Length(min=1)),
            v.Optional("transparent"): v.All(bool),
            v.Optional("height"): v.All(int),
            v.Optional("description"): v.All(str),
        }

    def get_schema(self):
        return v.Schema(self.base, extra=True)


from gpiozero import Servo
from time import sleep

servo1 = Servo(18)
servo2 = Servo(19)
config_array = []
current_door = []
config_filename = "servoconfig.txt"

try:
    while True:
        with open(config_filename) as config_file:
            config_array = config_file.readlines()

        for line in config_array:
            current_door = line.split(":")
            # print(current_door)

            if current_door[0].strip() == "Door1" and current_door[1].strip() == "closed":
                servo1.value = -1
                servo2.value = 1
            elif current_door[0].strip() == "Door1" and current_door[1].strip() == "open":
                servo1.value = 1
                servo2.value = -1

        sleep(1)

except KeyboardInterrupt:
    print("Program stopped")


import uuid
from readingdb.format import route_sort_key
from readingdb.utils import timestamp
import time
from typing import Any, Callable, Dict, List, Set, Tuple

import boto3
from boto3.dynamodb.conditions import Key

from readingdb.clean import *
from readingdb.reading import Reading, geohash_partition_key
from readingdb.route import Route
from readingdb.constants import *

class DB():
    ITEM_KEY = 'Items'
    LAST_EVAL_KEY = 'LastEvaluatedKey'

    def __init__(
        self,
        url,
        resource_name='dynamodb',
        region_name='ap-southeast-2',
        config=None,
        max_page_readings=1800,
    ):
        self.db = boto3.resource(
            resource_name,
            region_name=region_name,
            endpoint_url=url,
            config=config,
        )

        # DynamoDB only returns 1MB of data in a single query
        # use paginator on queries that stand a chance of returning
        # > 1MB of data.
        self.client = self.db.meta.client
        self.paginator = self.client.get_paginator('query')
        self.scan_paginator = self.client.get_paginator('scan')
        self.max_page_readings = max_page_readings

        self.reading_table = self.db.Table(Constants.READING_TABLE_NAME)
        self.org_table = self.db.Table(Constants.ORG_TABLE_NAME)

    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -------------------------- GENERAL ------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------

    def __paginate_table(
        self,
        table_name: str,
        decode_fn: Callable[[Dict[str, Any]], Any],
        query_key: str = None,
        query_value: str = None,
    )-> Any:
        if query_key is not None:
            pg = self.paginator.paginate(
                TableName=table_name,
                KeyConditionExpression=Key(query_key).eq(query_value)
            )
        else:
            pg = self.scan_paginator.paginate(
                TableName=table_name,
            )

        items = []
        for page in pg:
            for item in page[self.ITEM_KEY]:
                decode_fn(item)
                items.append(item)

        return items

    def all_tables(self) -> List[Any]:
        return list(self.db.tables.all())

    def create_reading_db(
        self,
    ) -> Tuple[Any, Any]:
        self.reading_table = self.__make_reading_table()
        self.org_table = self.__make_org_table()
        return (self.reading_table, self.org_table)

    def teardown_reading_db(self) -> None:
        self.__delete_table(Constants.READING_TABLE_NAME)
        self.__delete_table(Constants.ORG_TABLE_NAME)

    def __delete_table(self, table_name) -> None:
        self.db.Table(table_name).delete()

    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -------------------------- ROUTE --------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------

    def remove_route(self, route_id: str):
        self.org_table.delete_item(
            Key={
                Constants.PARTITION_KEY: Constants.ROUTE_PK,
                Constants.SORT_KEY: route_sort_key(route_id)
            }
        )

    def put_route(self, route: Route):
        return self.org_table.put_item(Item=route.item_data())

    def get_route(self, route_id: str) -> Dict[str, Any]:
        response = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(Constants.ROUTE_PK) &
                Key(Constants.SORT_KEY).eq(route_sort_key(route_id))
        )

        if len(response[self.ITEM_KEY]) < 1:
            return None

        item = response[self.ITEM_KEY][0]
        Route.decode_item(item)

        return item

    def route_geohashes(self, route_id: str) -> Set[str]:
        route = self.get_route(route_id)

        if route is None:
            return set()

        return set(route[Constants.ROUTE_HASHES])

    def routes_for_user(self, user_id: str) -> List[Dict[str, Any]]:
        groups = self.groups_for_user(user_id)
        routes = self.all_routes()

        return [r for r in routes if r[Constants.GROUP_ID] in groups]

    def all_routes(self) -> List[Dict[str, Any]]:
        response = self.org_table.query(
            KeyConditionExpression=Key(Constants.PARTITION_KEY).eq(Constants.ROUTE_PK)
        )

        return [Route.decode_item(item) for item in response[self.ITEM_KEY]]

    def update_route_name(self, route_id: str, name: str) -> None:
        r: Dict[str, Any] = self.get_route(route_id)

        if r[Constants.NAME] != name:
            self.org_table.update_item(
                Key={
                    Constants.PARTITION_KEY: Constants.ROUTE_PK,
                    Constants.SORT_KEY: route_sort_key(route_id)
                },
                UpdateExpression=f'set {Constants.NAME} = :r, {Constants.LAST_UPDATED} = :l',
                ExpressionAttributeValues={
                    ':r': name,
                    ':l': int(time.time())
                },
            )

    def set_route_status(self, route_id: str, status: int) -> None:
        r: Dict[str, Any] = self.get_route(route_id)

        if r[Constants.STATUS] != status:
            self.org_table.update_item(
                Key={
                    Constants.PARTITION_KEY: Constants.ROUTE_PK,
                    Constants.SORT_KEY: route_sort_key(route_id)
                },
                UpdateExpression=f'set {Constants.STATUS} = :r, {Constants.LAST_UPDATED} = :l',
                ExpressionAttributeValues={
                    ':r': status,
                    ':l': int(time.time())
                },
            )

    def __make_org_table(self):
        return self.db.create_table(
            TableName=Constants.ORG_TABLE_NAME,
            KeySchema=[
                {
                    'AttributeName':  Constants.PARTITION_KEY,
                    'KeyType': 'HASH'
                },
                {
                    'AttributeName': Constants.SORT_KEY,
                    'KeyType': 'RANGE'
                }
            ],
            AttributeDefinitions=[
                {
                    'AttributeName': Constants.PARTITION_KEY,
                    'AttributeType': 'S'
                },
                {
                    'AttributeName': Constants.SORT_KEY,
                    'AttributeType': 'S'
                },
            ],
            ProvisionedThroughput={
                'ReadCapacityUnits': 100,
                'WriteCapacityUnits': 100
            }
        )

    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -------------------------- READING ------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------

    def put_readings(self, readings: List[Reading]):
        with self.reading_table.batch_writer() as batch:
            for r in readings:
                batch.put_item(Item=r.item_data())

    def get_route_readings(self, route_id: str) -> List[Dict[str, Any]]:
        geohashes = self.route_geohashes(route_id)
        all_readings = []

        for geohash in geohashes:
            hash_readings = self.__paginate_table(
                Constants.READING_TABLE_NAME,
                Reading.decode,
                Constants.PARTITION_KEY,
                geohash_partition_key(geohash, Constants.PREDICTION),
            )
            all_readings.extend([r for r in hash_readings if r[Constants.ROUTE_ID] == route_id])

        return all_readings

    def geohash_readings(self, geohash: str, reading_type: str) -> List[Dict[str, Any]]:
        response = self.reading_table.query(
            KeyConditionExpression=Key(Constants.PARTITION_KEY).eq(geohash_partition_key(geohash, reading_type))
        )
        return response[self.ITEM_KEY]

    def put_reading(self, reading: Reading):
        return self.reading_table.put_item(Item=reading.item_data())

    def delete_reading_items(self, readings: List[Dict[str, str]])-> None:
        for reading in readings:
            self.reading_table.delete_item(
                Key=Reading.get_key(reading)
            )

    def __make_reading_table(self):
        return self.db.create_table(
            TableName=Constants.READING_TABLE_NAME,
            KeySchema=[
                {
                    'AttributeName': Constants.PARTITION_KEY,
                    'KeyType': 'HASH'
                },
                {
                    'AttributeName': Constants.SORT_KEY,
                    'KeyType': 'RANGE'
                }
            ],
            AttributeDefinitions=[
                {
                    'AttributeName': Constants.PARTITION_KEY,
                    'AttributeType': 'S'
                },
                {
                    'AttributeName': Constants.SORT_KEY,
                    'AttributeType': 'S'
                },

            ],
            ProvisionedThroughput={
                'ReadCapacityUnits': 500,
                'WriteCapacityUnits': 500
            }
        )

    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # --------------------------- LAYERS ------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------

    def put_layer(
        self,
        layer_id: str,
        readings: List[Dict[str, Any]] = None,
        name:str=None
    ) -> str:
        if readings is not None:
            existing_readings = self.layer_readings([layer_id])
            existing_reading_ids = set()
            current_reading_ids = set()

            for reading in readings:
                current_reading_ids.add(reading[Constants.READING_ID])

            for reading in existing_readings:
                reading_id = reading[Constants.READING_ID]
                existing_reading_ids.add(reading_id)
                if reading_id not in current_reading_ids:
                    self.remove_reading_from_layer(layer_id, reading)

            for reading in readings:
                if reading[Constants.READING_ID] not in existing_reading_ids:
                    self.add_reading_to_layer(layer_id, reading)

        item = {
            Constants.PARTITION_KEY: Constants.LAYER_PK,
            Constants.SORT_KEY: self.__layer_sort_key(layer_id),
        }

        if name is not None:
            item[Constants.LAYER_NAME] = name

        self.org_table.put_item(Item=item)

        return layer_id

    def remove_readings_from_layer(self, layer_id: str, readings: List[Dict[str, Any]]):
        for reading in readings:
            self.remove_reading_from_layer(layer_id, reading)

    def remove_reading_from_layer(self, layer_id: str, reading: Dict[str, Any]):
        self.org_table.delete_item(Key={
            Constants.PARTITION_KEY: self.__layer_reading_primary_key(layer_id),
            Constants.SORT_KEY: reading[Constants.READING_ID]
        })

    def add_readings_to_layer(self, layer_id:str, readings: List[Dict[str, Any]]) -> None:
        for reading in readings:
            self.add_reading_to_layer(layer_id, reading)

    def add_reading_to_layer(self, layer_id: str, reading: Dict[str, Any]):
        self.org_table.put_item(Item={
            Constants.PARTITION_KEY: self.__layer_reading_primary_key(layer_id),
            Constants.SORT_KEY: reading[Constants.READING_ID],
            Constants.READING_ID: reading[Constants.READING_ID],
            Constants.GEOHASH: reading[Constants.GEOHASH],
            Constants.READING_TYPE: reading[Constants.READING_TYPE],
        })

    def layer_ids_for_user(self, user_id: str):
        layer_ids = []

        group_ids = self.groups_for_user(user_id)
        for id in group_ids:
            layer_ids.extend(self.layer_ids_for_group(id))

        return layer_ids

    def layers_for_user(self, user_id:str) -> List[Dict[str, Any]]:
        layers = []

        group_ids = self.groups_for_user(user_id)
        for id in group_ids:
            layer_ids = self.layer_ids_for_group(id)

            for layer_id in layer_ids:
                layers.append(self.get_layer(layer_id))

        return layers

    def readings_for_layer_id(self, layer_id:str) -> List[Dict[str, Any]]:
        return self.layer_readings([layer_id])

    def layer_readings(self, layer_ids: str) -> List[Dict[str, Any]]:
        readings = []

        geohashes = set()
        reading_ids = set()

        for layer_id in layer_ids:
            identifiers = self.__layer_reading_identifiers(layer_id)

            for identifier in identifiers:
                geohashes.add(identifier[Constants.GEOHASH])
                reading_ids.add(identifier[Constants.SORT_KEY])

        for geohash in geohashes:
            geohash_readings = self.geohash_readings(geohash, Constants.PREDICTION)
            for geohash_reading in geohash_readings:
                if geohash_reading[Constants.READING_ID] in reading_ids:
                    readings.append(geohash_reading)

        return readings

    def identifiers_for_layers(self, layer_ids: List[str]):
        all_identifiers = []

        for layer_id in layer_ids:
            all_identifiers.extend(self.__layer_reading_identifiers(layer_id))

        return all_identifiers

    def __layer_reading_identifiers(self, layer_id: str) -> Dict[str, Any]:
        resp = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(self.__layer_reading_primary_key(layer_id))
        )

        return resp[self.ITEM_KEY]

    def get_layer(self, layer_id: str) -> Dict[str, Any]:
        response = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(Constants.LAYER_PK) &
                Key(Constants.SORT_KEY).eq(self.__layer_sort_key(layer_id))
        )

        if len(response[self.ITEM_KEY]) == 0:
            return None

        return response[self.ITEM_KEY][0]

    def __layer_id_from_layer_data(self, layer_data: List[Dict[str, Any]]) -> str:
        return layer_data[Constants.SORT_KEY].split('#')[1]

    def __layer_sort_key(self, layer_id: str) -> str:
        return f'Layer#{layer_id}'

    def __layer_reading_primary_key(self, layer_id: str):
        return f'LayerReading#{layer_id}'
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # ---------------------------- GROUPS -----------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------

    def put_group(self, group_id: str, name=None) -> None:
        item = {
            Constants.PARTITION_KEY: Constants.GROUP_PK,
            Constants.SORT_KEY: self.__group_key(group_id),
            Constants.GROUP_ID: group_id
        }

        if name is not None:
            item[Constants.GROUP_NAME] = name

        self.org_table.put_item(Item=item)

    def set_group_name(self, group_id:str, name:str) -> None:
        self.put_group(group_id, name)

    def get_group(self, group_id: str) -> Dict[str, Any]:
        resp = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(Constants.GROUP_PK) &
                Key(Constants.SORT_KEY).eq(self.__group_key(group_id))
        )

        return resp[self.ITEM_KEY][0]

    def user_add_group(self, user_id: str, group_id: str) -> None:
        self.org_table.put_item(Item={
            Constants.PARTITION_KEY: self.__user_group_pk(user_id),
            Constants.SORT_KEY: self.__group_key(group_id),
        })

    def user_remove_group(self, user_id: str, group_id: str) -> None:
        self.org_table.delete_item(Key={
            Constants.PARTITION_KEY: self.__user_group_pk(user_id),
            Constants.SORT_KEY: self.__group_key(group_id)
        })

    def group_add_layer(self, group_id: str, layer_id: str) -> None:
        self.org_table.put_item(Item={
            Constants.PARTITION_KEY: self.__group_key(group_id),
            Constants.SORT_KEY: self.__layer_group_pk(layer_id),
        })

    def group_remove_layer(self, group_id: str, layer_id: str) -> None:
        self.org_table.delete_item(Key={
            Constants.PARTITION_KEY: self.__group_key(group_id),
            Constants.SORT_KEY: self.__layer_group_pk(layer_id),
        })

    def groups_for_user(self, user_id: str) -> List[str]:
        response = self.org_table.query(KeyConditionExpression=
            Key(Constants.PARTITION_KEY).eq(self.__user_group_pk(user_id)))

        group_ids = []

        for item in response[self.ITEM_KEY]:
            group_ids.append(self.__id_from_key(item[Constants.SORT_KEY]))

        return group_ids

    def user_has_group(self, user_id: str, group_id: str) -> bool:
        response = self.org_table.query(KeyConditionExpression=
            Key(Constants.PARTITION_KEY).eq(self.__user_group_pk(user_id))
        )

        for item in response[self.ITEM_KEY]:
            if self.__id_from_key(item[Constants.SORT_KEY]) == group_id:
                return True

        return False

    def __user_group_pk(self, user_id: str) -> str:
        return f'UserGroup#{user_id}'

    def __id_from_key(self, agid: str) -> str:
        return agid.split("#")[-1]

    def layer_ids_for_group(self, group_id: str) -> str:
        response = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(self.__group_key(group_id))
        )

        layer_ids = []

        for item in response[self.ITEM_KEY]:
            layer_ids.append(self.__id_from_key(item[Constants.SORT_KEY]))

        return layer_ids

    def __layer_group_pk(self, layer_id: str) -> str:
        return f'LayerGroup#{layer_id}'

    def __group_key(self, acess_group_id: str) -> str:
        return f'Group#{acess_group_id}'

    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # --------------------------- ORG ---------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------

    def put_org(self, org_name:str, default_group_id: str = None) -> Dict[str, Any]:
        if default_group_id is None:
            default_group_id = str(uuid.uuid1())

        item = {
            Constants.PARTITION_KEY: Constants.ORG_PK,
            Constants.SORT_KEY: self.__org_sk(org_name),
            Constants.ORG_NAME: org_name,
            Constants.ORG_GROUP: default_group_id
        }

        self.org_table.put_item(Item=item)

        return item

    def get_orgs(self) -> List[Dict[str, Any]]:
        response = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(Constants.ORG_PK)
        )

        return response[self.ITEM_KEY]

    def get_org(self, org_name: str) -> Dict[str, Any]:
        response = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(Constants.ORG_PK) &
                Key(Constants.SORT_KEY).eq(self.__org_sk(org_name)),
        )

        if len(response[self.ITEM_KEY]) > 0:
            return response[self.ITEM_KEY][0]
        return None

    def __org_sk(self, org_id:str) -> str:
        return f'Org#{org_id}'

    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -------------------------- USER ---------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------
    # -----------------------------------------------------------------

    def user_data(self, org_name:str, user_id: str)-> Dict[str, Any]:
        response = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(self.__user_org_key(org_name)) &
                Key(Constants.SORT_KEY).eq(self.__user_sort_key(user_id))
        )

        return response[self.ITEM_KEY][0]

    def all_users(self, org_name:str) -> List[Dict[str, Any]]:
        resp = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(self.__user_org_key(org_name))
        )

        return resp[self.ITEM_KEY]

    def all_user_ids(self, org_name:str) -> List[str]:
        user_ids = []
        response = self.org_table.query(
            KeyConditionExpression=
                Key(Constants.PARTITION_KEY).eq(self.__user_org_key(org_name))
        )

        for item in response[self.ITEM_KEY]:
            user_ids.append(item[Constants.USER_ID])

        return user_ids

    def put_user(self, org_name, user_id: str) -> None:
        self.org_table.put_item(Item={
            Constants.PARTITION_KEY: self.__user_org_key(org_name),
            Constants.SORT_KEY: self.__user_sort_key(user_id),
            Constants.TIMESTAMP: timestamp(),
            Constants.USER_ID: user_id,
            Constants.ORG_NAME: org_name
        })

        org = self.get_org(org_name)

        self.user_add_group(user_id, org[Constants.ORG_GROUP])

    def __user_org_key(self, org_name: str) -> str:
        return f'Org#{org_name}'

    def __user_sort_key(self, user_id: str) -> str:
        return f'User#{user_id}'


import re, sys, os, time, json, pystray, colorsys, keyboard, tkinter as tk
from tkinter import Label, Frame, Entry, Toplevel, Button, LabelFrame
from threading import Thread
from pystray import Menu, MenuItem as item
from PIL import Image, ImageTk
from screeninfo import get_monitors
def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    global DEBUG
    if DEBUG == False:
        try:
            # PyInstaller creates a temp folder and stores path in _MEIPASS
            base_path = sys._MEIPASS
        except Exception:
            base_path = os.path.abspath(".")
        return os.path.join(base_path, relative_path)
    else:
        try:
            # PyInstaller creates a temp folder and stores path in _MEIPASS
            base_path = sys._MEIPASS
        except Exception:
            base_path = os.path.abspath(".")
            edited_base_path = base_path + "/Logitech GHub Battery Percentage Viewer"
            unedited_path = os.path.join(edited_base_path, relative_path)
            edited_path = unedited_path.replace('\\' , '/')
        return edited_path
DEBUG = False    # Defines what values to use for the location of files
""" Set DEBUG to False when freezing code """
Background_stuff_DEBUG = False    # Debug for Background_stuff thread, set to True to make all print functions in Background_stuff print to console, set to False if you dont want it to print to console
GUI_stuff_DEBUG = False    # Debug for GUI_stuff thread, set to True to make all print functions in Background_stuff print to console, set to False if you dont want it to print to console
Tray_stuff_DEBUG = False    # Debug for Tray_stuff thread, set to True to make all print functions in Background_stuff print to console, set to False if you dont want it to print to console
Colour_stuff_DEBUG = False
Tray_Custom_stuff_DEBUG = False
if Background_stuff_DEBUG == True:    # Prints current active status of Background stuff
    print("Background_stuff_DEBUG is Active")
if GUI_stuff_DEBUG == True:     # Prints current active status of GUI stuff
    print("GUI_stuff_DEBUG is Active")
if Tray_stuff_DEBUG == True:    # Prints current active status of Tray stuff
    print("Tray_stuff_DEBUG is Active")
if Colour_stuff_DEBUG == True:    # Prints current active status of Colour stuff
    print("Colour_stuff_DEBUG is Active")
if Tray_Custom_stuff_DEBUG == True:    # Prints current active status of Custom Location stuff
    print("Tray_Custom_stuff_DEBUG is Active")
def Background_stuff():
    global GUI_stuff_DEBUG
    global a_file
    global percentage
    global G502line
    global G915line
    global millivolts
    global timeline
    global charging
    global listhide
    global file_path
    global file
    global Chargestatus
    global counter
    global Background_stuff_DEBUG
    global quitmain
    def log(s):
        if Background_stuff_DEBUG == True:
            print(s)
    if quitmain == True:
        sys.exit()
    list = []
    NEWlist = []
    Chargestatus[0] = "0"
    Chargestatus[1] = "0"
    f = open(a_file, errors="ignore")
    for line in f:
        if G502line in line:
            log("line = " + line)           # Print
            line = re.findall(r'\d+', line)
            line = str(line); line = line[2:]; line = line[:-2]
            list.append(line)
            for i in range(3):
                followline = next(f)
                if timeline in followline:
                    followline = listhide
                else:
                    log("followline = " + followline)           # Print
                    if charging in followline:
                        del Chargestatus[0]
                        Chargestatus.insert(0, '1')
                        followline = listhide
                followline = re.findall(r'\d+', followline)
                followline = str(followline); followline = followline[2:]; followline = followline[:-2]
                list.append(followline)
        if G915line in line:
            log("line = " + line)           # Print
            line = re.findall(r'\d+', line)
            line = str(line); line = line[2:]; line = line[:-2]
            list.append(line)
            for i in range(3):
                followline = next(f)
                if timeline in followline:
                    followline = listhide   # Sets the line containing time to listhide
                else:
                    log("followline = " + followline)           # Print
                    if charging in followline:
                        del Chargestatus[1]
                        Chargestatus.append("1")
                        followline = listhide   # Sets the line containing charging to listhide
                followline = re.findall(r'\d+', followline)     # removes any items in the list that are not integers
                followline = str(followline); followline = followline[2:]; followline = followline[:-2]     # Removes all the values equal to listhide
                list.append(followline)     # adds followlone to the end of list
    if not list:
        log("List is empty")            # Print
        with open(resource_path('listfile.txt'), 'r') as filehandle:
            TEMPlist = json.load(filehandle)
        NEWlist = TEMPlist
        log("TEMPlist = " + str(TEMPlist))           # Print
        log("NEWlist = " + str(NEWlist))         # Print
    else:
        log("List is not Empty")            # Print
        log("list = " + str(list))           # Print
        while("" in list):
            list.remove("")     # Remove empty strings from list
        NEWlist = [x for x in list if int(x) <= 915]
        log("NEWlist = " + str(NEWlist))         # Print
        G502_Found = 0
        G915_Found = 0
        G502_Check = NEWlist[0]
        G915_Check = NEWlist[0]
        if G502_Check == str(502):
            log("G502 Check #1")            # Print
            list.remove(listhide)
            G502_Found = 1
        else:
            if G915_Check == str(915):
                log("G915 Check #2")            # Print
                list.remove(listhide)
                G915_Found = 1
        if G502_Found == 1:
            log("G502 Found #3")            # Print
            if len(NEWlist) == 4:
                log("NEWlist = 4")          # Print
                if NEWlist[-2] == str(915):
                    with open(resource_path('listfile.txt'), 'w') as filehandle:
                        json.dump(NEWlist, filehandle)
                else:
                    def swapPositions(list, pos1, pos2):
                        get = NEWlist[pos1], NEWlist[pos2]
                        NEWlist[pos2], NEWlist[pos1] = get
                        return NEWlist
                    pos1, pos2 = -1, -2
                    swapPositions(NEWlist, pos1=1, pos2=1)
            else:
                log("NEWlist = 2")          # Print
                with open(resource_path('listfile.txt'), 'r') as filehandle:
                    TEMPlist = json.load(filehandle)
                NEWlist.append(TEMPlist[-2])
                NEWlist.append(TEMPlist[-1])
                log("NEWlist = " + str(NEWlist))         # Print
                if NEWlist[-1] == str(915):
                    log("Rearranging")          # Print
                    def swapPositions(list, pos1, pos2):
                        get = NEWlist[pos1], NEWlist[pos2]
                        NEWlist[pos2], NEWlist[pos1] = get
                        return NEWlist
                    pos1, pos2 = -1, -2
                    swapPositions(NEWlist, pos1=1, pos2=1)
                log("NEWlist = " + str(NEWlist))         # Print
                with open(resource_path('listfile.txt'), 'w') as filehandle:
                    json.dump(NEWlist, filehandle)
        else:
            if G915_Found == 1:
                log("G915 Found")           # Print
                if len(NEWlist) == 2:
                    with open(resource_path('listfile.txt'), 'r') as filehandle:
                        TEMPlist = json.load(filehandle)
                NEWlist.insert(0, TEMPlist[1])
                NEWlist.insert(0, TEMPlist[0])
                log("NEWlist = " + str(NEWlist))         # Print
                with open(resource_path('listfile.txt'), 'w') as filehandle:
                    json.dump(NEWlist, filehandle)
        log("NEWlist = " + str(NEWlist))            # Print
        with open(resource_path('listfile.txt'), 'w') as filehandle:
            json.dump(NEWlist, filehandle)
        with open(resource_path('Current_Percentage.txt'), 'w') as filehandle:
            json.dump(NEWlist, filehandle)
        with open(resource_path('Current_Charge.txt'), 'w') as c:
            json.dump(Chargestatus, c)
    time.sleep(0)
    if GUI_stuff_DEBUG == False:
        global spacer
        log(spacer + 'Counter: ' + str(counter))            # Print
    log("Refresher")            # Print
    Refresher()
def Tray_stuff():
    global frame1
    global Tray_stuff_DEBUG
    global hideshow
    global showhidestate
    global quitmain
    global loc
    def log(s):
        if Tray_stuff_DEBUG == True:
            print(s)
    win=tk.Tk()
    def showhide():
        global hideshow
        global showhidestate
        if showhidestate == 1:
            log("hideshow = 1  ,  Window is now Visible")           # Print
            hideshow = 1
        if showhidestate == 0:
            log("hideshow = 0  ,  Window is now Hidden")            # Print
            hideshow = 0
    def quit_window(icon, item):
        global quitmain
        quitmain = True
        icon.stop()
        win.destroy()
        os._exit()
    def loc1():         # Bottom Location
        global loc
        loc = "150x150-1930+1029"
    def loc2():         # Top Location
        global loc
        loc = "150x150-1930-941"
    def loc3():         # Left Location
        global loc
        loc = "150x150-3697+999"
    def loc4():         # Right Location
        global loc
        loc = "150x150-1839+999"
    def CustomLoc():
        global loc
        global Tray_Custom_stuff_DEBUG
        global Colour_stuff_DEBUG
        def log(s):
                if Tray_Custom_stuff_DEBUG == True:
                    print(s)
        def SelectCom():
            global loc
            global MonXval
            global MonYval
            locXval = locXin.get()
            locYval = locYin.get()
            if '-' not in locXval:
                locX = "+" + locXval
            else:
                locX = locXval
            if '-' not in locYval:
                locY = "+" + locYval
            else:
                locY = locYval
            loctest = "150x150" + locX + locY
            if loctest != "150x150++":
                loc = "150x150" + locX + locY
            log("                                                                                " + loc)           # Print
        def CancelCom():
            root1.withdraw()
        def selection():
            curloc = re.findall(r'-?\d+', loc)      # Extract all numbers into a list
            log(curloc)           # Print
            log(curloc[2]+" :curloc[2]")           # Print
            curX = curloc[2]
            curY = curloc[3]
            currentloc.config(text="Current location: "+"X: "+str(curX)+"  "+"Y: "+str(curY))
        def dragenable(s):
            lastClickX = 0
            lastClickY = 0
            def SaveLastClickPos(event):
                global lastClickX, lastClickY
                lastClickX = event.x
                lastClickY = event.y
                print(lastClickX,lastClickY)
            def Dragging(event):
                global lastClickX, lastClickY
                print(lastClickX,lastClickY)
                x = event.x - lastClickX + root1.winfo_x()
                y = event.y - lastClickY + root1.winfo_y()
                root1.geometry("+%s+%s" % (x , y))
            root1.bind('<Button-1>', SaveLastClickPos)
            root1.bind('<B1-Motion>', Dragging)
        def dragdisable(s):
            root1.unbind('<Button-1>')
            root1.unbind('<B1-Motion>')
        def rgb_to_hex(r, g, b):
            # helper function
            def help(c):
                if c<0: return 0
                if c>255: return 255
                return c
            # make sure that values are within bounds
            r = help(r)
            g = help(g)
            b = help(b)
            # convert to hex
            # maintain 2 spaces each
            val = "%02x%02x%02x" % (r, g, b)
            # return UpperCase string
            return val.upper()
        def colour():
            global r,g,b
            global Colour_stuff_DEBUG
            def log(s):
                if Colour_stuff_DEBUG == True:
                    print(s)
            num_steps = 1800 # arbitrary
            """ Any Number above 1800 doesnt really change the smoothness of the transition of colours that much """
            hue = 0.0
            step_val = 1.0 / num_steps
            while True:
                rgb = colorsys.hsv_to_rgb(hue, 1, 1)
                hue += step_val
                hue %= 1.0 # cap hue at 1.0
                r = round(rgb[0] * 255)
                g = round(rgb[1] * 255)
                b = round(rgb[2] * 255)
                log(str(r)+' '+str(g)+' '+str(b))           # Print
                rgb_ints = (r, g, b)
                log(rgb_ints)           # Print
                time.sleep(0.01)
                log(str(r)+' '+str(g)+' '+str(b))           # Print
                log(rgb_to_hex(r,g,b))           # Print
                frame1['highlightbackground']="#"+rgb_to_hex(r,g,b)
        root1 = Toplevel()
        root1.title("Logitech GHub Battery Viewer")        # Names the Tk root window
        root1.overrideredirect(1)        # Removes title bar from window
        root1.wm_attributes("-topmost", True)        # Makes the window always stay on top
        root1.configure(background="#000000")        # Makes background of window black
        root1.geometry("+%s+%s" % (0 , 0))        # Sets the size of the window to fit everything
        frame1 = Frame(root1, highlightbackground="#000000", highlightthickness=2, bg='#000000')        # Border for the Custom Location Window
        frame1.grid(padx=0, pady=0)
        titletext=Label(frame1, text="Custom Location", fg='#ffffff', bg='#000000')        # Border for the Custom Location Window
        titletext.grid(row = 1, column = 0, pady = 2, columnspan = 4)
        Xtext=Label(frame1, text="X:", fg='#ffffff', bg='black')        # X: label for the Custom Location Window
        Xtext.grid(row = 2, column = 1, pady = 2, sticky="e")
        locXin = Entry(frame1, font=('calibre',10,'normal'), show = None, fg='#ffffff', bg='#000000')        # X value input for the Custom Location Window
        locXin.grid(row = 2, column = 2, pady = 2, padx = (0,4))
        Ytext=Label(frame1, text="Y:", fg='#ffffff', bg='#000000')        # Y: label for the Custom Location Window
        Ytext.grid(row = 3, column = 1, pady = 2, sticky="e")
        locYin = Entry(frame1, font=('calibre',10,'normal'), show = None, fg='#ffffff', bg='#000000')        # Y value input for the Custom Location Window
        locYin.grid(row = 3, column = 2, pady = 2, padx = (0,4))
        monitorlist = []
        for m in get_monitors():        # Gets monitor info
            log(m)        # Prints monitor info
            monitorlist.append(m)        # Adds monitor info to a list
        log(monitorlist)        # Prints the list containing the monitor info
        monlistlen = len(monitorlist)        # Gets the length of the list containing the monitor info
        level = -1
        newmonlist = []
        list123 = []
        dislist = []
        current = 0
        currentt = -1
        for i in range(monlistlen):        # Repeat the following code as many times as there are items in the list containing the monitor info
            level = level + 1
            dislisttext = "Display " + str(level)
            dislist.append(dislisttext)
            log(dislisttext)           # Print
            log(dislist)           # Print
            monlistitem = str(monitorlist[level])
            sep = ", width_mm="
            stripped = monlistitem.split(sep, 1)[0]        # Separates an item from the list containing the monitor info and removes any unnecessary data
            newmonlist.append(stripped)        # Adds the separated necessary data to a list
            log(stripped)        # Prints the data the necessary data the was spearated
            newitems = re.findall(r'-?\d+', stripped)      # Extract all numbers into a list
            list123.append(newitems)        # Adds the extracted data to a list
            log(list123)        # Prints the list of extracted data
        loclist=re.findall(r'-?\d+', loc)      # Extract all numbers into a list
        log(loclist)        # Prints the list of extracted data
        curX = loclist[2]
        curY = loclist[3]
        currentloc=Label(frame1, text="Current location: "+"Xâ€‰:â€Š"+str(curX)+"  "+"Yâ€‰: "+str(curY), fg='#ffffff', bg='#000000')       # Current location label for the Custom Location Window
        currentloc.grid(row = 7, column = 1, pady = 2, columnspan = 3)
        ButtonSel=Button(frame1, text="Select", bg="#3c3c3c", fg="white", activebackground="#5a5a5a", command=SelectCom)       # Select button for the Custom Location Window
        ButtonSel.grid(row = 10, column = 2, pady = 2, padx = 2, sticky="e", columnspan = 2)
        ButtonClose=Button(frame1, text="Close", bg="#3c3c3c", fg="white", activebackground="#5a5a5a", command=CancelCom)       # Close button for the Custom Location Window
        ButtonClose.grid(row = 10, column = 1, pady = 2, padx = (3,2), sticky="w", columnspan = 2)
        keyboard.on_press_key("ctrl", dragenable)       # Detect when the CTRL key is pressed and when it is call dragenable
        keyboard.on_release_key("ctrl", dragdisable)       # Detect when the CTRL key is released and when it is call dragdisable
        colour()
        selection()
    def hide_window():
        global visibility
        win.withdraw()
        image=Image.open(resource_path('battery.ico'))
        menu=(item('Quit', quit_window), item("Location:", Menu(item('Bottom', loc1), item('Top', loc2), item('Left', loc3), item('Right', loc4), item('Custom', CustomLoc))), item('Hide/Show', showhide))
        icon=pystray.Icon("name", image, "Battery Viewer", menu)
        icon.run()
    win.protocol('WM_DELETE_WINDOW', hide_window)
    hide_window()
    win.mainloop()
def log(s):
    if GUI_stuff_DEBUG == True:
        print(s)
def Draw():
    global G915
    global G502
    frame=tk.Frame(root,width=100,height=100,relief='solid',bd=0, bg="grey")
    frame.place(x=10,y=10)
    G915=tk.Label(frame,text=CURRENTPERCENTAGES, bg="grey", fg="white")
    G915.pack()
    G502=tk.Label(frame,text=CURRENTPERCENTAGES, bg="grey", fg="white")
    G502.pack()
def Refresher():
    global spacer
    global counter
    global showhidestate
    global hideshow
    global quitmain
    global loc
    global G915
    global G502
    if hideshow == 0:
        log("root.withdraw()")          # Print
        root.withdraw()
        showhidestate = 1
    if hideshow == 1:
        log("root.update()")            # Print
        root.update()
        root.deiconify()
        showhidestate = 0
    if quitmain == True:
        sys.exit()
    def show():
        root.update()
        root.deiconify()
    def hide():
        root.withdraw()
    with open(resource_path('Current_Percentage.txt'), 'r') as filehandle:
        CURRENTPERCENTAGES = json.load(filehandle)
    with open(resource_path('Current_Charge.txt'), 'r') as filehandle:
        CurrentCharge = json.load(filehandle)
    log("CurrentCharge = " + str(CurrentCharge))         # Print
    log("CURRENTPERCENTAGES = " + str(CURRENTPERCENTAGES))           # Print
    charge502 = "    "
    charge915 = "    "
    log(CurrentCharge[0] +" < first item in list")          # Print
    log(CurrentCharge[1] +" < second item in list")         # Print
    if CurrentCharge[0] == "1":
        log("G502: " + charge502 + "ðŸ—²")           # Print
        charge502 = "ðŸ—²"
    if CurrentCharge[1] == "1":
        log("G915: " + charge915 + "ðŸ—²")           # Print
        charge915 = "ðŸ—²"
    if loc == "150x150-1839+999":      # Right Location
        G502.configure(text="G"+CURRENTPERCENTAGES[0] + " :"+ charge502 + CURRENTPERCENTAGES[1] + "%", font=("Segoe UI", 7))
        G915.configure(text="G"+CURRENTPERCENTAGES[-2] + " :"+ charge915 + CURRENTPERCENTAGES[-1] + "%", font=("Segoe UI", 7))
    else:
        if loc == "150x150-3697+999":      # Left Location
            G502.configure(text="G"+CURRENTPERCENTAGES[0] + " :"+ charge502 + CURRENTPERCENTAGES[1] + "%", font=("Segoe UI", 7))
            G915.configure(text="G"+CURRENTPERCENTAGES[-2] + " :"+ charge915 + CURRENTPERCENTAGES[-1] + "%", font=("Segoe UI", 7))
        else:
            if loc == "150x150-1930+1029":      # Bottom Location
                G502.configure(text="G"+CURRENTPERCENTAGES[0] + " :"+ charge502 + CURRENTPERCENTAGES[1] + "%", font=("Segoe UI", 9))
                G915.configure(text="G"+CURRENTPERCENTAGES[-2] + " :"+ charge915 + CURRENTPERCENTAGES[-1] + "%", font=("Segoe UI", 9))
            else:
                if loc == "150x150-1930-941":      # Top Location
                    G502.configure(text="G"+CURRENTPERCENTAGES[0] + " :"+ charge502 + CURRENTPERCENTAGES[1] + "%", font=("Segoe UI", 9))
                    G915.configure(text="G"+CURRENTPERCENTAGES[-2] + " :"+ charge915 + CURRENTPERCENTAGES[-1] + "%", font=("Segoe UI", 9))
    root.geometry(loc) # Sets the size of the window
    counter = counter + 1
    spacer = "                                                                           "      # Used to make the counter stand out in the console, to make it easier to see
    log(spacer + 'Counter: ' + str(counter))           # Print
    root.after(1000, Background_stuff) # every second it reruns the code in the Refresher
Chargestatus = []   # Create list called Chargestatus
Chargestatus.append("0")    # set first item in list to 0
Chargestatus.append("0")    # set second item in list to 0
counter = 0
a_file = str(os.path.expandvars('%LOCALAPPDATA%'))+ "/LGHUB/settings.db"    # Gets the filepath for the Logitech GHub settings which contains the values for the battery percentages
print(a_file)         # Print
percentage = str("percentage")      # Line in a_file containing the word percentage
G502line = str("battery/g502wireless/percentage")       # Line in a_file containing battery/g502wireless/percentage,,, Used to determine which device the following info is in regards to
G915line = str("battery/g915/percentage")       # Line in a_file containing battery/g915/percentage,,, Used to determine which device the following info is in regards to
millivolts = str("millivolts")      # Line in a_file containing the word millivolts
timeline = "time"        # Line in a_file containing the word time
charging = "isCharging"      # Line in a_file containing the word isCharging
listhide = "999"        # Used to replace values in list to make it easier to remove them later
file_path = os.path.realpath(__file__)
file = resource_path('listfile.txt')
Chargestatus[0] = "0"
Chargestatus[1] = "0"
hideshow = 1
showhidestate = 1
quitmain = False
if quitmain == True:
    sys.exit()
loc = "150x150-1930+1029"
Thread(target = Tray_stuff).start()
CURRENTPERCENTAGES = []
root = tk.Tk()
root.title("Logitech GHub Battery Viewer")# Names the Tk root window
root.geometry("150x150-1930+1029") # Sets the size of the window
root.overrideredirect(1) # Removes title bar from window
root.configure(bg='grey') # Makes backgroud fo window grey
root.wm_attributes("-topmost", True) # Makes the window always stay on top
root.wm_attributes("-transparentcolor", "grey") # Makes the window background transparent
with open(resource_path('Current_Percentage.txt'), 'r') as filehandle:
    CURRENTPERCENTAGES = json.load(filehandle)
with open(resource_path('Current_Charge.txt'), 'r') as filehandle:
    CurrentCharge = json.load(filehandle)
Draw()
Refresher()
root.mainloop()


import torch
import torch.nn as nn
import torch.nn.functional as F
import sys
#sys.path.append('../../')
import argparse
import os
from functools import partial
import time
import statistics

from robustbench.utils import clean_accuracy, load_model
import autoattack
try:
    import other_utils
except ImportError:
    from autoattack import other_utils
from utils_tta import load_dataset, eval_fast, get_wc_acc, parse_args
from apgd_tta import apgd_restarts

#

def load_models(modelname, device, modeldir, modeldir_rb):
    if modelname == 'rebuffi_orig':
        model = load_model('Rebuffi2021Fixing_70_16_cutmix_extra',
            model_dir=modeldir_rb)
        model.to(device)
        model.eval()
        return model

    elif modelname == 'rebuffi_sodef':
        from models import create_model
        new_model = create_model(device, modeldir_rb)
        ckpt = torch.load(f'{modeldir}/Rebuffi2021Fixing_70_16_cutmix_extra/full.pth')
        new_model.load_state_dict(ckpt['state_dict'])
        new_model.eval()
        return new_model

    elif modelname == 'trades':
        from wideresnet import WideResNet
        model = WideResNet()
        ckpt = torch.load(f'{modeldir}/EXP/pre_train_model/wide10_trades_eps8_tricks.pt')
        model.load_state_dict(ckpt)
        model.to(device)
        model.eval()
        return model

    elif modelname == 'trades_sodef':
        from models_small import create_model
        model = create_model(device)
        ckpt = torch.load(f'{modeldir}/EXP/nips_model/full.pth')
        model.load_state_dict(ckpt['state_dict'])
        model.eval()
        return model

class ModelWithFeatures(nn.Module):
    """ to use both logits and intermediate features
    """
    def __init__(self, composite_model):
        super().__init__()
        self.composite_model = composite_model

    def forward(self, x, return_fts=False):
        if not return_fts:
            return self.composite_model(x)

        else:
            fts = self.composite_model[0](x)
            out = self.composite_model[1](fts)
            out = self.composite_model[2](out)
            return out, fts

if __name__ == '__main__':
    args = parse_args()
    device = 'cuda'

    if args.eps > 1. and args.norm == 'Linf':
        args.eps /= 255.
    if not args.data_path is None:
        assert os.path.exists(args.data_path)

    x_test, y_test = load_dataset(args.dataset, args.n_ex, device=device,
        data_dir=args.data_dir)
    print('data loaded')

    model = load_models(args.model, device, args.model_dir, args.model_dir_rb)
    print('model loaded')

    logger = other_utils.Logger(None)
    savedir = f'./results/{args.model}'
    other_utils.makedir(savedir)
    logsdir = f'./logs/{args.model}'
    other_utils.makedir(logsdir)
    logger.log_path = f'{logsdir}/stats.txt'

    if args.loss in ['l2', 'l1', 'linf']:
        assert 'sodef' in args.model
        test_model = ModelWithFeatures(model)
        test_model.eval()
    else:
        test_model = model

    runname = f'{args.attack}_1_{args.n_ex}_{args.norm}_eps_{args.eps:.5f}'

    if not args.indices is None:
        notes_run = f'_{args.indices}'
        ind = args.indices.split('-')
        ind_restr = list(range(int(ind[0]), int(ind[1])))
        print(ind_restr)
        sys.stdout.flush()
        x_test, y_test = x_test[ind_restr], y_test[ind_restr]
        runname += notes_run

    if args.attack == 'eval_fast':
        short_version = False #True
        #runname = f'{args.attack}_1_{args.n_ex}'
        runname += f'{"_short" if short_version else ""}'
        #runname += f'_{args.norm}_eps_{args.eps:.5f}'
        x_adv = eval_fast(test_model, x_test, y_test, eps=args.eps,
            savedir=savedir, bs=args.batch_size, short_version=short_version,
            eot_iter=args.eot_test, norm=args.norm,
            log_path=f'{savedir}/{runname}.txt')
        torch.save(x_adv, f'{savedir}/{runname}.pth')

    elif args.attack == 'maxloss':
        runname += f'_niter_{args.n_iter}_loss_{args.loss}'
        x_adv = eval_maxloss(test_model, x_test, y_test, eps=args.eps,
            savedir=savedir, #eot_iter=args.eot_test,
            verbose=True, seed=args.seed, norm=args.norm,
            bs=args.batch_size, loss=args.loss, n_iter=args.n_iter,
            log_path=f'{savedir}/{runname}.txt')
        torch.save(x_adv, f'{savedir}/{runname}.pth')

    elif args.attack == 'eval_with_square':
        runname += f'_niter_{args.n_iter}_loss_{args.loss}'
        runname += f'_nrestarts_{args.n_restarts}'
        x_adv = eval_with_square(test_model, x_test, y_test, eps=args.eps,
            savedir=savedir, #eot_iter=args.eot_test, #verbose=Truer
            seed=args.seed, opt_loss=True, n_restarts=args.n_restarts,
            bs=args.batch_size, loss=args.loss, n_iter=args.n_iter, norm=args.norm,
            log_path=f'{logsdir}/{runname}.txt')
        torch.save(x_adv, f'{savedir}/{runname}.pth')

    elif args.attack in ['interm', 'interm_ge', 'apgd', 'apgd_ge', 'apgd_on_features']:
        runname += f'_niter_{args.n_iter}_loss_{args.loss}' + \
            f'_nrestarts_{args.n_restarts}_init_{args.init}'
        if not args.step_size is None:
            runname += f'_stepsize_{args.step_size:.3f}'
        x_init = None
        n_batches = math.ceil(args.n_ex / args.batch_size)
        x_adv, x_best = x_test.clone(), x_test.clone()
        for c in range(n_batches):
            x_test_curr = x_test[c * args.batch_size:(c + 1) * args.batch_size]
            y_test_curr = y_test[c * args.batch_size:(c + 1) * args.batch_size]
            x_adv_curr, x_best_curr = apgd_restarts(test_model,
                x_test_curr, y_test_curr, n_restarts=args.n_restarts,
                verbose=True, n_iter=args.n_iter, loss=args.loss, eps=args.eps,
                norm=args.norm, log_path=f'{logsdir}/{runname}.txt')
            x_adv[c * args.batch_size:(c + 1) * args.batch_size] = x_adv_curr.clone()
            x_best[c * args.batch_size:(c + 1) * args.batch_size] = x_best_curr.clone()
        torch.save(x_adv, f'{savedir}/{runname}.pth')
        torch.save(x_best, f'{savedir}/{runname}_best.pth')

    elif args.attack == 'test_points':
        if not args.data_path is None:
            runname += f' {args.data_path.split("/")[-1]}'
            x_adv = torch.load(args.data_path)
        else:
            runname += ' clean points'
            x_adv = x_test.clone()
        print(x_adv.shape)

    elif args.attack in 'find_wc':
        xs = [
            # feature attacks
            'apgd_1_1000_Linf_eps_0.03137_niter_100_loss_l1_nrestarts_1_init_None.pth',
            'apgd_1_1000_Linf_eps_0.03137_niter_25_loss_l1_nrestarts_4_init_None.pth',
            #
            # AA on the original model
            'eval_fast_1_1000_Linf_eps_0.03137.pth',
            #
            #'eval_with_square_1_1000_Linf_eps_0.03137_niter_5000_loss_ce_nrestarts_1.pth'
            ]
        xs = [f'./results/rebuffi_sodef/{c}' for c in xs]
        for x in xs:
            assert os.path.exists(x), f'missing {x}'
        xtr = [
            # transfer apgd (points with best loss for unsuccessful cases are used)
            'apgd_1_1000_Linf_eps_0.03137_niter_100_loss_dlr-targeted_nrestarts_9_init_None_best.pth',
            'apgd_1_1000_Linf_eps_0.03137_niter_99_loss_cw_nrestarts_1_init_None_best.pth',
            'apgd_1_1000_Linf_eps_0.03137_niter_99_loss_dlr-targeted_nrestarts_3_init_None_best.pth',
            'apgd_1_1000_Linf_eps_0.03137_niter_99_loss_ce_nrestarts_1_init_None_best.pth',
            ]
        xtr = [c for c in xtr if args.norm in c]
        xtr = [f'./results/rebuffi_orig/{c}' for c in xtr]
        for x in xtr:
            assert os.path.exists(x), f'missing {x}'
        logger.log('\n'.join(xs))
        xs = [torch.load(x).cpu() for x in xs]
        logger.log('\n'.join(xtr))
        xs += [torch.load(x).cpu() for x in xtr]
        xs = xs[::-1]
        for i, x in enumerate(xs):
            other_utils.check_imgs(xs[i].cpu(), x_test.cpu(), args.norm)
        with torch.no_grad():
            acc, x_adv = get_wc_acc(model, xs, y_test,
                bs=args.batch_size, device=device, eot_test=1, logger=logger,
                loss=args.loss)
        #torch.save(x_adv, f'{savedir}/{runname}.pth')

    l_acc = []
    logger.log(runname)
    for c in range(args.eot_test):
        if c == 1:
            startt = time.time() # skip first since it's usually slower
        acc = clean_accuracy(model, x_adv, y_test, device=device,
            batch_size=args.batch_size)

        if c == 0:
            str_imgs = other_utils.check_imgs(x_adv.to(x_test.device), x_test, norm=args.norm)
            logger.log(str_imgs)
        logger.log(f'[{args.model}] robust acc={acc:.1%}')
    try:
        evalt = time.time() - startt
    except:
        evalt = 0.
    logger.log(f'runs={args.eot_test - 1} single run time={evalt / (args.eot_test - 1):.3f} s')
    logger.log('')


import abc
from typing import Any, AsyncIterator, Dict, Iterator, Optional, Tuple, Union

from erniebot.response import EBResponse
from erniebot.types import FilesType, HeadersType, ParamsType, ResponseT

from .protocol import Resource

class Creatable(Resource):
    """Creatable resource."""

    @classmethod
    def create(cls, **kwargs: Any) -> Union[EBResponse, Iterator[EBResponse]]:
        """Create a resource."""
        config = kwargs.pop("_config_", {})
        resource = cls.new_object(**config)
        create_kwargs = kwargs
        return resource.create_resource(**create_kwargs)

    @classmethod
    async def acreate(cls, **kwargs: Any) -> Union[EBResponse, AsyncIterator[EBResponse]]:
        """Asynchronous version of `create`."""
        config = kwargs.pop("_config_", {})
        resource = cls.new_object(**config)
        create_kwargs = kwargs
        resp = await resource.acreate_resource(**create_kwargs)
        return resp

    def create_resource(self, **create_kwargs: Any) -> Union[EBResponse, Iterator[EBResponse]]:
        path, params, headers, files, stream, request_timeout = self._prepare_create(create_kwargs)
        resp = self.request(
            method="POST",
            path=path,
            stream=stream,
            params=params,
            headers=headers,
            files=files,
            request_timeout=request_timeout,
        )
        # See https://github.com/python/mypy/issues/1533
        resp = self._postprocess_create(resp)  # type: ignore
        return resp

    async def acreate_resource(self, **create_kwargs: Any) -> Union[EBResponse, AsyncIterator[EBResponse]]:
        path, params, headers, files, stream, request_timeout = self._prepare_create(create_kwargs)
        resp = await self.arequest(
            method="POST",
            path=path,
            stream=stream,
            params=params,
            headers=headers,
            files=files,
            request_timeout=request_timeout,
        )
        resp = self._postprocess_create(resp)  # type: ignore
        return resp

    @abc.abstractmethod
    def _prepare_create(
        self, kwargs: Dict[str, Any]
    ) -> Tuple[
        str,
        Optional[ParamsType],
        Optional[HeadersType],
        Optional[FilesType],
        bool,
        Optional[float],
    ]:
        ...

    def _postprocess_create(self, resp: ResponseT) -> ResponseT:
        return resp


'''
@author: ANIK
'''

import random
import sys

from AlgebraicExpressionParser import ExpressionParser
from AlgebraicExpressionParser import Operator
from AlgebraicExpressionParser import Operators
from treelib import Tree

binaryOperators = ['A', 'O', 'U', 'R']
unaryOperators = ['G', 'F', '~']

qMat = []
qMat.append([-1])

def addNodeRec(selfID, parentID, selfVar, parentVar, synTree, expTree, qMat, qParent):

    if selfID[0] == 0:

        if expTree[selfID[0]][0] == 'G':

            synTree.create_node('FORALL i_{} \in {}'.format(selfVar[0], expTree[selfID[0]][1:]), selfID[0])

            parentVar = selfVar[0]
            selfVar[0] += 1

            qMat[0].append(0)
            qParent = 0
            qMat.append([0])

        elif expTree[selfID[0]][0] == 'F':

            synTree.create_node('EXISTS i_{} \in {}'.format(selfVar[0], expTree[selfID[0]][1:]), selfID[0])

            parentVar = selfVar[0]
            selfVar[0] += 1

            qMat[0].append(0)
            qParent = 0
            qMat.append([0])

        elif not (expTree[selfID[0]][0] in binaryOperators or expTree[selfID[0]][0] in unaryOperators):

            synTree.create_node('(\sigma, 0) \models {}'.format(expTree[selfID[0]]), selfID[0])

        else:

            synTree.create_node(expTree[selfID[0]], selfID[0])

    else:

        if parentVar == -1:

            if expTree[selfID[0]][0] == 'G':

                synTree.create_node('FORALL i_{} \in {}'.format(selfVar[0], expTree[selfID[0]][1:]), selfID[0], parent = parentID)

                parentVar = selfVar[0]
                selfVar[0] += 1

                qMat[0].append(selfID[0])
                qParent = selfID[0]
                qMat.append([qParent])

            elif expTree[selfID[0]][0] == 'F':

                synTree.create_node('EXISTS i_{} \in {}'.format(selfVar[0], expTree[selfID[0]][1:]), selfID[0], parent = parentID)

                parentVar = selfVar[0]
                selfVar[0] += 1

                qMat[0].append(selfID[0])
                qParent = selfID[0]
                qMat.append([qParent])

            elif not (expTree[selfID[0]][0] in binaryOperators or expTree[selfID[0]][0] in unaryOperators):

                synTree.create_node('(\sigma, 0) \models {}'.format(expTree[selfID[0]]), selfID[0], parent = parentID)

            else:

                synTree.create_node(expTree[selfID[0]], selfID[0], parent = parentID)

        else:

            if expTree[selfID[0]][0] == 'G':

                synTree.create_node('FORALL i_{} \in {} + i_{}{} + i_{}{}'.format(selfVar[0], expTree[selfID[0]][1:expTree[selfID[0]].find(',')], parentVar, expTree[selfID[0]][expTree[selfID[0]].find(','):-1], parentVar, expTree[selfID[0]][-1]), selfID[0], parent = parentID)

                parentVar = selfVar[0]
                selfVar[0] += 1

                for i in range(len(qMat)):

                    if qMat[i][0] == qParent:

                        qMat[i].append(selfID[0])
                        qParent = selfID[0]
                        qMat.append([qParent])

            elif expTree[selfID[0]][0] == 'F':

                synTree.create_node('EXISTS i_{} \in {} + i_{}{} + i_{}{}'.format(selfVar[0], expTree[selfID[0]][1:expTree[selfID[0]].find(',')], parentVar, expTree[selfID[0]][expTree[selfID[0]].find(','):-1], parentVar, expTree[selfID[0]][-1]), selfID[0], parent = parentID)

                parentVar = selfVar[0]
                selfVar[0] += 1

                for i in range(len(qMat)):

                    if qMat[i][0] == qParent:

                        qMat[i].append(selfID[0])
                        qParent = selfID[0]
                        qMat.append([qParent])

            elif not (expTree[selfID[0]][0] in binaryOperators or expTree[selfID[0]][0] in unaryOperators):

                synTree.create_node('(\sigma, i_{}) \models {}'.format(parentVar, expTree[selfID[0]]), selfID[0], parent = parentID)

            else:

                synTree.create_node(expTree[selfID[0]], selfID[0], parent = parentID)

    if expTree[selfID[0]][0] in binaryOperators:

        parentID = selfID[0]

        selfID[0] += 1
        addNodeRec(selfID, parentID, selfVar, parentVar, synTree, expTree, qMat, qParent)

        selfID[0] += 1
        addNodeRec(selfID, parentID, selfVar, parentVar, synTree, expTree, qMat, qParent)

    if expTree[selfID[0]][0] in unaryOperators:

        parentID = selfID[0]

        selfID[0] += 1
        addNodeRec(selfID, parentID, selfVar, parentVar, synTree, expTree, qMat, qParent)

def genSynTree(exp):

    operators = [Operator(symbol = 'AND', precedence = 2),
                Operator(symbol = 'OR', precedence = 2),
                Operator(symbol = 'G[a, b]', type = Operator.unary, precedence = 3, associativity = Operator.rtl, position = Operator.prefix),
                Operator(symbol = 'F[a, b]', type = Operator.unary, precedence = 3, associativity = Operator.rtl, position = Operator.prefix),
                Operator(symbol = 'U[a, b]', precedence = 2),
                Operator(symbol = 'R[a, b]', precedence = 2),
                Operator(symbol = '~', type = Operator.unary, precedence = 3, associativity = Operator.rtl, position = Operator.prefix)]

    for i in range(len(exp)):

        if exp[i] == '[':

            temporalOperator = exp[i - 1:exp[i:].find(']') + 1 + i]
            operators.append(Operator(symbol = temporalOperator, type = Operator.unary, precedence = 3, associativity = Operator.rtl, position = Operator.prefix))

    operators = Operators(operators)
    parser = ExpressionParser(operators)
    expTree = parser.syntax_tree(exp).preorder()

    for i in range(len(expTree)):

        if expTree[i][0] == 'U' or expTree[i][0] == 'R':

            exp = expTree[i]
            expTree.pop(i)
            expTree.insert(i, 'F' + exp[1:])
            expTree.insert(i + 1, 'AND')
            expTree.insert(i + 2, 'G' + exp[1:])

    synTree = Tree()
    selfID = [0]
    selfVar = [0]

    addNodeRec(selfID, 0, selfVar, -1, synTree, expTree, qMat, -1)

    return synTree

def getNodeData(synTree, nodeID):

    return synTree[nodeID].tag

def getNodeInterval(synTree, nodeID):

    tag = synTree.get_node(nodeID).tag
    start = (tag[tag.find('[') + 1: tag.find(',')])
    end = (tag[tag.find(',') + 2: tag.find(']')])

    return start, end

def getSubTree(synTree, nodeID):

    subTree = Tree()

    currentID = '{}'.format(subTree.create_node(synTree.get_node(nodeID).tag, random.randrange(100, 1000000)))
    currentID = int(currentID[currentID.find('identifier=') + 11:currentID.find(', data=')])

    def copyNodeRec(synTree, nodeID, parentID):

        if not synTree.get_node(nodeID).is_leaf():

            childrenList = synTree.children(nodeID)

            for child in childrenList:

                currentID = '{}'.format(child)
                currentID = '{}'.format(subTree.create_node(currentID[currentID.find('tag=') + 4:currentID.find(', identifier=')], random.randrange(100, 1000000), parent = parentID))
                currentID = int(currentID[currentID.find('identifier=') + 11:currentID.find(', data=')])

                nodeID = '{}'.format(child)
                nodeID = int(nodeID[nodeID.find('identifier=') + 11:nodeID.find(', data=')])

                copyNodeRec(synTree, nodeID, currentID)

    copyNodeRec(synTree, nodeID, currentID)

    return subTree

def treePartition(synTree, qMat, nodeID, time):

    if nodeID == -1 and qMat[0][1] == 0:

        newRoot = Tree()
        tag = synTree.get_node(0).tag

        if 'FORALL' in tag:

            rootID = newRoot.create_node('AND', random.randrange(100, 1000000)).identifier

        if 'EXISTS' in tag:

            rootID = newRoot.create_node('OR', random.randrange(100, 1000000)).identifier

        subTreeTwo = getSubTree(synTree, 0)
        newRoot.paste(rootID, subTreeTwo)

        synTree.get_node(0).tag = '{}{})'.format(tag[:tag.find(',') + 2], time)
        subTreeTwo.get_node(subTreeTwo.root).tag = '{}{}{}'.format(tag[:tag.find('[') + 1], time, tag[tag.find(','):])

        for i in range(len(qMat[1]) - 1):

            partNode(synTree, qMat[1][i + 1], time)
            treePartition(synTree, qMat, qMat[1][i + 1], time)

        subTreeOne = getSubTree(synTree, 0)
        newRoot.paste(rootID, subTreeOne)

        synTree = newRoot
        return synTree

    else:

        for j in range(len(qMat)):

            if qMat[j][0] == nodeID and len(qMat[j]) > 1:

                for i in range(len(qMat[j]) - 1):

                    partNode(synTree, qMat[j][i + 1], time)
                    treePartition(synTree, qMat, qMat[j][i + 1], time)

def partNode(synTree, nodeID, time):

    parentID = synTree.parent(nodeID).identifier
    tag = synTree.get_node(nodeID).tag

    if 'FORALL' in tag:

        newParentID = synTree.create_node('AND', random.randrange(100, 1000000), parent = parentID).identifier
        synTree.move_node(nodeID, newParentID)

        subTree = getSubTree(synTree, nodeID)
        subTree.get_node(subTree.root).tag = '{}{}{}'.format(tag[:tag.find('[') + 1], time, tag[tag.find(','):])

        synTree.paste(newParentID, subTree)

        synTree.get_node(nodeID).tag = '{}{})'.format(tag[:tag.find(',') + 2], time)

    if 'EXISTS' in tag:

        newParentID = synTree.create_node('OR', random.randrange(100, 1000000), parent = parentID).identifier
        synTree.move_node(nodeID, newParentID)

        subTree = getSubTree(synTree, nodeID)
        subTree.get_node(subTree.root).tag = '{}{}{}'.format(tag[:tag.find('[') + 1], time, tag[tag.find(','):])

        synTree.paste(newParentID, subTree)

        synTree.get_node(nodeID).tag = '{}{})'.format(tag[:tag.find(',') + 2], time)

def printMatrix(qMat):

    output = "";

    for i in range(len(qMat)):

        for j in range(len(qMat[i])):

            output += "{} ".format(qMat[i][j])

        print(output)
        output = ""

    print()

def main():

    if len(sys.argv) != 3:

        print('Missing or invalid STL formula.')

    else:

        exp = sys.argv[1]
        time = float(sys.argv[2])
        valid = False

        synTree = genSynTree(exp)
        print('SMT syntax tree:\n')
        synTree.show()

        for i in range(len(exp)):

            if exp[i] == '[':

                lower = exp[i + 1:exp[i + 2:].find(',') + i + 2]
                upper = exp[i + len(lower) + 3:exp[i + 4:].find(']') + i + 4]

                if float(lower) < time and time < float(upper):

                    valid = True

        if not valid:

            print('This formula does not require partitioning.')

        else:

            synTree = treePartition(synTree, qMat, -1, time)
            print('SMT syntax tree partitioned at time {}:\n'.format(time))
            synTree.show()

if __name__ == '__main__':

    main()
    pass