Skip to content

Instantly share code, notes, and snippets.

@Ramblurr
Last active June 4, 2022 09:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ramblurr/f4b1145cc42ad840f1b372e4619f055e to your computer and use it in GitHub Desktop.
Save Ramblurr/f4b1145cc42ad840f1b372e4619f055e to your computer and use it in GitHub Desktop.
a quick script to generate a reherseal schedule for a street band
from itertools import cycle
from datetime import date, timedelta
import random
import math
from tabulate import tabulate
# How many weeks should we generate a probenplan for?
weeks = 6
# What date does the first probe start on?
start_date = date(2022, 6, 8)
plan_format = {
# How many intensive songs should there be per probe?
"intensive": 1,
# How many durchspielen songs should there be per probe?
"durchspielen": 6,
# How many of the intensive songs should repeat the next week?
"repeat_intensive": 1,
# Should the song order be shuffled after one full rotation?
"shuffle": True,
}
# What are the numbers?
songs = [
"Asterix",
"Bella Ciao",
"Cumbia Sobre el Mar",
"Der Zug um 7.40",
"Grenzrenner",
"Inner Babylon",
"Kids Aren't Alright",
# "Klezma 34",
"Laisse Tomber Les Filles",
"L’estaca del pueblo",
"Metanioa",
"Monkeys Rally",
"Montserrat Serrat",
"Rasta Funk",
"Tammurriata Nera",
"Tschufittl Cocek",
"You Move You Lose",
]
def gen_probe(plan_format, song_cycle, last_plan):
"""
Generates a probenplan for a single probe
"""
number_intensive = plan_format["intensive"]
number_durchspielen = plan_format["durchspielen"]
repeat_intensive = plan_format["repeat_intensive"]
assert (
repeat_intensive <= number_intensive
), "the number of intensive to repeat must be less than or equal to the number of intensive"
intensive = []
durchspielen = []
for n in range(number_intensive):
s = next(song_cycle)
intensive.append(s)
if repeat_intensive > 0 and last_plan is not None:
for n in range(repeat_intensive):
s = last_plan["intensive"][n]
durchspielen.append(s)
durchspielen_start = repeat_intensive
durchspielen_fresh = number_durchspielen - repeat_intensive
else:
durchspielen_fresh = number_durchspielen
durchspielen_start = 0
for n in range(durchspielen_start, durchspielen_fresh):
s = next(song_cycle)
durchspielen.append(s)
return {"intensive": intensive, "durchspielen": durchspielen}
def generate_probenplan(plan_format, weeks, songs):
"""
Generates a probenplan for a certain number of weeks and a given
repertoire.
The plan will be generated according to the plan format.
"""
song_cycle = cycle(songs)
plans = []
weeks_till_cycle = len(songs) / (
plan_format["intensive"]
+ (plan_format["durchspielen"] - plan_format["repeat_intensive"])
)
if plan_format["shuffle"]:
random.shuffle(songs)
# I always round up to ensure we play every song at least once per cycle
# we might play some more than once, but that's math
round_weeks_till_cycle = math.ceil(weeks_till_cycle)
for week in range(weeks):
if plan_format["shuffle"] and week > 0 and week % round_weeks_till_cycle == 0:
random.shuffle(songs)
song_cycle = cycle(songs)
# print(f"shuffling at week {week}")
if week > 0:
last_plan = plans[-1]
else:
last_plan = None
probe = gen_probe(plan_format, song_cycle, last_plan)
plans.append(probe)
return plans, weeks_till_cycle
def inc_playcount(play_counts, song):
return play_counts.get(song, 0) + 1
def report_table(plan):
records = []
for n, s in enumerate(plan["intensive"]):
records.append(["intensive", s])
for n, s in enumerate(plan["durchspielen"]):
records.append(["durchspielen", s])
headers = ["type", "song"]
return tabulate(records, headers, tablefmt="github")
def report_play_counts(play_counts):
records = []
for song, count in play_counts.items():
records.append([song, count])
headers = ["song", "num times played"]
return tabulate(records, headers, tablefmt="github")
def report_probenplan(plans, songs, start_date, weeks_till_cycle):
weeks = len(plans)
print("─" * 100)
print(
f"## Probenplan for {len(songs)} songs for {len(plans)} weeks starting on {start_date}"
)
play_counts = {}
for i, plan in enumerate(plans):
probe_date = start_date + timedelta(days=i * 7)
print(f"### week {i+1} {probe_date}")
for n, s in enumerate(plan["intensive"]):
play_counts[s] = inc_playcount(play_counts, s)
for n, s in enumerate(plan["durchspielen"]):
play_counts[s] = inc_playcount(play_counts, s)
print()
print(report_table(plan))
print()
print("### Play Counts")
print(report_play_counts(play_counts))
if __name__ == "__main__":
plans, weeks_till_cycle = generate_probenplan(plan_format, weeks, songs)
report_probenplan(plans, songs, start_date, weeks_till_cycle)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment