From 4a1d7f0db1a0ddf7790ee94868ceeaf1c273d315 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 20:05:07 +0000 Subject: [PATCH 01/18] removed keys Signed-off-by: Arthur Lu --- src/cli/module.py | 44 ++++++++++++++++++++++ src/cli/superscript.py | 4 +- src/cli/testing.ipynb | 83 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/cli/module.py create mode 100644 src/cli/testing.ipynb diff --git a/src/cli/module.py b/src/cli/module.py new file mode 100644 index 0000000..8f0e6d6 --- /dev/null +++ b/src/cli/module.py @@ -0,0 +1,44 @@ +import data as d +class Module: + config = None + data = None + results = None + def __init__(self, config, apikey, tbakey, timestamp): + pass + def validate_config(self): + pass + def load_data(self): + pass + def process_data(self, exec_threads): + pass + def push_results(self): + pass + +class Match: + config = None + apikey = None + tbakey = None + timestamp = None + teams = None + + data = None + results = None + + def __init__(self, config, apikey, tbakey, timestamp, teams): + self.config = config + self.apikey = apikey + self.tbakey = tbakey + self.timestamp = timestamp + self.teams = teams + + def validate_config(self): + return True + + def load_data(self): + pass + + def process_data(self, exec_threads): + pass + + def push_results(self): + pass \ No newline at end of file diff --git a/src/cli/superscript.py b/src/cli/superscript.py index 70f497f..0a139c8 100644 --- a/src/cli/superscript.py +++ b/src/cli/superscript.py @@ -170,8 +170,8 @@ config_path = "config.json" sample_json = """{ "persistent":{ "key":{ - "database":"mongodb+srv://analysis:MU2gPeEjEurRt2n@2022-scouting-4vfuu.mongodb.net/?retryWrites=true&w=majority", - "tba":"UDvKmPjPRfwwUdDX1JxbmkyecYBJhCtXeyVk9vmO2i7K0Zn4wqQPMfzuEINXJ7e5" + "database":"", + "tba":"" }, "config-preference":"local", "synchronize-config":false diff --git a/src/cli/testing.ipynb b/src/cli/testing.ipynb new file mode 100644 index 0000000..83cbfa6 --- /dev/null +++ b/src/cli/testing.ipynb @@ -0,0 +1,83 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "class C1:\n", + "\tval = 0\n", + "\tdef __init__(self, i):\n", + "\t\tself.val = i\n", + "\n", + "class C2:\n", + "\tval = 0\n", + "\tdef __init__(self, i):\n", + "\t\tself.val = 2*i\n", + "\n", + "class C3:\n", + "\tval = 0\n", + "\tdef __init__(self, i):\n", + "\t\tself.val = 3*i" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[<__main__.C1 at 0x7fa84827afd0>,\n", + " <__main__.C2 at 0x7fa84827ae80>,\n", + " <__main__.C3 at 0x7fa8482020d0>]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "classes = [C1, C2, C3]\n", + "initialized = []\n", + "for c in classes:\n", + "\tinitialized.append(c(10))\n", + "initialized" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "interpreter": { + "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a" + }, + "kernelspec": { + "display_name": "Python 3.8.5 64-bit", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.5" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} From b9e2de2dc673987ac514cc019196522017a3ba2e Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 20:28:29 +0000 Subject: [PATCH 02/18] added working validate_config for Match module Signed-off-by: Arthur Lu --- src/cli/module.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/cli/module.py b/src/cli/module.py index 8f0e6d6..e1ed08d 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -32,7 +32,18 @@ class Match: self.teams = teams def validate_config(self): - return True + if self.config == None: + return "config cannot be empty" + elif self.apikey == None or self.apikey == "": + return "apikey cannot be empty" + elif self.tbakey == None or self.tbakey == "": + return "tbakey cannot be empty" + elif not(self.config["scope"] in ["competition", "season", "none"]): + return "scope must be one of: (competition, season, none)" + elif not(self.config["agglomeration"] in ["none", "mean"]): + return "agglomeration must be one of: (none, mean)" + else: + return None def load_data(self): pass From 8e8c19c5fd279a6a32e8379652edc5f00d36c3d7 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 20:42:47 +0000 Subject: [PATCH 03/18] added working load_data for Match module Signed-off-by: Arthur Lu --- src/cli/module.py | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/cli/module.py b/src/cli/module.py index e1ed08d..518ebf7 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -1,4 +1,13 @@ import data as d + +class AutoVivification(dict): + def __getitem__(self, item): + try: + return dict.__getitem__(self, item) + except KeyError: + value = self[item] = type(self)() + return value + class Module: config = None data = None @@ -21,8 +30,7 @@ class Match: timestamp = None teams = None - data = None - results = None + data = [] def __init__(self, config, apikey, tbakey, timestamp, teams): self.config = config @@ -32,21 +40,30 @@ class Match: self.teams = teams def validate_config(self): + return True, "" + """ if self.config == None: - return "config cannot be empty" + return False, "config cannot be empty" elif self.apikey == None or self.apikey == "": - return "apikey cannot be empty" + return False, "apikey cannot be empty" elif self.tbakey == None or self.tbakey == "": - return "tbakey cannot be empty" + return False, "tbakey cannot be empty" elif not(self.config["scope"] in ["competition", "season", "none"]): - return "scope must be one of: (competition, season, none)" + return False, "scope must be one of: (competition, season, none)" elif not(self.config["agglomeration"] in ["none", "mean"]): - return "agglomeration must be one of: (none, mean)" + return False, "agglomeration must be one of: (none, mean)" else: - return None + return True, "" + """ def load_data(self): - pass + scope = self.config["scope"] + for team in self.teams: + competitions = d.get_team_conpetitions(self.apikey, team, scope) # unimplemented + for competition in competitions: + for variable in self.config["tests"]: + match_data = d.get_team_match_data(self.apikey, competition, team) # needs modified implementation + self.data.append((team, competition, variable, match_data)) def process_data(self, exec_threads): pass From 72a14bfac9a02e342eaa7091cd98abfb9a118aec Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 20:56:06 +0000 Subject: [PATCH 04/18] minor fix Signed-off-by: Arthur Lu --- src/cli/module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/module.py b/src/cli/module.py index 518ebf7..6fdfb2e 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -62,7 +62,7 @@ class Match: competitions = d.get_team_conpetitions(self.apikey, team, scope) # unimplemented for competition in competitions: for variable in self.config["tests"]: - match_data = d.get_team_match_data(self.apikey, competition, team) # needs modified implementation + match_data = d.get_team_match_data(self.apikey, competition, team, variable) # needs modified implementation self.data.append((team, competition, variable, match_data)) def process_data(self, exec_threads): From d5ebb0348bec81a3c7ce0a908c2ca5eb7ea57fd5 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 21:27:35 +0000 Subject: [PATCH 05/18] finished rough outline for Match module Signed-off-by: Arthur Lu --- src/cli/module.py | 53 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/src/cli/module.py b/src/cli/module.py index 6fdfb2e..e9d85a7 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -1,4 +1,7 @@ import data as d +import signal +import numpy as np +import tra_analysis as an class AutoVivification(dict): def __getitem__(self, item): @@ -31,6 +34,7 @@ class Match: teams = None data = [] + results = [] def __init__(self, config, apikey, tbakey, timestamp, teams): self.config = config @@ -63,10 +67,53 @@ class Match: for competition in competitions: for variable in self.config["tests"]: match_data = d.get_team_match_data(self.apikey, competition, team, variable) # needs modified implementation - self.data.append((team, competition, variable, match_data)) + variable_tests = self.config["tests"][variable] + self.data.append({"team": team, "competition": competition, "variable": variable, "tests": variable_tests, "data": match_data}) + + def tests(test_data): + signal.signal(signal.SIGINT, signal.SIG_IGN) + + if(test_data["data"] == None): + return None + + data = np.array(test_data["data"]) + data = data[np.isfinite(data)] + ranges = list(range(len(data))) + + tests = test_data["tests"] + + results = AutoVivification() + + if "basic_stats" in tests: + results["basic_stats"] = an.basic_stats(data) + if "historical_analysis" in tests: + results["historical_analysis"] = an.histo_analysis([ranges, data]) + if "regression_linear" in tests: + results["regression_linear"] = an.regression(ranges, data, ['lin']) + if "regression_logarithmic" in tests: + results["regression_logarithmic"] = an.regression(ranges, data, ['log']) + if "regression_exponential" in tests: + results["regression_exponential"] = an.regression(ranges, data, ['exp']) + if "regression_polynomial" in tests: + results["regression_polynomial"] = an.regression(ranges, data, ['ply']) + if "regression_sigmoidal" in tests: + results["regression_sigmoidal"] = an.regression(ranges, data, ['sig']) + + return results def process_data(self, exec_threads): - pass + self.results = list(exec_threads.map(self.tests, self.data)) def push_results(self): - pass \ No newline at end of file + short_mapping = {"regression_linear": "lin", "regression_logarithmic": "log", "regression_exponential": "exp", "regression_polynomial": "ply", "regression_sigmoidal": "sig"} + results_short = AutoVivification() + i = 0 + for result in self.results: + for variable in result: + if variable in short_mapping: + short = short_mapping[variable] + else: + short = variable + d.push_team_match_results(self.data[i]["team"], self.data[i]["competition"], self.data[i]["variable"], short, result[variable]) + #results_short[ self.data["team"] ][ self.data["competition"] ][ self.data["variable"] ][short] = result[variable] + i+=1 \ No newline at end of file From f40939d69d0c1441cd1b2867e51481af19bf88e9 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 21:29:44 +0000 Subject: [PATCH 06/18] removed autovivification (likely not required) Signed-off-by: Arthur Lu --- src/cli/module.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/cli/module.py b/src/cli/module.py index e9d85a7..2910daa 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -3,14 +3,6 @@ import signal import numpy as np import tra_analysis as an -class AutoVivification(dict): - def __getitem__(self, item): - try: - return dict.__getitem__(self, item) - except KeyError: - value = self[item] = type(self)() - return value - class Module: config = None data = None @@ -82,7 +74,7 @@ class Match: tests = test_data["tests"] - results = AutoVivification() + results = {} if "basic_stats" in tests: results["basic_stats"] = an.basic_stats(data) @@ -106,7 +98,6 @@ class Match: def push_results(self): short_mapping = {"regression_linear": "lin", "regression_logarithmic": "log", "regression_exponential": "exp", "regression_polynomial": "ply", "regression_sigmoidal": "sig"} - results_short = AutoVivification() i = 0 for result in self.results: for variable in result: @@ -114,6 +105,5 @@ class Match: short = short_mapping[variable] else: short = variable - d.push_team_match_results(self.data[i]["team"], self.data[i]["competition"], self.data[i]["variable"], short, result[variable]) - #results_short[ self.data["team"] ][ self.data["competition"] ][ self.data["variable"] ][short] = result[variable] + d.push_team_match_results(self.data[i]["team"], self.data[i]["competition"], self.data[i]["variable"], short, result[variable]) # needs implementation i+=1 \ No newline at end of file From de81a03e3da925bbcdc4e3691be95c4d0b772e80 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 21:51:14 +0000 Subject: [PATCH 07/18] modified config validation for Match module Signed-off-by: Arthur Lu --- src/cli/module.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cli/module.py b/src/cli/module.py index 2910daa..555c12b 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -36,7 +36,6 @@ class Match: self.teams = teams def validate_config(self): - return True, "" """ if self.config == None: return False, "config cannot be empty" @@ -46,8 +45,10 @@ class Match: return False, "tbakey cannot be empty" elif not(self.config["scope"] in ["competition", "season", "none"]): return False, "scope must be one of: (competition, season, none)" - elif not(self.config["agglomeration"] in ["none", "mean"]): - return False, "agglomeration must be one of: (none, mean)" + elif self.config["agglomeration"] != "none": + return False, "agglomeration must be 'none', there are currently no supported Agglomeration methods" + elif self.config["tests"] == None: + return False, "tests must not be None, it may be empty {}" else: return True, "" """ From d16fe61a79601e70e0b1fd2134f31c5310e16207 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 21:56:44 +0000 Subject: [PATCH 08/18] added sample initializaition loop Signed-off-by: Arthur Lu --- src/cli/testing.ipynb | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/cli/testing.ipynb b/src/cli/testing.ipynb index 83cbfa6..904b8ac 100644 --- a/src/cli/testing.ipynb +++ b/src/cli/testing.ipynb @@ -48,6 +48,39 @@ "initialized" ] }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import module\n", + "module_references = {\"match\": module.Match}\n", + "module_initialized = []\n", + "for m in [\"match\"]:\n", + "\tmodule_initialized.append(module_references[m](\"\", \"\", \"\", 0, []))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "module_initialized" + ] + }, { "cell_type": "code", "execution_count": null, From 7f0d3fc7539314521b2a0d1c714bd5234fb20e21 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 21:58:02 +0000 Subject: [PATCH 09/18] minor fix Signed-off-by: Arthur Lu --- src/cli/module.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cli/module.py b/src/cli/module.py index 555c12b..e394167 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -36,6 +36,7 @@ class Match: self.teams = teams def validate_config(self): + return True, "" """ if self.config == None: return False, "config cannot be empty" From 8966900341508677b1b78d0ac3bd6b1ae6eae9c2 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 21 Oct 2021 22:33:26 +0000 Subject: [PATCH 10/18] changed sample json --- src/cli/superscript.py | 80 +++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/src/cli/superscript.py b/src/cli/superscript.py index 0a139c8..56d484c 100644 --- a/src/cli/superscript.py +++ b/src/cli/superscript.py @@ -177,48 +177,64 @@ sample_json = """{ "synchronize-config":false }, "variable":{ + "max-threads":0.5, + + "competition":"", "team":"", - "competition": "2020ilch", - "statistics":{ + + "event-delay":false, + "loop-delay":0, + "reportable":true, + + "teams":[], + + "modules":{ + "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"] + "tests":{ + "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 + "tests":{ + "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 + "tests":{ + "wheel-mechanism":true, + "low-balls":true, + "high-balls":true, + "wheel-success":true, + "strategic-focus":true, + "climb-mechanism":true, + "attitude":true + } } - }, - "event-delay":false, - "loop-delay":60 + } } }""" From afab67f8ef21ca066576eed5f1b1c5feb3fb2c2f Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 22 Oct 2021 01:40:56 +0000 Subject: [PATCH 11/18] changed Match module to use current data bindings Signed-off-by: Arthur Lu --- src/cli/module.py | 133 ++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 58 deletions(-) diff --git a/src/cli/module.py b/src/cli/module.py index e394167..4021989 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -23,89 +23,106 @@ class Match: apikey = None tbakey = None timestamp = None - teams = None + competition = None data = [] results = [] - def __init__(self, config, apikey, tbakey, timestamp, teams): + def __init__(self, config, apikey, tbakey, timestamp, competition): self.config = config self.apikey = apikey self.tbakey = tbakey self.timestamp = timestamp - self.teams = teams + self.competition = competition def validate_config(self): return True, "" - """ - if self.config == None: - return False, "config cannot be empty" - elif self.apikey == None or self.apikey == "": - return False, "apikey cannot be empty" - elif self.tbakey == None or self.tbakey == "": - return False, "tbakey cannot be empty" - elif not(self.config["scope"] in ["competition", "season", "none"]): - return False, "scope must be one of: (competition, season, none)" - elif self.config["agglomeration"] != "none": - return False, "agglomeration must be 'none', there are currently no supported Agglomeration methods" - elif self.config["tests"] == None: - return False, "tests must not be None, it may be empty {}" - else: - return True, "" - """ def load_data(self): - scope = self.config["scope"] - for team in self.teams: - competitions = d.get_team_conpetitions(self.apikey, team, scope) # unimplemented - for competition in competitions: - for variable in self.config["tests"]: - match_data = d.get_team_match_data(self.apikey, competition, team, variable) # needs modified implementation - variable_tests = self.config["tests"][variable] - self.data.append({"team": team, "competition": competition, "variable": variable, "tests": variable_tests, "data": match_data}) + self.data = d.load_match(self.apikey, self.competition) + + def simplestats(data_test): - def tests(test_data): signal.signal(signal.SIGINT, signal.SIG_IGN) - if(test_data["data"] == None): - return None - - data = np.array(test_data["data"]) + data = np.array(data_test[3]) data = data[np.isfinite(data)] ranges = list(range(len(data))) - tests = test_data["tests"] + test = data_test[2] - results = {} + if test == "basic_stats": + return an.basic_stats(data) - if "basic_stats" in tests: - results["basic_stats"] = an.basic_stats(data) - if "historical_analysis" in tests: - results["historical_analysis"] = an.histo_analysis([ranges, data]) - if "regression_linear" in tests: - results["regression_linear"] = an.regression(ranges, data, ['lin']) - if "regression_logarithmic" in tests: - results["regression_logarithmic"] = an.regression(ranges, data, ['log']) - if "regression_exponential" in tests: - results["regression_exponential"] = an.regression(ranges, data, ['exp']) - if "regression_polynomial" in tests: - results["regression_polynomial"] = an.regression(ranges, data, ['ply']) - if "regression_sigmoidal" in tests: - results["regression_sigmoidal"] = an.regression(ranges, data, ['sig']) + if test == "historical_analysis": + return an.histo_analysis([ranges, data]) - return results + if test == "regression_linear": + return an.regression(ranges, data, ['lin']) + + if test == "regression_logarithmic": + return an.regression(ranges, data, ['log']) + + if test == "regression_exponential": + return an.regression(ranges, data, ['exp']) + + if test == "regression_polynomial": + return an.regression(ranges, data, ['ply']) + + if test == "regression_sigmoidal": + return an.regression(ranges, data, ['sig']) def process_data(self, exec_threads): - self.results = list(exec_threads.map(self.tests, self.data)) + + tests = self.config["tests"] + data = self.data + + input_vector = [] + + for team in data: + + for variable in data[team]: + + if variable in tests: + + for test in tests[variable]: + + input_vector.append((team, variable, test, data[team][variable])) + + self.data = input_vector + self.results = list(exec_threads.map(self.simplestats, self.data)) def push_results(self): + short_mapping = {"regression_linear": "lin", "regression_logarithmic": "log", "regression_exponential": "exp", "regression_polynomial": "ply", "regression_sigmoidal": "sig"} + + class AutoVivification(dict): + def __getitem__(self, item): + try: + return dict.__getitem__(self, item) + except KeyError: + value = self[item] = type(self)() + return value + + result_filtered = self.results + input_vector = self.data + + return_vector = AutoVivification() + i = 0 - for result in self.results: - for variable in result: - if variable in short_mapping: - short = short_mapping[variable] - else: - short = variable - d.push_team_match_results(self.data[i]["team"], self.data[i]["competition"], self.data[i]["variable"], short, result[variable]) # needs implementation - i+=1 \ No newline at end of file + + for result in result_filtered: + + filtered = input_vector[i][2] + + try: + short = short_mapping[filtered] + return_vector[input_vector[i][0]][input_vector[i][1]][input_vector[i][2]] = result[short] + except KeyError: # not in mapping + return_vector[input_vector[i][0]][input_vector[i][1]][input_vector[i][2]] = result + + i += 1 + + self.results = return_vector + + d.push_match(self.apikey, self.competition, self.results) \ No newline at end of file From 3ac4e96d2dd63cc0c2061a78e6e15e26a4538e8d Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 28 Oct 2021 20:13:57 +0000 Subject: [PATCH 12/18] added Metric, Pit modules (theoretically working) Signed-off-by: Arthur Lu --- src/cli/module.py | 165 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 3 deletions(-) diff --git a/src/cli/module.py b/src/cli/module.py index 4021989..5d0fcbf 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -19,14 +19,15 @@ class Module: pass class Match: + config = None apikey = None tbakey = None timestamp = None competition = None - data = [] - results = [] + data = None + results = None def __init__(self, config, apikey, tbakey, timestamp, competition): self.config = config @@ -125,4 +126,162 @@ class Match: self.results = return_vector - d.push_match(self.apikey, self.competition, self.results) \ No newline at end of file + d.push_match(self.apikey, self.competition, self.results) + +class Metric: + + config = None + apikey = None + tbakey = None + timestamp = None + competition = None + + data = None + results = None + + def __init__(self, config, apikey, tbakey, timestamp, competition): + self.config = config + self.apikey = apikey + self.tbakey = tbakey + self.timestamp = timestamp + self.competition = competition + + def validate_config(self): + return True, "" + + def load_data(self): + self.data = d.pull_new_tba_matches(self.apikey, self.competition, self.timestamp) + + def process_data(self, exec_threads): + + elo_N = self.config["elo"]["N"] + elo_K = self.config["elo"]["K"] + + matches = self.data + + red = {} + blu = {} + + for match in matches: + + red = d.load_metric(self.apikey, self.competition, match, "red", self.config) + blu = d.load_metric(self.apikey, self.competition, match, "blue", self.config) + + elo_red_total = 0 + elo_blu_total = 0 + + gl2_red_score_total = 0 + gl2_blu_score_total = 0 + + gl2_red_rd_total = 0 + gl2_blu_rd_total = 0 + + gl2_red_vol_total = 0 + gl2_blu_vol_total = 0 + + for team in red: + + elo_red_total += red[team]["elo"]["score"] + + gl2_red_score_total += red[team]["gl2"]["score"] + gl2_red_rd_total += red[team]["gl2"]["rd"] + gl2_red_vol_total += red[team]["gl2"]["vol"] + + for team in blu: + + elo_blu_total += blu[team]["elo"]["score"] + + gl2_blu_score_total += blu[team]["gl2"]["score"] + gl2_blu_rd_total += blu[team]["gl2"]["rd"] + gl2_blu_vol_total += blu[team]["gl2"]["vol"] + + red_elo = {"score": elo_red_total / len(red)} + blu_elo = {"score": elo_blu_total / len(blu)} + + red_gl2 = {"score": gl2_red_score_total / len(red), "rd": gl2_red_rd_total / len(red), "vol": gl2_red_vol_total / len(red)} + blu_gl2 = {"score": gl2_blu_score_total / len(blu), "rd": gl2_blu_rd_total / len(blu), "vol": gl2_blu_vol_total / len(blu)} + + + if match["winner"] == "red": + + observations = {"red": 1, "blu": 0} + + elif match["winner"] == "blue": + + observations = {"red": 0, "blu": 1} + + else: + + observations = {"red": 0.5, "blu": 0.5} + + red_elo_delta = an.Metric().elo(red_elo["score"], blu_elo["score"], observations["red"], elo_N, elo_K) - red_elo["score"] + blu_elo_delta = an.Metric().elo(blu_elo["score"], red_elo["score"], observations["blu"], elo_N, elo_K) - blu_elo["score"] + + new_red_gl2_score, new_red_gl2_rd, new_red_gl2_vol = an.Metric().glicko2(red_gl2["score"], red_gl2["rd"], red_gl2["vol"], [blu_gl2["score"]], [blu_gl2["rd"]], [observations["red"], observations["blu"]]) + new_blu_gl2_score, new_blu_gl2_rd, new_blu_gl2_vol = an.Metric().glicko2(blu_gl2["score"], blu_gl2["rd"], blu_gl2["vol"], [red_gl2["score"]], [red_gl2["rd"]], [observations["blu"], observations["red"]]) + + red_gl2_delta = {"score": new_red_gl2_score - red_gl2["score"], "rd": new_red_gl2_rd - red_gl2["rd"], "vol": new_red_gl2_vol - red_gl2["vol"]} + blu_gl2_delta = {"score": new_blu_gl2_score - blu_gl2["score"], "rd": new_blu_gl2_rd - blu_gl2["rd"], "vol": new_blu_gl2_vol - blu_gl2["vol"]} + + for team in red: + + red[team]["elo"]["score"] = red[team]["elo"]["score"] + red_elo_delta + + red[team]["gl2"]["score"] = red[team]["gl2"]["score"] + red_gl2_delta["score"] + red[team]["gl2"]["rd"] = red[team]["gl2"]["rd"] + red_gl2_delta["rd"] + red[team]["gl2"]["vol"] = red[team]["gl2"]["vol"] + red_gl2_delta["vol"] + + for team in blu: + + blu[team]["elo"]["score"] = blu[team]["elo"]["score"] + blu_elo_delta + + blu[team]["gl2"]["score"] = blu[team]["gl2"]["score"] + blu_gl2_delta["score"] + blu[team]["gl2"]["rd"] = blu[team]["gl2"]["rd"] + blu_gl2_delta["rd"] + blu[team]["gl2"]["vol"] = blu[team]["gl2"]["vol"] + blu_gl2_delta["vol"] + + temp_vector = {} + temp_vector.update(red) + temp_vector.update(blu) + + d.push_metric(self.client, self.competition, temp_vector) + + def push_results(self): + pass + +class Pit: + + config = None + apikey = None + tbakey = None + timestamp = None + competition = None + + data = None + results = None + + def __init__(self, config, apikey, tbakey, timestamp, competition): + self.config = config + self.apikey = apikey + self.tbakey = tbakey + self.timestamp = timestamp + self.competition = competition + + def validate_config(self): + return True, "" + + def load_data(self): + self.data = d.load_pit(self.apikey, self.competition) + + def process_data(self, exec_threads): + return_vector = {} + for team in self.data: + for variable in self.data[team]: + if variable in self.config: + if not variable in return_vector: + return_vector[variable] = [] + return_vector[variable].append(self.data[team][variable]) + + self.results = return_vector + + def push_results(self): + d.push_pit(self.apikey, self.competition, self.results) \ No newline at end of file From 7be48af85eed7bc5544671144cc83b4c9ce8649c Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 28 Oct 2021 20:40:56 +0000 Subject: [PATCH 13/18] implemented dynamic module loading/running, fixed minor issue in metric module Signed-off-by: Arthur Lu --- src/cli/module.py | 10 +++---- src/cli/superscript.py | 65 ++++++++++++++---------------------------- 2 files changed, 27 insertions(+), 48 deletions(-) diff --git a/src/cli/module.py b/src/cli/module.py index 5d0fcbf..dfc9a16 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -150,12 +150,12 @@ class Metric: return True, "" def load_data(self): - self.data = d.pull_new_tba_matches(self.apikey, self.competition, self.timestamp) + self.data = d.pull_new_tba_matches(self.tbakey, self.competition, self.timestamp) def process_data(self, exec_threads): - elo_N = self.config["elo"]["N"] - elo_K = self.config["elo"]["K"] + elo_N = self.config["tests"]["elo"]["N"] + elo_K = self.config["tests"]["elo"]["K"] matches = self.data @@ -164,8 +164,8 @@ class Metric: for match in matches: - red = d.load_metric(self.apikey, self.competition, match, "red", self.config) - blu = d.load_metric(self.apikey, self.competition, match, "blue", self.config) + red = d.load_metric(self.apikey, self.competition, match, "red", self.config["tests"]) + blu = d.load_metric(self.apikey, self.competition, match, "blue", self.config["tests"]) elo_red_total = 0 elo_blu_total = 0 diff --git a/src/cli/superscript.py b/src/cli/superscript.py index 56d484c..7a75f09 100644 --- a/src/cli/superscript.py +++ b/src/cli/superscript.py @@ -163,8 +163,9 @@ import warnings import zmq from interface import splash, log, ERR, INF, stdout, stderr -from data import get_previous_time, pull_new_tba_matches, set_current_time, load_match, push_match, load_pit, push_pit, get_database_config, set_database_config, check_new_database_matches -from processing import matchloop, metricloop, pitloop +from data import get_previous_time, set_current_time, get_database_config, set_database_config, check_new_database_matches +from module import Match, Metric, Pit +#from processing import matchloop, metricloop, pitloop config_path = "config.json" sample_json = """{ @@ -254,6 +255,8 @@ def main(send, verbose = False, profile = False, debug = False): if verbose: splash(__version__) + modules = {"match": Match, "metric": Metric, "pit": Pit} + while True: try: @@ -289,31 +292,23 @@ def main(send, verbose = False, profile = False, debug = False): exit_code = 1 close_all() break - flag, exec_threads, competition, match_tests, metrics_tests, pit_tests = parse_config_variable(send, config) + flag, exec_threads, competition, config_modules = parse_config_variable(send, config) if flag: exit_code = 1 close_all() break - start = time.time() - send(stdout, INF, "loading match, metric, pit data (this may take a few seconds)") - match_data = load_match(client, competition) - metrics_data = pull_new_tba_matches(tbakey, competition, loop_start) - pit_data = load_pit(client, competition) - send(stdout, INF, "finished loading match, metric, pit data in "+ str(time.time() - start) + " seconds") - - start = time.time() - send(stdout, INF, "performing analysis on match, metrics, pit data") - match_results = matchloop(client, competition, match_data, match_tests, exec_threads) - metrics_results = metricloop(client, competition, metrics_data, metrics_tests) - pit_results = pitloop(client, competition, pit_data, pit_tests) - send(stdout, INF, "finished analysis in " + str(time.time() - start) + " seconds") - - start = time.time() - send(stdout, INF, "uploading match, metrics, pit results to database") - push_match(client, competition, match_results) - push_pit(client, competition, pit_results) - send(stdout, INF, "finished uploading results in " + str(time.time() - start) + " seconds") + for m in config_modules: + if m in modules: + start = time.time() + current_module = modules[m](config_modules[m], client, tbakey, loop_start, competition) + valid = current_module.validate_config() + if not valid: + continue + current_module.load_data() + current_module.process_data(exec_threads) + current_module.push_results() + print(m + " module finished in " + str(time.time() - start) + " seconds") if debug: f = open("matchloop.log", "w+") @@ -439,37 +434,21 @@ def parse_config_variable(send, config): send(stderr, ERR, "could not find competition field in config", code = 101) exit_flag = True try: - match_tests = config["variable"]["statistics"]["match"] + modules = config["variable"]["modules"] except: - send(stderr, ERR, "could not find match field in config", code = 102) - exit_flag = True - try: - metrics_tests = config["variable"]["statistics"]["metric"] - except: - send(stderr, ERR, "could not find metrics field in config", code = 103) - exit_flag = True - try: - pit_tests = config["variable"]["statistics"]["pit"] - except: - send(stderr, ERR, "could not find pit field in config", code = 104) + send(stderr, ERR, "could not find modules field in config", code = 102) exit_flag = True if competition == None or competition == "": send(stderr, ERR, "competition field in config must not be empty", code = 105) exit_flag = True - if match_tests == None: - send(stderr, ERR, "matchfield in config must not be empty", code = 106) - exit_flag = True - if metrics_tests == None: - send(stderr, ERR, "metrics field in config must not be empty", code = 107) - exit_flag = True - if pit_tests == None: - send(stderr, ERR, "pit field in config must not be empty", code = 108) + if modules == None: + send(stderr, ERR, "modules in config must not be empty", code = 106) exit_flag = True send(stdout, INF, "found and loaded competition, match, metrics, pit from config") - return exit_flag, exec_threads, competition, match_tests, metrics_tests, pit_tests + return exit_flag, exec_threads, competition, modules def resolve_config_conflicts(send, client, config, preference, sync): From bd87111e08709e825af2abad0d94894274a354c6 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Thu, 28 Oct 2021 21:12:28 +0000 Subject: [PATCH 14/18] fixed debug logging Signed-off-by: Arthur Lu --- src/cli/superscript.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/cli/superscript.py b/src/cli/superscript.py index 7a75f09..6df57f9 100644 --- a/src/cli/superscript.py +++ b/src/cli/superscript.py @@ -308,16 +308,11 @@ def main(send, verbose = False, profile = False, debug = False): current_module.load_data() current_module.process_data(exec_threads) current_module.push_results() - print(m + " module finished in " + str(time.time() - start) + " seconds") - - if debug: - f = open("matchloop.log", "w+") - json.dump(match_results, f, ensure_ascii=False, indent=4) - f.close() - - f = open("pitloop.log", "w+") - json.dump(pit_results, f, ensure_ascii=False, indent=4) - f.close() + send(stdout, INF, m + " module finished in " + str(time.time() - start) + " seconds") + if debug: + f = open(m + ".log", "w+") + json.dump({"data": current_module.data, "results":current_module.results}, f, ensure_ascii=False, indent=4) + f.close() set_current_time(client, loop_start) close_all() From d798bfe7d2ba3369aef5d6ed2a3f3c0b1a66b482 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Sat, 30 Oct 2021 03:11:10 +0000 Subject: [PATCH 15/18] module replaces processing --- src/cli/processing.py | 188 ----------------------------------------- src/cli/superscript.py | 1 - 2 files changed, 189 deletions(-) delete mode 100644 src/cli/processing.py diff --git a/src/cli/processing.py b/src/cli/processing.py deleted file mode 100644 index aa867f6..0000000 --- a/src/cli/processing.py +++ /dev/null @@ -1,188 +0,0 @@ -import numpy as np - -from tra_analysis import Analysis as an -from data import pull_new_tba_matches, push_metric, load_metric - -import signal - -def simplestats(data_test): - - signal.signal(signal.SIGINT, signal.SIG_IGN) - - data = np.array(data_test[3]) - data = data[np.isfinite(data)] - ranges = list(range(len(data))) - - test = data_test[2] - - if test == "basic_stats": - return an.basic_stats(data) - - if test == "historical_analysis": - return an.histo_analysis([ranges, data]) - - if test == "regression_linear": - return an.regression(ranges, data, ['lin']) - - if test == "regression_logarithmic": - return an.regression(ranges, data, ['log']) - - if test == "regression_exponential": - return an.regression(ranges, data, ['exp']) - - if test == "regression_polynomial": - return an.regression(ranges, data, ['ply']) - - if test == "regression_sigmoidal": - return an.regression(ranges, data, ['sig']) - -def matchloop(client, competition, data, tests, exec_threads): - - short_mapping = {"regression_linear": "lin", "regression_logarithmic": "log", "regression_exponential": "exp", "regression_polynomial": "ply", "regression_sigmoidal": "sig"} - - class AutoVivification(dict): - def __getitem__(self, item): - try: - return dict.__getitem__(self, item) - except KeyError: - value = self[item] = type(self)() - return value - - input_vector = [] - return_vector = AutoVivification() - - for team in data: - - for variable in data[team]: - - if variable in tests: - - for test in tests[variable]: - - input_vector.append((team, variable, test, data[team][variable])) - - result_filtered = exec_threads.map(simplestats, input_vector) - - i = 0 - - result_filtered = list(result_filtered) - - for result in result_filtered: - - filtered = input_vector[i][2] - - try: - short = short_mapping[filtered] - return_vector[input_vector[i][0]][input_vector[i][1]][input_vector[i][2]] = result[short] - except KeyError: # not in mapping - return_vector[input_vector[i][0]][input_vector[i][1]][input_vector[i][2]] = result - - i += 1 - - return return_vector - -def metricloop(client, competition, data, metrics): # listener based metrics update - - elo_N = metrics["elo"]["N"] - elo_K = metrics["elo"]["K"] - - matches = data - #matches = pull_new_tba_matches(tbakey, competition, timestamp) - - red = {} - blu = {} - - for match in matches: - - red = load_metric(client, competition, match, "red", metrics) - blu = load_metric(client, competition, match, "blue", metrics) - - elo_red_total = 0 - elo_blu_total = 0 - - gl2_red_score_total = 0 - gl2_blu_score_total = 0 - - gl2_red_rd_total = 0 - gl2_blu_rd_total = 0 - - gl2_red_vol_total = 0 - gl2_blu_vol_total = 0 - - for team in red: - - elo_red_total += red[team]["elo"]["score"] - - gl2_red_score_total += red[team]["gl2"]["score"] - gl2_red_rd_total += red[team]["gl2"]["rd"] - gl2_red_vol_total += red[team]["gl2"]["vol"] - - for team in blu: - - elo_blu_total += blu[team]["elo"]["score"] - - gl2_blu_score_total += blu[team]["gl2"]["score"] - gl2_blu_rd_total += blu[team]["gl2"]["rd"] - gl2_blu_vol_total += blu[team]["gl2"]["vol"] - - red_elo = {"score": elo_red_total / len(red)} - blu_elo = {"score": elo_blu_total / len(blu)} - - red_gl2 = {"score": gl2_red_score_total / len(red), "rd": gl2_red_rd_total / len(red), "vol": gl2_red_vol_total / len(red)} - blu_gl2 = {"score": gl2_blu_score_total / len(blu), "rd": gl2_blu_rd_total / len(blu), "vol": gl2_blu_vol_total / len(blu)} - - - if match["winner"] == "red": - - observations = {"red": 1, "blu": 0} - - elif match["winner"] == "blue": - - observations = {"red": 0, "blu": 1} - - else: - - observations = {"red": 0.5, "blu": 0.5} - - red_elo_delta = an.Metric().elo(red_elo["score"], blu_elo["score"], observations["red"], elo_N, elo_K) - red_elo["score"] - blu_elo_delta = an.Metric().elo(blu_elo["score"], red_elo["score"], observations["blu"], elo_N, elo_K) - blu_elo["score"] - - new_red_gl2_score, new_red_gl2_rd, new_red_gl2_vol = an.Metric().glicko2(red_gl2["score"], red_gl2["rd"], red_gl2["vol"], [blu_gl2["score"]], [blu_gl2["rd"]], [observations["red"], observations["blu"]]) - new_blu_gl2_score, new_blu_gl2_rd, new_blu_gl2_vol = an.Metric().glicko2(blu_gl2["score"], blu_gl2["rd"], blu_gl2["vol"], [red_gl2["score"]], [red_gl2["rd"]], [observations["blu"], observations["red"]]) - - red_gl2_delta = {"score": new_red_gl2_score - red_gl2["score"], "rd": new_red_gl2_rd - red_gl2["rd"], "vol": new_red_gl2_vol - red_gl2["vol"]} - blu_gl2_delta = {"score": new_blu_gl2_score - blu_gl2["score"], "rd": new_blu_gl2_rd - blu_gl2["rd"], "vol": new_blu_gl2_vol - blu_gl2["vol"]} - - for team in red: - - red[team]["elo"]["score"] = red[team]["elo"]["score"] + red_elo_delta - - red[team]["gl2"]["score"] = red[team]["gl2"]["score"] + red_gl2_delta["score"] - red[team]["gl2"]["rd"] = red[team]["gl2"]["rd"] + red_gl2_delta["rd"] - red[team]["gl2"]["vol"] = red[team]["gl2"]["vol"] + red_gl2_delta["vol"] - - for team in blu: - - blu[team]["elo"]["score"] = blu[team]["elo"]["score"] + blu_elo_delta - - blu[team]["gl2"]["score"] = blu[team]["gl2"]["score"] + blu_gl2_delta["score"] - blu[team]["gl2"]["rd"] = blu[team]["gl2"]["rd"] + blu_gl2_delta["rd"] - blu[team]["gl2"]["vol"] = blu[team]["gl2"]["vol"] + blu_gl2_delta["vol"] - - temp_vector = {} - temp_vector.update(red) - temp_vector.update(blu) - - push_metric(client, competition, temp_vector) - -def pitloop(client, competition, pit, tests): - - return_vector = {} - for team in pit: - for variable in pit[team]: - if variable in tests: - if not variable in return_vector: - return_vector[variable] = [] - return_vector[variable].append(pit[team][variable]) - - return return_vector \ No newline at end of file diff --git a/src/cli/superscript.py b/src/cli/superscript.py index 6df57f9..84b8e32 100644 --- a/src/cli/superscript.py +++ b/src/cli/superscript.py @@ -165,7 +165,6 @@ import zmq from interface import splash, log, ERR, INF, stdout, stderr from data import get_previous_time, set_current_time, get_database_config, set_database_config, check_new_database_matches from module import Match, Metric, Pit -#from processing import matchloop, metricloop, pitloop config_path = "config.json" sample_json = """{ From 0fd24d42e12a16fc929945cc5cdd6745ce023171 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Sat, 30 Oct 2021 03:51:03 +0000 Subject: [PATCH 16/18] removed testing notebook, anticipated removal of pandas requirement, added pandas and matplotlib to pyinstaller exclusion, removed unessasary option in build scripts --- build/build-CLI.bat | 2 +- build/build-CLI.sh | 2 +- src/cli/data.py | 1 - src/cli/superscript.spec | 5 +- src/cli/testing.ipynb | 116 --------------------------------------- src/requirements.txt | 2 - 6 files changed, 6 insertions(+), 122 deletions(-) delete mode 100644 src/cli/testing.ipynb diff --git a/build/build-CLI.bat b/build/build-CLI.bat index 22dd93c..29199e2 100644 --- a/build/build-CLI.bat +++ b/build/build-CLI.bat @@ -2,4 +2,4 @@ set pathtospec="../src/cli/superscript.spec" set pathtodist="../dist/" set pathtowork="temp/" -pyinstaller --onefile --clean --distpath %pathtodist% --workpath %pathtowork% %pathtospec% \ No newline at end of file +pyinstaller --clean --distpath %pathtodist% --workpath %pathtowork% %pathtospec% \ No newline at end of file diff --git a/build/build-CLI.sh b/build/build-CLI.sh index 302265b..e328718 100644 --- a/build/build-CLI.sh +++ b/build/build-CLI.sh @@ -2,4 +2,4 @@ pathtospec="../src/cli/superscript.spec" pathtodist="../dist/" pathtowork="temp/" -pyinstaller --onefile --clean --distpath ${pathtodist} --workpath ${pathtowork} ${pathtospec} \ No newline at end of file +pyinstaller --clean --distpath ${pathtodist} --workpath ${pathtowork} ${pathtospec} \ No newline at end of file diff --git a/src/cli/data.py b/src/cli/data.py index c46e726..1d9c056 100644 --- a/src/cli/data.py +++ b/src/cli/data.py @@ -1,5 +1,4 @@ import requests -import pandas as pd def pull_new_tba_matches(apikey, competition, cutoff): api_key= apikey diff --git a/src/cli/superscript.spec b/src/cli/superscript.spec index 04cafa7..5d09620 100644 --- a/src/cli/superscript.spec +++ b/src/cli/superscript.spec @@ -13,7 +13,10 @@ a = Analysis(['superscript.py'], ], hookspath=[], runtime_hooks=[], - excludes=[], + excludes=[ + "matplotlib", + "pandas" + ], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, diff --git a/src/cli/testing.ipynb b/src/cli/testing.ipynb deleted file mode 100644 index 904b8ac..0000000 --- a/src/cli/testing.ipynb +++ /dev/null @@ -1,116 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "class C1:\n", - "\tval = 0\n", - "\tdef __init__(self, i):\n", - "\t\tself.val = i\n", - "\n", - "class C2:\n", - "\tval = 0\n", - "\tdef __init__(self, i):\n", - "\t\tself.val = 2*i\n", - "\n", - "class C3:\n", - "\tval = 0\n", - "\tdef __init__(self, i):\n", - "\t\tself.val = 3*i" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[<__main__.C1 at 0x7fa84827afd0>,\n", - " <__main__.C2 at 0x7fa84827ae80>,\n", - " <__main__.C3 at 0x7fa8482020d0>]" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "classes = [C1, C2, C3]\n", - "initialized = []\n", - "for c in classes:\n", - "\tinitialized.append(c(10))\n", - "initialized" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "import module\n", - "module_references = {\"match\": module.Match}\n", - "module_initialized = []\n", - "for m in [\"match\"]:\n", - "\tmodule_initialized.append(module_references[m](\"\", \"\", \"\", 0, []))" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "module_initialized" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "interpreter": { - "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a" - }, - "kernelspec": { - "display_name": "Python 3.8.5 64-bit", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.5" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/src/requirements.txt b/src/requirements.txt index 88cc58b..52854df 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -1,6 +1,5 @@ requests pymongo -pandas tra-analysis dnspython @@ -11,7 +10,6 @@ scipy scikit-learn six pyparsing -pandas kivy==2.0.0rc2 From 108284a94b2e63c3fc10b02b9f60739f4ccbbaba Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Tue, 2 Nov 2021 05:37:27 +0000 Subject: [PATCH 17/18] formalized module interface --- src/cli/module.py | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/cli/module.py b/src/cli/module.py index dfc9a16..233e1aa 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -1,24 +1,37 @@ +import abc import data as d import signal import numpy as np import tra_analysis as an -class Module: - config = None - data = None - results = None - def __init__(self, config, apikey, tbakey, timestamp): - pass - def validate_config(self): - pass - def load_data(self): - pass - def process_data(self, exec_threads): - pass - def push_results(self): - pass +class Module(metaclass = abc.ABCMeta): -class Match: + @classmethod + def __subclasshook__(cls, subclass): + return (hasattr(subclass, 'validate_config') and + callable(subclass.validate_config) and + hasattr(subclass, 'load_data') and + callable(subclass.load_data) and + hasattr(subclass, 'process_data') and + callable(subclass.process_data) and + hasattr(subclass, 'push_results') and + callable(subclass.push_results) + ) + + @abc.abstractmethod + def validate_config(self): + raise NotImplementedError + @abc.abstractmethod + def load_data(self): + raise NotImplementedError + @abc.abstractmethod + def process_data(self, exec_threads): + raise NotImplementedError + @abc.abstractmethod + def push_results(self): + raise NotImplementedError + +class Match (Module): config = None apikey = None @@ -128,7 +141,7 @@ class Match: d.push_match(self.apikey, self.competition, self.results) -class Metric: +class Metric (Module): config = None apikey = None @@ -248,7 +261,7 @@ class Metric: def push_results(self): pass -class Pit: +class Pit (Module): config = None apikey = None From d234302cdc26cce03833877133f25a144d7d1f58 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 5 Nov 2021 23:17:42 +0000 Subject: [PATCH 18/18] added empty modules for future additions --- src/cli/module.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cli/module.py b/src/cli/module.py index 233e1aa..b3cac88 100644 --- a/src/cli/module.py +++ b/src/cli/module.py @@ -297,4 +297,13 @@ class Pit (Module): self.results = return_vector def push_results(self): - d.push_pit(self.apikey, self.competition, self.results) \ No newline at end of file + d.push_pit(self.apikey, self.competition, self.results) + +class Rating (Module): + pass + +class Heatmap (Module): + pass + +class Sentiment (Module): + pass \ No newline at end of file