// THIS CODE IS NOT SELF-CONTAINED IN THE TEXTBOOK -header lines needed


#include<iostream>

using namespace std;

class Student {
public:
   Student(int nov);
   ~Student();

   int get_no() const
   {  return no; }

   bool graduate() const
   {  return no_courses == TOTAL_COURSES;
                                    //   const static together
                                    //   with instance var
   }

   int evaluate_GPA() const;

   void record_grade(int grade);

   static int get_highest_GPA()     //   static function definition
   {  return highest_GPA; }         //   static var access

   static int get_no_students()     //   static function definition
   {  return no_students; }         //   static var access

   static const int PASS_GRADE = 5; //   static const var definition

   static const int TOTAL_COURSES = 40; //   static const var
                                        //   definition

private:
   static int no_students;              //   static var declaration
   static int highest_GPA;              //   static var declaration

   const int no;
   int no_courses;
   int completed_courses[TOTAL_COURSES];
};

int Student::no_students = 0;           //   static var definition

int Student::highest_GPA = 0;           //   static var definition

Student::Student(int nov) : no(nov), no_courses(0)
{
   no_students++;                       //   static var access
   cout << "Student with no " << no << " created!" << endl;
   cout << "There are " << no_students << " Students now!" << endl;
}

Student::~Student()
{
   no_students--;                       //   static var access
   cout << "Student with no " << no << " to be destroyed!" << endl;
   cout << "There are " << no_students  //   static var access
        << " Students now!" << endl;
}

void Student::record_grade(int grade)
{
   if (grade >= PASS_GRADE) {           //   const static together
                                        //   with instance var
      completed_courses[no_courses++] = grade;
   };
}

int Student::evaluate_GPA() const
{
   int curr_GPA = 0;
   if (no_courses > 0) {
      for (int i = 0; i < no_courses; i++)
         curr_GPA += completed_courses[i];
      if ((curr_GPA % no_courses) < (no_courses * 0.5))
         curr_GPA = curr_GPA / no_courses;
      else
         curr_GPA = ((curr_GPA / no_courses) + 1);
      if (graduate())
         if (curr_GPA > highest_GPA)    //   static var access
            highest_GPA = curr_GPA;     //   static var access
   }
   return curr_GPA;
}

int main()
{
   cout << Student::get_no_students()      //      static function call
        << endl;                           //      no instances yet

   Student s1(100);
   Student s2(200);

   cout << Student::get_no_students()      //      static function call
        << endl;
   cout << s2.get_no_students() << endl;   //      static function call
                                           //      using instance

   s1.record_grade(9);
   s1.record_grade(4);
   s1.record_grade(7);
   s1.record_grade(10);
   cout << "The student with no; " << s1.get_no()
        << " has current GPA: " << s1.evaluate_GPA() << endl;

   cout << "The total courses will be: "
        << s1.TOTAL_COURSES << endl;    //       static const var access
                                        //       using instance

   cout << "The pass grade is: "
        << Student::PASS_GRADE << endl; //       static const var access

   Student* ps3 = new Student(300);
   cout << ps3->get_no_students() << endl; //     static function call
                                           //     using pointer
   Student* ps4;
   cout << ps4->get_no_students() << endl; //     static function call
                                           //     using pointer

   delete ps3;

   return 0;
}
