######################################################################
##TZIUNIM Save this file as  TZIUNIM                                  #
## To use it, stay in the                                            #
##same directory, get into Maple (by typing: maple <Enter> )         #
##and then type:  read TZIUNIM<Enter>                                #
##Then follow the instructions given there                           #
##                                                                   #
##Written by Doron Zeilberger, Rutgers University ,                  #
#zeilberg at math dot rutgers dot edu                                #
######################################################################
 
#Created: Dec. 20, 2009
 
print(`Created:  Dec. 21, 2011`):
print(` This is TZIUNIM  `):
print(`to automatically compute course-grades `):

print(`Please report bugs to zeilberg at math dot rutgers dot edu`):
print(``):
 print(`The most current version of this  package and paper`):
 print(` are  available from`):
 print(`http://www.math.rutgers.edu/~zeilberg/  .`):
 print(`For a list of the procedures type ezra();, for help with`):
 print(`a specific procedure, type ezra(procedure_name);   .`):
 print(``):

with(combinat):

ezra1:=proc()

if args=NULL then
 print(` The supporting procedures are: `):
 print(``):

else
ezra(args):
fi:

end:

ezra:=proc()

if args=NULL then
 print(`The main procedures are: `):
 print(` AnalyzeSection, CheckValid,`):
print(` ComputeGrade, ComputeGradeG, Hodaot, Message, SectionGrades`):
print(` WeedOut `):


elif nops([args])=1 and op(1,[args])=AnalyzeSection then
print(`AnalyzeSection(S,CoV,J,X): analyzes the section S`):

elif nops([args])=1 and op(1,[args])=CheckValid then
print(`CheckValid(v): checks whether the vector v has a final grade`):

elif nops([args])=1 and op(1,[args])=ComputeGrade then
print(`ComputeGrade(v,C,J): Given a vector v of length 8 indicating`):
print(`[FirstName, LastName,QuizGradesList,Exam1,Exam2,FinalFrade,SccStatus,HomeworkGrade]`):
print(`returns the vector of length 12 with the same first`):
print(`8 components followed by the quiz-infomration,total grade, total grade if`):
print(`member of SCC, score for the course, and the letter grade`):
print(`For example, try:`):
print(`ComputeGrade(S[1][2],CU,J);`):



elif nops([args])=1 and op(1,[args])=Hodaot then
print(`Hodaot(C,CoV,J,X): makes messages for each person in the class`):
print(`For example, try: Hodaot(S1,CoV,J,X):`):

elif nops([args])=1 and op(1,[args])=Sader1 then
print(`Sader1(L): ranks a list K`):
print(`For example, try:`):
print(`Sader1([4,5,1,3]);`):

elif nops([args])=1 and op(1,[args])=SectionGrades then
print(`SectionGrades(S,CoV,J,X): computes the section grades`):
print(`For example, try:`):
print(`SectionGrades(S[1],CU,J,X);`):

elif nops([args])=1 and op(1,[args])=Message then
print(`Message(v,CoV,J): sends a message to student v`):
print(`J is a symbol to denote justified absence from a quiz or exam.`):
print(`For example, try:`):
print(`Message(S1[1],CU,J);`):

elif nops([args])=1 and op(1,[args])=WeedOut then
print(`WeedOut(Kita): weeds out class`):

else
print(`There is no ezra for`,args):
fi:
 
end:

#[A,B+,B,C+,C,D,F]
CU:=[460,430,400,370,325,280]:
#460-500: A ;   430-459: B+ ;   400-429: B ;   370-399: C+ ;   
#325-369: C ;   280-324: D ;   0-279: F . No Curve!. 


#ComputeGrade(v,CoV,J): Given a vector v of length 8 indicating
#[FirstName, LastName, QuizGrades, Exam1,Exam2,FinalGrade,SccStatus,HomeworkGrade]
#returns the vector of length 12 with the same first
#8 components followed by the triple [LowestQuizGrade, SecondLowestQuizGrade,TotalQuizes]
#followed by the BASE-line (for pro-rating),BASE-Line according to SCC membership,
#total grade, total grade according to 
#SCC membership, score for the course, and the letter grade
#For example, try:
#ComputeGrade(S[1][2],CU,J);
ComputeGrade:=proc(v,CoV,J) local tot1,tot2,tot3,BASE,LG1,LG2,QG,QG1,v1,MQ,QT,tot1a,tot2a,BASE1,BASE2,QGx,i1:
#[BOTELHO,HOLLY, [10,10,8.9,J,3,10,10,10,9,J],73,80,152,1,20]
v1:=v:
BASE1:=500:

MQ:=coeff(convert(v[3],`+`),J,1):
BASE1:=BASE1-MQ*10:
QG:=[]:
for i1 from 1 to nops(v[3]) do
 if v[3][i1]<>J then
  QG:=[op(QG),v[3][i1]]:
 fi:
od:

QGx:=add(x[QG[i1]],i1=1..nops(QG)):

LG1:=min(op(QG)):
if coeff(QGx,x[LG1],1)>1 then
QT:=convert(v[3],`+`)-MQ*J-2*LG1:
else
QG1:=convert(QG,set) minus {LG1}:

LG2:=min(op(QG1)):
QG:=convert(QG,set) minus {LG2}:
QT:=convert(v[3],`+`)-MQ*J-LG1-LG2:
fi:
tot1:=QT:

v1:=[op(v1),[MQ,LG1,LG2,QT]]:

if v[4]=J then
BASE1:=BASE1-100:
else
tot1:=tot1+v[4]:
fi:

if v[5]=J then
BASE1:=BASE1-100:
else
tot1:=tot1+v[5]:
fi:

tot1:=tot1+v[6]+v[8]:
tot2:=tot1:
BASE2:=BASE1:

if (v[7]=1 or v[7]=12) and v[4]<>J then
 BASE2:=BASE2-100:
 tot2:=tot2-v[4]:
fi:

if (v[7]=2 or v[7]=12) and v[5]<>J then
 BASE2:=BASE2-100:
 tot2:=tot2-v[5]:
fi:


tot1a:=(tot1/BASE1)*500.:
tot2a:=(tot2/BASE2)*500:

tot3:=max(tot1a,tot2a):
 
tot3:=evalf(tot3):

if tot3>=CoV[1] then
 RETURN([op(v1),[tot1,BASE1],[tot2,BASE2],tot3,A]):
elif tot3<CoV[1] and tot3>=CoV[2] then
 RETURN([op(v1),[tot1,BASE1],[tot2,BASE2],tot3,Bplus]):
elif tot3<CoV[2] and tot3>=CoV[3] then
 RETURN([op(v1),[tot1,BASE1],[tot2,BASE2],tot3,B]):
elif tot3<CoV[3] and tot3>=CoV[4] then
 RETURN([op(v1),[tot1,BASE1],[tot2,BASE2],tot3,Cplus]):
elif tot3<CoV[4] and tot3>=CoV[5] then
 RETURN([op(v1),[tot1,BASE1],[tot2,BASE2],tot3,C]):
elif tot3<CoV[5] and tot3>=CoV[6] then
 RETURN([op(v1),[tot1,BASE1],[tot2,BASE2],tot3,D]):
else
 RETURN([op(v1),[tot1,BASE1],[tot2,BASE2],tot3,F]):
fi:

end:



#[BOTELHO,HOLLY, [10,10,8.9,J,3,10,10,10,9,J],73,80,152,1,20]
#ComputeGradeG(v,CoV): Given a vector v of length 8 indicating
#[Name, Email, RUid,Exam1,Exam2,RecGrade,SccStatus,FinalGrade]
#returns the vector of length 13 with the same first
#8 components followed by the total grade, total grade if
#member of SCC, score for the course, and the letter grade
#and what is needed to get to the next grade
#followed by the number of missed quizes
#For example, try:
#ComputeGradeG(S[1][2],CU);
ComputeGradeG:=proc(v,CoV) local quizG,tot1,tot2,tot3,NA:

quizG:=convert(v[3],`+`):
NA:=coeff(quizG,J):


tot1:=v[4]+v[5]+v[6]+v[8]:
tot2:=v[8]*2.5:

if not type(tot1,numeric) or (not type(tot2,numeric)) then
RETURN([op(v),X3,X3,X3,X3,NotYet]):
fi:

if v[7]=1 then
 tot3:=max(tot1,tot2):
else
 tot3:=tot1:
fi:

if tot3>=CoV[1] then
 RETURN([op(v),tot1,tot2,tot3,A,tot3-CoV[1]]):
elif tot3<CoV[1] and tot3>=CoV[2] then
 RETURN([op(v),tot1,tot2,tot3,Bplus,tot3-CoV[1]]):
elif tot3<CoV[2] and tot3>=CoV[3] then
 RETURN([op(v),tot1,tot2,tot3,B,tot3-CoV[2]]):
elif tot3<CoV[3] and tot3>=CoV[4] then
 RETURN([op(v),tot1,tot2,tot3,Cplus,tot3-CoV[3]]):
elif tot3<CoV[4] and tot3>=CoV[5] then
 RETURN([op(v),tot1,tot2,tot3,C,tot3-CoV[4]]):
elif tot3<CoV[5] and tot3>=CoV[6] then
 RETURN([op(v),tot1,tot2,tot3,D,tot3-CoV[5]]):
else
 RETURN([op(v),tot1,tot2,tot3,F,tot3-CoV[6]]):
fi:

end:




#SectionGrades(S,CoV,X): computes the section grades
SectionGrades:=proc(S,CoV,J,X) local i,lu:

lu:=[]:
for i from 1 to nops(S) do
 if S[i][6]<>X then
 lu:=[op(lu),ComputeGrade(S[i],CoV,J)]:
  print(ComputeGrade(S[i],CoV,J)):
 fi:
od:
lu:
end:

#SectionGrades1(S,CoV,X): computes the section grades
SectionGrades1:=proc(S,CoV,J,X) local i,lu:

lu:=[]:
for i from 1 to nops(S) do
 if S[i][6]<>X then
 lu:=[op(lu),ComputeGrade(S[i],CoV,J)]:
 fi:
od:
lu:
end:


#Message(v,CoV,J): sends a message to student v
Message:=proc(v,CoV,J) local v1,gu1,gu2,tot1,tot2:

v1:=ComputeGrade(v,CoV,J):

print(`Dear `, v[2] ):
print(`Your score on the Final Exam was`, v[6] , `(out of 200) `):
print(``):
print(`I enjoyed having you in my class. As you may know by now,`):
print(`your grade for Math421  was`, convert(v1[13],string) ):
print(`I'd like to explain it.`):
print(``):
print(`The maximal number of points for people who took all the exams and all the quizes  is 500`):
print(`So the default Denominator is 500.`):
print(`The default Numerator (if you are member of neither Second Chance Clubs) is the`):
print(`Quizzes total score (10 quizzes, drop the two lowest grades) [MAX: 80] `):
print(`+ Exam 1 score (out of 100) `):
print(`+ Exam 2 score (out of 100) `):
print(`+Final Exam score (out of 200)`):
print(`+Homework/Notebook score (out of 20)`):
print(`In the default case, where you were never absent, the score is that Numerator`):
print(`If you had justified absences, the Denominator gets reduced. For example if you had justified absences from 3 quizzes`):
print(`The Denominator is 470, and I dropped the two loweset grades from the seven quizzes that you took, and the grade would be (Numerator/470)*500`):

if v[7]<>0 then
 print(`I will first compute the total score that you would have gotten WITHOUT  membership in the Second Chance Club(s)`):
fi:

print(``):
print(`Your Quiz grades were, in order, where J denotes a justified absence`):
print(v1[3]):
if v1[9][1]>0 then
print(`Since you had`, v1[9][1] , `justified absences in the quizes `):
print(`the denominator is`, 500-v1[9][1]*10):
fi:
if v1[4]<>J and v1[5]<>J then
print(`Dropping the two lowest grades, namely `, v1[9][2], `and `, v1[9][3], `, `):
print(`your quiz score adds up to:`,   v1[9][4] , `out of a total of `, 80-v1[9][1]*10 ):
print(`Your notebook/homework score was`, v1[8] , `(out of 20)`):
print(`Your score in Exam 1 was: ` ,  v1[4] ,`(out of 100)`):
print(`Your score in Exam 2 was: ` , v1[5] , `(out of 100)`):
print(`Your Final exam score was: ` , v1[6], `out of 200)` ):
gu1:=v1[4]+v1[5]+v1[6]+v1[8]+v1[9][4]:
print(`This adds up to:` , gu1, `out of`, 500-v1[9][1]*10):
tot1:=gu1/(500-v1[9][1]*10)*500. :
print(`Dividing the total by`, 500-v1[9][1]*10, `and multiplying by 500 yields the score of`, tot1):

elif v1[4]=J and v1[5]<>J then
print(`Dropping the two lowest grades`, v1[9][2],v1[9][3]):
print(`your quiz score adds up to:`,   v1[9][4] , `out of a total of `, 80-v1[9][1]*10 ):
print(`Your notebook/homework score was`, v1[8] , `(out of 20)`):
print(`You had a justified absence from Exam 1, so your denominator is`, 400-v1[9][1]*10):
print(`Your score in Exam 2 was: ` , v1[5] , `(out of 100)`):
print(`Your Final exam score was: ` , v1[6], `out of 200)` ):
gu1:=v1[5]+v1[6]+v1[8]+v1[9][4]:
tot1:=gu1/(400-v1[9][1]*10)*500.:
print(`This adds up to:` , gu1, `out of`, 400-v1[9][1]*10):
print(`Dividing the total by`, 400-v1[9][1]*10, `and multiplying by 500 yields the score of`, tot1):

elif v1[4]<>J and v1[5]=J then
print(`Dropping the two lowest grades`, v1[9][2],v1[9][3]):
print(`your quiz score adds up to:`,   v1[9][4] , `out of a total of `, 80-v1[9][1]*10 ):
print(`Your notebook/homework score was`, v1[8] , `(out of 20)`):
print(`Your had a justified absence from Exam 2, so your denominator is`, 400-v1[9][1]*10):
print(`Your score in Exam 1 was: ` , v1[4] , `(out of 100)`):
print(`Your Final exam score was: ` , v1[6], `out of 200)` ):
gu1:=v1[4]+v1[6]+v1[8]+v1[9][4]:

print(`This adds up to:` , gu1, `out of`, 400-v1[9][1]*10):
tot1:=gu1/(400-v1[9][1]*10)*500.:
print(`Dividing the total by`, 400-v1[9][1]*10, `and multiplying by 500 yields the score of`, tot1):

elif v1[4]<>J and v1[5]<>J then
print(`Dropping the two lowest grades`, v1[9][2],v1[9][3]):
print(`your quiz score adds up to:`,   v1[9][4] , `out of a total of `, 80-v1[9][1]*10 ):
print(`Your notebook/homework score was`, v1[8] , `(out of 20)`):
print(`You had  justified absences from both Exam1 and Exam 2, so your denominator is`, 300-v1[9][1]*10):
print(`Your Final exam score was: ` , v1[6], `out of 200)` ):
gu1:=v1[6]+v1[8]+v1[9][4]:
print(`This adds up to:` , gu1, `out of`, 300-v1[9][1]*10):
tot1:=gu1/(300-v1[9][1]*10)*500.:
print(`Dividing the total by`, 400-v1[9][1]*10, `and multiplying by 500 yields the score of`, tot1):
fi:


 
 if v1[7]=1 and v1[4]<>J then
  print(`Since you were also a member of the Second Chance Club for the First Exam`):
  print(`we also compute the total score disregarding the Exam 1 score so your total score is`, gu1-v1[4], `out of`, 400-v1[9][1]*10): 
  print(`dividing the modified Numerator`, gu1-v1[4] , `by the modified Denominator `, 400-v1[9][1]*10):
  print(`and multiplying by 500, yields the SCC(I) adjusted score to be`):
  tot2:=(gu1-v1[4])*500./(400-v1[9][1]*10):
  print(tot2):

   if tot2<tot1 then
     print(`since this is lower than the default score, being  a member`):
     print(`of SCC didn't help you and your score for determining your`):
     print(`grade is`, tot1):
   elif tot1=tot2 then
     print(`since this is the same as your default score, being  a member`):
     print(`of SCC didn't help you and your score for determining your`):
     print(`grade is`, tot1):
   else
     print(`since this is higher than your total score, being a member of`):
     print(`SCC did HELP you! and your score for compuing the grade is`):
     print(tot2):
   fi:
tot1:=max(tot1,tot2): 
 fi:



 if v1[7]=2 and v1[4]<>J then
  print(`Since you were also a member of the Second Chance Club for the Second Exam`):
  print(`we also compute the grade disregard the score of Exam 2, so your total score is`, gu1-v1[5], `out of`, 400-v1[9][1]*10): 
  print(`dividing the modified Numerator`, gu1-v1[5] , `by the modified Denominator `, 400-v1[9][1]*10):
  print(`and multiplying by 500, yields the SCC(II) adjusted score to be`):
  tot2:=(gu1-v1[5])*500./(400-v1[9][1]*10):
  print(tot2):

   if tot2<tot1 then
     print(`since this is lower than the default score, being  a member`):
     print(`of SCC didn't help you and your score for determining your`):
     print(`grade is`, tot1):
   elif tot1=tot2 then
     print(`since this is the same as your default score, being  a member`):
     print(`of SCC didn't help you and your score for determining your`):
     print(`grade is`, tot1):
   else
     print(`since this is higher than your total score, being a member of`):
     print(`SCC did HELP you! and your score for compuing the grade is`):
     print(tot2):
   fi:
tot1:=max(tot1,tot2): 
 fi:



 if v1[7]=12 and v1[4]<>J and v1[5]<>J then
  print(`Since you were also a member of the Second Chance Club for the Both Exams`):
  print(`we also compute the grade disregard both Exam 1 and Exam 2 score so your total score is`, gu1-v1[4]-v1[5], `out of`, 300-v1[9][1]*10): 
  print(`dividing the modified Numerator`, gu1-v1[4]-v1[5] , `by the modified Denominator `, 300-v1[9][1]*10):
  print(`and multiplying by 500, yields the SCC(I and II) adjusted score to be`):
  tot2:=(gu1-v1[4]-v1[5])*500./(300-v1[9][1]*10):
  print(tot2):

   if tot2<tot1 then
     print(`since this is lower than the default score, being  a member`):
     print(`of SCC didn't help you and your score for determining your`):
     print(`grade is`, tot1):
   elif tot1=tot2 then
     print(`since this is the same as your default score, being  a member`):
     print(`of SCC didn't help you and your score for determining your`):
     print(`grade is`, tot1):
   else
     print(`since this is higher than your total score, being a member of`):
     print(`SCC did HELP you! and your score for compuing the grade is`):
     print(tot2):
   fi:
tot1:=max(tot1,tot2): 
 fi:




print(`Recall that, according to the class's main webpage, the grades`):
print(`are assigned as follows`):
print(`460-500: A ;   430-459: B+ ;   400-429: B ;   370-399: C+ ; 325-369: C ;   280-324: D ;   0-279: F  `):
print(`This explains why your grade for the class is`, convert(v1[13],string) ):

print(`If you would like to examine your Final exam, you can do it`):
print(`in my office,  starting Jan. 23, 2012,`):
print(`during my office hours MTh 10:45-11:30am, at Hill 704.`):

if v1[13]=A then
print(`Congratulations for getting an A! Keep up the good work`):
print(`Good luck in your future studies, and have a good break!`):
print(`Best wishes,`):
print(`Dr. Z. `):
elif v1[13]=Bplus then
 print(`Advanced Calculus for Engineers (a.k.a. Calc5) is a very demanding class`):
 print(`and getting B+ is pretty neat!`):
print(`Good luck in your future studies, and have a good break!`):
print(`Best wishes`):
print(`Dr. Z. `):
elif v1[13]=D or v1[13]=F then
 print(`You probably didn't have enough time to study for this demanding class`):
 print(`I am sure that when you take it again, and have more time to study properly`):
 print(`you would do much better. `):
print(`Good luck in your future studies, and have a good break!`):
print(`Best wishes`):
print(`Dr. Z. `):
else
print(`Good luck in your future studies, and have a good break!`):
print(`Best wishes`):
print(`Dr. Z. `):
fi:
 
end:


#Hodaot(C,Cov,J,X): makes messages for each person in the class
#For example, try: Hodaot(S[1],CoV):
Hodaot:=proc(C,CoV,J,X) local i:
for i from 1 to nops(C) do
if type(C[i][6],numeric) then
writeto(C[i][1]):
Message(C[i],CoV,J):
fi:
od:
end:


#CheckValid(v): checks whether the vector v has a final grade
CheckValid:=proc(v)

if not type(v[6],numeric) then
 RETURN(false):
else
 RETURN(true):
fi:

end:

#[BOTELHO,HOLLY, [10,10,8.9,J,3,10,10,10,9,J],73,80,152,1,20]
#CheckS(v): checks whether the vector v is a good one
CheckS:=proc(v,J,X) local gu,g:
if nops(v)<>8 then
 print(v, `does not have 8 elements`):
 RETURN(false):
fi:

gu:={op(v[3])} minus {J,X}:

if {seq(type(g,numeric), g in gu)}<>{true} then
  RETURN(false):
fi:



if not ( v[4]<>J and v[4]<>X  and 0<=v[4] and v[4]<=100) then
 RETURN(false):
fi:

if not ( v[5]<>J and v[5]<>X  and 0<=v[5] and v[5]<=100) then
 RETURN(false):
fi:

if not ( v[6]<>J and v[6]<>X  and 0<=v[6] and v[6]<=200) then
 RETURN(false):
fi:

if not ( v[8]<>X  and 0<=v[8] and v[8]<=20) then
 RETURN(false):
fi:

if not member(v[7],{0,1,2,12,X}) then
 RETURN(false):
fi:

end:

#WeedOut(Kita): weeds out class
WeedOut:=proc(Kita) local i,gu,v:
gu:=[]:
for i from 1 to nops(Kita) do
v:=Kita[i]:

if  CheckValid(v) then
 if not CheckS(v) then
  print(v, `is illegal `):
 else
  gu:=[op(gu),v]:
 fi:
fi:
od:
gu:
end:


#Ranking1(L): given a list L finds the set of
#champions, followed by the second-in-commands etc.
Ranking1:=proc(L) local aluf,gu,L1,mu,i,T,s,j:
L1:=convert(L,set):

gu:=[]:
while L1<>{} do

aluf:=max(op(L1)):

mu:={};

for i from 1 to nops(L) do
if L[i]=aluf then
  mu:=mu union {i}:
fi:
L1:=L1 minus {aluf}:
od:
gu:=[op(gu),mu]:
od:

for i from 1 to nops(gu) do
for s in gu[i] do
 T[s]:=add(nops(gu[j]),j=1..i-1)+1:
od:
od:

[seq(T[s],s=1..nops(L))]:
end:








#AnalyzeSection(S,CoV): analyzes the section S
AnalyzeSection:=proc(S,CoV,J,X) local lu,gu,x,i,mu,ave,sd:

lu:=SectionGrades1(S,CoV,J,X):

gu:=add(x[lu[i][13]],i=1..nops(lu)):

mu:=[seq([lu[i][1],lu[i][6]],i=1..nops(lu))]:

print(`There were `, nops(lu), `students`):

print(coeff(gu,x[A],1) , `students got an A`):

print(coeff(gu,x[Bplus],1) , `students got a B+`):

print(coeff(gu,x[B],1) , `students got a B`):

print(coeff(gu,x[Cplus],1) , `students got a C+`):

print(coeff(gu,x[C],1) , `students got a C `):

print(coeff(gu,x[D],1) , `students got a D  `):

print(coeff(gu,x[F],1) , `students got an  F  `):

ave:=evalf(add(mu[i][2],i=1..nops(mu))/nops(mu)):

sd:=sqrt(evalf(add((mu[i][2]-ave)^2,i=1..nops(mu))/nops(mu))):

print(`The average on the Final exam was`, ave):


print(`The standard deviation was `, sd):

mu:

end:




