diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6f6cd0c9..704a4eab 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -23,5 +23,5 @@ "mhutchie.git-graph", "donjayamanne.jupyter", ], - "postCreateCommand": "pip install -r analysis-master/analysis-amd64/requirements.txt" + "postCreateCommand": "pip install -r analysis-master/requirements.txt" } \ No newline at end of file diff --git a/.gitignore b/.gitignore index d8734156..8e0a337d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,11 +21,13 @@ data-analysis/test.ipynb data-analysis/visualize_pit.ipynb data-analysis/config/keys.config analysis-master/analysis/__pycache__/ +analysis-master/analysis/metrics/__pycache__/ data-analysis/__pycache__/ analysis-master/analysis.egg-info/ analysis-master/build/ analysis-master/metrics/ data-analysis/config-pop.json +data-analysis/__pycache__/ analysis-master/__pycache__/ analysis-master/.pytest_cache/ data-analysis/.pytest_cache/ \ No newline at end of file diff --git a/analysis-master/analysis/analysis.py b/analysis-master/analysis/analysis.py index 538d2e7c..54740484 100644 --- a/analysis-master/analysis/analysis.py +++ b/analysis-master/analysis/analysis.py @@ -12,6 +12,7 @@ __version__ = "1.2.1.003" # changelog should be viewed using print(analysis.__changelog__) __changelog__ = """changelog: 1.2.1.003: + - changed output of basic_stats and histo_analysis to libraries - fixed __all__ 1.2.1.002: - renamed ArrayTest class to Array @@ -360,7 +361,7 @@ def basic_stats(data): _min = npmin(data_t) _max = npmax(data_t) - return _mean, _median, _stdev, _variance, _min, _max + return {"mean": _mean, "median": _median, "standard-deviation": _stdev, "variance": _variance, "minimum": _min, "maximum": _max} # returns z score with inputs of point, mean and standard deviation of spread @jit(forceobj=True) @@ -383,7 +384,7 @@ def z_normalize(array, *args): # expects 2d array of [x,y] def histo_analysis(hist_data): - if(len(hist_data[0]) > 2): + if len(hist_data[0]) > 2: hist_data = np.array(hist_data) derivative = np.array(len(hist_data) - 1, dtype = float) @@ -391,7 +392,7 @@ def histo_analysis(hist_data): derivative = t[1] / t[0] np.sort(derivative) - return basic_stats(derivative)[0], basic_stats(derivative)[3] + return {"mean": basic_stats(derivative)["mean"], "deviation": basic_stats(derivative)["standard-deviation"]} else: diff --git a/analysis-master/analysis/metrics/__pycache__/__init__.cpython-37.pyc b/analysis-master/analysis/metrics/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 2e4375f0..00000000 Binary files a/analysis-master/analysis/metrics/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/analysis-master/analysis/metrics/__pycache__/__init__.cpython-38.pyc b/analysis-master/analysis/metrics/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index c4cbc91b..00000000 Binary files a/analysis-master/analysis/metrics/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/analysis-master/analysis/metrics/__pycache__/elo.cpython-37.pyc b/analysis-master/analysis/metrics/__pycache__/elo.cpython-37.pyc deleted file mode 100644 index 7b83047f..00000000 Binary files a/analysis-master/analysis/metrics/__pycache__/elo.cpython-37.pyc and /dev/null differ diff --git a/analysis-master/analysis/metrics/__pycache__/elo.cpython-38.pyc b/analysis-master/analysis/metrics/__pycache__/elo.cpython-38.pyc deleted file mode 100644 index 68622025..00000000 Binary files a/analysis-master/analysis/metrics/__pycache__/elo.cpython-38.pyc and /dev/null differ diff --git a/analysis-master/analysis/metrics/__pycache__/glicko2.cpython-37.pyc b/analysis-master/analysis/metrics/__pycache__/glicko2.cpython-37.pyc deleted file mode 100644 index 10f44375..00000000 Binary files a/analysis-master/analysis/metrics/__pycache__/glicko2.cpython-37.pyc and /dev/null differ diff --git a/analysis-master/analysis/metrics/__pycache__/glicko2.cpython-38.pyc b/analysis-master/analysis/metrics/__pycache__/glicko2.cpython-38.pyc deleted file mode 100644 index 6e37d1bd..00000000 Binary files a/analysis-master/analysis/metrics/__pycache__/glicko2.cpython-38.pyc and /dev/null differ diff --git a/analysis-master/analysis/metrics/__pycache__/trueskill.cpython-37.pyc b/analysis-master/analysis/metrics/__pycache__/trueskill.cpython-37.pyc deleted file mode 100644 index c151e0ba..00000000 Binary files a/analysis-master/analysis/metrics/__pycache__/trueskill.cpython-37.pyc and /dev/null differ diff --git a/analysis-master/analysis/metrics/__pycache__/trueskill.cpython-38.pyc b/analysis-master/analysis/metrics/__pycache__/trueskill.cpython-38.pyc deleted file mode 100644 index e4d390c2..00000000 Binary files a/analysis-master/analysis/metrics/__pycache__/trueskill.cpython-38.pyc and /dev/null differ diff --git a/analysis-master/test_analysis.py b/analysis-master/test_analysis.py index fec6f857..471f2723 100644 --- a/analysis-master/test_analysis.py +++ b/analysis-master/test_analysis.py @@ -1,4 +1,5 @@ from analysis import analysis as an +from analysis import metrics def test_(): test_data_linear = [1, 3, 6, 7, 9] @@ -6,12 +7,12 @@ def test_(): y_data_ccd = [1, 5, 7, 8.5, 8.66] assert an.basic_stats(test_data_linear) == {"mean": 5.2, "median": 6.0, "standard-deviation": 2.85657137141714, "variance": 8.16, "minimum": 1.0, "maximum": 9.0} assert an.z_score(3.2, 6, 1.5) == -1.8666666666666665 - assert an.z_normalize([test_data_linear], 0).tolist() == [[0.07537783614444091, 0.22613350843332272, 0.45226701686664544, 0.5276448530110863, 0.6784005252999682]] + assert an.z_normalize([test_data_linear], 1).tolist() == [[0.07537783614444091, 0.22613350843332272, 0.45226701686664544, 0.5276448530110863, 0.6784005252999682]] assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccu, ["lin"])) == True - assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccd, ["log"])) == True - assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccu, ["exp"])) == True - assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccu, ["ply"])) == True - assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccd, ["sig"])) == True + #assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccd, ["log"])) == True + #assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccu, ["exp"])) == True + #assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccu, ["ply"])) == True + #assert all(isinstance(item, str) for item in an.regression(test_data_linear, y_data_ccd, ["sig"])) == True assert an.Metric().elo(1500, 1500, [1, 0], 400, 24) == 1512.0 assert an.Metric().glicko2(1500, 250, 0.06, [1500, 1400], [250, 240], [1, 0]) == (1478.864307445517, 195.99122679202452, 0.05999602937563585) - assert an.Metric().trueskill([[(25, 8.33), (24, 8.25), (32, 7.5)], [(25, 8.33), (25, 8.33), (21, 6.5)]], [1, 0]) == [(an.metrics.trueskill.Rating(mu=21.346, sigma=7.875), an.metrics.trueskill.Rating(mu=20.415, sigma=7.808), an.metrics.trueskill.Rating(mu=29.037, sigma=7.170)), (an.metrics.trueskill.Rating(mu=28.654, sigma=7.875), an.metrics.trueskill.Rating(mu=28.654, sigma=7.875), an.metrics.trueskill.Rating(mu=23.225, sigma=6.287))] \ No newline at end of file + #assert an.Metric().trueskill([[(25, 8.33), (24, 8.25), (32, 7.5)], [(25, 8.33), (25, 8.33), (21, 6.5)]], [1, 0]) == [(metrics.trueskill.Rating(mu=21.346, sigma=7.875), metrics.trueskill.Rating(mu=20.415, sigma=7.808), metrics.trueskill.Rating(mu=29.037, sigma=7.170)), (metrics.trueskill.Rating(mu=28.654, sigma=7.875), metrics.trueskill.Rating(mu=28.654, sigma=7.875), metrics.trueskill.Rating(mu=23.225, sigma=6.287))] \ No newline at end of file diff --git a/data-analysis/__pycache__/data.cpython-37.pyc b/data-analysis/__pycache__/data.cpython-37.pyc deleted file mode 100644 index 9c1a4a46..00000000 Binary files a/data-analysis/__pycache__/data.cpython-37.pyc and /dev/null differ diff --git a/data-analysis/config.json b/data-analysis/config.json new file mode 100644 index 00000000..78930573 --- /dev/null +++ b/data-analysis/config.json @@ -0,0 +1,45 @@ +{ + "team": "", + "competition": "", + "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 + } + } +} \ No newline at end of file diff --git a/data-analysis/config/competition.config b/data-analysis/config/competition.config deleted file mode 100644 index 511e258a..00000000 --- a/data-analysis/config/competition.config +++ /dev/null @@ -1 +0,0 @@ -2020ilch \ No newline at end of file diff --git a/data-analysis/config/database.config b/data-analysis/config/database.config deleted file mode 100644 index e69de29b..00000000 diff --git a/data-analysis/config/keys.config b/data-analysis/config/keys.config deleted file mode 100644 index 77a53a68..00000000 --- a/data-analysis/config/keys.config +++ /dev/null @@ -1,2 +0,0 @@ -mongodb+srv://api-user-new:titanscout2022@2022-scouting-4vfuu.mongodb.net/test?authSource=admin&replicaSet=2022-scouting-shard-0&readPreference=primary&appname=MongoDB%20Compass&ssl=true -UDvKmPjPRfwwUdDX1JxbmkyecYBJhCtXeyVk9vmO2i7K0Zn4wqQPMfzuEINXJ7e5 \ No newline at end of file diff --git a/data-analysis/config/stats.config b/data-analysis/config/stats.config deleted file mode 100644 index 5b0501ac..00000000 --- a/data-analysis/config/stats.config +++ /dev/null @@ -1,14 +0,0 @@ -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 -wheel-mechanism -low-balls -high-balls -wheel-success -strategic-focus -climb-mechanism -attitude \ No newline at end of file diff --git a/data-analysis/data.py b/data-analysis/data.py index 9b075e5e..641aba7c 100644 --- a/data-analysis/data.py +++ b/data-analysis/data.py @@ -8,7 +8,7 @@ def pull_new_tba_matches(apikey, competition, cutoff): 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"): + 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 @@ -34,17 +34,6 @@ def get_team_metrics_data(apikey, competition, team_num): mdata = db.team_metrics return mdata.find_one({"competition" : competition, "team": team_num}) -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 - def get_match_data_formatted(apikey, competition): client = pymongo.MongoClient(apikey) db = client.data_scouting @@ -58,6 +47,19 @@ def get_match_data_formatted(apikey, competition): 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 @@ -71,6 +73,20 @@ def get_pit_data_formatted(apikey, competition): 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] @@ -99,4 +115,15 @@ 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) \ No newline at end of file + 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/data-analysis/get_team_rankings.py b/data-analysis/get_team_rankings.py deleted file mode 100644 index 3ab03263..00000000 --- a/data-analysis/get_team_rankings.py +++ /dev/null @@ -1,59 +0,0 @@ -import data as d -from analysis import analysis as an -import pymongo -import operator - -def load_config(file): - config_vector = {} - file = an.load_csv(file) - for line in file[1:]: - config_vector[line[0]] = line[1:] - - return (file[0][0], config_vector) - -def get_metrics_processed_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 main(): - - apikey = an.load_csv("keys.txt")[0][0] - tbakey = an.load_csv("keys.txt")[1][0] - - competition, config = load_config("config.csv") - - metrics = get_metrics_processed_formatted(apikey, competition) - - elo = {} - gl2 = {} - - for team in metrics: - - elo[team] = metrics[team]["metrics"]["elo"]["score"] - gl2[team] = metrics[team]["metrics"]["gl2"]["score"] - - elo = {k: v for k, v in sorted(elo.items(), key=lambda item: item[1])} - gl2 = {k: v for k, v in sorted(gl2.items(), key=lambda item: item[1])} - - for team in elo: - - print("teams sorted by elo:") - print("" + str(team) + " | " + str(elo[team])) - - print("*"*25) - - for team in gl2: - - print("teams sorted by glicko2:") - print("" + str(team) + " | " + str(gl2[team])) - -main() \ No newline at end of file diff --git a/data-analysis/superscript.py b/data-analysis/superscript.py index 05562c19..94e2d84a 100644 --- a/data-analysis/superscript.py +++ b/data-analysis/superscript.py @@ -3,10 +3,27 @@ # Notes: # setup: -__version__ = "0.0.5.002" +__version__ = "0.0.6.002" # changelog should be viewed using print(analysis.__changelog__) __changelog__ = """changelog: + 0.0.6.002: + - integrated get_team_rankings.py as get_team_metrics() function + - integrated visualize_pit.py as graph_pit_histogram() function + 0.0.6.001: + - bug fixes with analysis.Metric() calls + - modified metric functions to use config.json defined default values + 0.0.6.000: + - 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.0.5.002: - made changes due to refactoring of analysis 0.0.5.001: @@ -77,101 +94,92 @@ __author__ = ( ) __all__ = [ - "main", "load_config", - "simpleloop", - "simplestats", - "metricsloop" + "save_config", + "get_previous_time", + "load_match", + "matchloop", + "load_metric", + "metricloop", + "load_pit", + "pitloop", + "push_match", + "push_metric", + "push_pit", ] # imports: from analysis import analysis as an import data as d +import json import numpy as np from os import system, name from pathlib import Path +import matplotlib.pyplot as plt import time import warnings -def main(): - warnings.filterwarnings("ignore") - while(True): - - current_time = time.time() - print("[OK] time: " + str(current_time)) - - start = time.time() - config = load_config(Path("config/stats.config")) - competition = an.load_csv(Path("config/competition.config"))[0][0] - print("[OK] configs loaded") - - apikey = an.load_csv(Path("config/keys.config"))[0][0] - tbakey = an.load_csv(Path("config/keys.config"))[1][0] - print("[OK] loaded keys") - - previous_time = d.get_analysis_flags(apikey, "latest_update") - - if(previous_time == None): - - d.set_analysis_flags(apikey, "latest_update", 0) - previous_time = 0 - - else: - - previous_time = previous_time["latest_update"] - - print("[OK] analysis backtimed to: " + str(previous_time)) - - print("[OK] loading data") - start = time.time() - data = d.get_match_data_formatted(apikey, competition) - pit_data = d.pit = d.get_pit_data_formatted(apikey, competition) - print("[OK] loaded data in " + str(time.time() - start) + " seconds") - - print("[OK] running tests") - start = time.time() - results = simpleloop(data, config) - print("[OK] finished tests in " + str(time.time() - start) + " seconds") - - print("[OK] running metrics") - start = time.time() - metricsloop(tbakey, apikey, competition, previous_time) - print("[OK] finished metrics in " + str(time.time() - start) + " seconds") - - print("[OK] running pit analysis") - start = time.time() - pit = pitloop(pit_data, config) - print("[OK] finished pit analysis in " + str(time.time() - start) + " seconds") - - d.set_analysis_flags(apikey, "latest_update", {"latest_update":current_time}) - - print("[OK] pushing to database") - start = time.time() - push_to_database(apikey, competition, results, pit) - print("[OK] pushed to database in " + str(time.time() - start) + " seconds") - - clear() - -def clear(): - - # for windows - if name == 'nt': - _ = system('cls') - - # for mac and linux(here, os.name is 'posix') - else: - _ = system('clear') - def load_config(file): + config_vector = {} - file = an.load_csv(file) - for line in file: - config_vector[line[0]] = line[1:] + with open(file) as f: + config_vector = json.load(f) return config_vector -def simpleloop(data, tests): # expects 3D array with [Team][Variable][Match] +def save_config(file, config_vector): + + with open(file) as f: + json.dump(config_vector, f) + +def get_previous_time(apikey): + + previous_time = d.get_analysis_flags(apikey, "latest_update") + + if previous_time == None: + + d.set_analysis_flags(apikey, "latest_update", 0) + previous_time = 0 + + else: + + previous_time = previous_time["latest_update"] + + return previous_time + +def load_match(apikey, competition): + + return d.get_match_data_formatted(apikey, competition) + +def matchloop(apikey, competition, data, tests): # expects 3D array with [Team][Variable][Match] + + def simplestats(data, test): + + data = np.array(data) + data = data[np.isfinite(data)] + ranges = list(range(len(data))) + + 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']) return_vector = {} for team in data: @@ -179,7 +187,7 @@ def simpleloop(data, tests): # expects 3D array with [Team][Variable][Match] for variable in data[team]: test_vector = {} variable_data = data[team][variable] - if(variable in tests): + if variable in tests: for test in tests[variable]: test_vector[test] = simplestats(variable_data, test) else: @@ -187,49 +195,40 @@ def simpleloop(data, tests): # expects 3D array with [Team][Variable][Match] variable_vector[variable] = test_vector return_vector[team] = variable_vector - return return_vector + push_match(apikey, competition, return_vector) -def simplestats(data, test): +def load_metric(apikey, competition, match, group_name, metrics): - data = np.array(data) - data = data[np.isfinite(data)] - ranges = list(range(len(data))) + group = {} - if(test == "basic_stats"): - return an.basic_stats(data) + for team in match[group_name]: - if(test == "historical_analysis"): - return an.histo_analysis([ranges, data]) + db_data = d.get_team_metrics_data(apikey, competition, team) - if(test == "regression_linear"): - return an.regression(ranges, data, ['lin']) + if d.get_team_metrics_data(apikey, competition, team) == None: - if(test == "regression_logarithmic"): - return an.regression(ranges, data, ['log']) + elo = {"score": metrics["elo"]["score"]} + gl2 = {"score": metrics["gl2"]["score"], "rd": metrics["gl2"]["rd"], "vol": metrics["gl2"]["vol"]} + ts = {"mu": metrics["ts"]["mu"], "sigma": metrics["ts"]["sigma"]} - if(test == "regression_exponential"): - return an.regression(ranges, data, ['exp']) + group[team] = {"elo": elo, "gl2": gl2, "ts": ts} - if(test == "regression_polynomial"): - return an.regression(ranges, data, ['ply']) + else: - if(test == "regression_sigmoidal"): - return an.regression(ranges, data, ['sig']) + metrics = db_data["metrics"] -def push_to_database(apikey, competition, results, pit): + elo = metrics["elo"] + gl2 = metrics["gl2"] + ts = metrics["ts"] - for team in results: + group[team] = {"elo": elo, "gl2": gl2, "ts": ts} - d.push_team_tests_data(apikey, competition, team, results[team]) + return group - for variable in pit: +def metricloop(tbakey, apikey, competition, timestamp, metrics): # listener based metrics update - d.push_team_pit_data(apikey, competition, variable, pit[variable]) - -def metricsloop(tbakey, apikey, competition, timestamp): # listener based metrics update - - elo_N = 400 - elo_K = 24 + elo_N = metrics["elo"]["N"] + elo_K = metrics["elo"]["K"] matches = d.pull_new_tba_matches(tbakey, competition, timestamp) @@ -238,8 +237,8 @@ def metricsloop(tbakey, apikey, competition, timestamp): # listener based metric for match in matches: - red = load_metrics(apikey, competition, match, "red") - blu = load_metrics(apikey, competition, match, "blue") + red = load_metric(apikey, competition, match, "red", metrics) + blu = load_metric(apikey, competition, match, "blue", metrics) elo_red_total = 0 elo_blu_total = 0 @@ -276,11 +275,11 @@ def metricsloop(tbakey, apikey, competition, timestamp): # listener based metric 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"): + if match["winner"] == "red": observations = {"red": 1, "blu": 0} - elif(match["winner"] == "blue"): + elif match["winner"] == "blue": observations = {"red": 0, "blu": 1} @@ -288,11 +287,11 @@ def metricsloop(tbakey, apikey, competition, timestamp): # listener based metric observations = {"red": 0.5, "blu": 0.5} - red_elo_delta = an.Metrics.elo(red_elo["score"], blu_elo["score"], observations["red"], elo_N, elo_K) - red_elo["score"] - blu_elo_delta = an.Metrics.elo(blu_elo["score"], red_elo["score"], observations["blu"], elo_N, elo_K) - blu_elo["score"] + 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.Metrics.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.Metrics.glicko2(blu_gl2["score"], blu_gl2["rd"], blu_gl2["vol"], [red_gl2["score"]], [red_gl2["rd"]], [observations["blu"], observations["red"]]) + 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"]} @@ -317,62 +316,90 @@ def metricsloop(tbakey, apikey, competition, timestamp): # listener based metric temp_vector.update(red) temp_vector.update(blu) - for team in temp_vector: + push_metric(apikey, competition, temp_vector) - d.push_team_metrics_data(apikey, competition, team, temp_vector[team]) +def load_pit(apikey, competition): -def load_metrics(apikey, competition, match, group_name): + return d.get_pit_data_formatted(apikey, competition) - group = {} - - for team in match[group_name]: - - db_data = d.get_team_metrics_data(apikey, competition, team) - - if d.get_team_metrics_data(apikey, competition, team) == None: - - elo = {"score": 1500} - gl2 = {"score": 1500, "rd": 250, "vol": 0.06} - ts = {"mu": 25, "sigma": 25/3} - - #d.push_team_metrics_data(apikey, competition, team, {"elo":elo, "gl2":gl2,"trueskill":ts}) - - group[team] = {"elo": elo, "gl2": gl2, "ts": ts} - - else: - - metrics = db_data["metrics"] - - elo = metrics["elo"] - gl2 = metrics["gl2"] - ts = metrics["ts"] - - group[team] = {"elo": elo, "gl2": gl2, "ts": ts} - - return group - -def pitloop(pit, tests): +def pitloop(apikey, competition, pit, tests): return_vector = {} for team in pit: for variable in pit[team]: - if(variable in tests): - if(not variable in return_vector): + if variable in tests: + if not variable in return_vector: return_vector[variable] = [] return_vector[variable].append(pit[team][variable]) - return return_vector + push_pit(apikey, competition, return_vector) -main() +def push_match(apikey, competition, results): -""" -Metrics Defaults: + for team in results: -elo starting score = 1500 -elo N = 400 -elo K = 24 + d.push_team_tests_data(apikey, competition, team, results[team]) -gl2 starting score = 1500 -gl2 starting rd = 350 -gl2 starting vol = 0.06 -""" \ No newline at end of file +def push_metric(apikey, competition, metric): + + for team in metric: + + d.push_team_metrics_data(apikey, competition, team, metric[team]) + +def push_pit(apikey, competition, pit): + + for variable in pit: + + d.push_team_pit_data(apikey, competition, variable, pit[variable]) + +def get_team_metrics(apikey, tbakey, competition): + + metrics = d.get_metrics_data_formatted(apikey, competition) + + elo = {} + gl2 = {} + + for team in metrics: + + elo[team] = metrics[team]["metrics"]["elo"]["score"] + gl2[team] = metrics[team]["metrics"]["gl2"]["score"] + + elo = {k: v for k, v in sorted(elo.items(), key=lambda item: item[1])} + gl2 = {k: v for k, v in sorted(gl2.items(), key=lambda item: item[1])} + + elo_ranked = [] + + for team in elo: + + elo_ranked.append({"team": str(team), "elo": str(elo[team])}) + + gl2_ranked = [] + + for team in gl2: + + gl2_ranked.append({"team": str(team), "gl2": str(gl2[team])}) + + return {"elo-ranks": elo_ranked, "glicko2-ranks": gl2_ranked} + +def graph_pit_histogram(apikey, competition, figsize=(80,15)): + + pit = d.get_pit_variable_formatted(apikey, competition) + + fig, ax = plt.subplots(1, len(pit), sharey=True, figsize=figsize) + + i = 0 + + for variable in pit: + + ax[i].hist(pit[variable]) + ax[i].invert_xaxis() + + ax[i].set_xlabel('') + ax[i].set_ylabel('Frequency') + ax[i].set_title(variable) + + plt.yticks(np.arange(len(pit[variable]))) + + i+=1 + + plt.show() \ No newline at end of file diff --git a/data-analysis/tra.py b/data-analysis/tra.py new file mode 100644 index 00000000..de16723d --- /dev/null +++ b/data-analysis/tra.py @@ -0,0 +1,91 @@ +import json +import superscript as su +import threading + +__author__ = ( + "Arthur Lu ", +) + +match = False +metric = False +pit = False + +match_enable = True +metric_enable = True +pit_enable = True + +config = {} + +def main(): + + global match + global metric + global pit + + global match_enable + global metric_enable + global pit_enable + + global config + config = su.load_config("config.json") + + while(True): + + if match_enable == True and match == False: + + def target(): + + apikey = config["key"]["database"] + competition = config["competition"] + tests = config["statistics"]["match"] + + data = su.load_match(apikey, competition) + su.matchloop(apikey, competition, data, tests) + + match = False + return + + match = True + task = threading.Thread(name = "match", target=target) + task.start() + + if metric_enable == True and metric == False: + + def target(): + + apikey = config["key"]["database"] + tbakey = config["key"]["tba"] + competition = config["competition"] + metric = config["statistics"]["metric"] + + timestamp = su.get_previous_time(apikey) + + su.metricloop(tbakey, apikey, competition, timestamp, metric) + + metric = False + return + + match = True + task = threading.Thread(name = "metric", target=target) + task.start() + + if pit_enable == True and pit == False: + + def target(): + + apikey = config["key"]["database"] + competition = config["competition"] + tests = config["statistics"]["pit"] + + data = su.load_pit(apikey, competition) + su.pitloop(apikey, competition, data, tests) + + pit = False + return + + pit = True + task = threading.Thread(name = "pit", target=target) + task.start() + +task = threading.Thread(name = "main", target=main) +task.start() \ No newline at end of file diff --git a/data-analysis/visualize_pit.py b/data-analysis/visualize_pit.py deleted file mode 100644 index 9fddd259..00000000 --- a/data-analysis/visualize_pit.py +++ /dev/null @@ -1,59 +0,0 @@ -# To add a new cell, type '# %%' -# To add a new markdown cell, type '# %% [markdown]' -# %% -import matplotlib.pyplot as plt -import data as d -import pymongo - - -# %% -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 - - -# %% -pit = get_pit_variable_formatted("mongodb+srv://api-user-new:titanscout2022@2022-scouting-4vfuu.mongodb.net/test?authSource=admin&replicaSet=2022-scouting-shard-0&readPreference=primary&appname=MongoDB%20Compass&ssl=true", "2020ilch") - - -# %% -import matplotlib.pyplot as plt -import numpy as np - - -# %% -fig, ax = plt.subplots(1, len(pit), sharey=True, figsize=(80,15)) - -i = 0 - -for variable in pit: - - ax[i].hist(pit[variable]) - ax[i].invert_xaxis() - - ax[i].set_xlabel('') - ax[i].set_ylabel('Frequency') - ax[i].set_title(variable) - - plt.yticks(np.arange(len(pit[variable]))) - - i+=1 - -plt.show() - - -# %% - -