From 0ad2588c3dec5c1c32c6d1c52b5d24d34434ebf2 Mon Sep 17 00:00:00 2001 From: Jeff Kaufman Date: Sun, 10 Jan 2021 19:03:08 +0000 Subject: [PATCH] offsets: better assign users to positions When someone is in spectator mode, always assign them to the last bucket. Fixes #172 When it is time to double up buckets, assign people to later buckets. Use all the buckets, instead of N-1. Fixes #174 --- html/demo.js | 3 +++ server.py | 44 ++++++++++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/html/demo.js b/html/demo.js index d306855..3527348 100644 --- a/html/demo.js +++ b/html/demo.js @@ -1559,6 +1559,9 @@ async function start_singing() { last_server_bpr = server_bpr; } singer_client.x_send_metadata("user_summary", 1); + if (in_spectator_mode) { + singer_client.x_send_metadata("spectator", 1); + } if (delay_seconds) { if (delay_seconds > 0) { diff --git a/server.py b/server.py index 357c95b..a33c253 100755 --- a/server.py +++ b/server.py @@ -340,6 +340,8 @@ def __init__(self, userid, name, last_heard_server_clock, delay_samples) -> None self.client_address = None # Last IP we saw them from self.client_telemetry = {} # unstructured info from client + self.in_spectator_mode = False; + self.mark_sent() self.send("bpm", state.bpm) @@ -475,25 +477,37 @@ def assign_delays(userid_lead) -> None: if initial_position > 90: initial_position = 90 + real_users = [user for user in active_users() if user not in imaginary_users] + leader = users[userid_lead] + spectators = [ + user for user in real_users + if user.in_spectator_mode and user.userid != userid_lead] + followers = [ + user for user in real_users + if not user.in_spectator_mode and user.userid != userid_lead] + + # Only the leader goes in bucket #1 state.first_bucket = initial_position + DELAY_INTERVAL - users[userid_lead].send("delay_seconds", state.first_bucket) + leader.send("delay_seconds", state.first_bucket) sendall("first_bucket", state.first_bucket) - positions = [initial_position + x*DELAY_INTERVAL - for x in range(2, LAYERING_DEPTH)] + n_follow_buckets = max(min(LAYERING_DEPTH - 1, len(followers)), 1) + follow_positions = [ + initial_position + (x+2)*DELAY_INTERVAL + for x in range(n_follow_buckets)] + state.max_position = follow_positions[-1] - # Randomly shuffle the remaining users, and assign them to positions. If we - # have more users then positions, then double up. - # TODO: perhaps we should prefer to double up from the end? - state.max_position = initial_position + DELAY_INTERVAL*2 + # Spectators all go in the last bucket. + for spectator in spectators: + spectator.send("delay_seconds", state.max_position) + + # Distribute followers randomly between the remaining buckets. for i, (_, user) in enumerate(sorted( - [(random.random(), user) - for user in active_users() - if user.userid != userid_lead and - user not in imaginary_users])): - position = positions[i % len(positions)] - user.send("delay_seconds", position) - state.max_position = max(position, state.max_position) + [(random.random(), follower) + for follower in followers])): + user.send("delay_seconds", + follow_positions[(len(follow_positions) - 1 - i) % + len(follow_positions)]) def update_users(userid, username, server_clock, client_read_clock) -> None: while len(imaginary_users) < N_IMAGINARY_USERS: @@ -1009,6 +1023,8 @@ def handle_post(in_data, query_string, print_status, client_address=None) -> Tup if client_address is not None: user.client_address = client_address + user.in_spectator_mode = query_params.get("spectator", None) + client_telemetry = query_params.get("client_telemetry", None) if client_telemetry: user.update_client_telemetry(json.loads(client_telemetry))