public void endSemester(School school, SaveData data) throws EndSemesterException {
		// Check if all grades have been input.
		// At the same time calculate all GPA and CGPA
		Grade grade = null;
		Course newCourse = null;
		for (Course course : getCourses().values()) {
			for (Student student : course.getGroups().getStudents()) {
				try {
					grade = student.getGrade(course);
					grade.calcGPA();
					student.calcCGPA();
				} catch (KeyErrorException e){
					throw new EndSemesterException(
							String.format(
									"Student %d, %s have no grades in Course %d, %s", 
									student.getID(), student.getName(),
									course.getID(), course.getName()));
				}
			}
			// Shallow copy all courses in semester for archiving.
			// By replacing courses in school with new ones.
			newCourse = new Course(course);
			// Instantiate No. of tutorials and lab groups.
			int group_count = 0;
			int capacity = newCourse.getGroups().getCapacity();
			if (course.getGroups().getTutorials() != null) {
				group_count = course.getGroups().getTutorials().size();
				for (int i=0; i<group_count; i++) {
					if (i == group_count - 1) {
						newCourse.getGroups().addTutorial(capacity - ((capacity/group_count)*i));
					}
					else {
						newCourse.getGroups().addTutorial(capacity/group_count);
					}
				}
			}
			if (course.getGroups().getLabs() != null) {
				group_count = course.getGroups().getLabs().size();
				for (int i=0; i<group_count; i++) {
					if (i == group_count - 1) {
						newCourse.getGroups().addLab(capacity - ((capacity/group_count)*i));
					}
					else {
						newCourse.getGroups().addLab(capacity/group_count);
					}
				}
			}
			school.getCourses().put(newCourse.getID(), newCourse);
		}
		data.setCurrentSemester(0);
	}