diff --git a/src/cli/socket-test.html b/src/cli/socket-test.html new file mode 100644 index 0000000..98f28a1 --- /dev/null +++ b/src/cli/socket-test.html @@ -0,0 +1,20 @@ + + + + WebSocket demo + + + + + \ No newline at end of file diff --git a/src/cli/superscript-socket.py b/src/cli/superscript-socket.py new file mode 100644 index 0000000..b87f636 --- /dev/null +++ b/src/cli/superscript-socket.py @@ -0,0 +1,275 @@ +# testing purposes only, not to be used or run + +import json +import multiprocessing +import os +import math +from multiprocessing import Pool +import time +import warnings +import sys +import asyncio +import websockets + +from interface import splash, log, ERR, INF, stdout, stderr +from dataset import get_previous_time, set_current_time, load_match, push_match, load_metric, push_metric, load_pit, push_pit +from processing import matchloop, metricloop, pitloop + +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 + } + } +}""" + +async def main(socket, path): + + #warnings.filterwarnings("ignore") + #sys.stderr = open("errorlog.txt", "w") + + #splash(__version__) + + #loop_exit_code = 0 + #loop_stored_exception = None + + while True: + + try: + + loop_start = time.time() + + current_time = time.time() + await socket.send("current time: " + str(current_time)) + + config = {} + if load_config(config_path, config) == 1: + sys.exit(1) + + error_flag = False + + try: + competition = config["competition"] + except: + await socket.send("could not find competition field in config") + error_flag = True + try: + match_tests = config["statistics"]["match"] + except: + await socket.send("could not find match_tests field in config") + error_flag = True + try: + metrics_tests = config["statistics"]["metric"] + except: + await socket.send("could not find metrics_tests field in config") + error_flag = True + try: + pit_tests = config["statistics"]["pit"] + except: + await socket.send("could not find pit_tests field in config") + error_flag = True + + if error_flag: + sys.exit(1) + error_flag = False + + if competition == None or competition == "": + await socket.send("competition field in config must not be empty") + error_flag = True + if match_tests == None: + await socket.send("match_tests field in config must not be empty") + error_flag = True + if metrics_tests == None: + await socket.send("metrics_tests field in config must not be empty") + error_flag = True + if pit_tests == None: + await socket.send("pit_tests field in config must not be empty") + error_flag = True + + if error_flag: + sys.exit(1) + + await socket.send("found and loaded competition, match_tests, metrics_tests, pit_tests from config") + + sys_max_threads = os.cpu_count() + try: + cfg_max_threads = config["max-threads"] + except: + await socket.send("max-threads field in config must not be empty, refer to documentation for configuration options", code = 109) + sys.exit(1) + + if cfg_max_threads > -sys_max_threads and cfg_max_threads < 0 : + alloc_processes = sys_max_threads + cfg_max_threads + elif cfg_max_threads > 0 and cfg_max_threads < 1: + alloc_processes = math.floor(cfg_max_threads * sys_max_threads) + elif cfg_max_threads > 1 and cfg_max_threads <= sys_max_threads: + alloc_processes = cfg_max_threads + elif cfg_max_threads == 0: + alloc_processes = sys_max_threads + else: + await socket.send("max-threads must be between -" + str(sys_max_threads) + " and " + str(sys_max_threads) + ", but got " + cfg_max_threads) + sys.exit(1) + + await socket.send("found and loaded max-threads from config") + await socket.send("attempting to start " + str(alloc_processes) + " threads") + try: + exec_threads = Pool(processes = alloc_processes) + except Exception as e: + await socket.send("unable to start threads") + #log(stderr, INF, e) + sys.exit(1) + await socket.send("successfully initialized " + str(alloc_processes) + " threads") + + exit_flag = False + + try: + apikey = config["key"]["database"] + except: + await socket.send("database key field in config must be present") + exit_flag = True + try: + tbakey = config["key"]["tba"] + except: + await socket.send("tba key field in config must be present") + exit_flag = True + + if apikey == None or apikey == "": + await socket.send("database key field in config must not be empty, please populate the database key") + exit_flag = True + if tbakey == None or tbakey == "": + await socket.send("tba key field in config must not be empty, please populate the tba key") + exit_flag = True + + if exit_flag: + sys.exit(1) + + await socket.send("found and loaded database and tba keys") + + previous_time = get_previous_time(apikey) + await socket.send("analysis backtimed to: " + str(previous_time)) + + start = time.time() + await socket.send("loading match data") + match_data = load_match(apikey, competition) + await socket.send("finished loading match data in " + str(time.time() - start) + " seconds") + + start = time.time() + await socket.send("performing analysis on match data") + results = matchloop(apikey, competition, match_data, match_tests, exec_threads) + await socket.send("finished match analysis in " + str(time.time() - start) + " seconds") + + start = time.time() + await socket.send("uploading match results to database") + push_match(apikey, competition, results) + await socket.send("finished uploading match results in " + str(time.time() - start) + " seconds") + + start = time.time() + await socket.send("performing analysis on team metrics") + results = metricloop(tbakey, apikey, competition, current_time, metrics_tests) + await socket.send("finished metric analysis and pushed to database in " + str(time.time() - start) + " seconds") + + start = time.time() + await socket.send("loading pit data") + pit_data = load_pit(apikey, competition) + await socket.send("finished loading pit data in " + str(time.time() - start) + " seconds") + + start = time.time() + await socket.send("performing analysis on pit data") + results = pitloop(apikey, competition, pit_data, pit_tests) + await socket.send("finished pit analysis in " + str(time.time() - start) + " seconds") + + start = time.time() + await socket.send("uploading pit results to database") + push_pit(apikey, competition, results) + await socket.send("finished uploading pit results in " + str(time.time() - start) + " seconds") + + set_current_time(apikey, current_time) + await socket.send("finished all tests in " + str(time.time() - loop_start) + " seconds, looping") + + except KeyboardInterrupt: + await socket.send("detected KeyboardInterrupt, killing threads") + if "exec_threads" in locals(): + exec_threads.terminate() + exec_threads.join() + exec_threads.close() + await socket.send("terminated threads, exiting") + loop_stored_exception = sys.exc_info() + loop_exit_code = 0 + break + except Exception as e: + await socket.send("encountered an exception while running") + print(e, file = stderr) + loop_exit_code = 1 + break + + sys.exit(loop_exit_code) + +def load_config(path, config_vector): + try: + f = open(path, "r") + config_vector.update(json.load(f)) + f.close() + #socket.send("found and opened config at <" + path + ">") + return 0 + except: + #log(stderr, ERR, "could not find config at <" + path + ">, generating blank config and exiting", code = 100) + f = open(path, "w") + f.write(sample_json) + f.close() + return 1 + +def save_config(path, config_vector): + try: + f = open(path) + json.dump(config_vector) + f.close() + return 0 + except: + return 1 + +if __name__ == "__main__": + if sys.platform.startswith("win"): + multiprocessing.freeze_support() + start_server = websockets.serve(main, "127.0.0.1", 5678) + asyncio.get_event_loop().run_until_complete(start_server) + asyncio.get_event_loop().run_forever() \ No newline at end of file diff --git a/src/cli/time-test.py b/src/cli/time-test.py new file mode 100644 index 0000000..9d2c587 --- /dev/null +++ b/src/cli/time-test.py @@ -0,0 +1,20 @@ +import asyncio +import datetime +import random +import websockets + +async def time(websocket, path): + print(path) + i = 0 + while True: + #now = datetime.datetime.utcnow().isoformat() + "Z" + #await websocket.send(now) + #await asyncio.sleep(random.random() * 3) + i += 1 + await websocket.send(str(i)) + await asyncio.sleep(1) + +start_server = websockets.serve(time, "127.0.0.1", 5678) + +asyncio.get_event_loop().run_until_complete(start_server) +asyncio.get_event_loop().run_forever() \ No newline at end of file