Exemplo n.º 1
0
//Add a new country to the list of adjacent countries
void Country::addConnection(Country &conn)
{
	connections.push_back(conn.getName());
	if (!conn.isAdjacent(name)) {
		conn.addConnection(*this);
	}
}
Exemplo n.º 2
0
/**
 * @brief Reinforcement phase decision making. Places all reinforcements on the
 * country with the fewest armies.
 */
std::string Strategy::reinforcePhase() {
	RiskMap* map = this->driver->getRiskMap();
	std::string playerName = this->driver->getCurrentPlayerName();

	int minArmies = 10000;
	Country* minArmiesCountry = nullptr;

	// add the reinforcements to the player
	int numCardsSelected = map->getPlayer(playerName)->getCards();
	int armiesEarned = convertCardsToReinforcements(numCardsSelected);
	if (armiesEarned > 0) {
		this->driver->addCardsTradeReinforcements(armiesEarned);
		this->driver->updatePlayerCards(-numCardsSelected);
	}

	// Reinforce the weakest country
	for (const std::string countryName : map->getCountriesOwnedByPlayer(playerName)) {
		Country* country = map->getCountry(countryName);
		int armies = country->getArmies();
		if (armies < minArmies) {
			minArmies = armies;
			minArmiesCountry = country;
		}
	}
	if (minArmiesCountry == nullptr) {
		return "";
	}
	return minArmiesCountry->getName();
}
Exemplo n.º 3
0
void HwFederateAmbassador::reflectAttributeValues (
        RTI::ObjectHandle                 theObject,     // supplied C1
  const RTI::AttributeHandleValuePairSet& theAttributes, // supplied C4
  const RTI::FedTime&                     theTime,       // supplied C1
  const char                             *theTag,        // supplied C4
        RTI::EventRetractionHandle        theHandle)     // supplied C1
throw (
  RTI::ObjectNotKnown,
  RTI::AttributeNotKnown,
  RTI::FederateOwnsAttributes,
  RTI::InvalidFederationTime,
  RTI::FederateInternalError)
{
   //-----------------------------------------------------------------
   // Find the Country instance this update is for.  If we can't find
   // it then I am getting data I didn't ask for.
   //-----------------------------------------------------------------
   Country *pCountry = Country::Find( theObject );

   if ( pCountry )
   {
      //-----------------------------------------------------------------
      // Set the new attribute values in this country instance.
      //-----------------------------------------------------------------
      pCountry->Update( theAttributes );
      pCountry->SetLastTime( theTime );
   }
   else
           throw RTI::ObjectNotKnown("received reflection for unknown OID");
}
Exemplo n.º 4
0
void HwFederateAmbassador::reflectAttributeValues (
        RTI::ObjectHandle                 theObject,     // supplied C1
  const RTI::AttributeHandleValuePairSet& theAttributes, // supplied C4
  const char                             *theTag)        // supplied C4
throw (
  RTI::ObjectNotKnown,
  RTI::AttributeNotKnown,
  RTI::FederateOwnsAttributes,
  RTI::FederateInternalError)
{
   //-----------------------------------------------------------------
   // Find the Country instance this update is for.  If we can't find
   // it then I am getting data I didn't ask for.
   //-----------------------------------------------------------------
   Country *pCountry = Country::Find( theObject );

   if ( pCountry )
   {
      //-----------------------------------------------------------------
      // Set the new attribute values in this country instance.
      //-----------------------------------------------------------------
      pCountry->Update( theAttributes );
      RTI::FedTime * zero_time = RTI::FedTimeFactory::makeZero();
      pCountry->SetLastTime(*zero_time );
      delete zero_time;
   }
}
Exemplo n.º 5
0
/**
 * @brief Determines if the countries on the map are a connected graph.
 * @param limitTo Limits the search to the given continent (by string name)
 */
bool RiskMap::isConnectedGraph(const std::string& limitTo) {
	std::map<const Country*, bool> visited = std::map<const Country*, bool>();
	for (auto const &ent1 : this->countries) {
		const Country& country = ent1.second;

		if (limitTo.size() > 0 && this->getContinentOfCountry(country.getName())->getName().compare(limitTo) != 0) {
			continue;
		}

		visited.insert(std::pair<const Country*, bool>(&country, false));
	}

	Country* country = nullptr;
	if (limitTo.size() > 0) {
		country = this->getCountry(*this->getCountriesInContinent(limitTo).begin());
	}
	else {
		country = &this->countries.begin()->second;
	}
	this->isConnectedGraphHelper(visited, country, limitTo);

	for (auto const &ent1 : visited) {
		if (!ent1.second) {
			Country country = *ent1.first;
			debug("Country " + country.getName() + " is not connected.");
			return false;
		}
	}

	return true;
}
Exemplo n.º 6
0
int main() {
    string name;
    string capitalcity;
    int population;
    int area;
    Country qveyana;
    vector <Country> v;
    while(ans1 == 'y') {
    cout << "Enter new information" << endl;
    cin >> name;
    cin >> capitalcity;
    cin >> population;
    cin >> area;
    qveyana.setInfo(name,capitalcity,population,area);
    v.push_back(qveyana);
    cout << "Continue? (y/n)" << endl;
    cin >> ans1;
}
        cout << "Enter country name to get information:" << endl;
        cin >> countryname;
        for(int i=0;i<v.size();i++){
                if (v[i].getName()==countryname)
                    cout<<v[i].splittedArea()<<endl;
            }
    return 0;
}
Exemplo n.º 7
0
bool World::addCountry(const char* _name, const char* _continent)
{
	lastOperationSuccess = true;
	//We cannot allow 2 times the same name.
	if (getCountryFromName(_name) != NULL)
	{
		lastOperationSuccess = false;
		lastErrorMessage = "The country already exists.";
		return false;
	}

	Continent* continent = getContinentFromName(_continent);

	if (continent == NULL)
	{
		lastOperationSuccess = false;
		lastErrorMessage = "The continent does not exists.";
		return false;
	}

	//Create the object.
	Country* countryObject = new Country(_name, (int)countriesVector->size());
	countryObject->setContinent(continent);

	//Once we have the infos of one, we add it to our vector.
	countriesVector->push_back(countryObject);
	return true;
}
Exemplo n.º 8
0
void MainScreen::allocateArmiesByNumberOfPlayers(const std::string playerName){
	RiskMap* map = this->driver->getRiskMap();
	const int armiesByNumPlayers[] = {40, 35, 30, 25, 20};
	int totalArmies = armiesByNumPlayers[map->getPlayers().size()-2];

	// Create a vector of country pointers for countries the player owns
	std::vector<Country*> playerCountries;
	for (auto const &countryName : map->getCountriesOwnedByPlayer(playerName)) {
		playerCountries.push_back(map->getCountry(countryName));
	}

	// Randomize order of country pointer list
	auto engine = std::default_random_engine{};
	std::shuffle(std::begin(playerCountries), std::end(playerCountries), engine);

	auto playerCountriesIter = playerCountries.begin();
	while (totalArmies > 0) {
		Country* country = *playerCountriesIter;
		country->addArmies(1);
		totalArmies--;
		std::advance(playerCountriesIter, 1);
		if (playerCountriesIter == playerCountries.end()) {
			playerCountriesIter = playerCountries.begin();
		}
	}

	// Signal to update the info widgets.
	for (auto &ent1: map->getPlayers()){
		map->getPlayer(ent1.first)->notifyObservers();
	}
}
Exemplo n.º 9
0
bool Countries::FindPlace(const char *country_val, const char *place_val,
						  DPoint2 &point)
{
	Country *country;

	int num = m_countries.GetSize();

	int i;
	for (i = 0; i < num; i++)
	{
		country = m_countries[i];

		if (country->m_full.CompareNoCase(country_val) != 0)
			continue;

		bool success = country->FindPlace(place_val, point, true);

		// try again with just the length of the initial sea
		if (!success)
			success = country->FindPlace(place_val, point, false);

		if (success)
			return true;
	}
	return false;
}
Exemplo n.º 10
0
/**
 * @brief Removes a country from the map.
 */
void RiskMap::removeCountry(const Country& country){
	std::string continent = (this->getContinentOfCountry(country.getName()))->getName();
	countries.erase(country.getName());
	if (mapGraph.removeNode(country.getName())){
		continents.erase(continent);
	}
	this->notifyObservers();
}
Exemplo n.º 11
0
bool World::pathFindCountry(Country* country1, Country* country2, Player* player)
{
	cout << "DEbug country 1+++++++++++++++++++++++" << country1->getName() << endl;
	cout << "DEbug country 2+++++++++++++++++++++++" << country2->getName() << endl;

	if (country1->getName() == country2->getName() || isCountryAdjacent(country1, country2))
	{
		return true;
	}
	queue<Country*> countryQueue;
	vector<Country*> boardersToCountry1 = country1->getBoarders();
	countryQueue.push(country1);
	while (countryQueue.empty() == false)
	{
		Country* c = countryQueue.front();
		countryQueue.pop();
		if (c->getName() == country2->getName())
		{
			//need to put marked back to false for every country
			//here but map iterator is my enemy
			for (std::map<string, Country*>::iterator it = _territories.begin(); it != _territories.end(); ++it)
			{
				it->second->marked = false;
			}
				
			return true;
		}
		for (int i = 0; i < c->getBoarders().size(); i++)
		{
			vector<Country*> allBoardersToC = c->getBoarders();
			for (int k = 0; k < allBoardersToC.size(); k++)
			{
				for (int j = 0; j < player->getListCountriesOwned().size(); j++)
				{

					if (allBoardersToC.at(k)->getName() == player->getListCountriesOwned().at(j)->getName() && allBoardersToC.at(k)->marked == false)
					{
						countryQueue.push(allBoardersToC.at(k));
					}
				}
			}
		}
	}
	/*for (int i = 0; i < boardersToCountry1.size(); i++)
	{
	for (int j = 0; j < player->getListCountriesOwned().size(); j++)
	{

	if (boardersToCountry1.at(i)->getName() == player->getListCountriesOwned().at(j)->getName())
	{
	return pathFindCountry(boardersToCountry1.at(i), country2, player);
	}
	}
	}*/
}
Exemplo n.º 12
0
QStringList Country::getCountryNames() {
    if (sCountryNames.isEmpty()) {
        Country cc;
        QMetaProperty mp(cc.metaProperty("val"));
        QMetaEnum qmen = mp.enumerator();
        for (int i=0; i<qmen.keyCount(); ++i) {
            sCountryNames += qmen.valueToKey(i);
        }
    }
    return sCountryNames;
}
Exemplo n.º 13
0
void Evaluation::computeConnectedComponents()
{
    // Do not use 42 here as it might change from outside this file
    // Rather obtain the number of countries from Global Settings
    int nb_countries = gs->get_global_settings()->get_countries().size();
    //bool markedCountries[42]; Must be allocated dinamically
    bool* markedCountries = (bool*) malloc (nb_countries * sizeof(bool));

    for(int i=0; i<nb_countries; i++)
    {
        markedCountries[i]=0;
    }

    stack<Country*> pile;
    list<Country*> countries = gs->countries_owned_by(gs->get_current_player());
    for (list<Country*>::iterator it = countries.begin(); it!=countries.end(); ++it)
    {
        markedCountries[(*it)->get_id()]=1;
        pile.push(*it);
    }



    while(!pile.empty()){
        Country* elem = pile.top();
        pile.pop(); // void
        if (markedCountries[elem->get_id()]==0){continue;}
        else{
            stack<Country*> parcours;
            Connected_component* connected_comp = new Connected_component(world_map, gs, probabilities);
            parcours.push(elem);
            while(!parcours.empty()){
                Country* father = parcours.top();
                parcours.pop(); // void
                if(markedCountries[father->get_id()]==0){continue;}
                else{
                    markedCountries[father->get_id()]=0;
                    connected_comp->add(father);

                    set<Country*> sons = (world_map->find(father))->second;

                    for(set<Country*>::iterator son = sons.begin(); son!=sons.end(); ++son)
                    {
                        if(gs->owner(*son) == gs->get_current_player()){
                            parcours.push(*son);
                        }
                    }
                }
            }
            connected_components.push_back(connected_comp);
        }
    }
}
Exemplo n.º 14
0
	void undoAction(AbstractAction::EnvType env)
	{
		int index = env->getCountryIndex();

		Country* country = (*env->getCountries())[index];



		country->setColor(Country::GREY);

		env->setCountryIndex(env->getCountryIndex() - 1);
	}
Exemplo n.º 15
0
void MapManager::populateCountryVector() {

	vector<string> adjacents;
	Country newCountry;
	for (int i = 0; i < getMapTerritories().size(); i++) {
		newCountry = Country(getMapTerritories().at(i)[0], getMapTerritories().at(i)[3]);
		adjacents = getAdjacents(i);
		newCountry.setConnections(adjacents);
		countries.push_back(newCountry);
	}


}
Exemplo n.º 16
0
	/**
	 * Add data from database into list view.
	 */
	void CountriesListScreen::addDataToListView()
	{
		// Clear data from map.
		mCountryMap.clear();

		// Create first section.
		NativeUI::ListViewSection* section = NULL;
		MAUtil::String sectionTitle("A");

		// For each country read create and add an ListViewItem widget.
		int countCountries = mDatabase.countCountries();
		for (int index = 0; index < countCountries; index++)
		{
			// If index is invalid skip this country.
			Country* country = mDatabase.getCountryByIndex(index);
			if (!country)
			{
				continue;
			}

			// If country's name is an empty string skip this country.
			MAUtil::String countryName = country->getName();
			if (countryName.length() == 0)
			{
				continue;
			}

			// Check if current country can go into current section.
			if (!section || countryName[0] != sectionTitle[0])
			{
				// Create new section.
				sectionTitle[0] = countryName[0];
				section = new NativeUI::ListViewSection(
					NativeUI::LIST_VIEW_SECTION_TYPE_ALPHABETICAL);
				section->setTitle(sectionTitle);
				section->setHeaderText(sectionTitle);
				mListView->addChild(section);
			}

			// Create and add list item for this country.
			NativeUI::ListViewItem* item = new NativeUI::ListViewItem();
			item->setText(countryName);
			item->setFontColor(COLOR_WHITE);
			item->setSelectionStyle(NativeUI::LIST_VIEW_ITEM_SELECTION_STYLE_GRAY);
			item->setIcon(country->getFlagID());
			section->addItem(item);

			mCountryMap.insert(item->getWidgetHandle(), country->getID());
		}
	}
bool CountryList::deleteNode(Country &nodeData)
{
   ListNode *nodePtr;       // To traverse the list
   ListNode *previousNode;  // To point to the previous node

   // Initialize nodePtr to head of list
   nodePtr = head->next;
   previousNode = head;

   // Skip all nodes whose code is not equal to the code pointed by pDeleteCode.
   while (nodePtr != NULL && strcmp(nodePtr->country.getCode(), nodeData.getCode()) != 0)
   {
      previousNode = nodePtr;
      nodePtr = nodePtr->next;
   }

   // If node-to-delete not found OR no nodes
   if (!nodePtr)
      return false;
   
   nodeData = nodePtr->country;  // return the deleted data
   previousNode->next = nodePtr->next;
   delete nodePtr;
   count--;
   return true;
}
Exemplo n.º 18
0
//Methods used to overwrite an existing object in the country or continent vectors.
void Map::editCountry(Country& coun) {
	for (Country& c : countries) {
		if (c.getName() == coun.getName())
			c = coun;
	}
	Notify();
}
Exemplo n.º 19
0
UINT GWCountryAPHandler::Execute( GWCountryAP* pPacket, Player* pPlayer )
{
    __ENTER_FUNCTION

    ServerPlayer* pServerPlayer = (ServerPlayer*)pPlayer;
    GUID_t guid = pPacket->GetGuid();

    USER* pUser = g_pOnlineUser->FindUser( guid );
    if( pUser == NULL )
    {
        Log::SaveLog( WORLD_LOGFILE, "GWCountryAPHandler...User GUID=%X not find!", 
            guid );
        return PACKET_EXE_CONTINUE;
    }

    INT nCountry = pUser->GetCountry();
    Country *pCountry = g_pCountryManager->GetCountry(nCountry);

    if (pCountry)
    {
        if (pUser->GetGUID() == pCountry->GetCountryInfo()->m_GuoWang)
        {
            BYTE cType  = pPacket->GetType();
            INT nAP     = pPacket->GetAP();

            switch (cType)
            {
            case 0:
                pCountry->AddActionPoint(nAP);
                break;
            case 1:
                pCountry->SubActionPoint(nAP);
                break;
            }

            Log::SaveLog( WORLD_LOGFILE, "GWCountryAPHandler...User GUID=%X ChangeAP = %d", 
                guid, nAP);
        }
    }

    return PACKET_EXE_CONTINUE ;

    __LEAVE_FUNCTION

        return PACKET_EXE_ERROR ;
}
Exemplo n.º 20
0
//-----------------------------------------------------------------
//
// METHOD:
//     Country* Country::Find( RTI::ObjectHandle objectId )
//
// PURPOSE:
//     Looks through the extent to find the Country instance
//     with the passed in object Id.
//
// RETURN VALUES:
//     Pointer to country object that has the specified
//     ObjectHandle. 
//
// HISTORY:
//     1) Created 11/6/96
//     2) Updated to RTI 1.3 3/26/98
//
//-----------------------------------------------------------------
Country* Country::Find( RTI::ObjectHandle objectId )
{
   Country *pCountry = NULL;

   for ( unsigned int i = 0; i < Country::ms_extentCardinality; i++ )
   {
      pCountry = Country::ms_countryExtent[ i ];

      if ( pCountry && pCountry->GetInstanceId() == objectId ) {
	break;
      } else {
	pCountry = NULL;
      }
   }

   return pCountry;
}
Exemplo n.º 21
0
bool Countries::WriteSHPPerCountry(const char *prefix)
{
	int unsigned num = m_countries.GetSize();
	for (int unsigned i = 0; i < num; i++)
	{
		Country *country = m_countries[i];

		if (country->m_places.GetSize() > 0)
		{
			vtString out_path = prefix;
			out_path += country->m_abb;
			out_path += ".shp";
			if (!country->WriteSHP(out_path))
				return false;
		}
	}
	return true;
}
Exemplo n.º 22
0
	bool doAction(AbstractAction::EnvType env)
	{
		int index = env->getCountryIndex();

		Country* country = (*env->getCountries())[index];

		int size = (*country->getAdjacents()).size();

		for (int i = 0; i < size; i++)
		{
			if ((*country->getAdjacents())[i]->getColor() == color)
				return false;
		}

		country->setColor(color);

		env->setCountryIndex(env->getCountryIndex() + 1);
	}
Exemplo n.º 23
0
void GameSaveInstance::addArmiesAndPlayersToMap(World * map)
{
	// Go through the map, assign players to countries they control and set the number of armies
	for (unsigned i = 0; i < countryInfos.size(); i++)
	{
		Country* country = map->getCountryFromName(countryInfos[i]->countryName.c_str());

		if (country == NULL)
		{
			setError(true, "Could not find saved country on map");
			return;
		}

		country->setControllingPlayer(getPlayerByName(countryInfos[i]->owningPlayer));

		country->addArmies(countryInfos[i]->numArmies);
	}
}
Exemplo n.º 24
0
void HwFederateAmbassador::provideAttributeValueUpdate (
        RTI::ObjectHandle        theObject,     // supplied C1
  const RTI::AttributeHandleSet& theAttributes) // supplied C4
throw (
  RTI::ObjectNotKnown,
  RTI::AttributeNotKnown,
  RTI::AttributeNotOwned,
  RTI::FederateInternalError)
{
   //-----------------------------------------------------------------
   // Find the Country instance this request is for.
   //-----------------------------------------------------------------
   Country *pCountry = Country::Find( theObject );

   if ( pCountry )
   {
      //-----------------------------------------------------------------
      // Touch the appropriate attribute values in this country
      // instance so that the get updated next cycle.
      //-----------------------------------------------------------------
      RTI::AttributeHandle attrHandle;

      //-----------------------------------------------------------------
      // We need to iterate through the AttributeHandleSet
      // to extract each AttributeHandle.  Based on the type
      // specified ( the value returned by getHandle() ) we need to
      // set the status of whether we should send this type of data.
      //-----------------------------------------------------------------
      for (unsigned int i = 0; i < theAttributes.size(); i++ )
      {
         attrHandle = theAttributes.getHandle( i );
         if ( attrHandle == Country::GetPopulationRtiId() )
         {
            // Touch population so that it gets update next cycle
            pCountry->SetPopulation( pCountry->GetPopulation() );
         }
         else if ( attrHandle == Country::GetNameRtiId() )
         {
            // Touch name so that it gets update next cycle
            pCountry->SetName( pCountry->GetName() );
         }
      }
   }
}
Exemplo n.º 25
0
unsigned int Countries::add_country_internal(Country &_c){
	auto iter = m_countries_name.find(_c);
	if (m_countries_name.find(_c) != m_countries_name.end())
		return (*iter).id();
	m_countries_id.insert(_c);
	m_countries_name.insert(_c);
	m_countries_sm_name.insert(_c);
	++m_last_id;
	return _c.id();
}
Exemplo n.º 26
0
unsigned int Countries::add_country(const std::string &_name,
							const std::string &_sm_name){
	Country c;
	std::string name = _name;
	std::string sm_name = _sm_name;

	boost::to_lower(name);
	boost::trim(name);

	boost::to_lower(sm_name);
	boost::trim(sm_name);

	c.set_name(name);
	c.set_small_name(sm_name);
	c.set_id(m_last_id);
	return add_country_internal(c);


}
Exemplo n.º 27
0
bool World::addLink(const char* _country, vector<const char*>* linkedCountries)
{
	lastOperationSuccess = true;
	Country* country = this->getCountryFromName(_country);
	if (country == NULL)
	{
		lastOperationSuccess = false;
		lastErrorMessage = "The country does not exists.";
		return false;
	}

	Country* tmp = NULL;
	vector<Country*>* linksVector = new vector<Country*>();
	for (int i = 0; i < linkedCountries->size(); i++)
	{
		tmp = getCountryFromName(linkedCountries->at(i));

		if (tmp == country)
		{
			lastOperationSuccess = false;
			lastErrorMessage = "Cannot link country to itself.";
			return false;
		}

		if (tmp) linksVector->push_back(tmp);
		else
		{
			lastOperationSuccess = false;
			lastErrorMessage = "One of the linked countries does not exists.";
			return false;
		}
	}

	country->connect(linksVector);

	//Important: two-ways connection. Bidirectionnal.
	for (int i = 0; i < linksVector->size(); i++)
		linksVector->at(i)->connect(country);

	numberOfLinks++;
	return true;
}
Exemplo n.º 28
0
/**
 * @brief Gets a list of continent names owned by a player
 */
string_set RiskMap::getContinentsOwnedByPlayer(const std::string& playerName) {
	string_set continentsOwned;
	for (auto &ent1: this->continents) {
		std::string continentName = ent1.first;
		string_set countriesInContent = this->getCountriesInContinent(continentName);

		bool totalOwnership = true;
		for (auto &countryName: countriesInContent) {
			Country* country = this->getCountry(countryName);
			if (country->getPlayer() != playerName) {
				totalOwnership = false;
				break;
			}
		}

		if (totalOwnership) {
			continentsOwned.insert(continentName);
		}
	}
	return continentsOwned;
}
Exemplo n.º 29
0
/**
 * @brief A signal sent to the Strategy class from the game driver to indicate
 * that a computer-controlled player should made their move.
 *
 * The AI strategy implementations override each of the fooPhase() methods
 * which return the name(s) of the country or countries to act upon.
 *
 * Empty string indicates the AI wishes to make no move, or there are none
 * possible.
 */
void Strategy::takeAction(Mode mode) {
	RiskMap* map = this->driver->getRiskMap();

	if (mode == REINFORCEMENT) {
		std::string countryName = this->reinforcePhase();
		if (countryName == "") {
			return;
		}
		Country* country = map->getCountry(countryName);
		Player* player = map->getPlayer(country->getPlayer());
		this->driver->reinforceCountry(player, country, player->getReinforcements());
	}
	else if (mode == ATTACK) {
		std::pair<std::string, std::string> countryNames = this->attackPhase();
		if (countryNames.first == "" || countryNames.second == "") {
			return;
		}
		driver->attackCountry(map->getCountry(countryNames.first), map->getCountry(countryNames.second));
	}
	else if (mode == FORTIFICATION) {
		std::pair<std::string, std::string> countryNames = this->fortifyPhase();
		if (countryNames.first == "" || countryNames.second == "") {
			return;
		}
		// Given the two countries, fortify so that the armies are as equal as possible.
		Country* origin = map->getCountry(countryNames.first);
		Country* destination = map->getCountry(countryNames.second);
		int splitDifference = std::abs(origin->getArmies() - destination->getArmies()) / 2;
		this->driver->fortifyCountry(origin, destination, splitDifference);
	}
}
Exemplo n.º 30
0
void drawCountry(Renderer* canvas, const Country &country, bool drawDescription) {
    /** Title area **/
    Font fontCountryName("resources/fonts/FreeSansBold.ttf", 30);
    fontCountryName.setColor(Color(0xf0, 0xff, 0xff));

    Text name(country.getName(), &fontCountryName);
    canvas->drawText(&name, Point(358, 105));
    
    /* Photo area */
    string photoPath = "data/countries/" + country.getIsoCode() + "/postal.png";
    FileUtils fileUtils;
    if (!fileUtils.fileExists(photoPath.c_str())) {
        photoPath = "data/countries/default-photo.jpg";
    }
    Surface photoSurface(photoPath);
    photoSurface.transform(4, 1, 1);
    Texture photoTexture(canvas->internal, photoSurface.toSDL());
    canvas->drawTexture(&photoTexture, Point(47, 115));

    Texture polaroidSurf(canvas->internal, "resources/images/game/polaroid.png");
    canvas->drawTexture(&polaroidSurf, Point(30, 108));

    string flagPath = "data/countries/" + country.getIsoCode() + "/flag.png";
    Surface flagSurface(flagPath);
    flagSurface.transform(0, .5, 1);
    Texture flagTexture(canvas->internal, flagSurface.toSDL());
    canvas->drawTexture(&flagTexture, Point(300, 110));

    if (drawDescription) {
        Font descFont("resources/fonts/FreeSansBold.ttf", 14);
        descFont.setColor(Color(0xd3, 0xba, 0xa4));

        Text description(country.getDescription(), &descFont);
        TextUtils textUtils;
        textUtils.drawLines(canvas, description, Point(358, 150), Dimension(360, 340));
    }
}