493 lines
12 KiB
Python
493 lines
12 KiB
Python
# Try to gather all the different formats and ways of labeling a semester, along with their associated dates.
|
|
|
|
import json, funcy, re, sys
|
|
|
|
# sem_to_short = { 'Summer 2021': 'su21', 'Fall 2021':'fa21', 'Winter 2022':'wi22', 'Spring 2022':'sp22', 'Summer 2022':'su22', 'Fall 2022':'fa22' }
|
|
|
|
season_to_number = { 'Fall': '70', 'Summer': '50', 'Spring': '30', 'Winter': '10'}
|
|
|
|
# Inverse
|
|
number_to_season = {v: k for k, v in season_to_number.items()}
|
|
|
|
s_to_n = {'sp':'30','su':'50','fa':'70'}
|
|
season_to_short = {
|
|
'Summer': 'su',
|
|
'Fall': 'fa',
|
|
'Winter': 'wi',
|
|
'Spring': 'sp'
|
|
}
|
|
|
|
|
|
# Given 'fa22' return 202270
|
|
def short_to_sis(s):
|
|
season = s[0:2]
|
|
return "20" + s[2:5] + s_to_n[season]
|
|
|
|
|
|
|
|
# go from sp20 to 2020spring
|
|
def short_to_long(s):
|
|
parts = re.search(r'(\w\w)(\d\d)', s)
|
|
yr = parts.group(2)
|
|
season = parts.group(1)
|
|
seasons = {'sp':'spring','su':'summer','fa':'fall','wi':'winter'}
|
|
return '20'+yr+seasons[season]
|
|
|
|
# from "Summer 2024" or "2024 Summer" to ("Summer", 2024)
|
|
def normalize(label):
|
|
"""Return (season, year) tuple, or None if not standard."""
|
|
m = re.search(r'(Fall|Summer|Spring|Winter)\s+(\d{4})', label, re.I)
|
|
if m:
|
|
return (m.group(1).title(), int(m.group(2)))
|
|
else:
|
|
m = re.search(r'(\d{4})\s+(Fall|Summer|Spring|Winter)', label, re.I)
|
|
if m:
|
|
return (m.group(2), int(m.group(1).title()))
|
|
return None
|
|
|
|
# from "Summer 2024" to 202450
|
|
def human_to_sis(semester):
|
|
try:
|
|
# Split the semester into its components
|
|
parts = semester.split()
|
|
|
|
# Extract the season and year
|
|
season = parts[0]
|
|
year = parts[1]
|
|
|
|
# Generate the code in the format "YYYYSS"
|
|
return f"{year}{season_to_number[season]}"
|
|
except Exception as e:
|
|
print(f"Couldn't parse semester: {semester}'")
|
|
return ''
|
|
|
|
# from 202450 to "Summer 2024"
|
|
def sis_to_human(sis_code):
|
|
try:
|
|
# Extract the year and season code
|
|
year = sis_code[:4]
|
|
season_code = sis_code[4:]
|
|
|
|
# Convert season code back to season name
|
|
season = number_to_season.get(season_code, "Unknown")
|
|
|
|
return f"{season} {year}"
|
|
except Exception as e:
|
|
print(f"Couldn't parse SIS code: {sis_code}")
|
|
return ''
|
|
|
|
# from "Summer 2024" to su24
|
|
def human_to_short(semester):
|
|
# Split the semester into its components
|
|
parts = semester.split()
|
|
|
|
# Extract the season and year
|
|
season = parts[0]
|
|
year = parts[1][2:] # Take the last two digits of the year
|
|
|
|
# Generate the short form
|
|
return f"{season_to_short[season]}{year}"
|
|
|
|
# given human readable form (Spring 2023) return that of the previous semester. Excluding winter.
|
|
def get_previous_season(season_year_str):
|
|
season_order = {"Spring": "Fall", "Summer": "Spring", "Fall": "Summer"}
|
|
|
|
try:
|
|
season, year = season_year_str.split()
|
|
year = int(year)
|
|
|
|
if season not in season_order or not (2000 <= year <= 2030):
|
|
raise ValueError("Invalid season or year")
|
|
|
|
previous_season = season_order[season]
|
|
|
|
# Decrement the year if transitioning from Spring to Fall
|
|
if season == "Spring":
|
|
year -= 1
|
|
|
|
return f"{previous_season} {year}"
|
|
|
|
except Exception as e:
|
|
return f"Error: {e}"
|
|
|
|
standard = ['Fall 2026', 'Summer 2026', 'Spring 2026', 'Winter 2026',
|
|
'Fall 2025', 'Summer 2025', 'Spring 2025', 'Winter 2025',
|
|
'Fall 2024', 'Summer 2024', 'Spring 2024', 'Winter 2024',
|
|
'Fall 2023', 'Summer 2023', 'Spring 2023', 'Winter 2023',
|
|
'Fall 2022', 'Summer 2022', 'Spring 2022', 'Winter 2022',
|
|
'Fall 2021', 'Summer 2021', 'Spring 2021',
|
|
'Fall 2020', 'Summer 2020', 'Spring 2020', 'Winter 2020',
|
|
'Fall 2019', 'Summer 2019', 'Spring 2019', 'Winter 2019',
|
|
'Fall 2018', 'Summer 2018', 'Spring 2018',
|
|
'Fall 2017', 'Summer 2017', 'Spring 2017', ]
|
|
|
|
code = 'fa26,su26,sp26,wi26,fa25,su25,sp25,wi25,fa24,su24,sp24,wi24,fa23,su23,sp23,wi23,fa22,su22,sp22,wi22,fa21,su21,sp21,fa20,su20,sp20,wi20,fa19,su19,sp19,wi19,fa18,su18,sp18,fa17,su17,sp17'.split(',')
|
|
|
|
begin = ['08/25','05/22','01/26','01/01', # not sure on fa26
|
|
'08/25','05/27','01/27','01/02',
|
|
'08/26','06/10','01/29','01/02',
|
|
'08/28','06/12','01/30','01/03',
|
|
'08/22','06/13','01/31','01/04',
|
|
'08/23','06/14','02/01',
|
|
'08/24','06/15','01/27','01/02',
|
|
'08/26','06/17','01/28','01/02',
|
|
'08/27','06/18','01/29',
|
|
'08/28','06/19','01/30']
|
|
|
|
canvas_label = []
|
|
|
|
sems_by_human_name = {}
|
|
startdate_by_code = dict(zip(code,begin))
|
|
|
|
|
|
for s in list(zip(standard,code,begin)):
|
|
season,year = s[0].split(' ')
|
|
cl = year + " " + season
|
|
sem_record = {'name': s[0], 'code': s[1], 'start': s[2] + '/' + s[1][-2:], 'number': year + season_to_number[s[0].split(' ')[0]]}
|
|
sems_by_human_name[s[0]] = sem_record
|
|
sems_by_human_name[s[1]] = sem_record
|
|
canvas_label.append(cl)
|
|
sems_by_human_name[cl] = sem_record
|
|
|
|
sems_by_short_name = funcy.project(sems_by_human_name, code)
|
|
|
|
|
|
def dump():
|
|
print("BY HUMAN READABLE NAME")
|
|
print(json.dumps(sems_by_human_name,indent=2))
|
|
|
|
print("\n\nBY SEM SHORTCODE")
|
|
print(json.dumps(sems_by_short_name,indent=2))
|
|
|
|
|
|
GET_FRESH_TERMS = 0
|
|
|
|
if (GET_FRESH_TERMS):
|
|
from pipelines import url, fetch_collapse
|
|
import codecs
|
|
canvas_terms = fetch_collapse(f'{url}/api/v1/accounts/1/terms', 'enrollment_terms')
|
|
ff = codecs.open('cache/courses/terms.txt', 'w', 'utf-8') # TODO unsafe overwrite
|
|
ff.write(json.dumps(canvas_terms, indent=2))
|
|
ff.close()
|
|
else:
|
|
canvas_terms = json.loads(open('cache/courses/terms.txt', 'r').read())
|
|
|
|
# Build main records from standard list
|
|
records = {}
|
|
for std, code_str, start in zip(standard, code, begin):
|
|
season, year = normalize(std)
|
|
records[(season, year)] = {
|
|
'standard': std,
|
|
'code': code_str,
|
|
'begin': start,
|
|
'canvas_term_id': None,
|
|
'canvas_name': None,
|
|
'canvas_start_at': None,
|
|
'canvas_end_at': None
|
|
}
|
|
|
|
# Attach canvas term ids where possible
|
|
for term in canvas_terms: # term_id, label
|
|
key = normalize(term['name'])
|
|
if key and key in records:
|
|
records[key]['canvas_term_id'] = term['id']
|
|
records[key]['canvas_name'] = term['name']
|
|
records[key]['canvas_start_at'] = term['start_at']
|
|
records[key]['canvas_end_at'] = term['end_at']
|
|
|
|
# Build alias lookup
|
|
lookup = {}
|
|
for key, rec in records.items():
|
|
season, year = key
|
|
aliases = [
|
|
rec['standard'],
|
|
f"{year} {season}",
|
|
f"{season} {year}",
|
|
rec['code'],
|
|
rec['canvas_name'] if rec['canvas_name'] else None,
|
|
str(rec['canvas_term_id'])
|
|
]
|
|
for alias in aliases:
|
|
if alias:
|
|
lookup[alias.lower()] = rec
|
|
|
|
def find_term(s):
|
|
return lookup.get(s.lower())
|
|
|
|
#print(find_term("2025 Fall"))
|
|
# {'standard': 'Fall 2025', 'code': 'fa25', 'begin': '08/25',
|
|
# 'canvas_term_id': 289, 'canvas_label': '2025 Fall'}
|
|
|
|
#print(find_term("fa25"))
|
|
# Same record as above
|
|
|
|
#print(find_term("Fall 2025"))
|
|
# Same record as above
|
|
|
|
|
|
def weeks_from_date():
|
|
from datetime import datetime, timedelta
|
|
|
|
weeks = int( input("how many weeks ahead? "))
|
|
|
|
# Replace this with your starting date
|
|
x = datetime.strptime("2025-05-27", "%Y-%m-%d")
|
|
|
|
# Add six weeks
|
|
six_weeks_later = x + timedelta(weeks=weeks)
|
|
|
|
print("Six weeks later:", six_weeks_later.strftime("%Y-%m-%d"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print ('')
|
|
options = { 1: ['print semester info',dump] ,
|
|
2: ['compute x weeks from date', weeks_from_date ],
|
|
}
|
|
|
|
|
|
if len(sys.argv) > 1 and re.search(r'^\d+',sys.argv[1]):
|
|
resp = int(sys.argv[1])
|
|
print("\n\nPerforming: %s\n\n" % options[resp][0])
|
|
|
|
else:
|
|
print ('')
|
|
for key in options:
|
|
print(str(key) + '.\t' + options[key][0])
|
|
|
|
print('')
|
|
resp = input('Choose: ')
|
|
|
|
# Call the function in the options dict
|
|
options[ int(resp)][1]()
|
|
|
|
"""
|
|
|
|
semester_list = {
|
|
"Fall 2022": {
|
|
"name": "Fall 2022",
|
|
"code": "fa22",
|
|
"start": "08/22/22"
|
|
},
|
|
"fa22": {
|
|
"name": "Fall 2022",
|
|
"code": "fa22",
|
|
"start": "08/22/22"
|
|
},
|
|
"2022 Fall": {
|
|
"name": "Fall 2022",
|
|
"code": "fa22",
|
|
"start": "08/22/22"
|
|
},
|
|
"Summer 2022": {
|
|
"name": "Summer 2022",
|
|
"code": "su22",
|
|
"start": "06/13/22"
|
|
},
|
|
"su22": {
|
|
"name": "Summer 2022",
|
|
"code": "su22",
|
|
"start": "06/13/22"
|
|
},
|
|
"2022 Summer": {
|
|
"name": "Summer 2022",
|
|
"code": "su22",
|
|
"start": "06/13/22"
|
|
},
|
|
"Spring 2022": {
|
|
"name": "Spring 2022",
|
|
"code": "sp22",
|
|
"start": "01/31/22"
|
|
},
|
|
"sp22": {
|
|
"name": "Spring 2022",
|
|
"code": "sp22",
|
|
"start": "01/31/22"
|
|
},
|
|
"2022 Spring": {
|
|
"name": "Spring 2022",
|
|
"code": "sp22",
|
|
"start": "01/31/22"
|
|
},
|
|
"Fall 2021": {
|
|
"name": "Fall 2021",
|
|
"code": "fa21",
|
|
"start": "08/23/21"
|
|
},
|
|
"fa21": {
|
|
"name": "Fall 2021",
|
|
"code": "fa21",
|
|
"start": "08/23/21"
|
|
},
|
|
"2021 Fall": {
|
|
"name": "Fall 2021",
|
|
"code": "fa21",
|
|
"start": "08/23/21"
|
|
},
|
|
"Summer 2021": {
|
|
"name": "Summer 2021",
|
|
"code": "su21",
|
|
"start": "06/14/21"
|
|
},
|
|
"su21": {
|
|
"name": "Summer 2021",
|
|
"code": "su21",
|
|
"start": "06/14/21"
|
|
},
|
|
"2021 Summer": {
|
|
"name": "Summer 2021",
|
|
"code": "su21",
|
|
"start": "06/14/21"
|
|
},
|
|
"Spring 2021": {
|
|
"name": "Spring 2021",
|
|
"code": "sp21",
|
|
"start": "02/01/21"
|
|
},
|
|
"sp21": {
|
|
"name": "Spring 2021",
|
|
"code": "sp21",
|
|
"start": "02/01/21"
|
|
},
|
|
"2021 Spring": {
|
|
"name": "Spring 2021",
|
|
"code": "sp21",
|
|
"start": "02/01/21"
|
|
},
|
|
"Fall 2020": {
|
|
"name": "Fall 2020",
|
|
"code": "fa20",
|
|
"start": "08/24/20"
|
|
},
|
|
"fa20": {
|
|
"name": "Fall 2020",
|
|
"code": "fa20",
|
|
"start": "08/24/20"
|
|
},
|
|
"2020 Fall": {
|
|
"name": "Fall 2020",
|
|
"code": "fa20",
|
|
"start": "08/24/20"
|
|
},
|
|
"Summer 2020": {
|
|
"name": "Summer 2020",
|
|
"code": "su20",
|
|
"start": "06/15/20"
|
|
},
|
|
"su20": {
|
|
"name": "Summer 2020",
|
|
"code": "su20",
|
|
"start": "06/15/20"
|
|
},
|
|
"2020 Summer": {
|
|
"name": "Summer 2020",
|
|
"code": "su20",
|
|
"start": "06/15/20"
|
|
},
|
|
"Spring 2020": {
|
|
"name": "Spring 2020",
|
|
"code": "sp20",
|
|
"start": "01/27/20"
|
|
},
|
|
"sp20": {
|
|
"name": "Spring 2020",
|
|
"code": "sp20",
|
|
"start": "01/27/20"
|
|
},
|
|
"2020 Spring": {
|
|
"name": "Spring 2020",
|
|
"code": "sp20",
|
|
"start": "01/27/20"
|
|
},
|
|
"Fall 2019": {
|
|
"name": "Fall 2019",
|
|
"code": "fa19",
|
|
"start": "08/26/19"
|
|
},
|
|
"fa19": {
|
|
"name": "Fall 2019",
|
|
"code": "fa19",
|
|
"start": "08/26/19"
|
|
},
|
|
"2019 Fall": {
|
|
"name": "Fall 2019",
|
|
"code": "fa19",
|
|
"start": "08/26/19"
|
|
},
|
|
"Summer 2019": {
|
|
"name": "Summer 2019",
|
|
"code": "su19",
|
|
"start": "06/17/19"
|
|
},
|
|
"su19": {
|
|
"name": "Summer 2019",
|
|
"code": "su19",
|
|
"start": "06/17/19"
|
|
},
|
|
"2019 Summer": {
|
|
"name": "Summer 2019",
|
|
"code": "su19",
|
|
"start": "06/17/19"
|
|
},
|
|
"Spring 2019": {
|
|
"name": "Spring 2019",
|
|
"code": "sp19",
|
|
"start": "01/28/19"
|
|
},
|
|
"sp19": {
|
|
"name": "Spring 2019",
|
|
"code": "sp19",
|
|
"start": "01/28/19"
|
|
},
|
|
"2019 Spring": {
|
|
"name": "Spring 2019",
|
|
"code": "sp19",
|
|
"start": "01/28/19"
|
|
},
|
|
"Fall 2018": {
|
|
"name": "Fall 2018",
|
|
"code": "fa18",
|
|
"start": "08/27/18"
|
|
},
|
|
"fa18": {
|
|
"name": "Fall 2018",
|
|
"code": "fa18",
|
|
"start": "08/27/18"
|
|
},
|
|
"2018 Fall": {
|
|
"name": "Fall 2018",
|
|
"code": "fa18",
|
|
"start": "08/27/18"
|
|
},
|
|
"Summer 2018": {
|
|
"name": "Summer 2018",
|
|
"code": "su18",
|
|
"start": "06/18/18"
|
|
},
|
|
"su18": {
|
|
"name": "Summer 2018",
|
|
"code": "su18",
|
|
"start": "06/18/18"
|
|
},
|
|
"2018 Summer": {
|
|
"name": "Summer 2018",
|
|
"code": "su18",
|
|
"start": "06/18/18"
|
|
},
|
|
"Spring 2018": {
|
|
"name": "Spring 2018",
|
|
"code": "sp18",
|
|
"start": "01/29/18"
|
|
},
|
|
"sp18": {
|
|
"name": "Spring 2018",
|
|
"code": "sp18",
|
|
"start": "01/29/18"
|
|
},
|
|
"2018 Spring": {
|
|
"name": "Spring 2018",
|
|
"code": "sp18",
|
|
"start": "01/29/18"
|
|
}
|
|
}
|
|
""" |