-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #923 from cornell-dti/automate_email
Eric / Implemented Script For Automating Email Outreach Information (In Progress)
- Loading branch information
Showing
4 changed files
with
437 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,3 +48,6 @@ yarn-error.log* | |
|
||
.idea | ||
.DS_Store | ||
|
||
# ignore virtual environment | ||
venv/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
Course,Professor,Emails,Has course/professor use QMI before | ||
AEP 1100,Chris Xu,[email protected],-1 | ||
AEP 2550,Or Katz,[email protected],-1 | ||
AEP 3100,Peter McMahon,[email protected],-1 | ||
AEP 3200,Ankit Disa,[email protected],-1 | ||
AEP 3550,Valla Fatemi,[email protected],-1 | ||
AEP 3620,Kenji Yasuda,[email protected],-1 | ||
AEP 4340,Lisa Wickham,[email protected],-1 | ||
AEP 4400,Jeffrey Moses,[email protected],-1 | ||
BIOMG 1290,Charles Aquadro,[email protected],-1 | ||
BIOMG 1350,"Chris Fromme, Kelly Liu","[email protected], [email protected]",-1 | ||
BIOMG 2800,"Kristina Blake-Hodek, Maria Serrano","[email protected], [email protected]",-1 | ||
BIOMG 3300,Kevin Siegenthaler,[email protected],-1 | ||
BIOMG 3350,"Stephen Jesch, Frank Pugh","[email protected], [email protected]",-1 | ||
BIOMG 4320,Chun Han,[email protected],-1 | ||
BIOMG 4400,Stephen Jesch,[email protected],-1 | ||
BIOMG 4610,Mariana Wolfner,[email protected],-1 | ||
BIOMG 4880,Zeribe Nwosu,[email protected],-1 | ||
CHEM 2070,Julie Laudenschlager,[email protected],-1 | ||
CHEM 2080,Robert DiStasio,[email protected],-1 | ||
CHEM 2090,Youn Jue Bae,[email protected],-1 | ||
CHEM 3580,"Geoffrey Coates, Brett Fors","[email protected], [email protected]",-1 | ||
CHEM 3880,Barbara Baird,[email protected],-1 | ||
CHEM 4100,Peter Wolczanski,[email protected],-1 | ||
CHEM 4810,Fernando Escobedo,[email protected],-1 | ||
CHEME 2200,T. Michael Duncan,[email protected],-1 | ||
CHEME 3230,Sarah Hormozi,[email protected],-1 | ||
CHEME 3320,Shuwen Yue,[email protected],-1 | ||
CHEME 3900,Sijin Li,[email protected],-1 | ||
CHEME 4020,Ilana Brito,[email protected],-1 | ||
CHEME 4620,"Brian Bauer, William Cleary, Marsha Kowal, Jeffrey Varner, Alex Woltornist","[email protected], [email protected], [email protected], [email protected], [email protected]",-1 | ||
CS 1110,"Michael Clarkson, Lillian Lee","[email protected], [email protected]",0 | ||
CS 1112,Daisy Fan,[email protected],2 | ||
CS 1340,"Jon Kleinberg, Karen Levy","[email protected], [email protected]",-1 | ||
CS 1700,Haym Hirsh,[email protected],-1 | ||
CS 2110,"Matthew Eichhorn, Curran Muhlberger","[email protected], [email protected]",2 | ||
CS 2800,"Joe Halpern, Eva Tardos","[email protected], [email protected]",0 | ||
CS 3110,Anshuman Mohan,[email protected],0 | ||
CS 3410,"Zachary Susag, Hakim Weatherspoon","[email protected], [email protected]",2 | ||
CS 3420,Nils Napp,[email protected],-1 | ||
CS 3700,Kevin Ellis,[email protected],-1 | ||
CS 3780,"Tushaar Gangavarapu, Karthik Sridharan","[email protected], [email protected]",-1 | ||
CS 4300,Cristian Danescu-Niculescu-Mizil,[email protected],2 | ||
CS 4410,Robbert VanRenesse,[email protected],0 | ||
CS 4450,Rachit Agarwal,[email protected],-1 | ||
CS 4670,"Bharath Hariharan, Wei-Chiu Ma","[email protected], [email protected]",2 | ||
CS 4740,"Claire Cardie, Tanya Goyal","[email protected], [email protected]",-1 | ||
CS 4744,Mats Rooth,[email protected],-1 | ||
CS 4756,Kuan Fang,[email protected],-1 | ||
CS 4782,"Jennifer Sun, Kilian Weinberger","[email protected], [email protected]",-1 | ||
CS 4789,Wen Sun,[email protected],0 | ||
CS 4810,Dexter Kozen,[email protected],-1 | ||
CS 4813,Nicholas Spooner,[email protected],-1 | ||
CS 4820,Michael Kim,[email protected],2 | ||
CS 4850,Robert Kleinberg,[email protected],-1 | ||
ECE 2100,Carl Bernard,[email protected],-1 | ||
ECE 2300,Zhiru Zhang,[email protected],2 | ||
ECE 2400,Anne Bracy,[email protected],-1 | ||
ECE 2720,Vikram Krishnamurthy,[email protected],-1 | ||
ECE 3100,Qing Zhao,[email protected],-1 | ||
ECE 3140,Nils Napp,[email protected],2 | ||
ECE 3150,Amit Lal,[email protected],-1 | ||
ECE 3200,Ziv Goldfeld,[email protected],-1 | ||
ECE 4150,David Hysell,[email protected],-1 | ||
ECE 4160,Elizabeth Helbling,[email protected],-1 | ||
ECE 4210,Francesca Parise,[email protected],-1 | ||
ECE 4271,David Delchamps,[email protected],-1 | ||
ECE 4370,Karan Mehta,[email protected],-1 | ||
ECE 4520,Lang Tong,[email protected],-1 | ||
ECE 4590,R. van Dover,[email protected],-1 | ||
ECE 4670,Aaron Wagner,[email protected],-1 | ||
ECE 4740,Alyosha Molnar,[email protected],-1 | ||
ECE 4760,Van Adams,[email protected],-1 | ||
ECE 4910,Bruce Johnson,[email protected],-1 | ||
ECON 1110,George Orlov,[email protected],-1 | ||
ECON 1120,Fikri Pitsuwan,[email protected],-1 | ||
ECON 2300,Arnab Basu,[email protected],-1 | ||
ECON 3030,Philipp Kircher,[email protected],-1 | ||
ECON 3040,Mathieu Taschereau-Dumouchel,[email protected],-1 | ||
ECON 3110,Kevin Packard,[email protected],-1 | ||
ECON 3120,Douglas McKee,[email protected],-1 | ||
ECON 3140,Joerg Stoye,[email protected],-1 | ||
ECON 3430,Stephanie Thomas,[email protected],-1 | ||
ECON 3475,Michele Belot,[email protected],-1 | ||
ECON 3550,Elizabeth Tennant,[email protected],-1 | ||
ECON 3670,Brandon Tripp,[email protected],-1 | ||
ECON 3711,John Cawley,[email protected],-1 | ||
ECON 3770,Evan Riehl,[email protected],-1 | ||
ECON 3860,C.-Y. Cynthia Lin Lawell,[email protected],-1 | ||
ECON 3865,Shanjun Li,[email protected],-1 | ||
ECON 4020,Lawrence Blume,[email protected],-1 | ||
ECON 4210,Kristoffer Nimark,[email protected],-1 | ||
ECON 4270,Stephen Coate,[email protected],-1 | ||
ECON 4600,Levon Barseghyan,[email protected],-1 | ||
ECON 4620,Adam Harris,[email protected],-1 | ||
ECON 4660,Ted O'Donoghue,[email protected],-1 | ||
ECON 4903,Eleonora Patacchini,[email protected],-1 | ||
INFO 1260,"Jon Kleinberg, Karen Levy","[email protected], [email protected]",-1 | ||
INFO 1300,Royal Westwater,[email protected],-1 | ||
INFO 3130,Moon Duchin,[email protected],-1 | ||
INFO 3140,Shimon Edelman,[email protected],-1 | ||
INFO 3200,Claire Wardle,[email protected],-1 | ||
INFO 3950,Paul Ginsparg,[email protected],-1 | ||
INFO 4100,Rene Kizilcec,[email protected],-1 | ||
INFO 4120,Cheng Zhang,[email protected],-1 | ||
INFO 4152,Walker White,[email protected],-1 | ||
INFO 4220,Cristobal Cheyre Forestier,[email protected],-1 | ||
INFO 4250,Daniel Susser,[email protected],-1 | ||
INFO 4260,Steven Jackson,[email protected],-1 | ||
INFO 4300,Cristian Danescu-Niculescu-Mizil,[email protected],-1 | ||
INFO 4310,Jeff Rzeszotarski,[email protected],-1 | ||
INFO 4320,Francois Guimbretiere,[email protected],-1 | ||
INFO 4360,Drew Margolin,[email protected],-1 | ||
INFO 4450,Susan Fussell,[email protected],-1 | ||
INFO 4940,Sharlane Cleare,[email protected],-1 | ||
MATH 1106,Marie MacDonald,[email protected],-1 | ||
MATH 1110,Hosea Wondo,[email protected],-1 | ||
MATH 1120,Luke Serafin,[email protected],-1 | ||
MATH 1340,Matthew Haulmark,[email protected],-1 | ||
MATH 1910,Timothy Healey,[email protected],-1 | ||
MATH 1920,Sergio Chaves,[email protected],-1 | ||
MATH 2210,Benjamin Dozier,[email protected],-1 | ||
MATH 2220,Justin Moore,[email protected],-1 | ||
MATH 2240,Jason Manning,[email protected],-1 | ||
MATH 2310,Alex Townsend,[email protected],-1 | ||
MATH 2930,David Freund,[email protected],-1 | ||
MATH 2940,Frans Schalekamp,[email protected],-1 | ||
MATH 3110,Timothy Riley,[email protected],-1 | ||
MATH 3320,Dan Barbasch,[email protected],-1 | ||
MATH 3340,Rachel Webb,[email protected],-1 | ||
MATH 3360,Karola Meszaros,[email protected],-1 | ||
MATH 4180,Chun Pong Chu,[email protected],-1 | ||
MATH 4200,John Hubbard,[email protected],-1 | ||
MATH 4280,Alexander Vladimirsky,[email protected],-1 | ||
MATH 4310,Andreea Iorga,[email protected],-1 | ||
MATH 4500,James West,[email protected],-1 | ||
MATH 4540,Xiaodong Cao,[email protected],-1 | ||
MATH 4710,Laurent Saloff-Coste,[email protected],-1 | ||
MATH 4740,Sungwoo Jeong,[email protected],-1 | ||
ORIE 3120,Peter Frazier,[email protected],-1 | ||
ORIE 3310,David Shmoys,[email protected],-1 | ||
ORIE 3741,Soroosh Shafiee,[email protected],-1 | ||
ORIE 4126,Eric Gentsch,[email protected],-1 | ||
ORIE 4130,Shane Henderson,[email protected],-1 | ||
ORIE 4152,Negin Majedi,[email protected],-1 | ||
ORIE 4160,Paul Golz,[email protected],-1 | ||
ORIE 4600,John Richard Callister,[email protected],-1 | ||
ORIE 4742,Sid Banerjee,[email protected],-1 | ||
PHYS 1102,Nam Jung Kim,[email protected],-1 | ||
PHYS 1112,Philip Krasicky,[email protected],-1 | ||
PHYS 1116,Csaba Csaki,[email protected],-1 | ||
PHYS 1203,Nils Deppe,[email protected],-1 | ||
PHYS 2208,Matthias Liepe,[email protected],-1 | ||
PHYS 2213,Ryan Tapping,[email protected],-1 | ||
PHYS 2214,Itai Cohen,[email protected],-1 | ||
PHYS 2218,Liam McAllister,[email protected],-1 | ||
PHYS 3310,"Jim Alexander, Kyle Shen","[email protected], [email protected]",-1 | ||
PHYS 3316,Xiaomeng Liu,[email protected],-1 | ||
PHYS 3318,Ivan Bazarov,[email protected],-1 | ||
PHYS 4410,Anders Ryd,[email protected],-1 | ||
PHYS 4443,Katja Nowack,[email protected],-1 | ||
PHYS 4444,Yuval Grossman,[email protected],-1 | ||
PHYS 4488,James Sethna,[email protected],-1 | ||
PHYS 4688,Georg Hoffstaetter de Torquat,[email protected],-1 | ||
STSCI 2150,Melissa Smith,[email protected],-1 | ||
STSCI 3740,Yang Ning,[email protected],-1 | ||
STSCI 4520,David Kent,[email protected],-1 | ||
STSCI 4550,Younghoon Kim,[email protected],-1 | ||
"PHYS 2217, AEP 2170",Abigail Crites,[email protected],-1 | ||
"AEP 3630, PHYS 3360",Earl Kirkland,[email protected],-1 | ||
"ECE 4380, AEP 4450",Francesco Monticone,[email protected],-1 | ||
"AEP 4840, ECE 4840",David Hammer,[email protected],-1 | ||
"BTRY 3020, STSCI 2100, STSCI 3200",Jeremy Entner,[email protected],-1 | ||
"STSCI 3080, BTRY 3080",Florentina Bunea,[email protected],-1 | ||
"STSCI 4090, BTRY 4090, MATH 4720",Marten Wegkamp,[email protected],-1 | ||
"STSCI 4100, BTRY 4100",Dana Yang,[email protected],-1 | ||
"CHEM 1570, CHEM 3570",Cynthia Kinsland,[email protected],-1 | ||
"CS 4220, MATH 4260",Anil Damle,[email protected],-1 | ||
"CS 4754, INFO 4410",Malte Jung,[email protected],-1 | ||
"CS 4758, ECE 4180",Anastasia Bizyaeva,[email protected],-1 | ||
"CS 4852, ECON 3825",Cristobal Cheyre Forestier,[email protected],-1 | ||
"ECON 3280, ECON 4280",Milena Djourelova,[email protected],-1 | ||
"INFO 2310, INFO 4340",Kyle Harms,[email protected],-1 | ||
"INFO 3312, INFO 2951",Benjamin Soltoff,[email protected],-1 | ||
"MATH 4030, MATH 3040",Anil Nerode,[email protected],-1 | ||
"STSCI 3510, ORIE 3510",Jim Dai,[email protected],-1 | ||
"STSCI 3110, STSCI 2110",Kevin Packard,[email protected],-1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
import requests | ||
import csv | ||
import json | ||
|
||
def grab_json(url): | ||
return json.loads(requests.get(url).text) | ||
|
||
rosterURL = "https://classes.cornell.edu/api/2.0/config/rosters.json" | ||
rosters = grab_json(rosterURL)['data']['rosters'] | ||
# Get the most recent semester from the json | ||
# Note that slug is sem/year (e.g SP25) | ||
roster = rosters[-1]['slug'] | ||
# If the most recent semester is a WINTER or SUMMER sem, use the sem before it | ||
if "WI" in roster or "SU" in roster: | ||
roster = rosters[-2]['slug'] | ||
|
||
# Get all subjects for that semester | ||
subjectsURL = "https://classes.cornell.edu/api/2.0/config/subjects.json?roster="+roster | ||
subjects = grab_json(subjectsURL)['data']['subjects'] | ||
|
||
relevent_courses = [ | ||
'CS', | ||
'BTRY', | ||
'INFO', | ||
'ORIE', | ||
'ECON', | ||
'PHYS', | ||
'CHEM', | ||
'CHEME', | ||
'ECE', | ||
'AEP', | ||
'BIO', | ||
'BIOMG', | ||
'MATH', | ||
'STSCI' | ||
] | ||
|
||
# Classes to blacklist because professors are not interested in using QMI | ||
blacklist = [ | ||
'INFO 3152', | ||
'CS 3152', | ||
'INFO 4400', | ||
'INFO 4390' | ||
'INFO 4152', | ||
'CS 4152' | ||
] | ||
|
||
def getCourseStatus(course, professors): | ||
""" | ||
Returns the status of the course/professors in the past semester on whether they have used QMI before | ||
2 indicates that both the course and professor have used QMI before | ||
1 indicates that professor used QMI before | ||
0 indicates that course used QMI before | ||
-1 indicates that neither the course nor the professor have used QMI before | ||
:param course: The course subject and its code (e.g CS 1110) | ||
:param professors: The string that consist of all the professors teaching the course this sem (e.g "Michael Clarkson, Lillian Lee" ) | ||
""" | ||
with open('../scripts/trackers/past_semester.csv', 'r') as file: | ||
csvreader = csv.reader(file) | ||
header = next(csvreader) | ||
|
||
for row in csvreader: | ||
if row[0] == course: | ||
# List of professors in the current semester | ||
current_professors = professors.split(", ") | ||
|
||
# List of professors in the past semester | ||
past_professors = row[1].split(", ") | ||
|
||
# Checks if at least one professor in the current semester is in the past professors | ||
if any(p in past_professors for p in current_professors) or professors in past_professors: | ||
# If the course previously decided to use QMI and the professor is in the past professors, return 2 (both course/prof used QMI) | ||
if row[4] == "yes": | ||
return 2 | ||
|
||
# If the course previously decided not to use QMI and the professor is in the past professors, return the status from the past semester | ||
return row[3] | ||
|
||
# If the professor is not in the past professors | ||
else: | ||
# If the course previously decided to use QMI, return 0 (course used QMI) | ||
if row[4] == "yes": | ||
return 0 | ||
# If the course previously decided not to use QMI, but the course and professor has used QMI before, return 0 (course used QMI) | ||
elif row[4] == "no" and row[3] in ["2", "0"]: | ||
return 0 | ||
return -1 | ||
# If no match is found, return -1 after checking all rows | ||
return -1 | ||
|
||
classesJSON = [] | ||
for s in subjects: | ||
if s['value'] in relevent_courses: | ||
classURL = "https://classes.cornell.edu/api/2.0/search/classes.json?roster="+roster+"&subject=" + s['value'] | ||
classesJSON.extend(grab_json(classURL)['data']['classes']) | ||
|
||
def getProfessorInfo(instructors): | ||
""" | ||
Returns the names and emails of the professors teaching the course | ||
:param instructors: The list of instructors teaching the course | ||
""" | ||
accum_names = "" # To accumulate all the professor names | ||
accum_emails = "" # To accumulate all the professor emails | ||
for professor in instructors: | ||
name = professor['firstName'] + " " + professor['lastName'] + ", " | ||
email = professor['netid'] + '@cornell.edu' + ", " | ||
accum_names += name | ||
accum_emails += email | ||
# Remove preceding and trailing , and " | ||
return accum_names.strip(', ').strip('\"'), accum_emails.strip(', ').strip('\"') | ||
|
||
# Some courses are not relevant | ||
# We will filter out these courses if they contain these words | ||
irrelevant_courses = ["Independent", "Research", "Project", "Projects", "Academic Support", "Sem", "Seminar", "Supplement", "Honors", "Thesis"] | ||
|
||
classes = [] | ||
for c in classesJSON: | ||
instructors = c['enrollGroups'][0]['classSections'][0]['meetings'][0]['instructors'] | ||
names, emails = getProfessorInfo(instructors) | ||
hasProfessor = names != "" | ||
isUndergrad = int(c['catalogNbr']) < 5000 | ||
isNonResearch = all(word not in c['titleShort'] for word in irrelevant_courses) | ||
# At least 3 credits | ||
isCredit = c['enrollGroups'][0]['unitsMinimum'] > 2 | ||
# Course must be on campus and not Cornell Tech | ||
isOnCampus = c['enrollGroups'][0]['classSections'][0]['locationDescr'] == "Ithaca, NY (Main Campus)" | ||
|
||
course = c['subject'] + " " + c['catalogNbr'] | ||
|
||
# Course must not be blacklisted | ||
isNotBlacklisted = course not in blacklist | ||
item = { | ||
'Course': course, | ||
'Professor': names, | ||
'Emails': emails, | ||
'Has course/professor use QMI before': getCourseStatus(course, names) | ||
} | ||
if hasProfessor and isUndergrad and isNonResearch and isCredit and isOnCampus and isNotBlacklisted: | ||
classes.append(item) | ||
|
||
# Dictionary to store professor and the courses they teach | ||
professor_courses = {} | ||
|
||
# Populate the dictionary | ||
for item in classes: | ||
course = item['Course'] | ||
professor = item['Professor'] | ||
email = item['Emails'] | ||
status = item['Has course/professor use QMI before'] | ||
key = (professor, email, status) | ||
if key in professor_courses: | ||
# Adds the course to the set of courses the professor teaches | ||
professor_courses[key].add(course) | ||
else: | ||
professor_courses[key] = {course} | ||
|
||
professors_with_multiple_courses = {} | ||
|
||
# Find professors teaching multiple courses | ||
for professor, course_list in professor_courses.items(): | ||
if len(course_list) > 1: | ||
professors_with_multiple_courses[professor] = course_list | ||
|
||
# Output results | ||
if professors_with_multiple_courses: | ||
for (professor_name, professor_email, status), course_list in professors_with_multiple_courses.items(): | ||
# Remove the individual courses from the classes list that have the same professor | ||
for item in classes: | ||
if item['Course'] in course_list: | ||
classes.remove(item) | ||
class_list = list(course_list) # Convert set to list | ||
# Append the combined version of the courses | ||
classes.append({ | ||
'Course': ', '.join(course_list), | ||
'Professor': professor_name, | ||
'Emails': professor_email, | ||
'Has course/professor use QMI before': status | ||
}) | ||
else: | ||
print("No professors teach multiple courses.") | ||
|
||
with open('../scripts/classes.csv', 'w') as file: | ||
field = ["Course", "Professor", "Emails", 'Has course/professor use QMI before'] | ||
writer = csv.DictWriter(file, fieldnames=field) | ||
|
||
# Write header | ||
writer.writeheader() | ||
|
||
# Write rows to the CSV | ||
writer.writerows(classes) |
Oops, something went wrong.