updates to stats
This commit is contained in:
parent
9712e3eeb5
commit
42a1c941f5
16
courses.py
16
courses.py
|
|
@ -261,24 +261,24 @@ def users_in_depts_live(depts=[], termid='171'):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def course_enrollment(id=''):
|
def course_enrollment(id='', verbose=0):
|
||||||
print("Getting enrollments for course id %s" % str(id))
|
if verbose: print("Getting enrollments for course id %s" % str(id))
|
||||||
if not id:
|
if not id:
|
||||||
id = input('Course id? ')
|
id = input('Course id? ')
|
||||||
t = url + '/api/v1/courses/%s/enrollments?role[]=StudentEnrollment' % str(id)
|
t = url + '/api/v1/courses/%s/enrollments?role[]=StudentEnrollment' % str(id)
|
||||||
print(t)
|
if verbose: print(t)
|
||||||
emts = fetch(t,0)
|
emts = fetch(t,verbose)
|
||||||
print(emts)
|
if verbose: print(emts)
|
||||||
emt_by_id = {}
|
emt_by_id = {}
|
||||||
for E in emts:
|
for E in emts:
|
||||||
print(E)
|
if verbose: print(E)
|
||||||
try:
|
try:
|
||||||
emt_by_id[E['user_id']] = E
|
emt_by_id[E['user_id']] = E
|
||||||
except Exception as exp:
|
except Exception as exp:
|
||||||
print("Skipped that class with this exception: %s" % str(exp))
|
print("Skipped [%s] with this exception: %s" % (str(E), str(exp)))
|
||||||
ff = codecs.open('cache/courses/%s.json' % str(id), 'w', 'utf-8')
|
ff = codecs.open('cache/courses/%s.json' % str(id), 'w', 'utf-8')
|
||||||
ff.write(json.dumps(emt_by_id, indent=2))
|
ff.write(json.dumps(emt_by_id, indent=2))
|
||||||
print( " %i results" % len(emts) )
|
if verbose: print( " %i results" % len(emts) )
|
||||||
return emt_by_id
|
return emt_by_id
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1221,6 +1221,19 @@ AND e.workflow="active" """ % (canvasid)
|
||||||
return [a,b]
|
return [a,b]
|
||||||
return [x[0] for x in allrows]
|
return [x[0] for x in allrows]
|
||||||
|
|
||||||
|
# get enrollments in a course, name and canvasid
|
||||||
|
def get_course_enrollments(courseid):
|
||||||
|
q = """SELECT u.name, u.canvasid FROM courses AS c
|
||||||
|
JOIN enrollment AS e ON e.course_id=c.id
|
||||||
|
JOIN users AS u ON u.id=e.user_id
|
||||||
|
WHERE c.canvasid=%s
|
||||||
|
AND e.type="StudentEnrollment"
|
||||||
|
AND e.workflow="active";""" % str(courseid)
|
||||||
|
(connection,cursor) = db()
|
||||||
|
cursor.execute(q)
|
||||||
|
allrows = cursor.fetchall()
|
||||||
|
return allrows
|
||||||
|
|
||||||
|
|
||||||
# get teacher name from local db
|
# get teacher name from local db
|
||||||
def course_quick_stats(canvasid):
|
def course_quick_stats(canvasid):
|
||||||
|
|
|
||||||
100
stats.py
100
stats.py
|
|
@ -18,13 +18,22 @@
|
||||||
- Check if grades were used and make sense
|
- Check if grades were used and make sense
|
||||||
- Compute mean, % > 70, median, etc.
|
- Compute mean, % > 70, median, etc.
|
||||||
|
|
||||||
|
- Anonymization steps
|
||||||
|
- replace teacher names w/ id number
|
||||||
|
- replace student names w/ id number
|
||||||
|
- replace course names w/ course code
|
||||||
|
|
||||||
- Script 2 - given all semester schedules, generate lists of:
|
- Script 2 - given all semester schedules, generate lists of:
|
||||||
- CRNs which are online, online live, hybrid, inperson, excluded
|
- CRNs which are online, online live, hybrid, inperson, excluded
|
||||||
- CRNs in which teacher and course have passed pocr (and semester is greater than their pass date)
|
- CRNs in which teacher and course have passed pocr (and semester is greater than their pass date)
|
||||||
- CRNs in which teacher passed pocr for a different course (and semester is greater than their pass date)
|
- CRNs in which teacher passed pocr for a different course (and semester is greater than their pass date)
|
||||||
- CRNs to exclude, for example SP20, because of covid. Possibly SU20 and FA20
|
- CRNs to exclude, for example SP20, because of covid. Possibly SU20 and FA20
|
||||||
|
|
||||||
|
- CRNs with are POCR approved
|
||||||
- CRNs in which teacher has done more than the minimum training in online teaching
|
- CRNs in which teacher has done more than the minimum training in online teaching
|
||||||
|
|
||||||
|
- Student ids which have participated in the online orientation over a certain threshold
|
||||||
|
|
||||||
- Next steps: generate the x-reference for what categories teachers are in, and
|
- Next steps: generate the x-reference for what categories teachers are in, and
|
||||||
integrate into the main data file.
|
integrate into the main data file.
|
||||||
|
|
||||||
|
|
@ -32,6 +41,21 @@
|
||||||
|
|
||||||
-
|
-
|
||||||
"""
|
"""
|
||||||
|
import codecs, os
|
||||||
|
import json, csv, requests, sys, re
|
||||||
|
from multiprocessing import Semaphore
|
||||||
|
from statistics import mean, median, stdev
|
||||||
|
from pipelines import fetch, url
|
||||||
|
from courses import getCoursesInTerm, course_enrollment
|
||||||
|
from localcache import get_course_enrollments
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
all_grades_file = f"cache/grades_all.csv"
|
||||||
|
all_courses_file = f"cache/course_grades_all.csv"
|
||||||
|
all_courses_file2 = f"cache/course_grades_compact.csv"
|
||||||
|
all_courses_file3 = f"cache/course_grades_full.csv"
|
||||||
|
student_orientation_participation = f'cache/participation_orientation_courses.json'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def num(s):
|
def num(s):
|
||||||
|
|
@ -41,17 +65,7 @@ def num(s):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return float(s)
|
return float(s)
|
||||||
|
|
||||||
import json, csv, requests, sys, re
|
|
||||||
from multiprocessing import Semaphore
|
|
||||||
from statistics import mean, median, stdev
|
|
||||||
from pipelines import fetch, url
|
|
||||||
from courses import getCoursesInTerm
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
all_grades_file = f"cache/grades_all.csv"
|
|
||||||
all_courses_file = f"cache/course_grades_all.csv"
|
|
||||||
all_courses_file2 = f"cache/course_grades_compact.csv"
|
|
||||||
all_courses_file3 = f"cache/course_grades_full.csv"
|
|
||||||
|
|
||||||
def sem_num_to_code(sem_num):
|
def sem_num_to_code(sem_num):
|
||||||
p = re.search(r'^(\d\d\d\d)(\d\d)$', sem_num)
|
p = re.search(r'^(\d\d\d\d)(\d\d)$', sem_num)
|
||||||
|
|
@ -116,9 +130,54 @@ def grades(writer, sem, COURSE_ID, course_code):
|
||||||
print("Exception:", e)
|
print("Exception:", e)
|
||||||
|
|
||||||
|
|
||||||
schedules = {}
|
def get_student_orientations():
|
||||||
|
courses = {'iLearn Student Orientation 2022':'9768', # 8170 students
|
||||||
|
'Kickstart Online Orientation - Transfer':'36', # 6149
|
||||||
|
'Kickstart Online Orientation - New to College':'35', # 5392
|
||||||
|
'LIB732 SP18':'3295', # 2193
|
||||||
|
'LIB732 FA17':'2037', # 1868
|
||||||
|
'LIB732 SP17':'69', # 1645
|
||||||
|
'Kickstart Online Orientation - Returning':'37', # 1463
|
||||||
|
'iLearn Student Orientation 2023':'15924', # 1292
|
||||||
|
'LIB732 SU17':'1439' # 1281
|
||||||
|
}
|
||||||
|
|
||||||
import codecs, os
|
views_bycourse = {}
|
||||||
|
all_student_ids = set()
|
||||||
|
|
||||||
|
# get pageviews of each orientation course
|
||||||
|
for c,i in courses.items():
|
||||||
|
print(c)
|
||||||
|
cache_file_name = f'cache/participation_course_{i}.json'
|
||||||
|
student_ids = [x[1] for x in get_course_enrollments(i)]
|
||||||
|
all_student_ids.update(student_ids)
|
||||||
|
if os.path.exists(cache_file_name):
|
||||||
|
pv = json.loads(codecs.open(cache_file_name,'r','utf-8').read())
|
||||||
|
else:
|
||||||
|
pv = get_student_page_views(i, student_ids)
|
||||||
|
codecs.open(cache_file_name,'w','utf-8').write(json.dumps(pv,indent=2))
|
||||||
|
views_bycourse[i] = pv
|
||||||
|
|
||||||
|
# add up pageviews for each student
|
||||||
|
views_bystudent = {}
|
||||||
|
for student_id in all_student_ids:
|
||||||
|
views_bystudent[student_id] = sum([views_bycourse[i].get(student_id,0) for i in courses.values()])
|
||||||
|
codecs.open(student_orientation_participation,'w','utf-8').write(json.dumps(views_bystudent,indent=2))
|
||||||
|
|
||||||
|
def get_student_page_views(course_id, student_ids):
|
||||||
|
page_views = {}
|
||||||
|
verbose = 0
|
||||||
|
|
||||||
|
for student_id in student_ids:
|
||||||
|
a = f'/api/v1/courses/{course_id}/analytics/users/{student_id}/activity'
|
||||||
|
response = fetch(url + a, verbose)
|
||||||
|
page_views[student_id] = sum(response.get('page_views', {}).values())
|
||||||
|
|
||||||
|
if verbose: print(page_views)
|
||||||
|
return page_views
|
||||||
|
|
||||||
|
schedules = {}
|
||||||
|
orientations = {}
|
||||||
|
|
||||||
def load_schedules():
|
def load_schedules():
|
||||||
global schedules
|
global schedules
|
||||||
|
|
@ -129,6 +188,13 @@ def load_schedules():
|
||||||
sem = m.group(1)
|
sem = m.group(1)
|
||||||
schedules[sem] = json.loads( codecs.open('cache/schedule/' + f, 'r', 'utf-8').read() )
|
schedules[sem] = json.loads( codecs.open('cache/schedule/' + f, 'r', 'utf-8').read() )
|
||||||
|
|
||||||
|
def load_orientations():
|
||||||
|
global orientations
|
||||||
|
if not orientations:
|
||||||
|
orientations = json.loads( codecs.open(student_orientation_participation,'r','utf-8').read() )
|
||||||
|
return orientations
|
||||||
|
|
||||||
|
|
||||||
def to_crn_fallback(name):
|
def to_crn_fallback(name):
|
||||||
#print(name)
|
#print(name)
|
||||||
name = name.lower()
|
name = name.lower()
|
||||||
|
|
@ -295,7 +361,7 @@ def process_one_course_grades_full(block, out_f, teacher_to_code, course_to_code
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# "course_code course pocr_status teacher_code mode student_id scaled_score"
|
# "course_code course pocr_status orientation_status teacher_code mode student_id scaled_score"
|
||||||
|
|
||||||
(final_mean, final_median, final_stdev, final_min, final_max, final_count) = [round(f(final_scores)) for f in fxns]
|
(final_mean, final_median, final_stdev, final_min, final_max, final_count) = [round(f(final_scores)) for f in fxns]
|
||||||
final_pct_passed = above_70(final_scores, final_max)
|
final_pct_passed = above_70(final_scores, final_max)
|
||||||
|
|
@ -308,10 +374,13 @@ def process_one_course_grades_full(block, out_f, teacher_to_code, course_to_code
|
||||||
good_code = ilearn_name_to_course_code(course_code)
|
good_code = ilearn_name_to_course_code(course_code)
|
||||||
pocr = 1 if lookup_pocr(teacher, good_code, sem2) else 0
|
pocr = 1 if lookup_pocr(teacher, good_code, sem2) else 0
|
||||||
|
|
||||||
|
o = load_orientations()
|
||||||
|
|
||||||
for row in block:
|
for row in block:
|
||||||
student_id = row[3]
|
student_id = row[3]
|
||||||
|
orientation = o[student_id] if student_id in o else 0
|
||||||
scaled_score = round(num(row[7]) / final_max, 2)
|
scaled_score = round(num(row[7]) / final_max, 2)
|
||||||
out_f.writerow([crs_code, good_code, pocr, tch_code, mode, student_id, scaled_score])
|
out_f.writerow([crs_code, good_code, pocr, orientation, tch_code, mode, student_id, scaled_score])
|
||||||
print(course_code)
|
print(course_code)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Exception:", e)
|
print("Exception:", e)
|
||||||
|
|
@ -352,7 +421,7 @@ def process_grades():
|
||||||
|
|
||||||
out_fullrows = codecs.open(all_courses_file3,'w','utf-8')
|
out_fullrows = codecs.open(all_courses_file3,'w','utf-8')
|
||||||
out_f = csv.writer(out_fullrows)
|
out_f = csv.writer(out_fullrows)
|
||||||
out_f.writerow("course_code course pocr_status teacher_code mode student_id scaled_score".split(" "))
|
out_f.writerow("course_code course pocr_status orientation_status teacher_code mode student_id scaled_score".split(" "))
|
||||||
|
|
||||||
out_compact = codecs.open(all_courses_file2,'w','utf-8')
|
out_compact = codecs.open(all_courses_file2,'w','utf-8')
|
||||||
out_c = csv.writer(out_compact)
|
out_c = csv.writer(out_compact)
|
||||||
|
|
@ -393,6 +462,7 @@ if __name__ == "__main__":
|
||||||
2: ['process grades csv file',process_grades] ,
|
2: ['process grades csv file',process_grades] ,
|
||||||
3: ['test shortname parse',nametest] ,
|
3: ['test shortname parse',nametest] ,
|
||||||
4: ['test sem codes',codetest] ,
|
4: ['test sem codes',codetest] ,
|
||||||
|
5: ['get student data from orientations', get_student_orientations],
|
||||||
}
|
}
|
||||||
print ('')
|
print ('')
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue