diff --git a/driver.py b/driver.py
index 245f250..1b7ef7e 100644
--- a/driver.py
+++ b/driver.py
@@ -6,10 +6,9 @@ import helperFunctions as HF
 import scheduledPayrollWindow as PWin
 
 
-#TODO workflow with git
+#TODO demonstrate workflow with git
 #TODO search section/date (show curr and orig people assigned)
 
-#TODO code comment
 #TODO document how to setup for next semester (staff and section changes)
 #TODO document how to get through the cert expiration every week
 
@@ -49,7 +48,6 @@ stfD = pd.read_csv(staffDatabaseFilename,dtype=str,index_col=False)
 #remove leading/trailing whitespace
 secD = secD.apply(lambda x: x.str.strip())
 stfD = stfD.apply(lambda x: x.str.strip())
-#stfD = stfD.apply(lambda x: x.str.lower())
 
 #rewrite to file (each GUI function reads/writes on its own so that the state on disk matches what the user expects while the program is running)
 secD.to_csv(sectionDatabaseFilename,index=False,index_label=False)
@@ -81,9 +79,6 @@ df2 = pd.read_csv(sectionDatabaseFilename[:-4]+"_Orig.csv",dtype=str)
 df1.fillna(value="",inplace=True)
 df2.fillna(value="",inplace=True)
 
-#diff=df1[~df1.astype(str).apply(tuple, 1).isin(df2.astype(str).apply(tuple, 1))]
-#diff=pd.concat([df1,df2]).drop_duplicates(keep=False)
-
 diff = df1.merge(df2, indicator=True, how='outer')
 diff=diff.loc[diff['_merge'] != 'both']
 
@@ -91,8 +86,4 @@ print("\n"+"-"*200+"\nTo-Date difference from default shifts:")
 print(diff)
 print("-"*200)
 
-
-
 #PWin.scheduledPayWin(sectionDatabaseFilename,RegHoursFilename,defaultFont)
-
-#HF.sendEmail("murraydr","CSE102 Substitution","This is a test message")
diff --git a/helperFunctions.py b/helperFunctions.py
index ff826bd..32b94e0 100644
--- a/helperFunctions.py
+++ b/helperFunctions.py
@@ -20,7 +20,8 @@ sectionDatabaseFilename="sectionsDatabase.csv"
 staffDatabaseFilename="staffDatabase.csv"
 
 
-#Converts full names to nedIDs and then back again based on the staff database
+#Converts full name to nedID based on the staff database
+#Uses a mildly 'fuzzy' search where the searched-for string must only occur *somewhere* in the actual full name
 def nameToID(searchName,getAllMatches=False):
 	if searchName == "":
 		return ""
@@ -34,6 +35,8 @@ def nameToID(searchName,getAllMatches=False):
 		return ret
 	else:
 		return ret[0]
+		
+#Converts netID to full name for GUI human-readability
 def IDToName(searchID):
 	if searchID=="":
 		return ""
@@ -43,6 +46,7 @@ def IDToName(searchID):
 		name+="*"#append asterisk to name
 	return name
 	
+#Tests if two requests overlap i.e. have at least one day/time combo in common
 def isRequestOverlap(req1,req2):
 	print(req1)
 	print(req2)
@@ -59,37 +63,49 @@ def isRequestOverlap(req1,req2):
 						overlap=True
 	return overlap
 	
+#Get the time that a section takes place during
 def getTimeFromSection(section):
 	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
 	return(secD.loc[secD['Section']==section]['Time'].iloc[0])
 	
+#Get the location that a section takes place in
 def getLocationFromSection(section):
 	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
 	return(secD.loc[secD['Section']==section]['Location'].iloc[0])
 	
-def isAssigned(netID,period,date):
-	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
-	ret= False
-	filt = (secD.loc[(secD['Section']==period) & (secD['Date']==date)].apply(lambda r: r.astype('string').str.contains(netID).any(), axis=1))
-	if filt.any():	#if the requestor is not assigned to that section
-		ret=True
-	return ret
-	
-def reassign(date,period,oldID,newID):
-	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
-	secD.loc[(secD['Section']==period) & (secD['Date']==date)]=secD.loc[(secD['Section']==period) & (secD['Date']==date)].replace(oldID,newID)
-	secD.to_csv(sectionDatabaseFilename,index=False,index_label=False)
-	
-def getSectionTitles():
-	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
-	sections=list(secD.drop_duplicates(subset=["Section"])["Section"].values)
-	return sections
-	
+#Get all dates that a section takes place in
 def getDatesFromSection(sec):
 	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
 	dates = list(secD.loc[secD["Section"]==sec]["Date"])
 	return dates
 	
+#Tests if a netID is currently assigned to a given section on a given date
+def isAssigned(netID,period,date):
+	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
+	ret= False
+	filt = (secD.loc[(secD['Section']==period) & (secD['Date']==date)].apply(lambda r: r.astype('string').str.contains(netID).any(), axis=1))
+	if filt.any():	#if the requestor is among the names in that section-date
+		ret=True
+	return ret
+	
+#Overwrite a netID in one row of the section database with another
+def reassign(date,period,oldID,newID):
+	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
+	secD.loc[(secD['Section']==period) & (secD['Date']==date)]=secD.loc[(secD['Section']==period) & (secD['Date']==date)].replace(oldID,newID)
+	secD.to_csv(sectionDatabaseFilename,index=False,index_label=False)
+	
+#Get the strings of all section titles currently in the database (dropping duplicates)
+def getAllSectionTitles():
+	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
+	sections=list(secD.drop_duplicates(subset=["Section"])["Section"].values)
+	return sections
+	
+#Get the strings of all names currently in the staff database
+def getAllNames():
+	stfD = pd.read_csv(staffDatabaseFilename,dtype=str,index_col=False)
+	return list(stfD["Name"].values)
+	
+#Add or subtract from the count of a given person's sub request history in one category (e.g. rejections)
 def incrementSubCount(netID,category,amount=1):
 	stfD = pd.read_csv(staffDatabaseFilename,dtype=str,index_col=False)
 	if category==0 or category=="APP":
@@ -108,8 +124,8 @@ def incrementSubCount(netID,category,amount=1):
 	stfD.loc[stfD['NetID']==netID,columnName]=str(float(stfD.loc[stfD['NetID']==netID,columnName])+amount)
 	stfD.to_csv(staffDatabaseFilename,index=False,index_label=False)
 	
+#Get an array of the counts of each category of sub history (Approved, Accepted, Rejected, Cancelled, Fulfilled) for a given person
 def getSubCount(netID):
-
 	stfD = pd.read_csv(staffDatabaseFilename,dtype=str,index_col=False)
 	APP = stfD.loc[(stfD["NetID"]==netID)]["Approved Substitutions"].values[0]
 	ACC = stfD.loc[(stfD["NetID"]==netID)]["Accepted Substitutions"].values[0]
@@ -118,6 +134,9 @@ def getSubCount(netID):
 	FUL = stfD.loc[(stfD["NetID"]==netID)]["Fulfilled Substitutions"].values[0]
 	return (APP,ACC,REJ,CAN,FUL)
 	
+#Get a "high score" list or a "low score" list of names/scores based on a numeric string showing which categories to count
+#0: Approved, 1: Accepted, 2: Rejected, 3: Cancelled, 4: Fulfilled
+#E.g. "12" gives the ULAs with the most total accepted and rejected requests thusfar.
 def getTopSubs(categoryStr,fewest=False,num=1):
 	if categoryStr=="":
 		return ""
@@ -142,7 +161,7 @@ def getTopSubs(categoryStr,fewest=False,num=1):
 		stfD[header]+=(stfD[name].astype(float))
 	return stfD.sort_values(header,axis=0,ascending = fewest).head(num)[["Name",header]].to_string(index=False)
 	
-	
+#Test if a given single shift exists, i.e. if that section meets on that date.
 def shiftExists(period,date):
 	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
 	try:
@@ -152,6 +171,7 @@ def shiftExists(period,date):
 		return False
 	return True
 	
+#Get a list of all names currently assigned to a given section on a given date
 def getAllNamesFromSection(periods,dates):
 	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
 	others=[]
@@ -183,7 +203,7 @@ def dateBeforeOrEqual(date1, date2):
 	else:
 		return False
 	
-#create string files for easy pasting into google forms
+#create string files for easy pasting into Google forms
 def createStrings():
 	stfD = pd.read_csv(staffDatabaseFilename,dtype=str,index_col=False)
 	secD = pd.read_csv(sectionDatabaseFilename,dtype=str,index_col=False)
@@ -208,10 +228,12 @@ def createStrings():
 		seen=set()
 		f.write('\n'.join([x for x in vals if not (x in seen or seen.add(x))]))
 		
-		
+#Create the content of form-letter emails to be sent based on the request details and the chosen approval status
 def generateEmails(requestList):
 	emails=[]
 	for req in requestList:
+	
+		#Unpack the request into named variables (for readability in the string formatting below)
 		timestamp = req[0]
 		requestor = IDToName(req[1]).strip("*")
 		section = req[2]
@@ -221,28 +243,27 @@ def generateEmails(requestList):
 		status = req[6]
 		statusReason = req[7]
 		
+		#Check if a replacement was specified at all
 		if replacement!="":
 			replaced=True
 		else:
 			replaced=False
 			
+		#Unpack sections and dates to always be a list
 		if ";" in section:
 			sections = section.split(";")
 		else:
 			sections=[section]
-			
 		if ";" in date:
 			dates = date.split(";")
 		else:
 			dates=[date]
 		
-		
-		
 		times=[]
 		locations=[]
-		if status=="APP" or status=="ACC": #For now, don't tell the ULAs that their acceptance was begrudging.  We can change this later if desired.
+		if status=="APP" or status=="ACC": #For now, don't tell the ULAs that their acceptance was begrudging so they don't try and game the system by lying about the real reason.  We can change this later if desired.
 			status="approved"
-			changed=True
+			changed=True	#Our database entries were changed
 			for s in sections:
 				times.append(getTimeFromSection(s))
 				locations.append(getLocationFromSection(s))
@@ -251,7 +272,7 @@ def generateEmails(requestList):
 				status="rejected"
 			else:
 				status="cancelled"
-			changed=False
+			changed=False	#Our database entries were changed
 			for s in sections:
 				try:
 					times.append(getTimeFromSection(s))
@@ -329,6 +350,7 @@ def generateEmails(requestList):
 						
 							emails.append([recipient,subject,message])
 		
+	#Send emails (or print to terminal if debugging and actuallySend == False)
 	sendEmails(emails,actuallySend=False)
 		
 			
@@ -336,7 +358,12 @@ def generateEmails(requestList):
 	
 	
 #duumyParam is to make really sure that the author of the code that calls this functions really intends to actually send emails (by forcing them to use the keyword)
-def sendEmails(emails,dummyParam=False,actuallySend=False):
+def sendEmails(emails,dummyParam="DUMMY",actuallySend=False):
+
+	#Catch incorrect use of this method by someone who doesn't understand the args.
+	if dummyParam!="DUMMY":
+		print("DON'T USE THE helperFunctions.sendEmails() method unless you know what you're doing! This can send actual emails to people's inbox!")
+		return
 
 	if actuallySend:
 		#https://www.geeksforgeeks.org/send-mail-gmail-account-using-python/
@@ -368,8 +395,13 @@ def sendEmails(emails,dummyParam=False,actuallySend=False):
 			print("\n"+"-"*80+"\nEmail would be sent to "+email[0]+":\nSubject: "+email[1]+"\nMessage:\n"+email[2]+"\n"+"-"*80)
 		
 	
-	
+#Get the raw data from the Google Forms API
+#FYI: The first part of this code dealing with connection/authentication was not written by me and is largely a black box.
+#This function only adds requests that are more recent than the last time it was run, so that the original data in the Google cloud never needs to be cleared
 def getForms(subRequestsFilename):
+
+	#BLACKBOX AUTHENTICATION MAGIC
+	#--------------------------------------------------------------------------
 	#Requires some installation/setup https://developers.google.com/forms/api/quickstart/python
 	
 	SCOPES = ["https://www.googleapis.com/auth/forms.responses.readonly"]
@@ -401,21 +433,25 @@ def getForms(subRequestsFilename):
 	form_id = '1x-8fkuMAcQlTl36SdsbCG0tfClKAcvNshnV8L_Hl904'
 	result = service.forms().responses().list(formId=form_id).execute()
 	
+	#END OF BLACKBOX AUTHENTICATION MAGIC
+	#--------------------------------------------------------------------------
 	
 	subs = pd.read_csv(subRequestsFilename,dtype=str)
 	
-	
+	#Check when the last time the data was downloaded
 	with open("lastUpdatedToken.txt",'r') as f:
 		line = f.readline()
 		if line != "":
 			prevTime=datetime.strptime(line,"%Y-%m-%d %H:%M:%S.%f")
 		else:
-			prevTime=datetime.strptime("1975-01-01 01:01:01.000000","%Y-%m-%d %H:%M:%S.%f")
+			prevTime=datetime.strptime("1975-01-01 01:01:01.000000","%Y-%m-%d %H:%M:%S.%f")#If the file was blank, (such as by just being created) use an aribtrary very early date
+	
 	data=result["responses"]
+	#Unpack the ugly data structure that Google Forms returns
 	for req in data:
 		try:
 			reason=req["answers"]["22a5ae9b"]["textAnswers"]["answers"][0]["value"]
-		except KeyError:
+		except KeyError:#No reason specified
 			reason = ""
 		requestor=req["answers"]["7bb6a9dd"]["textAnswers"]["answers"][0]["value"]
 		
@@ -435,11 +471,18 @@ def getForms(subRequestsFilename):
 		sections=sections[:-1]
 		
 		timeStr = req["createTime"][:-1].replace("T"," ")+"000"
+		
+		#The timestamp needs formatting adjustment and a time-zone shift to EST
 		timeStamp=datetime.strptime(timeStr, '%Y-%m-%d %H:%M:%S.%f')-timedelta(hours=4,minutes=0)
+		
+		#If the request is more recent than our last download, then our database doesn't yet 'know' about it and it needs to be added.
 		if timeStamp>prevTime:
 			reqDict={"Timestamp": [timeStr], "Requestor": [requestor], "Section": [sections], "Dates": [dates], "Replacement": [replacement], "Reason": [reason]}
 			subs=pd.concat([subs,pd.DataFrame(reqDict)],ignore_index=True)
 	subs.sort_values(by=["Timestamp"],inplace=True)
+	
+	#Write the updated request list to file
 	subs.to_csv(subRequestsFilename,index=False,index_label=False)
+	#Write the timestamp to the token for checking when this function was last run
 	with open("lastUpdatedToken.txt",'w') as f:
-		f.write(str(datetime.now()))
\ No newline at end of file
+		f.write(str(datetime.now()))
diff --git a/lastUpdatedToken.txt b/lastUpdatedToken.txt
index 58fa9ca..9df1bdd 100644
--- a/lastUpdatedToken.txt
+++ b/lastUpdatedToken.txt
@@ -1 +1 @@
-2022-10-04 15:15:51.231447
\ No newline at end of file
+2023-10-11 14:08:24.903282
\ No newline at end of file
diff --git a/sectionsDatabase.csv b/sectionsDatabase.csv
index 4bc8598..300af45 100644
--- a/sectionsDatabase.csv
+++ b/sectionsDatabase.csv
@@ -1714,4 +1714,4 @@ Sec 56,13,11/21,12:40 PM-2:30 PM,403 Computer Center,john7531,imranmoh,,,,,,,,,,
 Sec 56,14,11/28,12:40 PM-2:30 PM,403 Computer Center,john7531,imranmoh,,,,,,,,,,,,,,,,,,
 Sec 56,14,11/30,12:40 PM-2:30 PM,403 Computer Center,john7531,imranmoh,,,,,,,,,,,,,,,,,,
 Sec 56,15,12/05,12:40 PM-2:30 PM,403 Computer Center,john7531,imranmoh,,,,,,,,,,,,,,,,,,
-Sec 56,15,12/07,12:40 PM-2:30 PM,403 Computer Center,john7531,imranmoh,,,,,,,,,,,,,,,,,,
\ No newline at end of file
+Sec 56,15,12/07,12:40 PM-2:30 PM,403 Computer Center,john7531,imranmoh,,,,,,,,,,,,,,,,,,
diff --git a/substitutionApprovalWindow.py b/substitutionApprovalWindow.py
index cc9b868..d71ca83 100644
--- a/substitutionApprovalWindow.py
+++ b/substitutionApprovalWindow.py
@@ -10,20 +10,16 @@ pd.set_option('display.min_rows', 20)
 pd.set_option('display.expand_frame_repr', False)
 pd.set_option('max_colwidth', 20)
 
-
-
+#This is the main window for the substitution requests interface
 def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequestsArchiveFilename,defaultFont=("Courier",11)):
 
-
 	#read in sub requests from the provided csv filepath
 	subRequests=[]
 	with open(subRequestsFilename) as f:
 		headerLine=f.readline()
 		reader = csv.reader(f)
 		for row in reader:
-			subRequests.append(row+[""])
-			
-	
+			subRequests.append(row+[""])	
 			
 	#format fields is Requester, Period, Date, Replacement, Reason, Times, CurrAssigned, Errors
 	columnWidths=[20,16,16,20,30,50,50,20]
@@ -35,8 +31,9 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 		row.append(sg.Text(headerVals[i],expand_x=True,expand_y=True,size=(columnWidths[i],1)))
 	layout=[row]
 				
-	#track how many requests are for a specific timeslot		
-	datetimeFreq={}	
+	#--------------------------------------------------------------------------
+	#Basic error checking before opening display (determines which requests are in red)
+	datetimeFreq={}	#track how many requests are for a specific timeslot
 	for i in range(len(subRequests)):
 		oldID=subRequests[i][1]
 		periods=subRequests[i][2].split(';')
@@ -50,12 +47,16 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 				else:
 					datetimeFreq[datetime]=1
 				if not HF.shiftExists(period,date):
-					subRequests[i][6]+="No such shift\n"
+					subRequests[i][6]+="No such shift\n"	#Add to the list of errors with this request
 				else:
 					if not HF.isAssigned(oldID,period,date):
-						subRequests[i][6]+=oldID+" not assigned\n"
+						subRequests[i][6]+=oldID+" not assigned\n"	#Add to the list of errors with this request
 					if newID != "" and HF.isAssigned(newID,period,date):
-						subRequests[i][6]+=newID+" already assigned\n"
+						subRequests[i][6]+=newID+" already assigned\n"	#Add to the list of errors with this request
+	
+	
+	#--------------------------------------------------------------------------
+	#Formatting the text for the main window
 	for i in range(len(subRequests)):
 		request=subRequests[i]
 		netID=request[1]
@@ -86,7 +87,6 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 		
 		others=str(others)[1:-1]
 		others=others.replace("'","")
-		#others=others.replace("],","]\n"+" "*(sum(columnWidths[:6])+16)+"|")
 		
 		textVals=[HF.IDToName(netID),*request[2:4],newSubName,request[5],timeStr,others,request[6].strip("\n")]
 		
@@ -100,6 +100,7 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 		layout.append(row)
 		layout.append([sg.Text('-'*(sum(columnWidths)+27))])
 		
+	#Adding buttons
 	layout.append([sg.Button('Ok'), sg.Button('Cancel'), sg.Button('See Sub History'), sg.Button('Make Manual Changes')])
 	layout=[[sg.Column(layout,scrollable=True,expand_y=True,expand_x=True)]]
 
@@ -112,6 +113,8 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 	event=-1
 	while event != sg.WIN_CLOSED and completed==False:
 		event, values = window.read()
+		
+		#values.values() is an array of the input from all window elements, we use strides to get the checkboxes as "columns" instead of "rows"
 		approveValues=list(values.values())[::5]
 		acceptValues=list(values.values())[1::5]
 		rejectValues=list(values.values())[2::5]
@@ -122,22 +125,22 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 		nAcc = sum([1 for d in acceptValues if True == d])
 		nRej = sum([1 for d in rejectValues if True == d])
 		nCan = sum([1 for d in cancelValues if True == d])
-		
-		
-		
 			
+		#event is the most recent "click" from the user
 		if event == "See Sub History":
-			SHW.subHisWin(staffDatabaseFilename,subRequestsArchiveFilename,defaultFont)
+			SHW.subHisWin(subRequestsArchiveFilename,defaultFont)	#open history window
 		if event == "Make Manual Changes":
-			window['Ok'].Update(disabled=True)	#This is to prevent undefined behavior where manual changes are not represented in the error-checking of the main window
-			SMW.subManualWin(staffDatabaseFilename,secDFilename,subRequestsArchiveFilename,defaultFont)
-			event = "Cancel"
-		if event == 'Ok':
+			window['Ok'].Update(disabled=True)	#This is to prevent undefined behavior as a result of manual changes not being represented in the main window
+			SMW.subManualWin(subRequestsArchiveFilename,defaultFont)	#open manual change window
+			event = "Cancel"	#after we return from the manual change window, just close the whole program
+			
 		
+		if event == 'Ok':
+	
 			valid=True
 			dialogShown = False	#Do not show multiple error dialogues even if there are multiple problems.
 			
-			#If two responses are checked in ANY single line, then it is not valid input
+			#If two responses are both checked in ANY single line, then it is not valid input
 			if True in [True for i, j, k, l in zip(approveValues, acceptValues, rejectValues, cancelValues) if ((i and j) or (i and k) or (j and k) or (i and l) or (j and l) or (k and l))]:
 				valid=False
 				if not dialogShown:
@@ -154,6 +157,7 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 			otherReqCache={}
 			for i in range(len(subRequests)):
 				if approveValues[i] or acceptValues[i]:
+					#If any of the app/acc lines have an error, then it is not valid input
 					if subRequests[i][6] != "":
 						valid=False
 						if not dialogShown:
@@ -212,9 +216,10 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 								else:
 									amount = 1
 								if approveValues[i] or acceptValues[i]:	#If this request was checked "approved" or "accepted"
-									HF.reassign(date,period,oldID,newID)
+									HF.reassign(date,period,oldID,newID)	#Actually make the changes in the database
+								#HF.incrementSubCount is for tracking how many subs this person requested and what their outcome was
 									if newID !="":
-										HF.incrementSubCount(newID,4,amount=amount)
+										HF.incrementSubCount(newID,4,amount=amount)#Also track how many sub requests were filled by each person
 									if approveValues[i]:
 										HF.incrementSubCount(oldID,0,amount=amount)
 									if acceptValues[i]:
@@ -224,7 +229,7 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 								if cancelValues[i]:
 									HF.incrementSubCount(oldID,3,amount=amount)
 						if (not approveValues[i] and not acceptValues[i] and not rejectValues[i] and not cancelValues[i]):
-							trimmedSubrequests.append(subRequests[i][:-1])
+							trimmedSubrequests.append(subRequests[i][:-1])#Trimmed requests is the list of requests that had no action taken and thus must be re-added to the list of pending requests
 						else:
 							if approveValues[i]:
 								result="APP"
@@ -234,12 +239,13 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 								result="REJ"
 							elif cancelValues[i]:
 								result="CAN"
-							resolvedSubrequests.append(subRequests[i][:-1]+[result]+[values["-INPUT_REASON_"+str(i)+"-"]])
+							resolvedSubrequests.append(subRequests[i][:-1]+[result]+[values["-INPUT_REASON_"+str(i)+"-"]])#Resolved requests is kept to be appended to the archived requests database
 							
-					#	If the program crashes during email sending (such as with invalid login) it will deliberately NOT reach the code where it writes to databases
+					#If the program crashes during email sending (such as with invalid login) it will deliberately NOT reach the code where it writes to databases
+					#KEEP THIS LINE BEFORE THE WRITING STEPS
 					HF.generateEmails(resolvedSubrequests)
 							
-
+					#Write to the respective databases
 					with open(subRequestsFilename,'w', newline='') as f:
 						f.write(headerLine)
 						writer = csv.writer(f)
@@ -253,4 +259,4 @@ def subAppWin(staffDatabaseFilename,secDFilename,subRequestsFilename,subRequests
 		elif event == 'Cancel':
 			completed=True
 
-	window.close()
\ No newline at end of file
+	window.close()
diff --git a/substitutionHistoryWindow.py b/substitutionHistoryWindow.py
index fd81cfd..7255daf 100644
--- a/substitutionHistoryWindow.py
+++ b/substitutionHistoryWindow.py
@@ -3,7 +3,7 @@ import csv
 import pandas as pd
 import helperFunctions as HF
 
-def subHisWin(staffDatabaseFilename,subRequestsArchiveFilename,defaultFont):
+def subHisWin(subRequestsArchiveFilename,defaultFont):
 
 	history = pd.read_csv(subRequestsArchiveFilename,dtype=str)
 
@@ -22,6 +22,7 @@ def subHisWin(staffDatabaseFilename,subRequestsArchiveFilename,defaultFont):
 	while event != sg.WIN_CLOSED and event != "Close Window":
 		event, values = window.read()
 		
+		#If event is the pressing of an incrementing button AND the textbox search returns exactly one name
 		if event in ["+APP","-APP","+ACC","-ACC","+REJ","-REJ","+CAN","-CAN","+FUL","-FUL"] and netID != -1 and len(netIDs)<=1:
 			if event[0]=="+":
 				change = 1
@@ -33,16 +34,6 @@ def subHisWin(staffDatabaseFilename,subRequestsArchiveFilename,defaultFont):
 			event = "Find History"
 			
 		if event=="Find History":
-			window['+APP'].Update(disabled=False)
-			window['-APP'].Update(disabled=False)
-			window['+ACC'].Update(disabled=False)
-			window['-ACC'].Update(disabled=False)
-			window['+REJ'].Update(disabled=False)
-			window['-REJ'].Update(disabled=False)
-			window['+CAN'].Update(disabled=False)
-			window['-CAN'].Update(disabled=False)
-			window['+FUL'].Update(disabled=False)
-			window['-FUL'].Update(disabled=False)
 			name = values[0]
 			netIDs=HF.nameToID(name,getAllMatches=True)
 			if not hasattr(netIDs,'__len__') or len(netIDs)==0:
@@ -58,10 +49,21 @@ def subHisWin(staffDatabaseFilename,subRequestsArchiveFilename,defaultFont):
 					names = [HF.IDToName(i) for i in netIDs[:]]
 					window['OUTPUT'].update(value="Multiple matches found: ["+", ".join(names)+"]")
 				else:
-				
+					#Enable the incrementing buttons once a single valid name is found
+					window['+APP'].Update(disabled=False)
+					window['-APP'].Update(disabled=False)
+					window['+ACC'].Update(disabled=False)
+					window['-ACC'].Update(disabled=False)
+					window['+REJ'].Update(disabled=False)
+					window['-REJ'].Update(disabled=False)
+					window['+CAN'].Update(disabled=False)
+					window['-CAN'].Update(disabled=False)
+					window['+FUL'].Update(disabled=False)
+					window['-FUL'].Update(disabled=False)
+					#Get the number of previous requests in each category for that ULA
 					APP,ACC,REJ,CAN,FUL=HF.getSubCount(netID)
 									
-					#Printing options for Pandas
+					#Printing options for the Pandas dataframe
 					pd.set_option('display.min_rows', 20)
 					pd.set_option('display.expand_frame_repr', False)
 					pd.set_option('max_colwidth', 30)
@@ -71,9 +73,11 @@ def subHisWin(staffDatabaseFilename,subRequestsArchiveFilename,defaultFont):
 						output="No history"
 					else:
 						output=str(output.to_string(index=False))
+					#Change the textbox to include the relevant data
 					window['OUTPUT'].update(value=name+"; "+netID+"\n"+"APP:"+APP+"  ACC:"+ACC+"  REJ:"+REJ+"  CAN:"+CAN+"  FUL:"+FUL+"\n"+output)
 					
 		if event=="Hall of Fame":
+			#Disable the incrementing buttons while in "Hall of Fame" mode since there is no single name attached.
 			window['+APP'].Update(disabled=True)
 			window['-APP'].Update(disabled=True)
 			window['+ACC'].Update(disabled=True)
@@ -84,9 +88,12 @@ def subHisWin(staffDatabaseFilename,subRequestsArchiveFilename,defaultFont):
 			window['-CAN'].Update(disabled=True)
 			window['+FUL'].Update(disabled=True)
 			window['-FUL'].Update(disabled=True)
+			
 			#Printing options for Pandas
 			pd.set_option('display.expand_frame_repr', False)
 			pd.set_option('max_colwidth', 30)
+			
+			#Display instructions while the inputStr is not a valid input for the Hall of Fame
 			output='To customize which categories to add (App,Acc,Rej,Can,Ful):\nuse 0,1,2,3,4 or any combination thereof in the text box then click "Hall of Fame" again\n(e.g. "12" yields Accepted plus Rejected)\n'
 			inputStr=values[0]
 			if inputStr=="" or not inputStr.isnumeric():
@@ -97,4 +104,3 @@ def subHisWin(staffDatabaseFilename,subRequestsArchiveFilename,defaultFont):
 				
 		
 	window.close()
-	
\ No newline at end of file
diff --git a/substitutionManualWindow.py b/substitutionManualWindow.py
index 38dbf33..b38c639 100644
--- a/substitutionManualWindow.py
+++ b/substitutionManualWindow.py
@@ -4,13 +4,13 @@ import pandas as pd
 import helperFunctions as HF
 from datetime import datetime, timedelta
 
-def subManualWin(staffDatabaseFilename,secDFilename,subRequestsArchiveFilename,defaultFont):
+def subManualWin(subRequestsArchiveFilename,defaultFont):
 
-	stfD = pd.read_csv(staffDatabaseFilename,dtype=str,index_col=False)
-
-	allnames=list(stfD["Name"].values)
-	sections=HF.getSectionTitles()
+	#Pull all names and section titles for the poopulation of the drop-down boxes
+	allnames=HF.getAllNames()
+	sections=HF.getAllSectionTitles()
 
+	#Define the window's layout
 	layout=[[sg.Text("Email?| Sec   | Date   | Replacee                        | Replacement")],
 		[sg.Checkbox('',size=(3,1),key='-EMAILCHECK-'),sg.Combo(sections,size=(6,1),key="-SECTION-",readonly=True, enable_events=True),sg.Combo([""],size=(6,1),key='-DATE-',readonly=True, enable_events=True),sg.Combo([""],size=(30,1),key="-REPLACEE-", enable_events=True,readonly=True),sg.Combo(allnames,size=(30,1),key="-REPLACEMENT-", enable_events=True,readonly=True)],
 		[sg.Text("Reason for manual change: "),sg.Input(key='-REASON-')],
@@ -22,45 +22,50 @@ def subManualWin(staffDatabaseFilename,secDFilename,subRequestsArchiveFilename,d
 	#Event Loop to process "events" and get the "values" of the inputs
 	#Cease running if they close the window
 	event=-1
-	
 	while event != sg.WIN_CLOSED and event != "Close Window":
 		event, values = window.read()
 		
+		#If the 'section' box is interacted with and is not blank (i.e. an option was selected from the dropdown box)
 		if event=="-SECTION-" and values['-SECTION-']!="":
 			sec=values['-SECTION-']
 			dates=HF.getDatesFromSection(sec)
-			window["-DATE-"].update(values=dates)
+			window["-DATE-"].update(values=dates)#update the dropdown box of dates with the appropriate values for this section
 			window["-REPLACEE-"].update(values=[""])
 			
+		#If the 'date' box is interacted with and is not blank (i.e. an option was selected from the dropdown box)
 		if event=="-DATE-" and values['-DATE-']!="":
 			date=values["-DATE-"]
 			names=list(HF.getAllNamesFromSection(sec,date))[0]
-			window["-REPLACEE-"].update(values=names)
+			window["-REPLACEE-"].update(values=names)#update the dropdown box of names with the appropriate values for this section/date combo
 			
-		
+		#Button was pressed to process the manual change
 		if event == "Make Change":
 			sec=values['-SECTION-']
 			date=values["-DATE-"]
 			replacee=HF.nameToID(values["-REPLACEE-"])
 			replacement=HF.nameToID(values["-REPLACEMENT-"])
 			
-			timeStamp=str(datetime.now())
-			request=[timeStamp,replacee,sec,date,replacement,values["-REASON-"],"APP","MANUALLY CHANGED BY COURSE ADMINS"]
+			timeStamp=str(datetime.now())#Consider the submission time to be right now, when the button was pressed.
+			request=[timeStamp,replacee,sec,date,replacement,values["-REASON-"],"APP","MANUALLY CHANGED BY COURSE ADMINS"]#create a request in the style of the Google form, for archiving purposes
 				
-			HF.reassign(date,sec,replacee,replacement)
+			HF.reassign(date,sec,replacee,replacement)#Actually perform the replacement
 				
+			#Send the email confirmations out to the relevant parties
+			#NOTE: This is BEFORE the writing step so that if there's an error in emails (such as failed to authenticate) the code aborts BEFORE writing chnages to the database.
+			if values['-EMAILCHECK-']:
+				HF.generateEmails([request])
+				
+			#write to the archive database
 			with open(subRequestsArchiveFilename,'a', newline='') as f:
 				writer = csv.writer(f)
 				writer.writerows([request])
 				
-				
+			#Reset the dropdowns to the original options
 			window["-SECTION-"].update(values=sections)
 			window["-DATE-"].update(values=[""])
 			window["-REPLACEE-"].update(values=[""])
 			window["-REPLACEMENT-"].update(values=allnames)
-			if values['-EMAILCHECK-']:
-				HF.generateEmails([request])
 		
 		
 		
-	window.close()
\ No newline at end of file
+	window.close()
diff --git a/substitutionRequestForm.csv b/substitutionRequestForm.csv
index c302847..6697163 100644
--- a/substitutionRequestForm.csv
+++ b/substitutionRequestForm.csv
@@ -1 +1,27 @@
 Timestamp,Requestor,Section,Dates,Replacement,Reason
+2023-09-19 13:57:17.596000,sipahiog,Sec 46,09/19,haggart3,Sickness 
+2023-09-19 18:45:55.239000,sebalyma,Sec 40,10/10,ngvivian,will be in ohio for beginning of that week 
+2023-09-19 22:32:06.420000,mcgui186,Sec 6,09/21,schul769,Funeral
+2023-09-20 17:12:04.654000,austi143,Sec 11,09/20,,"Grandpa had stroke, have to go home"
+2023-09-20 17:12:30.949000,gautamya,Sec 21,09/20,,Sick
+2023-09-20 17:29:31.529000,upadhy19,Sec 4,09/20,,Strong Stomachache
+2023-09-21 13:22:29.001000,sipahiog,Sec 46,09/21,,Sickness
+2023-09-21 18:25:24.758000,mcgui186,R_HR2,09/21,sipahiog,Funeral
+2023-09-21 18:26:11.335000,mcgui186,R_HR1,09/21,haggart3,Funeral
+2023-09-23 14:25:11.349000,borekmi1,Sec 1,09/25,sebalyma,Problem with the transportation to MSU
+2023-09-25 17:05:16.919000,burgejae,Sec 46,09/26,aggarw75,Important meeting came up 
+2023-09-25 17:05:25.520000,anindhos,M_HR1;M_HR2,09/25,bhardw41,Mandatory project meeting
+2023-09-25 21:37:26.276000,aggarw75,Sec 11,09/27,lnumehak,
+2023-09-26 01:51:03.453000,john7531,S_HR1;S_HR2,10/02,bhardw41,Laptop died. Replacement may not come before my shift.
+2023-09-26 14:52:30.307000,darshanv,W_HR1;W_HR2;Sec 20,09/27,micksoph,Visiting the SSN office for on campus registration and receiving SSN
+2023-09-26 16:25:19.977000,sipahiog,T_HR1;T_HR2,09/26,haggart3,Something came up with a class
+2023-09-28 14:58:15.450000,sonarsoh,Sec 17,10/02;10/04,tagaychr,broken arm
+2023-10-03 19:14:01.917000,sipahiog,Sec 30,10/09,john7531,out of town
+2023-10-04 19:47:39.642000,schne542,Sec 19,10/09,aggarw75,I have a doctors appointment on 10/9 back home. 
+2023-10-04 20:02:13.852000,mcgui186,R_HR1;R_HR2,10/05,haggart3,I need to go to helproom for a project of mine
+2023-10-04 20:07:34.501000,sipahiog,Sec 46,10/10,haggart3,Out of town
+2023-10-09 17:51:15.406000,austi143,Sec 11,10/09,bhardw41,I’m sick
+2023-10-11 01:06:38.157000,pittend2,Sec 25,10/11,kumararn,Sick
+2023-10-11 16:49:39.541000,murraydr,M_HR1;M_HR2,10/09,,test1
+2023-10-11 16:50:11.365000,murraydr,M_HR1,10/02;10/09,,test2
+2023-10-11 17:24:59.666000,austi143,Sec 11,10/11,lnumehak,I’m sick