void APIServiceManager::_CloseXMLHeader(uint32 cacheStyle) { switch( cacheStyle ) { case EVEAPI::CacheStyles::Long: // 2 hour cache timer _BuildSingleXMLTag( "cachedUntil", Win32TimeToString(Win32TimeNow() + 120*Win32Time_Minute).c_str() ); break; case EVEAPI::CacheStyles::Short: // 5 minute cache timer _BuildSingleXMLTag( "cachedUntil", Win32TimeToString(Win32TimeNow() + 5*Win32Time_Minute).c_str() ); break; case EVEAPI::CacheStyles::Modified: // 15 minute cache timer _BuildSingleXMLTag( "cachedUntil", Win32TimeToString(Win32TimeNow() + 15*Win32Time_Minute).c_str() ); break; } }
const char *PyLookupResolver::LookupInt(uint64 value) const { //hackish check for win32 time looking things... if(value > 127900000000000000LL && value < 130000000000000000LL) { //this is not thread safe or reentrant.. m_dateBuffer = Win32TimeToString(value); return(m_dateBuffer.c_str()); } if(value > 0xFFFFFFFFLL || value < MIN_RESOLVABLE_INT) return NULL; std::map<uint32, std::string>::const_iterator res; res = m_intRecords.find(uint32(value)); if(res == m_intRecords.end()) return NULL; return(res->second.c_str()); }
void TimeToString( const Seperator& cmd ) { const char* cmdName = cmd.arg( 0 ).c_str(); if( 1 == cmd.argCount() ) { sLog.Error( cmdName, "Usage: %s win32-time [win32-time] ...", cmdName ); return; } for( size_t i = 1; i < cmd.argCount(); ++i ) { const std::string& timeStr = cmd.arg( i ); uint64 t; sscanf( timeStr.c_str(), I64u, &t ); const std::string time = Win32TimeToString( t ); sLog.Log( cmdName, "%s is %s.", timeStr.c_str(), time.c_str() ); } }
void APIServiceManager::_BuildXMLHeader() { // Build header at beginning of XML document, so clear existing xml document _XmlDoc.Clear(); // object pointed to by '_pXmlDocOuterTag' is automatically deleted by the TinyXML system with the above call if( _pXmlElementStack != NULL ) { delete _pXmlElementStack; _pXmlElementStack = NULL; } _pXmlElementStack = new std::stack<TiXmlElement *>(); TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "UTF-8", "" ); _XmlDoc.LinkEndChild( decl ); _pXmlDocOuterTag = new TiXmlElement( "eveapi" ); _XmlDoc.LinkEndChild( _pXmlDocOuterTag ); _pXmlDocOuterTag->SetAttribute( "version", "2" ); TiXmlElement * currentTime = new TiXmlElement( "currentTime" ); currentTime->LinkEndChild( new TiXmlText( Win32TimeToString(Win32TimeNow()).c_str() )); _pXmlDocOuterTag->LinkEndChild( currentTime ); }
void Character::UpdateSkillQueue() { Client *c = m_factory.entity_list.FindCharacter( itemID() ); SkillRef currentTraining = GetSkillInTraining(); if( currentTraining ) { if( m_skillQueue.empty() || currentTraining->typeID() != m_skillQueue.front().typeID ) { // either queue is empty or skill with different typeID is in training ... // stop training: _log( ITEM__ERROR, "%s (%u): Stopping training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); /* uint64 timeEndTrain = currentTraining->expiryTime(); if(timeEndTrain != 0) { double nextLevelSP = currentTraining->GetSPForLevel( currentTraining->skillLevel() + 1 ); double SPPerMinute = GetSPPerMin( currentTraining ); double minRemaining = (double)(timeEndTrain - Win32TimeNow()) / (double)Win32Time_Minute; currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); } currentTraining->Clear_expiryTime(); */ EvilNumber timeEndTrain = currentTraining->GetAttribute(AttrExpiryTime); if (timeEndTrain != 0) { EvilNumber nextLevelSP = currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) + 1 ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); EvilNumber minRemaining = (timeEndTrain - EvilNumber(Win32TimeNow())) / (double)Win32Time_Minute; //currentTraining->Set_skillPoints( nextLevelSP - (minRemaining * SPPerMinute) ); EvilNumber skillPointsTrained = nextLevelSP - (minRemaining * SPPerMinute); currentTraining->SetAttribute(AttrSkillPoints, skillPointsTrained); sLog.Debug( "", "Skill %s (%u) trained %u skill points before termination from training queue", currentTraining->itemName().c_str(), currentTraining->itemID(), skillPointsTrained.get_float() ); } currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrainingStopped osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = 0; PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // nothing currently in training currentTraining = SkillRef(); } } EvilNumber nextStartTime = EvilTimeNow(); while( !m_skillQueue.empty() ) { if( !currentTraining ) { // something should be trained, get desired skill uint32 skillTypeID = m_skillQueue.front().typeID; currentTraining = GetSkill( skillTypeID ); if( !currentTraining ) { _log( ITEM__ERROR, "%s (%u): Skill %u to train was not found.", itemName().c_str(), itemID(), skillTypeID ); break; } sLog.Debug( "Character::UpdateSkillQueue()", "%s (%u): Starting training of skill %s (%u)", m_itemName.c_str(), m_itemID, currentTraining->itemName().c_str(), currentTraining->itemID() ); EvilNumber SPPerMinute = GetSPPerMin( currentTraining ); EvilNumber NextLevel = currentTraining->GetAttribute(AttrSkillLevel) + 1; EvilNumber SPToNextLevel = currentTraining->GetSPForLevel( NextLevel ) - currentTraining->GetAttribute(AttrSkillPoints); sLog.Debug( " ", "Training skill at %f SP/min", SPPerMinute.get_float() ); sLog.Debug( " ", "%f SP to next Level of %d", SPToNextLevel.get_float(), NextLevel.get_int() ); SPPerMinute.to_float(); SPToNextLevel.to_float(); nextStartTime.to_float(); EvilNumber timeTraining = nextStartTime + EvilTime_Minute * SPToNextLevel / SPPerMinute; currentTraining->MoveInto( *this, flagSkillInTraining ); double dbl_timeTraining = timeTraining.get_float() + (double)(Win32Time_Second * 10); currentTraining->SetAttribute(AttrExpiryTime, dbl_timeTraining); // Set server-side // skill expiry + 10 sec sLog.Debug( " ", "Calculated time to complete training = %s", Win32TimeToString((uint64)dbl_timeTraining).c_str() ); if( c != NULL ) { OnSkillStartTraining osst; osst.itemID = currentTraining->itemID(); osst.endOfTraining = timeTraining.get_float(); PyTuple* tmp = osst.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } } if( currentTraining->GetAttribute(AttrExpiryTime) <= EvilTimeNow() ) { // training has been finished: sLog.Debug( "Character::UpdateSkillQueue()", "%s (%u): Finishing training of skill %s (%u).", itemName().c_str(), itemID(), currentTraining->itemName().c_str(), currentTraining->itemID() ); currentTraining->SetAttribute(AttrSkillLevel, currentTraining->GetAttribute(AttrSkillLevel) + 1 ); currentTraining->SetAttribute(AttrSkillPoints, currentTraining->GetSPForLevel( currentTraining->GetAttribute(AttrSkillLevel) ), true); nextStartTime = currentTraining->GetAttribute(AttrExpiryTime); currentTraining->SetAttribute(AttrExpiryTime, 0); currentTraining->MoveInto( *this, flagSkill, true ); if( c != NULL ) { OnSkillTrained ost; ost.itemID = currentTraining->itemID(); PyTuple* tmp = ost.Encode(); c->QueueDestinyEvent( &tmp ); PySafeDecRef( tmp ); c->UpdateSkillTraining(); } // erase first element in skill queue m_skillQueue.erase( m_skillQueue.begin() ); // nothing currently in training currentTraining = SkillRef(); } // else the skill is in training ... else break; } // Re-Calculate total SP trained and store in internal variable: _CalculateTotalSPTrained(); // Save character and skill data: SaveCharacter(); SaveSkillQueue(); }
std::tr1::shared_ptr<std::string> APIAccountManager::_APIKeyRequest(const APICommandCall * pAPICommandCall) { bool status = false; uint32 userID, apiRole; std::string username; std::string password; std::string keyType; std::string action; std::string apiLimitedKey; std::string apiFullKey; std::string accountID; std::string keyTag; sLog.Debug("APIAccountManager::_APIKeyRequest()", "EVEmu API - Account Service Manager - CALL: APIKeyRequest.xml.aspx"); // 1: Decode arguments: if( pAPICommandCall->find( "username" ) != pAPICommandCall->end() ) username = pAPICommandCall->find( "username" )->second; else { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: No 'username' parameter found in call argument list - exiting with error" ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } if( pAPICommandCall->find( "password" ) != pAPICommandCall->end() ) password = pAPICommandCall->find( "password" )->second; else { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: No 'password' parameter found in call argument list - exiting with error" ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } if( pAPICommandCall->find( "keytype" ) != pAPICommandCall->end() ) keyType = pAPICommandCall->find( "keytype" )->second; else { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: No 'keytype' parameter found in call argument list - exiting with error" ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } if( keyType != "full" ) if( keyType != "limited" ) { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: 'keytype' parameter has invalid value '%s' - exiting with error", keyType.c_str() ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } if( pAPICommandCall->find( "action" ) != pAPICommandCall->end() ) action = pAPICommandCall->find( "action" )->second; else { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: No 'action' parameter found in call argument list - exiting with error" ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } if( action != "new" ) if( action != "get" ) { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: 'action' parameter has invalid value '%s' - exiting with error", action.c_str() ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } // 2: Authenticate the username and password against the account table: status = _AuthenticateUserNamePassword( username, password ); if( !status ) { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: username='******' password='******' does not authenticate.", username.c_str(), password.c_str() ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } // 2a: Get accountID using username, now that it's been validated: status = m_db.GetAccountIdFromUsername( username, &accountID ); if( !status ) { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: username='******' cannot be found in 'account' table.", username.c_str() ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } // 3: Determine if this account's userID exists: status = m_db.GetApiAccountInfoUsingAccountID( accountID, &userID, &apiFullKey, &apiLimitedKey, &apiRole ); // 4: Generate new random 64-character hexadecimal API Keys: // Write new API Key to database if key request 'action' is 'new': if( !status ) { // 4a: If userID does not exist for this accountID, then insert a new row into the 'accountApi' table regardless of 'get' or 'new': apiLimitedKey = _GenerateAPIKey(); apiFullKey = _GenerateAPIKey(); status = m_db.InsertNewUserIdApiKeyInfoToDatabase( atol(accountID.c_str()), apiFullKey, apiLimitedKey, EVEAPI::Roles::Player ); } if( action == "new" ) if( keyType == "limited" ) apiLimitedKey = _GenerateAPIKey(); else //if( keyType == "full" ) apiFullKey = _GenerateAPIKey(); if( action == "new" ) { if( status ) // 4b: If userID already exists, generate new API keys and write them back to the database under that userID: status = m_db.UpdateUserIdApiKeyDatabaseRow( userID, apiFullKey, apiLimitedKey ); } // 5: Build XML document to return to API client: userID = 0; apiFullKey = ""; apiLimitedKey = ""; apiRole = 0; //status = m_db.GetAccountIdFromUsername( username, &accountID ); status = m_db.GetApiAccountInfoUsingAccountID( accountID, &userID, &apiFullKey, &apiLimitedKey, &apiRole ); if( !status ) { sLog.Error( "APIAccountManager::_APIKeyRequest()", "ERROR: username='******' cannot be found in 'account' table.", username.c_str() ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } // 6: Return the userID and the API key requested in the xml structure: _BuildXMLHeader(); { _BuildSingleXMLTag( "userID", std::string(itoa(userID)) ); if( keyType == "full" ) { keyTag = "apiFullKey"; _BuildSingleXMLTag( keyTag, apiFullKey ); } else { keyTag = "apiLimitedKey"; _BuildSingleXMLTag( keyTag, apiLimitedKey ); } _BuildSingleXMLTag( "expiresOn", Win32TimeToString(Win32TimeNow() + 180*Win32Time_Day) ); } _CloseXMLHeader( EVEAPI::CacheStyles::Long ); return _GetXMLDocumentString(); }
std::tr1::shared_ptr<std::string> APICharacterManager::_CharacterSheet(const APICommandCall * pAPICommandCall) { size_t i; sLog.Error( "APICharacterManager::_CharacterSheet()", "TODO: Insert code to validate userID and apiKey" ); sLog.Debug("APICharacterManager::_CharacterSheet()", "EVEmu API - Character Service Manager - CALL: CharacterSheet.xml.aspx"); if( pAPICommandCall->find( "userid" ) == pAPICommandCall->end() ) { sLog.Error( "APICharacterManager::_CharacterSheet()", "ERROR: No 'userID' parameter found in call argument list - exiting with error and sending back NOTHING" ); return BuildErrorXMLResponse( "106", "Must provide userID parameter for authentication." ); } if( pAPICommandCall->find( "apikey" ) == pAPICommandCall->end() ) { sLog.Error( "APICharacterManager::_CharacterSheet()", "ERROR: No 'apiKey' parameter found in call argument list - exiting with error and sending back NOTHING" ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } if( pAPICommandCall->find( "characterid" ) == pAPICommandCall->end() ) { sLog.Error( "APICharacterManager::_CharacterSheet()", "ERROR: No 'characterID' parameter found in call argument list - exiting with error and sending back NOTHING" ); return BuildErrorXMLResponse( "105", "Invalid characterID." ); } // Make calls to the APICharacterDB class to grab all data for this call and populate the xml structure with that data uint32 characterID = atoi( pAPICommandCall->find( "characterid" )->second.c_str() ); std::vector<std::string> skillTypeIDList; std::vector<std::string> skillPointsList; std::vector<std::string> skillLevelList; std::vector<std::string> skillPublishedList; m_charDB.GetCharacterSkillsTrained( characterID, skillTypeIDList, skillPointsList, skillLevelList, skillPublishedList ); std::vector<std::string> charInfoList; m_charDB.GetCharacterInfo( characterID, charInfoList ); std::map<std::string, std::string> charAttributes; m_charDB.GetCharacterAttributes( characterID, charAttributes ); sLog.Error( "APICharacterManager::_CharacterSheet()", "INFO: Sections Currently hard-coded: attributeEnhancers, certificates, corporation roles" ); std::vector<std::string> rowset; _BuildXMLHeader(); { _BuildXMLTag( "result" ); { _BuildSingleXMLTag( "characterID", std::string(itoa(characterID)) ); _BuildSingleXMLTag( "name", charInfoList.at(12) ); _BuildSingleXMLTag( "DoB", Win32TimeToString(strtoull(charInfoList.at(8).c_str(), NULL, 0) )); _BuildSingleXMLTag( "race", charInfoList.at(11) ); _BuildSingleXMLTag( "bloodLine", charInfoList.at(10) ); _BuildSingleXMLTag( "ancestry", charInfoList.at(9) ); _BuildSingleXMLTag( "gender", ( (atoi(charInfoList.at(14).c_str()) > 0) ? "Male" : "Female") ); _BuildSingleXMLTag( "corporationName", charInfoList.at(13) ); _BuildSingleXMLTag( "corporationID", charInfoList.at(2) ); _BuildSingleXMLTag( "allianceName", "none" ); _BuildSingleXMLTag( "allianceID", "0" ); _BuildSingleXMLTag( "cloneName", "Clone Grade Pi" ); _BuildSingleXMLTag( "cloneSkillPoints", "54600000" ); _BuildSingleXMLTag( "balance", charInfoList.at(0) ); // TODO: code these for real, as what follows are hard coded examples to fill out the whole xml document: // Attribute Enhancers (implants) _BuildXMLTag( "attributeEnhancers" ); { /* _BuildXMLTag( "memoryBonus" ); { _BuildSingleXMLTag( "augmentatorName", "Memory Augmentation - Basic" ); _BuildSingleXMLTag( "augmentatorValue", "3" ); } _CloseXMLTag(); // close tag "memoryBonus" _BuildXMLTag( "perceptionBonus" ); { _BuildSingleXMLTag( "augmentatorName", "Ocular Filter - Basic" ); _BuildSingleXMLTag( "augmentatorValue", "3" ); } _CloseXMLTag(); // close tag "perceptionBonus" _BuildXMLTag( "willpowerBonus" ); { _BuildSingleXMLTag( "augmentatorName", "Neural Boost - Basic" ); _BuildSingleXMLTag( "augmentatorValue", "3" ); } _CloseXMLTag(); // close tag "willpowerBonus" _BuildXMLTag( "intelligenceBonus" ); { _BuildSingleXMLTag( "augmentatorName", "Snake Delta" ); _BuildSingleXMLTag( "augmentatorValue", "3" ); } _CloseXMLTag(); // close tag "intelligenceBonus" _BuildXMLTag( "charismaBonus" ); { _BuildSingleXMLTag( "augmentatorName", "Limited Social Adaptation Chip" ); _BuildSingleXMLTag( "augmentatorValue", "3" ); } _CloseXMLTag(); // close tag "charismaBonus" */ } _CloseXMLTag(); // close tag "attributeEnhancers" // TODO: code these for real, as what follows are hard coded examples to fill out the whole xml document: // Attributes _BuildXMLTag( "attributes" ); { _BuildSingleXMLTag( "intelligence", charAttributes.find( std::string(itoa(AttrIntelligence)))->second ); _BuildSingleXMLTag( "memory", charAttributes.find( std::string(itoa(AttrMemory)))->second ); _BuildSingleXMLTag( "charisma", charAttributes.find( std::string(itoa(AttrCharisma)))->second ); _BuildSingleXMLTag( "perception", charAttributes.find( std::string(itoa(AttrPerception)))->second ); _BuildSingleXMLTag( "willpower", charAttributes.find( std::string(itoa(AttrWillpower)))->second ); } _CloseXMLTag(); // close tag "attributes" // Skills rowset.clear(); rowset.push_back("typeID"); rowset.push_back("skillpoints"); rowset.push_back("level"); rowset.push_back("published"); _BuildXMLRowSet( "skills", "typeID", &rowset ); { for(i=0; i<skillTypeIDList.size(); i++) { rowset.clear(); rowset.push_back(skillTypeIDList.at(i)); rowset.push_back(skillPointsList.at(i)); rowset.push_back(skillLevelList.at(i)); rowset.push_back(skillPublishedList.at(i)); _BuildXMLRow( &rowset ); } } _CloseXMLRowSet(); // close rowset "skills" // TODO: code these for real, as what follows are hard coded examples to fill out the whole xml document: // Certificates: rowset.clear(); rowset.push_back("certificateID"); _BuildXMLRowSet( "certificates", "certificateID", &rowset ); { // for(i=0; i<skillTypeIDList.size(); i++) // { rowset.clear(); //rowset.push_back(certificatesList.at(i)); rowset.push_back("1"); _BuildXMLRow( &rowset ); // } } _CloseXMLRowSet(); // close rowset "certificates" // TODO: code these for real, as what follows are hard coded examples to fill out the whole xml document: // Corporation Roles: //rowset.clear(); //rowset.push_back(""); //_BuildXMLRowSet( "", "", &rowset ); //{ //} _CloseXMLRowSet(); // close rowset "" } _CloseXMLTag(); // close tag "result" } _CloseXMLHeader( EVEAPI::CacheStyles::Long ); return _GetXMLDocumentString(); }
std::tr1::shared_ptr<std::string> APICharacterManager::_SkillInTraining(const APICommandCall * pAPICommandCall) { sLog.Error( "APICharacterManager::_SkillInTraining()", "TODO: Insert code to validate userID and apiKey" ); sLog.Debug("APICharacterManager::_SkillInTraining()", "EVEmu API - Character Service Manager - CALL: SkillInTraining.xml.aspx"); if( pAPICommandCall->find( "userid" ) == pAPICommandCall->end() ) { sLog.Error( "APICharacterManager::_SkillInTraining()", "ERROR: No 'userID' parameter found in call argument list - exiting with error and sending back NOTHING" ); return BuildErrorXMLResponse( "106", "Must provide userID parameter for authentication." ); } if( pAPICommandCall->find( "apikey" ) == pAPICommandCall->end() ) { sLog.Error( "APICharacterManager::_SkillInTraining()", "ERROR: No 'apiKey' parameter found in call argument list - exiting with error and sending back NOTHING" ); return BuildErrorXMLResponse( "203", "Authentication failure." ); } if( pAPICommandCall->find( "characterid" ) == pAPICommandCall->end() ) { sLog.Error( "APICharacterManager::_SkillInTraining()", "ERROR: No 'characterID' parameter found in call argument list - exiting with error and sending back NOTHING" ); return BuildErrorXMLResponse( "105", "Invalid characterID." ); } // Make calls to the APICharacterDB class to grab all data for this call and populate the xml structure with that data uint32 characterID = atoi( pAPICommandCall->find( "characterid" )->second.c_str() ); std::map<std::string, std::string> charLearningAttributesString; std::map<uint32, uint32> charLearningAttributes; m_charDB.GetCharacterAttributes( characterID, charLearningAttributesString ); charLearningAttributes.insert( std::pair<uint32, uint32>( AttrMemory, ((uint32)(atoi(charLearningAttributesString.find(std::string(itoa(AttrMemory)))->second.c_str()))) )); charLearningAttributes.insert( std::pair<uint32, uint32>( AttrIntelligence, ((uint32)(atoi(charLearningAttributesString.find(std::string(itoa(AttrIntelligence)))->second.c_str()))) )); charLearningAttributes.insert( std::pair<uint32, uint32>( AttrCharisma, ((uint32)(atoi(charLearningAttributesString.find(std::string(itoa(AttrCharisma)))->second.c_str()))) )); charLearningAttributes.insert( std::pair<uint32, uint32>( AttrWillpower, ((uint32)(atoi(charLearningAttributesString.find(std::string(itoa(AttrWillpower)))->second.c_str()))) )); charLearningAttributes.insert( std::pair<uint32, uint32>( AttrPerception, ((uint32)(atoi(charLearningAttributesString.find(std::string(itoa(AttrPerception)))->second.c_str()))) )); std::vector<std::string> queueOrderList; std::vector<std::string> queueSkillTypeIdList; std::vector<std::string> queueSkillLevelList; std::vector<std::string> queueSkillRankList; std::vector<std::string> queueSkillIdList; std::vector<std::string> queueSkillPrimaryAttrList; std::vector<std::string> queueSkillSecondaryAttrList; std::vector<std::string> queueSkillPointsTrainedList; uint32 queueSkillPrimaryAttribute; uint32 queueSkillSecondaryAttribute; std::vector<uint32> queueSkillStartSP; std::vector<uint32> queueSkillEndSP; std::vector<uint64> queueSkillStartTime; std::vector<uint64> queueSkillEndTime; EvilNumber spPerMinute(0.0); EvilNumber skillStartSP(0.0); EvilNumber skillEndSP(0.0); EvilNumber timeNow(0.0); uint64 skillStartTime; uint64 skillEndTime; bool status = m_charDB.GetCharacterSkillQueue( characterID, queueOrderList, queueSkillTypeIdList, queueSkillLevelList, queueSkillRankList, queueSkillIdList, queueSkillPrimaryAttrList, queueSkillSecondaryAttrList, queueSkillPointsTrainedList ); if( status ) { sLog.Error( "APICharacterManager::_SkillInTraining()", "INFO: Calculation of Skill End Time based on Effective SP/min does NOT include implants/boosters at this time" ); timeNow = EvilTimeNow(); queueSkillPrimaryAttribute = charLearningAttributes.find( atoi(queueSkillPrimaryAttrList.at(0).c_str()) )->second; queueSkillSecondaryAttribute = charLearningAttributes.find( atoi(queueSkillSecondaryAttrList.at(0).c_str()) )->second; skillStartSP = EvilNumber(atoi( queueSkillPointsTrainedList.at(0).c_str() )); queueSkillStartSP.push_back( static_cast<uint32>( skillStartSP.get_int() )); skillEndSP = SkillPointsAtLevel( atoi(queueSkillLevelList.at(0).c_str()), atoi(queueSkillRankList.at(0).c_str()) ); queueSkillEndSP.push_back( static_cast<uint32>( skillEndSP.get_int() ) ); spPerMinute = SkillPointsPerMinute( queueSkillPrimaryAttribute, queueSkillSecondaryAttribute ); skillStartTime = static_cast<uint64>(SkillStartingTime( skillStartSP, skillEndSP, spPerMinute, timeNow ).get_int()); skillEndTime = static_cast<uint64>(SkillEndingTime( skillStartSP, skillEndSP, spPerMinute, timeNow ).get_int()); queueSkillStartTime.push_back( skillStartTime ); queueSkillEndTime.push_back( skillEndTime ); } // EXAMPLE: std::vector<std::string> rowset; _BuildXMLHeader(); { _BuildXMLTag( "result" ); { if( status ) { _BuildSingleXMLTag( "currentTQTime", Win32TimeToString(static_cast<uint64>(timeNow.get_int())) ); _BuildSingleXMLTag( "trainingEndTime", Win32TimeToString(skillEndTime) ); _BuildSingleXMLTag( "trainingStartTime", Win32TimeToString(skillStartTime) ); _BuildSingleXMLTag( "trainingTypeID", queueSkillTypeIdList.at(0) ); _BuildSingleXMLTag( "trainingStartSP", std::string(itoa(skillStartSP.get_int())) ); _BuildSingleXMLTag( "trainingDestinationSP", std::string(itoa(skillEndSP.get_int())) ); _BuildSingleXMLTag( "trainingToLevel", queueSkillLevelList.at(0) ); _BuildSingleXMLTag( "skillInTraining", "1" ); } else { _BuildSingleXMLTag( "skillInTraining", "0" ); } } _CloseXMLTag(); // close tag "result" } _CloseXMLHeader( EVEAPI::CacheStyles::Modified ); return _GetXMLDocumentString(); }