(******
 * This file defines objects and operation in the STUDENT menu
 *
 *
 *)
 
 
(* Operations from the Student menu *)
module Student;
from Gradesheet import GradeSheet, StudentInfo, Column, ID, Grade, CalculatedScore;
export all;

  operation AddNewStudent is
	 inputs: gs:GradeSheet, si:StudentInfo;
	 outputs: gs':GradeSheet;
	 description: (*
		Adds a new student to the Gradesheet.
		The student must have an ID that is not
		the same as a student already in the Gradesheet.
		The ID field is required and must be eight characters or less.  
    The Name is also a required field and the Group and Comments fields are optional. *);
	
	precondition:
    (*
         * There is no student info record in the gradesheet with the same id as the
         * record to be added.
         *)
        not (exists (si' in gs.silist) si'.id = si.id); 
        
 postcondition:
        (*
         * A student info record is in the output gradesheet if and only if it is the new
         * student info record to be added or it is in the input gradesheet.
         *)
        forall (si':StudentInfo)
            (si' in gs'.silist) iff ((si' = si) or (si' in gs.silist));  
	
  end AddNewStudent;
	

	
  operation EditStudent is
	inputs: gs:GradeSheet, siList:StudentInfo, old_si:StudentInfo, new_si:StudentInfo;
	outputs: gs':GradeSheet;
	description: (*
		User must select a student from a list of
		existing students.  The new student information
		replaces the old one.  If changed, the ID must still be unique.
	*);
	
	 precondition:
        (*
         * The old and new user records are not the same.
         *)
        (old_si != new_si)

            and

        (*
         * The old record is in the given db.
         *)
        (old_si in gs.silist)

            and

        (*
         * There is no user record in the input gradesheet with the same id as the
         * new record to be added.
         *)
        (not (exists (new_si' in gs.silist) new_si'.id = new_si.id));
        
	
  end EditStudent;

  operation DeleteStudent is
	inputs: gs:GradeSheet, si:StudentInfo;
	outputs: gs':GradeSheet;
	description: (*
		Removes an existing student from the Gradesheet.
		User must select student from a list of existing students.
		The gradesheet that is the output is the same as the input,
		except that the selected student is removed.
	*);
	precondition: 
	(* The StudentInfo record is in the input GradeSheet *)
	si in gs.silist;
	
	postcondition:
		(*
         * A user record is in the output db if and only if it is not the
         * existing record to be deleted and it is in the input db.
         *)
        (forall (si':StudentInfo)
            (si' in gs'.silist) iff ((si' != si) and (si' in gs.silist)));
	
	
	
  end DeleteStudent;




  operation SortStudentsByID is
	inputs: gs:GradeSheet, si:StudentInfo;
	outputs: gs':GradeSheet;
	description: (*
		This operation replaces the current GradeSheet with a 
		newly ordered by ID GradeSheet.
	*);
	precondition: (*none so far*);
	postcondition: 
    (* all students are sill in the gradesheet*)
    (forall (si' in gs.silist) (si' in gs'.silist))
    and
    (* students are in the correct order *)
  (forall(i: integer)
    gs'.silist[i].id < gs'.silist[i+1].id);
  end SortStudentsByID;
  
  
    operation SortStudentsByGrade is
	inputs: gs:GradeSheet, si:StudentInfo;
	outputs: gs':GradeSheet;
	description: (*
		This operation replaces the current GradeSheet with a 
		newly ordered by Name GradeSheet.
	*);
	precondition: (*none so far*);
	postcondition: 
    (* all students are sill in the gradesheet*)
    (forall (si' in gs.silist) (si' in gs'.silist))
    and
    (* students are in the correct order *)
  (forall(i: integer)
    gs'.silist[i].grade < gs'.silist[i+1].grade);

  end SortStudentsByGrade;
  
      operation SortStudentsByScore is
	inputs: gs:GradeSheet, si:StudentInfo;
	outputs: gs':GradeSheet;
	description: (*
		This operation replaces the current GradeSheet with a 
		newly ordered by Score GradeSheet.
	*);
	precondition: (*none so far*);
	postcondition: 
    (* all students are sill in the gradesheet*)
    (forall (si' in gs.silist) (si' in gs'.silist))
    and
    (* students are in the correct order *)
  (forall(i: integer)
    gs'.silist[i].calcdscore < gs'.silist[i+1].calcdscore);

  end SortStudentsByScore;

      operation SortStudentsByName is
	inputs: gs:GradeSheet, si:StudentInfo;
	outputs: gs':GradeSheet;
	description: (*
		This operation replaces the current GradeSheet with a 
		newly ordered by Name GradeSheet.
	*);
	precondition: (*none so far*);
	postcondition: ;

  end SortStudentsByName;


end Student;