one thing that is clear to me is that the preferred name logic should really be removed entirely from the coldcall.py program and moved into the coldcall.py file. I'm currently ignoring that functionality in the coldcallbot-manual.py but I haven't yet fully removed it from the other.
122 lines
4.8 KiB
Python
122 lines
4.8 KiB
Python
#!/usr/bin/env python3
|
|
|
|
from collections import defaultdict
|
|
from datetime import datetime
|
|
from random import choices
|
|
from os import listdir
|
|
from csv import DictReader
|
|
|
|
import os.path
|
|
import re
|
|
|
|
class ColdCall():
|
|
def __init__ (self, record_attendance=True, preferred_name_field=None):
|
|
self.today = str(datetime.date(datetime.now()))
|
|
# how much less likely should it be that a student is called upon?
|
|
self.weight = 2
|
|
self.record_attendance = record_attendance
|
|
|
|
# filenames
|
|
self.__fn_studentinfo = "data/student_information.tsv"
|
|
self.__fn_daily_calllist = f"data/call_list-{self.today}.tsv"
|
|
self.__fn_daily_attendance = f"data/attendance-{self.today}.tsv"
|
|
self.__preferred_name_field = preferred_name_field
|
|
|
|
if preferred_name_field != None:
|
|
self.preferred_names = self.__get_preferred_names()
|
|
else:
|
|
self.preferred_names = None
|
|
|
|
def __load_prev_questions(self):
|
|
previous_questions = defaultdict(int)
|
|
|
|
for fn in listdir("./data/"):
|
|
if re.match("call_list-\d{4}-\d{2}-\d{2}.tsv", fn):
|
|
with open(f"./data/{fn}", 'r') as f:
|
|
for row in DictReader(f, delimiter="\t"):
|
|
if not row["answered"] == "FALSE":
|
|
previous_questions[row["unique_name"]] += 1
|
|
|
|
return previous_questions
|
|
|
|
def __get_preferred_names(self):
|
|
# translate the unique name into the preferred students name,
|
|
# if possible, otherwise return the unique name
|
|
|
|
preferred_names = {}
|
|
with open(self.__fn_studentinfo, 'r') as f:
|
|
for row in DictReader(f, delimiter="\t"):
|
|
row["Your UW student number"] = row[self.__preferred_name_field]
|
|
|
|
return(preferred_names)
|
|
|
|
def __get_preferred_name(self, selected_student):
|
|
if selected_student in self.preferred_names:
|
|
return self.preferred_names[selected_student]
|
|
else:
|
|
return None
|
|
|
|
def select_student_from_list(self, students_present):
|
|
prev_questions = self.__load_prev_questions()
|
|
|
|
# created a weighted list by starting out with everybody 1
|
|
weights = {s : 1 for s in students_present}
|
|
|
|
for s in students_present:
|
|
for i in range(0, prev_questions[s]):
|
|
# reduce the weight by a factor of 1/weight each time the student has been called upon
|
|
weights[s] = weights[s] / self.weight
|
|
|
|
# choose one student from the weighted list
|
|
# print(weights) # DEBUG LINE
|
|
return choices(list(weights.keys()), weights=list(weights.values()), k=1)[0]
|
|
|
|
def record_attendance(self, students_present):
|
|
# if it's the first one of the day, write it out
|
|
if not os.path.exists(self.__fn_daily_attendance):
|
|
with open(self.__fn_daily_attendance, "w") as f:
|
|
print("\t".join(["timestamp", "attendance_list"]), file=f)
|
|
|
|
# open for appending the student
|
|
with open(self.__fn_daily_attendance, "a") as f:
|
|
print("\t".join([str(datetime.now()),
|
|
",".join(students_present)]),
|
|
file=f)
|
|
|
|
def record_coldcall(self, selected_student):
|
|
# if it's the first one of the day, write it out
|
|
if not os.path.exists(self.__fn_daily_calllist):
|
|
with open(self.__fn_daily_calllist, "w") as f:
|
|
print("\t".join(["unique_name", "timestamp", "answered", "assessment"]), file=f)
|
|
|
|
# open for appending the student
|
|
with open(self.__fn_daily_calllist, "a") as f:
|
|
print("\t".join([selected_student, str(datetime.now()),
|
|
"MISSING", "MISSING"]), file=f)
|
|
|
|
def coldcall(self, students_present):
|
|
selected_student = self.select_student_from_list(students_present)
|
|
|
|
# record the called-upon student in the right place
|
|
if self.record_attendance:
|
|
self.record_attendance(students_present)
|
|
self.record_coldcall(selected_student)
|
|
|
|
preferred_name = self.__get_preferred_name(selected_student)
|
|
if preferred_name:
|
|
coldcall_message = f"{preferred_name} (@{selected_student}), you're up!"
|
|
else:
|
|
coldcall_message = f"@{selected_student}, you're up!"
|
|
return coldcall_message
|
|
|
|
# cc = ColdCall()
|
|
|
|
# test_student_list = ["jordan", "Kristen Larrick", "Madison Heisterman", "Maria.Au20", "Laura (Alia) Levi", "Leona Aklipi", "anne", "emmaaitelli", "ashleylee", "allie_partridge", "Tiana_Cole", "Hamin", "Ella Qu", "Shizuka", "Ben Baird", "Kim Do", "Isaacm24", "Sam Bell", "Courtneylg"]
|
|
# print(cc.coldcall(test_student_list))
|
|
|
|
# test_student_list = ["jordan", "Kristen Larrick", "Mako"]
|
|
# print(cc.coldcall(test_student_list))
|
|
|
|
# test_student_list = ["jordan", "Kristen Larrick"]
|
|
# print(cc.coldcall(test_student_list))
|