Contract Program
with
File Input and Output

// main for books version (Chapter 11, Section 6) of contract program using
// a list   - with strings
// Also: Prints all contracts from this file using an iterator
// Adds ability to read from a file and write to a file

// file:   ch11tts1.cpp



#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <fstream.h>

#include "contrct6.h"
#include "common2.h"
#include "ch10lst1.h"


typedef
	char String80[81];

void GetFileName(String80 prompt, String80 fileName);

void GetProperties(String80 properties);
void GetNewString(String80 string, String80 property);
char GetOperatorChoice();
int GetContractID();

void DisplayInfo(Contract contract);
void ChangeInfo( Contract& contract);

void DisplayClosingMessage();
void DisplayIntro();


int GetSquareFootage();
int GetNumDesks();
int GetNumDays();

void ProcessUserChoices();

void DisplayContract(ListOfContracts& contracts);
void ChangeContract(ListOfContracts& contracts);
void DisplayAllContracts(ListOfContracts& contracts);
void AddContract(ListOfContracts& contracts);
void DeleteContract(ListOfContracts& contracts);

void ReadInstances(ListOfContracts& contracts);
// changed from Initialize....

void OutputData(ListOfContracts& contracts);
void WriteInfo(ofstream& outFile, Contract contract);
void CreateContract(int contractID, Contract& contract);


void main()
{
	DisplayIntro();
	ProcessUserChoices();
	DisplayClosingMessage();
}



char GetOperatorChoice()
{// please enter choice
// make a while loop and talk about redundancy.
	char choice;

	cout << "Please choose one of the following operations\n";
	cout << "         'D' to display the information for a contract\n";
	cout << "         'L' to display the information on ALL contracts\n";
	cout << "         'C' to change the information for a contract\n";
	cout << "         'A' to add a contract to the list\n";
	cout << "         'E' to eliminate a contract from the list\n";
	cout << "         'Q' to quit the program\n";
	cin >> choice;
	return choice;
}

int GetContractID()
{// loop choice 1-5

	int num;
	cout << "\nPlease enter the ID for the contract you wish to work with\n";
	cout << "Choose 0 (zero) when you are finished with this operation.\n";
	cin >> num;
	return num;
}

void GetNewString(String80 string, String80 property)
{
	cout << "Please enter the new " << property << endl;
	cin.ignore(80, '\n'); // clear out any unprocessed characters - especially \0
	cin.get(string, 81);
}

void 	ChangeInfo( Contract& contract)
{       String80 string;
	String80 properties;
	GetProperties(properties);
	int index = 0;
	while (properties[index])
	{	switch (properties[index])
		{  case '1':
				GetNewString(string, "ContracteeName");
				contract.ChangeContracteeName(string);
				break;

			case '2':
				GetNewString(string, "Office Street Address");
				contract.ChangeOfficeStreetAddress(string);
				break;
			case '3':
				GetNewString(string, "Office City");
				contract.ChangeOfficeCity(string);
				break;
			case '4':
				GetNewString(string, "Office State");
				contract.ChangeOfficeState(string);
				break;
			case '5':
				GetNewString(string, "Office Zip Code");
				contract.ChangeOfficeZip(string);
				break;
			case '6':
				int sqFootage;
				sqFootage = GetSquareFootage();
				contract.ChangeSquareFootage(sqFootage);
				break;
			case '7':
				int numDesks;
				numDesks = GetNumDesks();
				contract.ChangeNumDesks(numDesks);
				break;
			case '8':
				int numDays;
				numDays = GetNumDays();
				contract.ChangeNumDays(numDays);
				break;
			default:
				cout << endl << properties[index] << " is an invalid code.\n";

		}  // end switch
		index++;
	} // end while
	clrscr();
	DisplayInfo(contract); // allow user to see changes before proceeding
}



void CreateContract(int contractID, Contract& contract)
{       String80 string;
	contract.ChangeID(contractID);

	GetNewString(string, "ContracteeName");
	contract.ChangeContracteeName(string);

	GetNewString(string, "Office Street Address");
	contract.ChangeOfficeStreetAddress(string);

	GetNewString(string, "Office City");
	contract.ChangeOfficeCity(string);

	GetNewString(string, "Office State");
	contract.ChangeOfficeState(string);

	GetNewString(string, "Office Zip Code");
	contract.ChangeOfficeZip(string);

	int sqFootage;
	sqFootage = GetSquareFootage();
	contract.ChangeSquareFootage(sqFootage);

	int numDesks;
	numDesks = GetNumDesks();
	contract.ChangeNumDesks(numDesks);

	int numDays;
	numDays = GetNumDays();
	contract.ChangeNumDays(numDays);

	clrscr();
	DisplayInfo(contract);
}


void DisplayInfo(Contract contract)
{
	cout << "                Contract ID: "
		  << contract.ProvideID() << endl;
	cout << "Contractee Name:  " << contract.ProvideContracteeName() << endl;

	cout << "\nOffice ";
	cout << "Address:\n    "<< contract.ProvideOfficeStreetAddress() << "  "
		  << contract.ProvideOfficeCity() << ", "
		  << contract.ProvideOfficeState() << " "
		  << contract.ProvideOfficeZip() <<  endl;

	int sqFootage;
	sqFootage = contract.ProvideSquareFootage();
	cout << "\nThe square footage: " << sqFootage << "     ";

	int numDesks;
	numDesks = contract.ProvideNumberOfDesks();
	cout << "The number of desks: " << numDesks << endl;

	int numDays;
	numDays = contract.ProvideNumberOfDays();
	cout << "The number of days:  " << numDays << "   ";

	double charge;
	charge = contract.ProvidePerWeekCharge();
	cout << "The per week charge:   " << charge << endl;
	cout << endl << endl;

}



void GetProperties(String80 properties)
{       cin.ignore(80, '\n');
	cout << "Please enter the codes corresponding to the properties you want to change\n";
	cout << "Enter as many as you desire. When finished, hit Enter.\n";

	cout << "          '1':  Contractee Name\n";
	cout << "          '2':  Office Street Address\n";
	cout << "          '3':  Office City\n";
	cout << "          '4':  Office State\n";
	cout << "          '5':  Office Zip\n";
	cout << "          '6':  square Footage\n";
	cout << "          '7':  number of desks\n";
	cout << "          '8':  number of days per week\n";
	cin.get(properties,81);
}

void 	DisplayClosingMessage()
{	cout << "\n\n\n     H A V E   F U N";
}

void DisplayIntro()
{	cout << "               W E L CO M E   TO   O L Y M P I A ' S\n";
	cout << "         O F F I C E   C O N T R A C T   P R O G R A M\n\n\n";
}

int GetSquareFootage()
{	int sqFootage;
	cout << "\nWhat is the new square footage for the contract?";
	cin >> sqFootage;
	return sqFootage;
}


int GetNumDesks()
{	int numDesks;
	cout << "\nWhat is the new number of desks for the contract?";
	cin >> numDesks;
	return numDesks;
}


int GetNumDays()
{	int numDays;
	cout << "\nWhat is the new number of days for the contract?";
	cin >> numDays;
	return numDays;
}

void ProcessUserChoices()
{
// Code to create the list of contracts
   ListOfContracts contracts;
   ReadInstances(contracts);   // Load the database

   bool done = false;   // Is the user finished processing contracts?
   char choice;
   choice = GetOperatorChoice();

   while (!done)
	{	switch (choice)
		{	case 'D':
			case 'd':
				DisplayContract(contracts);
				break; // case 'd'
			case 'C':
			case 'c':
				ChangeContract(contracts);
				break; // case 'c'

			case 'L':
			case 'l':
				DisplayAllContracts(contracts);
				break;

			case 'A':
			case 'a':
				AddContract(contracts);
				break;

			case 'E':
			case 'e':
				DeleteContract(contracts);
				break;

			case 'Q':
			case 'q':
				cout << "Do you  really want to want to quit (Y) or (N)\n";
				char answ;
				cin >> answ;
				if ((answ =='Y') || (answ == 'y'))
				{
					done = true;
					OutputData(contracts);
				}

				break;
			default:
				cout << "Invalid choice. Please try again";
				choice = GetOperatorChoice();
		}  // end switch
		if (!done)
		{
			choice = GetOperatorChoice();
		}

	}
}

void DisplayContract(ListOfContracts& contracts)
{ int contractID;
  bool found;
  Contract contract;
  contractID = GetContractID();
  while (contractID != 0)
  {  found = contracts.FindContract(contractID, contract);
	  if (found)
	  {  clrscr();
		  DisplayInfo(contract);
	  }
	  else
	  {	cout << "\nContract " << contractID << " is not in list.\n";
	  }
	  contractID = GetContractID();
	}
}

void ChangeContract(ListOfContracts& contracts)
{       int contractID;
	bool found;
	Contract contract;
	contractID = GetContractID();
	while (contractID != 0)
	{  found = contracts.FindContract(contractID, contract);
		if (found)
		{
			ChangeInfo(contract);
			contracts.ReplaceContract(contract);
		}
		else
		{	cout << "\nContract " << contractID << " is not in list.\n";
		}
		contractID = GetContractID();
	}
}

void DisplayAllContracts(ListOfContracts& contracts)
{       Contract contract;
	contracts.Reset();
	for (; contracts.AreThereMore(); )
	{  contract.CopyContract(contracts.GetNext());
		DisplayInfo(contract);
	}
}

void AddContract(ListOfContracts& contracts)
{       int contractID;
	contractID = GetContractID();
	Contract contract;
	while (contractID != 0)   // The user wants to add another contract
	{	CreateContract(contractID, contract);
		contracts.Add(contract);
		contractID = GetContractID();
	}
}

void DeleteContract(ListOfContracts& contracts)
{       int contractID;
	contractID = GetContractID();
	while (contractID != 0) // The user wants to delete a contract
	{	contracts.Delete(contractID);
		contractID = GetContractID();
	}
}


void ReadInstances(ListOfContracts& contracts)
{
	// Get from user the file holding the contract database
	String80 fileName;
	GetFileName("Please enter the file containing the contract database.",
					fileName);

	ifstream inputData (fileName);
	if (!inputData)
	{	cout << "Cannot open input file\n";
		exit(1);
	}


	String80 name;
	String80 streetAddress;
	String80 city;
	String80 state;
	String80 zip;
	int ID;
	int sqFootage;
	int desks;
	int days;

	String80 dummy;
	char chDummy;

	Contract contract;


	while (!inputData.eof())
	{  if (inputData.fail())
	{	inputData.clear();
		inputData >> chDummy;
		cout << "Invalid value entered\n";

	}

		inputData >> ID;
		inputData >> chDummy; // to skip comma
		inputData.get(name, 81,',');
		inputData >> chDummy; // to skip comma
		inputData.get(streetAddress, 81,',');
		inputData >> chDummy; // to skip comma
		inputData.get(city, 81,',');
		inputData >> chDummy; // to skip comma
		inputData.get(state, 81,',');
		inputData >> chDummy; // to skip comma
		inputData.get(zip, 81,',');
		inputData >> chDummy; // to skip comma
		inputData >> sqFootage;
		inputData >> chDummy; // to skip comma
		inputData >> desks;
		inputData >> chDummy; // to skip comma
		inputData >> days;
		inputData.getline(dummy, 80);


		// Create a contract, assign its properties values and insert it into the list.
		contract.ChangeContracteeName(name);
		contract.ChangeOfficeStreetAddress(streetAddress);
		contract.ChangeOfficeCity(city);
		contract.ChangeOfficeState(state);
		contract.ChangeOfficeZip(zip);

		contract.ChangeID(ID);
		contract.ChangeSquareFootage(sqFootage);
		contract.ChangeNumDesks(desks);
		contract.ChangeNumDays(days);

		contracts.Add(contract);

	}

}


void GetFileName(String80 prompt, String80 fileName)
{ 	cout << endl; // just to make space
	cout << prompt << endl;
	cin.getline(fileName, 40);
}

void OutputData(ListOfContracts& contracts)
{       String80 fileName;
	cin.ignore();
	GetFileName("Please enter the file in which to save the contract database.",
					fileName);


	ofstream outFile (fileName);
	if (!outFile)
	{	cout << "Cannot open output file\n";
		exit(1);
	}


	Contract contract;
	contracts.Reset();
	for (; contracts.AreThereMore(); )
	{  contract.CopyContract(contracts.GetNext());
		WriteInfo(outFile, contract);
	}

}

void WriteInfo(ofstream& outFile, Contract contract)
{	outFile << contract.ProvideID();
	outFile << "," << contract.ProvideContracteeName();

	outFile << ",";
	outFile << contract.ProvideOfficeStreetAddress() << ","
		  << contract.ProvideOfficeCity() << ","
		  << contract.ProvideOfficeState() << ","
		  << contract.ProvideOfficeZip();

	int sqFootage;
	sqFootage = contract.ProvideSquareFootage();
	outFile << "," << sqFootage;

	int numDesks;
	numDesks = contract.ProvideNumberOfDesks();
	outFile << "," << numDesks;

	int numDays;
	numDays = contract.ProvideNumberOfDays();
	outFile << "," << numDays;

	double charge;
	charge = contract.ProvidePerWeekCharge();
	outFile << "," << charge << endl;
}