import asyncio import atexit import datetime import json import os.path import socket from functools import lru_cache from pathlib import Path from time import sleep, time import matplotlib.pyplot as plt import socketio from apscheduler.schedulers.background import BackgroundScheduler from flask import Flask, render_template, request from flask_cors import CORS sio = socketio.Server() app = Flask(__name__) CORS(app, resources={r"/*": {"origins": "*"}}) app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app) # We request users to send the run number to prevent accidentially getting old requests from a previous run # This maybe will give to much errors from people forgetting to change their number # Remove it? # TODO # Save and read from a file to persist over reboots # Save progress through time during 1 run # Save result of different runs db = {"current_run": None, "run_start_timer": None, "run_data": {}} function_times = [] function_data = [] def save_data(): with open('data.json', 'w') as outfile: json.dump(db, outfile) def load_data(): with open('data.json', 'r') as infile: db = json.load(infile) data_file = Path("data.json") if data_file.is_file(): load_data() @app.route("/") def index(): return render_template('index.html') @app.route("/start_run/") def start_run(run_index): if "Authorization" not in request.headers or request.headers[ 'Authorization'] != "dsfqlkjmlkjls,,n": return "Unauthorized" request_data = live_request( f'/start_run/{run_index}') #make request show up on the live requests if not run_index.isdigit(): return f'{run_index} is not a number' if run_index in db["run_data"]: return "This run is already ran, take another number." db["current_run"] = run_index starttime = time() db["run_data"][run_index] = {"starttime": starttime, "data": {}} save_data() # TODO send start request to the first person in the chain. Probably a zeus part already written as example sio.emit('start_run', run_index) return f'Run {run_index} started at {starttime}' @app.route("/link/start//") def link_start(run, link_index): request_data = live_request(f'/link/start/{run}/{link_index}' ) #make request show up on the live requests if not run.isdigit() or not link_index.isdigit(): return f'{run} and/or {link_index} is not a number' start = time() if db["current_run"] != run: response = "Wrong run number, check that you update your run", 404 else: run_data = db["run_data"][run]["data"] if link_index in run_data: response = "you already started in this run. Ignoring this request." else: run_data[link_index] = {"id": link_index, "start": time()} save_data() sio.emit('link_start', run_data[link_index]) response = "Success." stop = time() function_data.append(stop - start) function_times.append(len(function_times)) return response @app.route("/link/handoff//") def link_handoff(run, link_index): request_data = live_request(f'/link/handoff/{run}/{link_index}' ) #make request show up on the live requests if not run.isdigit() or not link_index.isdigit(): return f'{run} and/or {link_index} is not a number' if db["current_run"] != run: return "Wrong run number, check that you updated you run", 404 else: if index not in db["run_data"][run]["data"]: return "This link did not start yet..." link_data = db["run_data"][run]["data"][link_index] save_data() if "handoff" in link_data: return "you already handed off control during this run. Ignoring this request" else: link_data["handoff"] = time() sio.emit('link_handoff', link_data) return "Success." @sio.event def connect(sid, data): if db["current_run"]: current_run = db["run_data"][db["current_run"]] sio.emit('sync_current_run', current_run, room=sid) def live_request(route_data): ip = request.remote_addr request_data = {} request_data["hostname"] = lookup_hostname(ip) request_data["time"] = time() request_data["route"] = route_data sio.emit('live_request', request_data) @lru_cache() def lookup_hostname(ip): return socket.gethostbyaddr(ip)[0].split(".")[0] # def plot_graph(): # try: # x = function_times # y = function_data # plt.plot(x, y) # plt.show() # except: # pass if __name__ == '__main__': # scheduler = BackgroundScheduler() # scheduler.add_job(func=plot_graph, trigger="interval", seconds=5) # scheduler.start() app.run(host="10.1.0.155", debug=True) # shut down the scheduler when exiting the app # atexit.register(lambda: scheduler.shutdown())