(****** * This file defines objects and operations related to student grade prediction * *) module StudentIF; from Gradesheet import StudentInfo, GradeSheet; from Gradesheet import DataItem,MaxScore; from Gradesheet import computeGrade, Weight; from Gradesheet import GradedItem; from Gradesheet import Grade; from Gradesheet import Score; from Tools import Scheme,Min,Max; from Tools import GradeNumber, GradeLetter; from Departmentserver import Server, UserId, Password, User; export all; operation predictFinal is inputs: gi:GradedItem*, gr:Grade, gs:GradeSheet; outputs: gi':GradedItem*; description: (* Takes hypothetical scores for ungraded assignments and produces a final grade based on the hypothetical grades. If a score for an ungraded item is left blank, it will be treated as a zero. If predicted scores are impossible, a message "not possible" will be posted next to the impossible score. *); precondition: (* * There must be at least one GradedItem containing a grade. *) exists (item in gi) item.score!=nil; postcondition: (* A hypothetical final grade is found by summing up the total points for all graded and predicted assignments, then dividing that by all the points possible for all assignments *) computeGrade(gi, gr); end predictFinal; operation predictEmpties is inputs: gi:GradedItem*, sch:Scheme, dg:GradeLetter; outputs: gi':GradedItem*; description: (* Takes a hypothetical final score for the course and fills in all ungraded assignements with the scores needed on each assignment to achieve the hypothetical final grade. The predicted scores for each column are roughly proportional to each other based on max score. For example if assignment1 is worth 100 points and assignment2 is also worth 100 points and the final grade desired requires a total of 150 points total from assignment1 and assignment2, then the prediction will be 75 points for each. *); precondition: exists (item in gi) item.score!=nil; postcondition: forall(i:integer | i>=1 and i<=#gi) if(gi[i].score=nil) then (gi[i].score = gi[i].maxscore*((gradeToScore(dg,sch)/100-sumGradedAssn(gi))/sumUngradedWeights(gi))) else gi'[i].score = gi[i].score ; end predictEmpties; operation populateData is inputs: g:GradeSheet; outputs: g':GradeSheet; description: (* Takes the information downloaded from the department server and displays it on the screen with other student's names anonymized. All other students have "******" as a replacement to their names. Also order other students in class is randomized so alphabetical order can't be used to find other student's identities. *); precondition: (* not required for this milestone, but coming soon *); postcondition: (* not required for this milestone, but coming soon *); end populateData; operation login inputs: s:Server, uid:UserId, passwd:Password; outputs: gs':GradeSheet; pre: exists (u in s.users) (u.userid = uid) and (u.password = passwd); post: gs' = s.sgs; description: (* Students must log in to the department server to obtain their grade information. If the user name and password exist on the server's user list, then return the Gradesheet with the student grades, otherwise nil. *); end login; function sumGradedAssn(gi:GradedItem*)= if (#gi = 0) then 0 else if gi[1].score!=nil then ((gi[1].score/gi[1].maxscore)*gi[1].weight) + sumGradedAssn(gi[2:#gi]) else sumGradedAssn(gi[2:#gi]); function sumUngradedWeights(gi:GradedItem*) = if(#gi = 0) then 0 else if gi[1].score=nil then gi[1].weight + sumUngradedWeights(gi[2:#gi]) else sumUngradedWeights(gi[2:#gi]); function scoreToGrade(s:Score, sch:Scheme) -> (gl:GradeLetter) = forall(i:integer | i>=1 and i<#sch.gradenbr) if (sch.gradenbr[i].min <= s) and (sch.gradenbr[i].max >= s) then gl=sch.gradeltr[i] ; function gradeToScore(g:GradeLetter, sch:Scheme) -> (s:Score) = forall(i:integer | i>=1 and i<#sch.gradenbr) if (sch.gradeltr[i]=g) then s=sch.gradenbr[i].min ; end StudentIF;