Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4daf3a6

Browse files
committedJun 10, 2020
converted everything to python
1 parent 8970b0c commit 4daf3a6

12 files changed

+171
-403
lines changed
 

‎.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# top-most EditorConfig file
2+
root = true
3+
4+
# Unix-style newlines with a newline ending every file
5+
[*]
6+
end_of_line = lf
7+
insert_final_newline = true
8+
9+
# 4 space indentation
10+
[*.py]
11+
charset = utf-8
12+
indent_style = space
13+
indent_size = 4

‎README.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,22 @@ This is where we do the scheduling magic.
44

55
## How to use
66

7-
1. `getSchoolTimezones.js` averages timezones across a school based on the timezones of the students who RSVP'd from that school.
8-
2. `orderSchools.py` does the big work, creating a schedule of schools based on the average timezone (preferring to start at 2 PM localized when possible), then using the school schedule to generate a schedule of students (`student schedule utc.csv`). This schedule maximizes the number of students who get a good localized timeslot, but this leads to a very broken up ceremony as students are spread out. To fix this, manually cluster the students using Google Sheets (upload the csv, pick start times for clusters and use the drag autofill feature).
7+
average school timezones
8+
generate schedule
9+
merge schedule
10+
get uuids
11+
genereate quote audio
12+
import sql
13+
play ceremony audio
14+
15+
16+
maybe:
17+
convert m4a
18+
reset timeslots
19+
20+
21+
1. `average school times.js` averages timezones across a school based on the timezones of the students who RSVP'd from that school.
22+
2. `gener.py` does the big work, creating a schedule of schools based on the average timezone (preferring to start at 2 PM localized when possible), then using the school schedule to generate a schedule of students (`student schedule utc.csv`). This schedule maximizes the number of students who get a good localized timeslot, but this leads to a very broken up ceremony as students are spread out. To fix this, manually cluster the students using Google Sheets (upload the csv, pick start times for clusters and use the drag autofill feature).
923
3. `mergeScheduleWithRSVP.py` creates the final dataset, which includes students' RSVP info, their school start time (UTC), and their start time (UTC). Send an email to people with their start times UTC, and localized if we have their timezone.
1024
4. get uuids
1125
5.
@@ -14,10 +28,12 @@ This is where we do the scheduling magic.
1428

1529
Just make sure you use the autoformatter when you're done (`npm run format`). You'll have to install the Python dependencies (including the formatter, [black](https://github.com/psf/black)) separately from your `npm install`.
1630

31+
black .
32+
1733
# TODO
1834

1935
- add the above sql calls when deleting so that auto increment is fixed
2036
- fix licenses on all repos here (GPL) and add all the fixins (contributors etc, check the Github community todolist)
2137
- make all scripts python and add a requirements.txt
2238
- make all scripts take command line input (either in args/flags or when running if no flags passed)/.env stuff so nothing is hard coded
23-
- add reset sql script
39+
- add reset sql script

‎average_school_timezones.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import csv
2+
import statistics
3+
from collections import defaultdict
4+
5+
# load data
6+
filename = input("Enter contacts filename (default: contacts.csv): ") or "contacts.csv"
7+
with open("data/{}".format(filename), encoding="utf-8") as scheduleFile:
8+
contacts = [
9+
{k: v for k, v in row.items()}
10+
for row in csv.DictReader(scheduleFile, skipinitialspace=True)
11+
]
12+
13+
# prepare default dicts so we don't have to check if key exists
14+
school_to_timezones = defaultdict(list)
15+
school_to_student_count = defaultdict(int)
16+
17+
for contact in contacts:
18+
# use default value for schools
19+
school = "Unknown" if contact["Your school"] == "" else contact["Your school"]
20+
21+
# append timezone if it parses, otherwise ignore
22+
try:
23+
tz = int(contact["Time Zone"])
24+
school_to_timezones[school].append(tz)
25+
except ValueError:
26+
print("No timezone found for {}".format(contact["Your Full Name"]))
27+
28+
# increment number of students in this school
29+
school_to_student_count[school] += 1
30+
31+
schools = []
32+
SEC_PER_PERSON = 30
33+
34+
# generate data
35+
for school, timezones in school_to_timezones.items():
36+
total_students = school_to_student_count[school]
37+
schools.append(
38+
{
39+
"School": school,
40+
"Average Timezone": round(statistics.mean(timezones)),
41+
"Students": total_students,
42+
"Seconds": round(total_students * SEC_PER_PERSON, 2),
43+
"Minutes": round(total_students * SEC_PER_PERSON / 60, 2),
44+
"Hours": round(total_students * SEC_PER_PERSON / 60 / 60, 2),
45+
}
46+
)
47+
48+
# save CSV
49+
filename = (
50+
input("Enter timezones filename (default: school timezones.csv): ")
51+
or "school timezones.csv"
52+
)
53+
with open(
54+
"data/{}".format(filename), "w", encoding="utf-8", newline=""
55+
) as timezones_file:
56+
csvFields = list(schools[0].keys())
57+
writer = csv.DictWriter(timezones_file, fieldnames=csvFields)
58+
writer.writeheader()
59+
writer.writerows(schools)
60+
print("\n--> Saved {}".format(filename))

‎generate_schedule.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ def comparer(left, right):
3636

3737

3838
# load data then sort by descending timezone and ascending school within timezone
39-
filename = input("Enter timezones filename (default: school timezones.csv): ") or "school timezones.csv"
39+
filename = (
40+
input("Enter timezones filename (default: school timezones.csv): ")
41+
or "school timezones.csv"
42+
)
4043
with open("data/{}".format(filename), encoding="utf-8") as schoolTimezonesFile:
4144
data = [
4245
{k: v if k == "School" else float(v) for k, v in row.items()}
@@ -222,15 +225,18 @@ def __eq__(self, other):
222225
print(tabulate(print_order, headers="keys"))
223226

224227
# save utc student schedule
225-
filename = input("Enter student schedule filename (default: student schedule utc.csv): ") or "student schedule utc.csv"
228+
filename = (
229+
input("Enter student schedule filename (default: student schedule utc.csv): ")
230+
or "student schedule utc.csv"
231+
)
226232
with open(
227233
"data/{}".format(filename), "w", encoding="utf-8", newline=""
228234
) as studentScheduleFile:
229235
csvFields = list(pretty_order[0].keys())
230236
writer = csv.DictWriter(studentScheduleFile, fieldnames=csvFields)
231237
writer.writeheader()
232238
writer.writerows(pretty_order)
233-
print("\n--> Saved student schedule utc.csv!")
239+
print("\n--> Saved {}".format(filename))
234240

235241
pretty_order = [
236242
{

‎getSchoolTimezones.js

Lines changed: 0 additions & 67 deletions
This file was deleted.

‎getUUIDs.js

Lines changed: 0 additions & 68 deletions
This file was deleted.

‎get_minecraft_uuids.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import csv
2+
import requests
3+
4+
# load contacts
5+
filename = input("Enter contacts filename (default: contacts.csv): ") or "contacts.csv"
6+
with open("data/{}".format(filename), encoding="utf-8") as scheduleFile:
7+
contacts = [
8+
{k: v for k, v in row.items()}
9+
for row in csv.DictReader(scheduleFile, skipinitialspace=True)
10+
]
11+
12+
# if user says they have minecraft account, fetch their UUID
13+
def fetch_uuid(contact):
14+
if (
15+
contact[
16+
"I confirm I have a Minecraft Java Edition account or will get one before the ceremony"
17+
]
18+
== "Yup, I got it!"
19+
):
20+
username = contact["Your Minecraft Username"]
21+
data = requests.get("https://api.ashcon.app/mojang/v2/user/{}".format(username))
22+
data.json()
23+
contact["UUID"] = data["uuid"]
24+
return contact
25+
else:
26+
contact["UUID"] = ""
27+
return contact
28+
29+
30+
contacts_with_uuids = [fetch_uuid(contact) for contact in contacts]
31+
32+
# save CSV
33+
filename = input("Enter contacts filename (default: contacts.csv): ") or "contacts.csv"
34+
with open(
35+
"data/{}".format(filename), "w", encoding="utf-8", newline=""
36+
) as timezones_file:
37+
csvFields = list(contacts_with_uuids[0].keys())
38+
writer = csv.DictWriter(timezones_file, fieldnames=csvFields)
39+
writer.writeheader()
40+
writer.writerows(contacts_with_uuids)
41+
print("\n--> Saved {}".format(filename))

‎merge_schedule_with_contacts.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@
1010
SAVE_SCHOOL_HTML = True
1111

1212
# load clustered schedule (make sure you go make that first in google sheets)
13-
filename = input("Enter clustered schedule filename (default: student schedule utc clustered.csv): ") or "student schedule utc clustered.csv"
13+
filename = (
14+
input(
15+
"Enter clustered schedule filename (default: student schedule utc clustered.csv): "
16+
)
17+
or "student schedule utc clustered.csv"
18+
)
1419
with open("data/{}".format(filename), encoding="utf-8") as file:
1520
data = [
1621
{k: v for k, v in row.items()}
@@ -109,23 +114,33 @@
109114

110115
if SAVE_SCHOOL_CSV:
111116
# save utc school schedule
112-
filename = input("Enter school schedule CSV filename (default: school schedule utc.csv): ") or "school schedule utc.csv"
117+
filename = (
118+
input("Enter school schedule CSV filename (default: school schedule utc.csv): ")
119+
or "school schedule utc.csv"
120+
)
113121
with open(
114122
"data/{}".format(filename), "w", encoding="utf-8", newline=""
115123
) as schoolScheduleCSVFile:
116124
csvFields = ["School", "Start Time"]
117125
writer = csv.DictWriter(schoolScheduleCSVFile, fieldnames=csvFields)
118126
writer.writeheader()
119127
writer.writerows(schoolOrder)
120-
print("\n--> Saved FINAL school schedule utc CSV!")
128+
print("\n--> Saved {}".format(filename))
121129

122130
if SAVE_SCHOOL_HTML:
123131
# use tabulate to save html school schedule
124-
filename = input("Enter school schedule HTML filename (default: school-schedule.html): ") or "school-schedule.html"
125-
with open("data/{}".format(filename), "w", encoding="utf-8") as schoolScheduleHTMLFile:
126-
schoolScheduleHTMLFile.write(tabulate(schoolOrder, headers="keys", tablefmt="html"))
132+
filename = (
133+
input("Enter school schedule HTML filename (default: school-schedule.html): ")
134+
or "school-schedule.html"
135+
)
136+
with open(
137+
"data/{}".format(filename), "w", encoding="utf-8"
138+
) as schoolScheduleHTMLFile:
139+
schoolScheduleHTMLFile.write(
140+
tabulate(schoolOrder, headers="keys", tablefmt="html")
141+
)
127142
print(schoolOrder)
128-
print("\n--> Saved FINAL school schedule utc HTML!")
143+
print("\n--> Saved {}".format(filename))
129144

130145
# save final dataset
131146
finalData = []
@@ -138,12 +153,15 @@
138153
student["Approx Time Zone"] = item["Time Zone"]
139154
finalData.append(student)
140155

141-
filename = input("Enter student schedule filename (default: student schedule utc.csv): ") or "student schedule utc.csv"
156+
filename = (
157+
input("Enter student schedule filename (default: student schedule utc.csv): ")
158+
or "student schedule utc.csv"
159+
)
142160
with open(
143161
"data/{}".format(filename), "w", encoding="utf-8", newline=""
144162
) as studentScheduleFile:
145163
csvFields = list(finalData[0].keys())
146164
writer = csv.DictWriter(studentScheduleFile, fieldnames=csvFields)
147165
writer.writeheader()
148166
writer.writerows(finalData)
149-
print("\n--> Saved FINAL student schedule utc.csv!")
167+
print("\n--> Saved {}".format(filename))

‎package-lock.json

Lines changed: 0 additions & 234 deletions
This file was deleted.

‎package.json

Lines changed: 0 additions & 18 deletions
This file was deleted.

‎play_ceremony_audio.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def playAudio(filePath, name):
3030
audio = AudioSegment.from_mp3(filePath)
3131
play(audio)
3232

33+
3334
filename = input("Enter data filename (default: contacts.csv): ") or "contacts.csv"
3435
with open("data/{}".format(filename), encoding="utf-8") as scheduleFile:
3536
graduates = [

‎reset_timeslots.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@
2929
cursor.execute(sql)
3030
print("> Reset timeslots")
3131
finally:
32-
connection.close()
32+
connection.close()

0 commit comments

Comments
 (0)
Please sign in to comment.