-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmitGradesGeneric.ur
96 lines (76 loc) · 4.23 KB
/
mitGradesGeneric.ur
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
(* Assignment of final grades, with export in MIT Online Grades format *)
open Bootstrap
functor Make(M : sig
con grades :: {Unit}
val grades : $(mapU string grades)
val gfl : folder grades
end) = struct
functor Make(N : sig
con groups :: {Unit}
(* Boolean flags indicating membership in classes of users *)
con others :: {Type}
(* Miscellaneous remaining fields of the users table *)
constraint groups ~ others
constraint [MitId, UserName, IsStudent, IsListener, Units, SubjectNum, SectionNum, LastName, FirstName, MiddleInitial, Grade, Min, Max] ~ (mapU bool groups ++ others)
con keyName :: Name
con otherKeys :: {{Unit}}
constraint [keyName] ~ otherKeys
val users : sql_table ([MitId = string, UserName = string, IsStudent = bool, IsListener = bool, Units = string, SubjectNum = string, SectionNum = string, LastName = string, FirstName = string, MiddleInitial = string] ++ mapU bool groups ++ others) ([keyName = [UserName]] ++ otherKeys)
val grades : Grades.t
(* Current user allowed to access grades interface? *)
val access : transaction FinalGrades.access
end) = struct
open N
val show_commonName = mkShow (fn {UserName = s} => s)
structure FG = FinalGrades.Make(struct
con key = [UserName = string]
val tab = users
val filter = (WHERE tab.IsStudent)
type summaries = list (string * int)
type summary = int
fun summary sms u = Option.get 0 (List.assoc u.UserName sms)
con grades = M.grades
val grades = M.grades
val gfl = M.gfl
val keyLabel = "Student"
val summaryLabel = "Average"
val gradeLabel = "Grade"
val access = access
end)
val summaries =
all_grades <- Grades.allStudents grades;
return (Grades.averagesOf all_grades)
val eq_UserName = mkEq (fn {UserName = s1 : string} {UserName = s2 : string} => s1 = s2)
val csv =
acc <- access;
case acc of
FinalGrades.Forbidden => error <xml>Access denied</xml>
| _ =>
sms <- summaries;
grs <- FG.grades sms;
sheet <- query (SELECT users.MitId, users.UserName, users.Units, users.SubjectNum, users.SectionNum, users.LastName, users.FirstName, users.MiddleInitial
FROM users
WHERE users.IsStudent
AND users.MitId <> ''
ORDER BY users.LastName, users.FirstName, users.MiddleInitial)
(fn {Users = r} sheet =>
let
val grade =
case List.assoc {UserName = r.UserName} grs of
None => error <xml>No grade found for {[r.UserName]}!</xml>
| Some g =>
@@Record.select [fn _ => string] [fn _ => unit] [M.grades] M.gfl [string]
(fn [u] (text : string) () => text)
M.grades g
val row = r.LastName ^ "," ^ r.FirstName ^ "," ^ r.MiddleInitial ^ "," ^ r.MitId ^ "," ^ r.SubjectNum ^ "," ^ r.SectionNum ^ "," ^ grade ^ "," ^ r.Units ^ ",\n"
in
return (sheet ^ row)
end)
"Last Name,First Name,Middle,MIT ID,Subject #,Section #,Grade,Units,Comment\n";
returnBlob (textBlob sheet) (blessMime "text/csv")
type a = _
val ui = Ui.seq (Ui.computed FG.ui summaries,
Ui.const <xml><a class="btn btn-primary"
link={csv}>Export for MIT Online Grade Submission</a></xml>)
end
end