
//
//  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"

#ifdef GNU
#include <multimap.h> 
#else
#include <map>
#endif

//  The solution uses the typedefs throughout.

typedef std::multimap< std::string, StudentRecord,
                       std::less<std::string> > StudentMMap;
typedef StudentMMap::value_type StudentPair;


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

int
main()
{
  StudentMMap students;
  StudentMMap::iterator itr;

  //
  //  A & B combined: inserting into a multimap.  There is no need to 
  //   check the insert results because duplicate entries are allowed!
  //
  StudentPair to_ins1("Stewart", StudentRecord( "stewa1", "freshman",
					       "12234567890"));
  itr = students.insert( to_ins1 );

  StudentPair to_ins2( "Smith",
		       StudentRecord( "smith3", "junior",
				       "29384756102", 1000.0, 0, 0 ));
  itr = students.insert( to_ins2 );
  std::cout << (*itr).second << "\n";

  StudentPair to_ins3( "Jones", StudentRecord() );
  itr = students.insert( to_ins3 );			
  std::cout << (*itr).second << "\n" << std::endl;

  StudentPair to_ins4( "Anderson", StudentRecord("anders8", "senior",
						 "12121212121" ));
  itr = students.insert( to_ins4  );   
  //  C.   Exercise 2b 
  std::cout << "Key: " << (*itr).first << "\nStudentRecord:\n"
	    << (*itr).second << std::endl;


  //  Inserting duplicates:
  StudentPair to_ins5("Stewart",StudentRecord("stewa2", "senior",
					      "041526173849"));
  StudentPair to_ins6("Anderson",StudentRecord("anders17", "freshman",
					       "9753124680"));
  itr = students.insert( to_ins5 );
  itr = students.insert( to_ins6 );

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

  //  Exercise 5:

  //  Adding for Stewart.  If not there, insert a default StudentRecord
  if ( (itr = students.find("Stewart")) == students.end() ) {
    std::cout << "Stewart not found, so inserting ... " << std::endl;
    itr = students.insert( StudentPair( "Stewart", StudentRecord() ));
  }
  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;
    itr = students.insert( StudentPair( "Barnes", StudentRecord() ));
  }
  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.
  StudentMMap::iterator start_itr = students.lower_bound("S");
  StudentMMap::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 );
}


  
