This commit is contained in:
Peter Howell 2025-08-10 14:49:44 -07:00
parent 962aed84d6
commit a84ddbb60d
2 changed files with 67 additions and 49 deletions

View File

@ -1254,9 +1254,11 @@ def enroll_gott_workshops():
#['2025-02-23 16:00:00', 'GOTT 6: Intro to Synchronous Teaching (Sync/Hyflex)', 21835],
#['2025-03-14 17:00:00', 'GOTT 5: The Essentials of Blended Learning (Hybrid) ', '21886'],
#['2025-02-23 16:00:00', 'GOTT 1: Intro to Teaching Online (2 week, async)', 21874]
['2025-05-26 17:00:00', 'GOTT 2: Introduction to Asynchronous Teaching and Learning', 23015],
['2025-06-01 17:00:00', 'GOTT 1: Intro to Teaching Online', 23083],
['2025-06-01 17:00:00', 'GOTT 4: Assessments in Digital Learning', 21898],
#['2025-05-26 17:00:00', 'GOTT 2: Introduction to Asynchronous Teaching and Learning', 23015],
#['2025-06-01 17:00:00', 'GOTT 1: Intro to Teaching Online', 23083],
#['2025-06-01 17:00:00', 'GOTT 4: Assessments in Digital Learning', 21898],
['2025-08-11 13:00:00', 'GOTT 1: Introduction to Online Teaching with Canvas', 23232],
]
#print(json.dumps(signups,indent=4))
#print(json.dumps(by_email,indent=4))
@ -1466,15 +1468,17 @@ def set_custom_start_dates():
TERM = term['canvas_term_id']
SEM = term['code']
term_start_month = term['begin'].split('/')[0]
term_start_day = term['begin'].split('/')[1]
term_start_month = int(term['begin'].split('/')[0])
term_start_day = int(term['begin'].split('/')[1])
term_start_year = '20' + term['code'][2:4]
print(f"term begins on {term_start_month}/{term_start_day}")
filepath = f"cache/overview_semester_shells_{SEM}.csv"
if not os.path.exists(filepath):
print(f"file does not exist: {filepath}")
output_path = f"cache/overview_semester_shells_annotated{SEM}.csv"
input_path = f"cache/overview_semester_shells_{SEM}.csv"
if not os.path.exists(input_path):
print(f"file does not exist: {input_path}")
print("Run overview_start_dates first")
return
@ -1499,13 +1503,17 @@ def set_custom_start_dates():
except ValueError:
return None
with open(filepath, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
with open(input_path, newline='', encoding='utf-8') as infile, \
open(output_path, "w", newline='', encoding='utf-8') as outfile:
reader = csv.DictReader(infile)
fieldnames = reader.fieldnames + [
"ignore","is_early_start", "is_late_start", "shell_custom_start", "shell_warn_crosslist_sections"
]
writer = csv.DictWriter(outfile, fieldnames=fieldnames)
writer.writeheader()
for row in reader:
annotations = {}
# Skip shells with no sections
if int(row["shell_numsections"]) == 0:
continue
@ -1514,35 +1522,43 @@ def set_custom_start_dates():
shortname = row["shell_shortname"]
num_sections = int(row["shell_numsections"])
# Check early/late start
if sched_start:
if (sched_start.month, sched_start.day) != (int(term_start_month), int(term_start_day)):
if (sched_start.month, sched_start.day) < (int(term_start_month), int(term_start_day)):
annotations["is_early_start"] = sched_start.date().isoformat()
else:
annotations["is_late_start"] = sched_start.date().isoformat()
# Initialize new columns
row["ignore"] = ""
row["is_early_start"] = ""
row["is_late_start"] = ""
row["shell_custom_start"] = ""
row["shell_warn_crosslist_sections"] = ""
# Check if shell_start is manually set
# check for cops program
department = shortname.split()[0].rstrip("0123456789") # → "JLE"
if department in ("JLE", "JFT"):
row["ignore"] = department
# Early/late start check
if sched_start:
sched_mmdd = (sched_start.month, sched_start.day)
term_mmdd = (term_start_month, term_start_day)
if sched_mmdd < term_mmdd:
row["is_early_start"] = sched_start.date().isoformat()
elif sched_mmdd > term_mmdd:
row["is_late_start"] = sched_start.date().isoformat()
# shell_start override
if shell_start:
annotations["shell_custom_start"] = shell_start.date().isoformat()
row["shell_custom_start"] = shell_start.date().isoformat()
else:
if "is_early_start" in annotations or "is_late_start" in annotations:
if row["is_early_start"] or row["is_late_start"]:
adjust_shell_startdate(row)
# Check section numbers in shortname vs shell_numsections
# Crosslist check
if '/' in shortname:
parts = shortname.split()
section_part = parts[-1] # last part assumed to be section numbers
section_groups = section_part.split('/')
if len(section_groups) != num_sections:
annotations["shell_warn_crosslist_sections"] = section_part
# Print row and annotations if anything notable happened
if annotations:
print("Annotations:", annotations)
print("Row:", row)
print("-" * 80)
section_part = parts[-1]
section_count = len(section_part.split('/'))
if section_count != num_sections:
row["shell_warn_crosslist_sections"] = section_part
writer.writerow(row)
return
'''
# Do we adjust the start date? Only if it doesn't match term
@ -1867,9 +1883,10 @@ def create_sandboxes():
#(20761, ' Sandbox GOTT1 FA24'),
#(21770, ' Sandbox GOTT1 WI25'),
#(21772, ' Sandbox GOTT2 WI25'),
(23083, ' Sandbox GOTT1 SU25'),
(23015, ' Sandbox GOTT2 SU25'),
(21898, ' Sandbox GOTT4 SU25'),
#(23083, ' Sandbox GOTT1 SU25'),
#(23015, ' Sandbox GOTT2 SU25'),
#(21898, ' Sandbox GOTT4 SU25'),
(23232, ' Sandbox GOTT1 FA25'),
]
filepath = 'cache/sandbox_courses.pkl'
@ -2537,16 +2554,17 @@ def bulk_unenroll():
print(f"Failed to unenroll student with id {enrollment_id} from course {course_id}. Error: {response.text}")
def fetch_announcements():
course_id = 20603
announcements_url = f"{url}/api/v1/announcements?context_codes[]=course_{course_id}"
def fetch_announcements(course_id=0):
if not course_id:
course_id = input("course id> ")
announcements_url = f"{url}/api/v1/announcements?context_codes[]=course_{course_id}&start_date=2025-01-01&end_date=2025-12-31"
announcements = fetch(announcements_url)
print(json.dumps(announcements,indent=2))
filename = f"cache/announcements{course_id}.json"
filename = f"cache/announcements_{course_id}.json"
with open(filename, "w") as file:
json.dump(announcements, file)
json.dump(announcements, file,indent=2)
print("Announcements saved to ", filename)

View File

@ -2243,6 +2243,8 @@ def cross_ref_training():
term = "202570"
# Fetch from Canvas DB. Make sure its recently updated.
# Also relies on schedule being in database. Run localcache2.courses_to_sched()
# OR localcache2.refresh_semester_schedule_db()
#courses = all_2x_sem_courses_teachers('202550', '202570') #
courses = all_sem_courses_teachers(term)
@ -2456,7 +2458,7 @@ def cross_ref_training():
sheet.column_dimensions['A'].width = 20
sheet.column_dimensions['B'].width = 30
sheet.column_dimensions['C'].width = 75
formatted_date = datetime.datetime.now().strftime('%Y%m%d')
formatted_date = dt.now().strftime('%Y%m%d')
wb.save(f"C:/Users/phowell/Downloads/GOTT_Completion_masterlist_{formatted_date}_summarized.xlsx")
def cross_ref_training_withcsv():
@ -2709,7 +2711,6 @@ def summarize_submissions(submissions):
})
return summary
from datetime import datetime
import pytz
def format_assignments_results_table(results):
@ -2722,14 +2723,14 @@ def format_assignments_results_table(results):
def to_pacific(iso):
if not iso:
return "-"
utc = datetime.strptime(iso, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=pytz.utc)
utc = dt.strptime(iso, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=pytz.utc)
pacific = utc.astimezone(pytz.timezone("US/Pacific"))
return pacific.strftime("%Y-%m-%d %I:%M%p")
# Sort by assignment due date (missing dates go last)
def get_due_at(item):
dt = item["assignment"].get("due_at")
return datetime.max if not dt else datetime.strptime(dt, "%Y-%m-%dT%H:%M:%SZ")
return dt.max if not dt else dt.strptime(dt, "%Y-%m-%dT%H:%M:%SZ")
results = sorted(results, key=get_due_at)
@ -2856,7 +2857,6 @@ def summarize_student_logs(id=0):
import re
import json
from collections import defaultdict
from datetime import datetime
from localcache2 import course_from_id
if id==0: