// SportHangman1.cpp : Defines the entry point for the console application.
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <vector>
// Good practice: idenfify usage within library
#include <algorithm>   // for random_shuffle

using namespace std;

// Poor practice: global constants
const int NUM = 15;
const int MAX = 5;
const int BASEBALL = 1;
const int FOOTBALL = 2;
const int BASKETBALL = 3;

// Poor practice: global variables
// Use a STL vector to store the word list and add to it
vector<string> newwordlist;
//vector<string> ::iterator targetword;

// Poor Practice: variable list without compile calculated NUM constant
const string wordlist[NUM] = {"padres", "giants", "rockies",
    "dodgers", "diamondbacks", "lakers", "pistons", "spurs",
    "pacers", "kings", "browns", "cowboys", "titans", "niners",
    "panthers"};

// Classes are undeveloped, not encapsulated, and not fully implemented
// Poor practice: non-encapsulated class data
// Poor practice: global constant for setting class name limits
// non-usage order in declaration, should be friends, public, protected, private
// use multiple classes
//base class
class Athlete{
private:
	char firstname[MAX];
	char lastname[MAX];
public:
	char position[MAX];
	char team[MAX];
};

// poor practice: non-typed return on class methods
// no implementation of methods
// no encapsulation of data for inherited methods
// no polymorphism across classes for common api -- set() method
// no helper stream classes for debugging
// logic of methods found in main routine with local variables
// inheritance
class BaseballPlayer:public Athlete{
public:
	void timeofyear();
};

class FootballPlayer:public Athlete{
public:
	void numberofgames();
};

class BasketballPlayer:public Athlete{
public:
	void numberofplayers();
};

int main() {
    srand(time(0));
    char play;
	string newword;
	string target;
	int i = 0;
	int sport;
	char timeofyear;
	int numberofgames;
	int numberofplayers;
	
	// Populate the vector with the team list
	while (i < NUM) {
		newwordlist.push_back(wordlist[i]);
		i = i + 1;
	}
	// See if this worked
	cout << "new word list holds " << newwordlist.size() << " words.\n\n";

	// Add some words to the list, dynamically size the vector
	do { 
		cout << "Add another team to the list <y/n>? ";
		cin >> play;
		if (play == 'y'){
			cout << "  Enter new team name for the list: ";
			cin >> newword;
			newwordlist.push_back(newword);
			i = i + 1;
		}
	}
	while (play != 'n');
	// See if this worked
	cout << "new team list holds " << newwordlist.size() << " teams.\n\n";

	// Only accept y or n for an answer, exception handling
	do { 
		cout << "Will you play a word game? <y/n> ";
		cin >> play;
		// conversion of int to char; possible loss of data
		play = tolower(play);
	}
	while (play != 'y' && play != 'n');


	
    while (play == 'y') {
		// Shuffle the order each time and just get the first word
		random_shuffle(newwordlist.begin(), newwordlist.end() );
		target = newwordlist[0];
		// print this out just to see how it is working
		cout << "  ==>  vector word is: " << newwordlist[0] << "\n";

        int length = target.length();
        string attempt(length, '-');
        string badchars;
        int guesses = 6;

        cout << "Enter my secret team name. It has " << length
            << " letters, and you guess\n"
            << "one letter at a time. You get " << guesses
            << " wrong guesses.\n";
        cout << "Your word: " << attempt << endl;

        while (guesses > 0 && attempt != target) {
            char letter;

            cout << "Guess a letter: ";
            cin >> letter;
            if (badchars.find(letter) != string::npos
                || attempt.find(letter) != string::npos) {
                cout << "You already guessed that. Try again.\n";
                    continue;
            }

            int loc = target.find(letter);
			// signed / unsigned mismatch warning
            if (loc == string::npos) {
                cout << "Oh, bad guess!\n";
                --guesses;
                badchars += letter; // add to string
            }
            else {
                cout << "Good guess!\n";
                attempt[loc]=letter;
                // check if letter appears again
                loc = target.find(letter, loc + 1);
                
				// signed / unsigned mismatch
				while (loc != string::npos) {
                    attempt[loc]=letter;
                    loc = target.find(letter, loc + 1);
                }
           }
            cout << "Your word: " << attempt << endl;
            if (attempt != target) {
                if (badchars.length() > 0)
                    cout << "Bad choices: " << badchars << endl;
                cout << guesses << " bad guesses left\n";
            }
        }
		
		// I have not finished this area, see the other project for inheritance
		if (guesses > 0){
            cout << "That's right!\n";
			cout << "What Sport is this team from? <1-baseball, 2-football, 3-basketball> : ";
			cin >> sport;

			if (sport == BASEBALL) {
				cout << "Enter the time of year baseball is played: ";
				cin >> timeofyear;
			}
			else if (sport == FOOTBALL) {
				cout << "Enter the number of football games played: ";
				cin >> numberofgames;
			}
			else {  // (sport == BASKETBALL){
				cout << "Enter the number of players on the team: ";
				cin >> numberofplayers;
			}
			
		
		}
        else
            cout << "Sorry, the word is " << target << ".\n";

		// Only accept y or n for an answer, exception handling
		do { 
			cout << "\nWill you play another? <y/n> ";
			cin >> play;
			// conversion of int to char; possible loss of data
			play = tolower(play);
		}
		while (play != 'y' && play != 'n');
    }
		
		
	cout << "Bye\n";

    return 0; 
}

void BasketballPlayer::numberofplayers()
{
	
}


// SportHangman2.cpp : Defines the entry point for the console application.
#include <iostream>
#include <string>
//#include <cstdlib>		// srand()
#include <ctime>		// time()
#include <vector>
#include <algorithm>   // random_shuffle

using namespace std;

class Athlete {
	friend ostream & operator<<( ostream & os, const Athlete & athlete );
public:
    static const string KNOWN_TEAMS[];
    static const int KNOWN_TEAMS_MAX;
	static void update_teams();
	static void show_teams();
	static const vector<string> & get_teams() { return teams; };
	
	Athlete() {};
	virtual void set() = 0;
	virtual void show( ostream & os ) const = 0;
private:
	static vector<string> teams;

	string firstname;
	string lastname;
	string position;
	string team;
};

const string Athlete::KNOWN_TEAMS[] = {"padres", "giants", "rockies",
    "dodgers", "diamondbacks", "lakers", "pistons", "spurs",
    "pacers", "kings", "browns", "cowboys", "titans", "niners",
    "panthers"};
// Variable length records means this MAX must be manually done
const int Athlete::KNOWN_TEAMS_MAX = 15;
vector<string> Athlete::teams;

void Athlete::update_teams() {
	// Populate the vector with the team list
	int index = 0;
	if ( teams.size() == 0 ) {
	  while (index < KNOWN_TEAMS_MAX) {
		teams.push_back(KNOWN_TEAMS[index]);
		++index;
	  }
	}
	cout << "Team list now holds " << teams.size() << " words.\n\n";

	// Add some words to the list, dynamically size the vector
	char play;
	string team;
	do { 
		cout << "Add another team to the list ? ";
		cin >> play;
		if (play == 'y'){
			cout << "  Enter new team name for the list: ";
			cin >> team;
			teams.push_back(team);
		}
	} while (play != 'n');
	// See if this worked
	cout << "new team list holds " << teams.size() << " teams.\n\n";
}
void Athlete::show_teams() {
	const int MAX = teams.size();
	const int NL = 5;
	string divider;
	cout << "Teams are:\n";
	for ( int index = 0; index < MAX; ++index) {
		divider = (index % NL) ? " " : "\n"; 
		cout << teams[index] << divider;
	}
}
void Athlete::set() {
	cout << "Enter First name\n";
	cin >> firstname;
	cout << "Enter Last name\n";
	cin >> lastname;
	cout << "Enter team name\n";
	cin >> team;
	cout << "Enter team position\n";
	cin >> position;
}
void Athlete::show (ostream & os) const {
	os << "Name: " << firstname << " " << lastname << "\n"
	   << "Team: " << team << " position: " << position << "\n";
}
ostream & operator<<( ostream & os, const Athlete & athlete ) {
	athlete.show(os);
	return os;
}
// inheritance
class BaseballPlayer : public Athlete {
	friend ostream & operator<<( ostream & os, const BaseballPlayer & player );
public:
	virtual void set();
	virtual void show( ostream & os ) const;
private:
	char timeofyear;
};


void BaseballPlayer::set() {
	Athlete::set();
	cout << "Enter the time of year\n";
	cin >> timeofyear;
}
void BaseballPlayer::show( ostream & os ) const {
	Athlete::show(os);
	os << "Time of Year: " << timeofyear << "\n";
}
ostream & operator<<( ostream & os, const BaseballPlayer & player ) {
	player.show(os);
	return os;
}

class FootballPlayer : public Athlete {
	friend ostream & operator<<( ostream & os, const FootballPlayer & player );
public:
	virtual void set();
	virtual void show( ostream & os ) const;
private:
	int numberofgames;
};

void FootballPlayer::set() {
	Athlete::set();
	cout << "Enter the number of games\n";
	cin >> numberofgames;
}
void FootballPlayer::show( ostream & os ) const {
	Athlete::show(os);
	os << "Number of Games: " << numberofgames << "\n";
}
ostream & operator<<( ostream & os, const FootballPlayer & player ) {
	player.show(os);
	return os;
}

class BasketballPlayer : public Athlete {
	friend ostream & operator<<( ostream & os, const BasketballPlayer & player );
public:
	virtual void set();
	virtual void show( ostream & os ) const;
private:
	int numberofplayers;
};


void BasketballPlayer::set() {
	Athlete::set();
	cout << "Enter the number of players\n";
	cin >> numberofplayers;
}
void BasketballPlayer::show( ostream & os ) const {
	Athlete::show(os);
	os << "Number of Players: " << numberofplayers << "\n";
}
ostream & operator<<( ostream & os, const BasketballPlayer & player ) {
	player.show(os);
	return os;
}
int main() {

	// get the time at the present moment and set the random seed to the current time
	// ... guarantees each run will be a unique random sequence
    srand(time(0));

	enum { BASEBALL = 1, FOOTBALL, BASKETBALL };

	Athlete::update_teams();
	Athlete::show_teams();


	const vector<string> & teams = Athlete::get_teams();
	vector<string> newwordlist(teams);

	const int MAX_GUESSES = 6;
    char play;
	string newword;
	string target;
	int sport;
	Athlete * player;
	vector<Athlete *> players;
	

	// Only accept y or n for an answer, exception handling
	do { 
		cout << "Will you play a word game? <y/n> ";
		cin >> play;
		play = static_cast<char>(tolower(play));
	} while (play != 'y' && play != 'n');
	
    while (play == 'y') {
		// Shuffle the order each time and just get the first word
		random_shuffle(newwordlist.begin(), newwordlist.end() );
		target = newwordlist[0];
		// print this out just to see how it is working
		cout << "  ==>  vector word is: " << newwordlist[0] << "\n";

        int length = target.length();
        string attempt(length, '-');
        string badchars;
        int guesses = MAX_GUESSES;

        cout << "Enter my secret team name. It has " << length
            << " letters, and you guess\n"
            << "one letter at a time. You get " << guesses
            << " wrong guesses.\n";
        cout << "Your word: " << attempt << endl;

        while (guesses > 0 && attempt != target) {
            char letter;

            cout << "Guess a letter: ";
            cin >> letter;
            if (badchars.find(letter) != string::npos
                || attempt.find(letter) != string::npos) {
                cout << "You already guessed that. Try again.\n";
                    continue;
            }

            unsigned int loc = target.find(letter);
            if (loc == string::npos) {
                cout << "Oh, bad guess!\n";
                --guesses;
                badchars += letter; // add to string
            }
            else {
                cout << "Good guess!\n";
                attempt[loc]=letter;
                // check if letter appears again
                loc = target.find(letter, loc + 1);
                
				while (loc != string::npos) {
                    attempt[loc]=letter;
                    loc = target.find(letter, loc + 1);
                }
           }
            cout << "Your word: " << attempt << endl;
            if (attempt != target) {
                if (badchars.length() > 0)
                    cout << "Bad choices: " << badchars << endl;
                cout << guesses << " bad guesses left\n";
            }
        }
		
		if (guesses > 0){
            cout << "That's right!\n";
			cout << "What Sport is this team from? <1-baseball, 2-football, 3-basketball> : ";
			cin >> sport;
			switch (sport) {
				case BASEBALL : player = new BaseballPlayer();
					            player->set();
								break;
				case FOOTBALL : player = new FootballPlayer();
					            player->set();
								break;
				case BASKETBALL : player = new BasketballPlayer();
					            player->set();
								break;
				default : cout << "Invalid choice, player not added\n";
						  player = NULL;
					break;
			}
			if ( player != NULL ) {
				players.push_back(player);
				player = NULL;
			}
		}
        else
            cout << "Sorry, the word is " << target << ".\n";

		// Only accept y or n for an answer, exception handling
		do { 
			cout << "\nWill you play another? <y/n> ";
			cin >> play;
			play = static_cast<char>(tolower(play));
		}
		while (play != 'y' && play != 'n');
    }
	
	// show players, deallocate memory
	const vector<Athlete*>::iterator END = players.end();
	for (vector<Athlete*>::iterator it = players.begin(); it != END; ++it) {
		cout << **it;
		// OR (*it)->show(cout);
		delete *it;
	}
	cout << "Bye\n";

    return 0; 
}