
//
//  File: main.C
//
//  This is a simple program to demonstrate the use of STL maps.
//  See the lab description for more details.
//


#ifdef GNU
#include <iostream.h>
#define std
#else
#include <iostream>
#endif

#include "student.h"
#include <map> 

//  The solution uses the typedefs throughout.

typedef std::map< std::string, StudentRecord, std::less<std::string> > StudentMap;
typedef StudentMap::value_type StudentPair;


//  Exercise 6:
void
PrintMap( const StudentMap& students )
{
  std::cout << "\n\nContents of the student map:\n";
  for ( StudentMap::const_iterator itr = students.begin();
	itr != students.end(); ++ itr ) {
    std::cout << (*itr).first << "\n" << (*itr).second << std::endl;
  }
}

int
main()
{
  StudentMap students;

  //
  //  A. Inserting into a map using the [] operator.
  //
  students["Stewart"] = StudentRecord( "stewa1", "freshman", "12234567890" );
  students["Smith"] = StudentRecord( "smith3", "junior", "29384756102",
					 1000.0, 0, 0 );
  std::cout << students["Smith"] << "\n";
  std::cout << students["Jones"] << "\n" << std::endl;

  //
  //  B. Inserting using the "insert" operator.  The syntax gets a bit ugly...
  //
  StudentPair stu_value( "Anderson", StudentRecord("anders", "senior", "12121212121" ));
  std::pair< StudentMap::iterator, bool > 
    insert_result = students.insert( stu_value );
  if ( insert_result.second ) {
    std::cout << "Successful." << std::endl;
    //  C.   Exercise 2b
    std::cout << "Key: " << (*insert_result.first).first << "\nStudentRecord:\n"
	      << (*insert_result.first).second << std::endl;
  }
  else
    std::cout << "Unsuccessful." << std::endl;

  //
  // D.  Typedefs have been moved to above.
  //

  // 
  // E.
  //
  // students["Stewart"].add_grades( 4, 16.0 );
  // std::cout << "Stewart's gpa is now " << students["Stewart"].gpa()
  //           << std::endl;
  // students["Barnes"].pay( 9000 );
  // std::cout << "Barnes has paid $" << students["Barnes"].get_tuition()
  //          << "  in tuition.\nHer student id is  "
  //          << students["Barnes"].get_id() << std::endl;

  //  Exercise 5:

  //  Adding for Stewart.  If not there, insert a default StudentRecord
  StudentMap::iterator itr;
  if ( (itr = students.find("Stewart")) == students.end() ) {
    std::cout << "Stewart not found, so inserting ... " << std::endl;
    insert_result = students.insert( StudentPair( "Stewart", StudentRecord() ));
    if ( !insert_result.second) 
      std::cout << "Failed inserting 'Stewart'." << std::endl;
    itr = insert_result.first;
  }
  else {
    std::cout << "Stewart found" << std::endl;
  }
  (*itr).second.add_grades( 4, 16.0 );
  std::cout << "Stewart's gpa is now " << (*itr).second.gpa()
            << std::endl;
  
  //  Adding for Barnes.  If not there, insert a default StudentRecord
  if ( (itr = students.find("Barnes")) == students.end() ) {
    std::cout << "Barnes not found, so inserting ... " << std::endl;
    insert_result = students.insert( StudentPair( "Barnes", StudentRecord() ));
    if ( !insert_result.second) 
      std::cout << "Failed inserting 'Barnes'." << std::endl;
    itr = insert_result.first;
  }
  else {
    std::cout << "Barnes found" << std::endl;
  }
  (*itr).second.pay( 9000 );
  std::cout << "Barnes has paid $" << (*itr).second.get_tuition()
            << "  in tuition.\nHer student id is  "
            << (*itr).second.get_id() << std::endl;

  //  Exercise 6
  PrintMap( students );

  //  Exercise 7
  for ( itr=students.begin(); itr!=students.end(); ++itr )
    (*itr).second.add_grades( 4, 16.0 );

  // Exercise 9  This takes O(d + log n) time, where d is the number
  // of entries deleted and n is the number of entries in the tree
  // prior to deletion.  If the entries were found and deleted individually
  // it would require O(d log n) time.
  StudentMap::iterator start_itr = students.lower_bound("S");
  StudentMap::iterator end_itr = start_itr;
  while ( end_itr != students.end() && (*end_itr).first[0] == 'S' )
    ++ end_itr;
  students.erase( start_itr, end_itr );
  std::cout << "\nAfter erasing 'S's ..." << std::endl;
  PrintMap( students );
}


  
