From 089ff7ec0171a52c5fb4bc244af4c4eb8c442f60 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Sat, 12 Jun 2021 07:09:26 +0000 Subject: [PATCH] separated gui and cli dev files began refactoring superscript in cli application Former-commit-id: ee309b9f8b6c5317422f1b2593bde027efb7337b --- build/build-CLI.bat | 2 +- build/build-CLI.sh | 2 +- src/cli/cli_interface.py | 44 +++++++ src/{ => cli}/data.py | 0 src/cli/superscript.py | 214 +++++++++++++++++++++++++++++++++ src/{ => cli}/superscript.spec | 0 src/gui/data.py | 129 ++++++++++++++++++++ src/{ => gui}/design.kv | 0 src/{ => gui}/main.py | 0 src/{ => gui}/superscript.py | 0 10 files changed, 389 insertions(+), 2 deletions(-) create mode 100644 src/cli/cli_interface.py rename src/{ => cli}/data.py (100%) create mode 100644 src/cli/superscript.py rename src/{ => cli}/superscript.spec (100%) create mode 100644 src/gui/data.py rename src/{ => gui}/design.kv (100%) rename src/{ => gui}/main.py (100%) rename src/{ => gui}/superscript.py (100%) diff --git a/build/build-CLI.bat b/build/build-CLI.bat index 522e5fc..22dd93c 100644 --- a/build/build-CLI.bat +++ b/build/build-CLI.bat @@ -1,4 +1,4 @@ -set pathtospec="../src/superscript.spec" +set pathtospec="../src/cli/superscript.spec" set pathtodist="../dist/" set pathtowork="temp/" diff --git a/build/build-CLI.sh b/build/build-CLI.sh index 9837f2a..302265b 100644 --- a/build/build-CLI.sh +++ b/build/build-CLI.sh @@ -1,4 +1,4 @@ -pathtospec="../src/superscript.spec" +pathtospec="../src/cli/superscript.spec" pathtodist="../dist/" pathtowork="temp/" diff --git a/src/cli/cli_interface.py b/src/cli/cli_interface.py new file mode 100644 index 0000000..9fd5765 --- /dev/null +++ b/src/cli/cli_interface.py @@ -0,0 +1,44 @@ +import sys +import time +from os import system, name +import platform + +empty_delim = " " +hard_divided_delim = "|" +soft_divided_delim = ":" +l_brack = "[" +r_brack = "]" + +ERR = "[ERR]" +INF = "[INF]" + +stdout = sys.stdout +stderr = sys.stderr + +def log(target, level, message, code = 0): + + message = time.ctime() + empty_delim + str(level) + l_brack + str(code) + r_brack + empty_delim + soft_divided_delim + empty_delim + message + print(message, file = target) + +def clear(): + if name == "nt": + system("cls") + else: + system("clear") + +def splash(version): + + def hrule(): + print("#"+38*"-"+"#") + def box(s): + temp = "|" + temp += s + temp += (40-len(s)-2)*" " + temp += "|" + print(temp) + + hrule() + box(" superscript version: " + version) + box(" os: " + platform.system()) + box(" python: " + platform.python_version()) + hrule() \ No newline at end of file diff --git a/src/data.py b/src/cli/data.py similarity index 100% rename from src/data.py rename to src/cli/data.py diff --git a/src/cli/superscript.py b/src/cli/superscript.py new file mode 100644 index 0000000..dfd0151 --- /dev/null +++ b/src/cli/superscript.py @@ -0,0 +1,214 @@ +# Titan Robotics Team 2022: Superscript Script +# Written by Arthur Lu, Jacob Levine, and Dev Singh +# Notes: +# setup: + +__version__ = "0.8.6" + +# changelog should be viewed using print(analysis.__changelog__) +__changelog__ = """changelog: + 0.8.6: + - added proper main function + 0.8.5: + - added more gradeful KeyboardInterrupt exiting + - redirected stderr to errorlog.txt + 0.8.4: + - added better error message for missing config.json + - added automatic config.json creation + - added splash text with version and system info + 0.8.3: + - updated matchloop with new regression format (requires tra_analysis 3.x) + 0.8.2: + - readded while true to main function + - added more thread config options + 0.8.1: + - optimized matchloop further by bypassing GIL + 0.8.0: + - added multithreading to matchloop + - tweaked user log + 0.7.0: + - finished implementing main function + 0.6.2: + - integrated get_team_rankings.py as get_team_metrics() function + - integrated visualize_pit.py as graph_pit_histogram() function + 0.6.1: + - bug fixes with analysis.Metric() calls + - modified metric functions to use config.json defined default values + 0.6.0: + - removed main function + - changed load_config function + - added save_config function + - added load_match function + - renamed simpleloop to matchloop + - moved simplestats function inside matchloop + - renamed load_metrics to load_metric + - renamed metricsloop to metricloop + - split push to database functions amon push_match, push_metric, push_pit + - moved + 0.5.2: + - made changes due to refactoring of analysis + 0.5.1: + - text fixes + - removed matplotlib requirement + 0.5.0: + - improved user interface + 0.4.2: + - removed unessasary code + 0.4.1: + - fixed bug where X range for regression was determined before sanitization + - better sanitized data + 0.4.0: + - fixed spelling issue in __changelog__ + - addressed nan bug in regression + - fixed errors on line 335 with metrics calling incorrect key "glicko2" + - fixed errors in metrics computing + 0.3.0: + - added analysis to pit data + 0.2.1: + - minor stability patches + - implemented db syncing for timestamps + - fixed bugs + 0.2.0: + - finalized testing and small fixes + 0.1.4: + - finished metrics implement, trueskill is bugged + 0.1.3: + - working + 0.1.2: + - started implement of metrics + 0.1.1: + - cleaned up imports + 0.1.0: + - tested working, can push to database + 0.0.9: + - tested working + - prints out stats for the time being, will push to database later + 0.0.8: + - added data import + - removed tba import + - finished main method + 0.0.7: + - added load_config + - optimized simpleloop for readibility + - added __all__ entries + - added simplestats engine + - pending testing + 0.0.6: + - fixes + 0.0.5: + - imported pickle + - created custom database object + 0.0.4: + - fixed simpleloop to actually return a vector + 0.0.3: + - added metricsloop which is unfinished + 0.0.2: + - added simpleloop which is untested until data is provided + 0.0.1: + - created script + - added analysis, numba, numpy imports +""" + +__author__ = ( + "Arthur Lu ", + "Jacob Levine ", +) + +__all__ = [ + "load_config", + "save_config", + "get_previous_time", + "load_match", + "matchloop", + "load_metric", + "metricloop", + "load_pit", + "pitloop", + "push_match", + "push_metric", + "push_pit", +] + +# imports: + +import json + +from cli_interface import splash, log, ERR, INF, stdout, stderr + +config_path = "config.json" +sample_json = """{ + "max-threads": 0.5, + "team": "", + "competition": "2020ilch", + "key":{ + "database":"", + "tba":"" + }, + "statistics":{ + "match":{ + "balls-blocked":["basic_stats","historical_analysis","regression_linear","regression_logarithmic","regression_exponential","regression_polynomial","regression_sigmoidal"], + "balls-collected":["basic_stats","historical_analysis","regression_linear","regression_logarithmic","regression_exponential","regression_polynomial","regression_sigmoidal"], + "balls-lower-teleop":["basic_stats","historical_analysis","regression_linear","regression_logarithmic","regression_exponential","regression_polynomial","regression_sigmoidal"], + "balls-lower-auto":["basic_stats","historical_analysis","regression_linear","regression_logarithmic","regression_exponential","regression_polynomial","regression_sigmoidal"], + "balls-started":["basic_stats","historical_analyss","regression_linear","regression_logarithmic","regression_exponential","regression_polynomial","regression_sigmoidal"], + "balls-upper-teleop":["basic_stats","historical_analysis","regression_linear","regression_logarithmic","regression_exponential","regression_polynomial","regression_sigmoidal"], + "balls-upper-auto":["basic_stats","historical_analysis","regression_linear","regression_logarithmic","regression_exponential","regression_polynomial","regression_sigmoidal"] + + }, + "metric":{ + "elo":{ + "score":1500, + "N":400, + "K":24 + }, + "gl2":{ + "score":1500, + "rd":250, + "vol":0.06 + }, + "ts":{ + "mu":25, + "sigma":8.33 + } + }, + "pit":{ + "wheel-mechanism":true, + "low-balls":true, + "high-balls":true, + "wheel-success":true, + "strategic-focus":true, + "climb-mechanism":true, + "attitude":true + } + } +}""" + +def main(): + + splash(__version__) + +def load_config(config_vector): + try: + f = open(path, "r") + except: + log(stderr, ERR, "could not find config at <" + path + ">, generating blank config and exiting") + f = open(path, "w") + f.write(sample_json) + f.close() + return 1 + + config_vector = json.load(f) + f.close() + return 0 + +def save_config(path, config_vector): + try: + f = open(path) + json.dump(config_vector) + f.close() + return 0 + except: + return 1 + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/superscript.spec b/src/cli/superscript.spec similarity index 100% rename from src/superscript.spec rename to src/cli/superscript.spec diff --git a/src/gui/data.py b/src/gui/data.py new file mode 100644 index 0000000..641aba7 --- /dev/null +++ b/src/gui/data.py @@ -0,0 +1,129 @@ +import requests +import pymongo +import pandas as pd +import time + +def pull_new_tba_matches(apikey, competition, cutoff): + api_key= apikey + x=requests.get("https://www.thebluealliance.com/api/v3/event/"+competition+"/matches/simple", headers={"X-TBA-Auth_Key":api_key}) + out = [] + for i in x.json(): + if i["actual_time"] != None and i["actual_time"]-cutoff >= 0 and i["comp_level"] == "qm": + out.append({"match" : i['match_number'], "blue" : list(map(lambda x: int(x[3:]), i['alliances']['blue']['team_keys'])), "red" : list(map(lambda x: int(x[3:]), i['alliances']['red']['team_keys'])), "winner": i["winning_alliance"]}) + return out + +def get_team_match_data(apikey, competition, team_num): + client = pymongo.MongoClient(apikey) + db = client.data_scouting + mdata = db.matchdata + out = {} + for i in mdata.find({"competition" : competition, "team_scouted": team_num}): + out[i['match']] = i['data'] + return pd.DataFrame(out) + +def get_team_pit_data(apikey, competition, team_num): + client = pymongo.MongoClient(apikey) + db = client.data_scouting + mdata = db.pitdata + out = {} + return mdata.find_one({"competition" : competition, "team_scouted": team_num})["data"] + +def get_team_metrics_data(apikey, competition, team_num): + client = pymongo.MongoClient(apikey) + db = client.data_processing + mdata = db.team_metrics + return mdata.find_one({"competition" : competition, "team": team_num}) + +def get_match_data_formatted(apikey, competition): + client = pymongo.MongoClient(apikey) + db = client.data_scouting + mdata = db.teamlist + x=mdata.find_one({"competition":competition}) + out = {} + for i in x: + try: + out[int(i)] = unkeyify_2l(get_team_match_data(apikey, competition, int(i)).transpose().to_dict()) + except: + pass + return out + +def get_metrics_data_formatted(apikey, competition): + client = pymongo.MongoClient(apikey) + db = client.data_scouting + mdata = db.teamlist + x=mdata.find_one({"competition":competition}) + out = {} + for i in x: + try: + out[int(i)] = d.get_team_metrics_data(apikey, competition, int(i)) + except: + pass + return out + +def get_pit_data_formatted(apikey, competition): + client = pymongo.MongoClient(apikey) + db = client.data_scouting + mdata = db.teamlist + x=mdata.find_one({"competition":competition}) + out = {} + for i in x: + try: + out[int(i)] = get_team_pit_data(apikey, competition, int(i)) + except: + pass + return out + +def get_pit_variable_data(apikey, competition): + client = pymongo.MongoClient(apikey) + db = client.data_processing + mdata = db.team_pit + out = {} + return mdata.find() + +def get_pit_variable_formatted(apikey, competition): + temp = get_pit_variable_data(apikey, competition) + out = {} + for i in temp: + out[i["variable"]] = i["data"] + return out + +def push_team_tests_data(apikey, competition, team_num, data, dbname = "data_processing", colname = "team_tests"): + client = pymongo.MongoClient(apikey) + db = client[dbname] + mdata = db[colname] + mdata.replace_one({"competition" : competition, "team": team_num}, {"_id": competition+str(team_num)+"am", "competition" : competition, "team" : team_num, "data" : data}, True) + +def push_team_metrics_data(apikey, competition, team_num, data, dbname = "data_processing", colname = "team_metrics"): + client = pymongo.MongoClient(apikey) + db = client[dbname] + mdata = db[colname] + mdata.replace_one({"competition" : competition, "team": team_num}, {"_id": competition+str(team_num)+"am", "competition" : competition, "team" : team_num, "metrics" : data}, True) + +def push_team_pit_data(apikey, competition, variable, data, dbname = "data_processing", colname = "team_pit"): + client = pymongo.MongoClient(apikey) + db = client[dbname] + mdata = db[colname] + mdata.replace_one({"competition" : competition, "variable": variable}, {"competition" : competition, "variable" : variable, "data" : data}, True) + +def get_analysis_flags(apikey, flag): + client = pymongo.MongoClient(apikey) + db = client.data_processing + mdata = db.flags + return mdata.find_one({flag:{"$exists":True}}) + +def set_analysis_flags(apikey, flag, data): + client = pymongo.MongoClient(apikey) + db = client.data_processing + mdata = db.flags + return mdata.replace_one({flag:{"$exists":True}}, data, True) + +def unkeyify_2l(layered_dict): + out = {} + for i in layered_dict.keys(): + add = [] + sortkey = [] + for j in layered_dict[i].keys(): + add.append([j,layered_dict[i][j]]) + add.sort(key = lambda x: x[0]) + out[i] = list(map(lambda x: x[1], add)) + return out \ No newline at end of file diff --git a/src/design.kv b/src/gui/design.kv similarity index 100% rename from src/design.kv rename to src/gui/design.kv diff --git a/src/main.py b/src/gui/main.py similarity index 100% rename from src/main.py rename to src/gui/main.py diff --git a/src/superscript.py b/src/gui/superscript.py similarity index 100% rename from src/superscript.py rename to src/gui/superscript.py