CRef<CSimpleRebalanceStrategy> CreateSimpleRebalanceStrategy(CConfig& config, const string& driver_name) { return CRef<CSimpleRebalanceStrategy>(new CSimpleRebalanceStrategy( config.GetInt(driver_name, "rebalance_requests", CConfig::eErr_NoThrow, REBALANCE_REQUESTS_DEFAULT), s_SecondsToMilliseconds(config.GetString(driver_name, "rebalance_time", CConfig::eErr_NoThrow, NCBI_AS_STRING(REBALANCE_TIME_DEFAULT)), SECONDS_DOUBLE_TO_MS_UL(REBALANCE_TIME_DEFAULT)))); }
int main( int argc, char **argv ) { string CFGFile = "update_dota_elo.cfg"; if( argc > 1 && argv[1] ) CFGFile = argv[1]; CConfig CFG; CFG.Read( CFGFile ); string Server = CFG.GetString( "db_mysql_server", string( ) ); string Database = CFG.GetString( "db_mysql_database", "ghost" ); string User = CFG.GetString( "db_mysql_user", string( ) ); string Password = CFG.GetString( "db_mysql_password", string( ) ); int Port = CFG.GetInt( "db_mysql_port", 0 ); cout << "connecting to database server" << endl; MYSQL *Connection = NULL; if( !( Connection = mysql_init( NULL ) ) ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } my_bool Reconnect = true; mysql_options( Connection, MYSQL_OPT_RECONNECT, &Reconnect ); if( !( mysql_real_connect( Connection, Server.c_str( ), User.c_str( ), Password.c_str( ), Database.c_str( ), Port, NULL, 0 ) ) ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "connected" << endl; cout << "beginning transaction" << endl; string QBegin = "BEGIN"; if( mysql_real_query( Connection, QBegin.c_str( ), QBegin.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "creating tables" << endl; string QCreate1 = "CREATE TABLE IF NOT EXISTS dota_elo_scores ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(15) NOT NULL, server VARCHAR(100) NOT NULL, score REAL NOT NULL )"; string QCreate2 = "CREATE TABLE IF NOT EXISTS dota_elo_games_scored ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, gameid INT NOT NULL )"; if( mysql_real_query( Connection, QCreate1.c_str( ), QCreate1.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( mysql_real_query( Connection, QCreate2.c_str( ), QCreate2.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "getting unscored games" << endl; queue<uint32_t> UnscoredGames; string QSelectUnscored = "SELECT id FROM games WHERE id NOT IN ( SELECT gameid FROM dota_elo_games_scored ) ORDER BY id"; if( mysql_real_query( Connection, QSelectUnscored.c_str( ), QSelectUnscored.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } else { MYSQL_RES *Result = mysql_store_result( Connection ); if( Result ) { vector<string> Row = MySQLFetchRow( Result ); while( !Row.empty( ) ) { UnscoredGames.push( UTIL_ToUInt32( Row[0] ) ); Row = MySQLFetchRow( Result ); } mysql_free_result( Result ); } else { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } cout << "found " << UnscoredGames.size( ) << " unscored games" << endl; while( !UnscoredGames.empty( ) ) { uint32_t GameID = UnscoredGames.front( ); UnscoredGames.pop( ); string QSelectPlayers = "SELECT dota_elo_scores.id, gameplayers.name, spoofedrealm, newcolour, winner, score FROM dotaplayers LEFT JOIN dotagames ON dotagames.gameid=dotaplayers.gameid LEFT JOIN gameplayers ON gameplayers.gameid=dotaplayers.gameid AND gameplayers.colour=dotaplayers.colour LEFT JOIN dota_elo_scores ON dota_elo_scores.name=gameplayers.name AND server=spoofedrealm WHERE dotaplayers.gameid=" + UTIL_ToString( GameID ); if( mysql_real_query( Connection, QSelectPlayers.c_str( ), QSelectPlayers.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } else { MYSQL_RES *Result = mysql_store_result( Connection ); if( Result ) { cout << "gameid " << UTIL_ToString( GameID ) << " found" << endl; bool ignore = false; uint32_t rowids[10]; string names[10]; string servers[10]; bool exists[10]; int num_players = 0; float player_ratings[10]; int player_teams[10]; int num_teams = 2; float team_ratings[2]; float team_winners[2]; int team_numplayers[2]; team_ratings[0] = 0.0; team_ratings[1] = 0.0; team_numplayers[0] = 0; team_numplayers[1] = 0; vector<string> Row = MySQLFetchRow( Result ); while( Row.size( ) == 6 ) { if( num_players >= 10 ) { cout << "gameid " << UTIL_ToString( GameID ) << " has more than 10 players, ignoring" << endl; ignore = true; break; } uint32_t Winner = UTIL_ToUInt32( Row[4] ); if( Winner != 1 && Winner != 2 ) { cout << "gameid " << UTIL_ToString( GameID ) << " has no winner, ignoring" << endl; ignore = true; break; } else if( Winner == 1 ) { team_winners[0] = 1.0; team_winners[1] = 0.0; } else { team_winners[0] = 0.0; team_winners[1] = 1.0; } if( !Row[0].empty( ) ) rowids[num_players] = UTIL_ToUInt32( Row[0] ); else rowids[num_players] = 0; names[num_players] = Row[1]; servers[num_players] = Row[2]; if( !Row[5].empty( ) ) { exists[num_players] = true; player_ratings[num_players] = UTIL_ToFloat( Row[5] ); } else { cout << "new player [" << Row[1] << "] found" << endl; exists[num_players] = false; player_ratings[num_players] = 1000.0; } uint32_t Colour = UTIL_ToUInt32( Row[3] ); if( Colour >= 1 && Colour <= 5 ) { player_teams[num_players] = 0; team_ratings[0] += player_ratings[num_players]; team_numplayers[0]++; } else if( Colour >= 7 && Colour <= 11 ) { player_teams[num_players] = 1; team_ratings[1] += player_ratings[num_players]; team_numplayers[1]++; } else { cout << "gameid " << UTIL_ToString( GameID ) << " has a player with an invalid newcolour, ignoring" << endl; ignore = true; break; } num_players++; Row = MySQLFetchRow( Result ); } mysql_free_result( Result ); if( !ignore ) { if( num_players == 0 ) cout << "gameid " << UTIL_ToString( GameID ) << " has no players, ignoring" << endl; else if( team_numplayers[0] == 0 ) cout << "gameid " << UTIL_ToString( GameID ) << " has no Sentinel players, ignoring" << endl; else if( team_numplayers[1] == 0 ) cout << "gameid " << UTIL_ToString( GameID ) << " has no Scourge players, ignoring" << endl; else { cout << "gameid " << UTIL_ToString( GameID ) << " is calculating" << endl; float old_player_ratings[10]; memcpy( old_player_ratings, player_ratings, sizeof( float ) * 10 ); team_ratings[0] /= team_numplayers[0]; team_ratings[1] /= team_numplayers[1]; elo_recalculate_ratings( num_players, player_ratings, player_teams, num_teams, team_ratings, team_winners ); for( int i = 0; i < num_players; i++ ) { cout << "player [" << names[i] << "] rating " << UTIL_ToString( (uint32_t)old_player_ratings[i] ) << " -> " << UTIL_ToString( (uint32_t)player_ratings[i] ) << endl; if( exists[i] ) { string QUpdateScore = "UPDATE dota_elo_scores SET score=" + UTIL_ToString( player_ratings[i], 2 ) + " WHERE id=" + UTIL_ToString( rowids[i] ); if( mysql_real_query( Connection, QUpdateScore.c_str( ), QUpdateScore.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } else { string EscName = MySQLEscapeString( Connection, names[i] ); string EscServer = MySQLEscapeString( Connection, servers[i] ); string QInsertScore = "INSERT INTO dota_elo_scores ( name, server, score ) VALUES ( '" + EscName + "', '" + EscServer + "', " + UTIL_ToString( player_ratings[i], 2 ) + " )"; if( mysql_real_query( Connection, QInsertScore.c_str( ), QInsertScore.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } } } } } else { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } string QInsertScored = "INSERT INTO dota_elo_games_scored ( gameid ) VALUES ( " + UTIL_ToString( GameID ) + " )"; if( mysql_real_query( Connection, QInsertScored.c_str( ), QInsertScored.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } cout << "copying dota elo scores to scores table" << endl; string QCopyScores1 = "DELETE FROM scores WHERE category='dota_elo'"; string QCopyScores2 = "INSERT INTO scores ( category, name, server, score ) SELECT 'dota_elo', name, server, score FROM dota_elo_scores"; if( mysql_real_query( Connection, QCopyScores1.c_str( ), QCopyScores1.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( mysql_real_query( Connection, QCopyScores2.c_str( ), QCopyScores2.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "committing transaction" << endl; string QCommit = "COMMIT"; if( mysql_real_query( Connection, QCommit.c_str( ), QCommit.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "done" << endl; return 0; }
int main( ) { // seed the RNG srand( (unsigned int) time( NULL ) ); // check if the log folder exists if( !UTIL_FileExists( "log" ) ) { #ifdef WIN32 CreateDirectoryA( "log", NULL ); #else system( "mkdir log" ); system( "chmod 777 log" ); #endif } // check if the cfg folder exists if( !UTIL_FileExists( "cfg" ) ) { #ifdef WIN32 CreateDirectoryA( "cfg", NULL ); #else system( "mkdir cfg" ); system( "chmod 777 cfg" ); #endif } // read config file CConfig CFG; CFG.Read( CFGFile ); gLog = CFG.GetInt( "bot_log", 1 ) == 0 ? false : true; // catch SIGABRT and SIGINT signal( SIGABRT, SignalCatcher ); signal( SIGINT, SignalCatcher ); #ifndef WIN32 // disable SIGPIPE since some systems like OS X don't define MSG_NOSIGNAL signal( SIGPIPE, SIG_IGN ); #endif // initialize curses gCurses = true; initscr( ); #ifdef WIN32 resize_term( 28, 97 ); #endif clear( ); noecho( ); cbreak( ); gMainWindow = newwin( LINES - 3, COLS - 17, 0, 0 ); gBottomBorder = newwin( 1, COLS, LINES - 3, 0 ); gRightBorder = newwin( LINES - 3, 1, 0, COLS - 17 ); gInputWindow = newwin( 2, COLS, LINES - 2, 0 ); gChannelWindow = newwin( LINES - 3, 16, 0, COLS - 16 ); mvwhline( gBottomBorder, 0, 0, 0, COLS ); mvwvline( gRightBorder, 0, 0, 0, LINES ); wrefresh( gBottomBorder ); wrefresh( gRightBorder ); scrollok( gMainWindow, TRUE ); keypad( gInputWindow, TRUE ); scrollok( gInputWindow, TRUE ); CONSOLE_Draw( ); nodelay( gInputWindow, TRUE ); // print something for logging purposes CONSOLE_Print( "[CCBOT] starting up" ); #ifdef WIN32 // increase process priority CONSOLE_Print( "[CCBOT] setting process priority to \"high\"" ); SetPriorityClass( GetCurrentProcess( ), HIGH_PRIORITY_CLASS ); // initialize winsock CONSOLE_Print( "[CCBOT] starting winsock" ); WSADATA wsadata; if( WSAStartup( MAKEWORD( 2, 2 ), &wsadata ) != 0 ) { CONSOLE_Print( "[CCBOT] error starting winsock" ); return 1; } #endif // initialize ccbot gCCBot = new CCCBot( &CFG ); while( true ) { // block for 50ms on all sockets - if you intend to perform any timed actions more frequently you should change this // that said it's likely we'll loop more often than this due to there being data waiting on one of the sockets but there aren't any guarantees if( gCCBot->Update( ) ) break; bool Quit = false; int c = wgetch( gInputWindow ); while( c != ERR ) { if( c == 8 || c == 127 || c == KEY_BACKSPACE || c == KEY_DC ) { // Backspace, Delete if( !gInputBuffer.empty( ) ) gInputBuffer.erase( gInputBuffer.size( ) - 1, 1 ); } else if( c == 9 ) { // Tab } #ifdef WIN32 else if( c == 10 || c == 13 || c == PADENTER ) #else else if( c == 10 || c == 13 ) #endif { // CR, LF // process input buffer now string Command = gInputBuffer; if( Command[0] == gCCBot->m_BNETs[0]->GetCommandTrigger( ) ) { CONSOLE_Print( "[CONSOLE] " + Command ); CIncomingChatEvent event = CIncomingChatEvent( CBNETProtocol :: CONSOLE_INPUT, 0, 0, gCCBot->m_BNETs[0]->GetRootAdmin( ), Command ); gCCBot->m_BNETs[0]->ProcessChatEvent( &event ); } else gCCBot->m_BNETs[0]->QueueChatCommand( Command, false ); gInputBuffer.clear( ); } #ifdef WIN32 else if( c == 22 ) { // Paste char *clipboard = NULL; long length = 0; if( PDC_getclipboard( &clipboard, &length ) == PDC_CLIP_SUCCESS ) { gInputBuffer += string( clipboard, length ); PDC_freeclipboard( clipboard ); } } #endif else if( c == 27 ) { // Escape button gInputBuffer.clear( ); } else if( c >= 32 && c <= 255 ) { // Printable characters gInputBuffer.push_back( c ); } #ifdef WIN32 else if( c == PADSLASH ) gInputBuffer.push_back( '/' ); else if( c == PADSTAR ) gInputBuffer.push_back( '*' ); else if( c == PADMINUS ) gInputBuffer.push_back( '-' ); else if( c == PADPLUS ) gInputBuffer.push_back( '+' ); #endif else if( c == KEY_RESIZE ) CONSOLE_Resize( ); // clamp input buffer size if( gInputBuffer.size( ) > 200 ) gInputBuffer.erase( 200 ); c = wgetch( gInputWindow ); gInputWindowChanged = true; } CONSOLE_Draw( ); if( Quit ) break; } // shutdown ghost CONSOLE_Print( "[CCBOT] shutting down" ); delete gCCBot; gCCBot = NULL; #ifdef WIN32 // shutdown winsock CONSOLE_Print( "[CCBOT] shutting down winsock" ); WSACleanup( ); #endif // shutdown curses endwin( ); if( gRestart ) { #ifdef WIN32 _spawnl( _P_OVERLAY, "ccbot.exe", "ccbot.exe", NULL ); #else execl( "ccbot++", "ccbot++", NULL ); #endif } return 0; }
int main( int argc, char **argv ) { string CFGFile = "update_w3mmd_elo.cfg"; if( argc > 1 && argv[1] ) CFGFile = argv[1]; CConfig CFG; CFG.Read( CFGFile ); string Server = CFG.GetString( "db_mysql_server", string( ) ); string Database = CFG.GetString( "db_mysql_database", "ghost" ); string User = CFG.GetString( "db_mysql_user", string( ) ); string Password = CFG.GetString( "db_mysql_password", string( ) ); int Port = CFG.GetInt( "db_mysql_port", 0 ); string Category = CFG.GetString( "update_category", string( ) ); string PlayerA = CFG.GetString("oh_main_user", string( ) ); string PlayerB = CFG.GetString("oh_user_to_main_user", string( ) ); if( PlayerA.empty() || PlayerB.empty()) { cout << "Skipping this game, no correct configs for player to merge found" << endl; return 1; } if( Category.empty( ) ) { cout << "no update_category specified in config file" << endl; return 1; } cout << "connecting to database server" << endl; MYSQL *Connection = NULL; if( !( Connection = mysql_init( NULL ) ) ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } my_bool Reconnect = true; mysql_options( Connection, MYSQL_OPT_RECONNECT, &Reconnect ); if( !( mysql_real_connect( Connection, Server.c_str( ), User.c_str( ), Password.c_str( ), Database.c_str( ), Port, NULL, 0 ) ) ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "connected" << endl; cout << "beginning transaction" << endl; string QBegin = "BEGIN"; if( mysql_real_query( Connection, QBegin.c_str( ), QBegin.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "creating tables" << endl; string QCreate1 = "CREATE TABLE IF NOT EXISTS w3mmd_elo_scores ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, category VARCHAR(25) NOT NULL, name VARCHAR(15) NOT NULL, server VARCHAR(100) NOT NULL, score REAL NOT NULL )"; string QCreate2 = "CREATE TABLE IF NOT EXISTS w3mmd_elo_games_scored ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, category VARCHAR(25), gameid INT NOT NULL )"; if( mysql_real_query( Connection, QCreate1.c_str( ), QCreate1.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( mysql_real_query( Connection, QCreate2.c_str( ), QCreate2.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "getting unscored games" << endl; queue<uint32_t> UnscoredGames; string QSelectUnscored = "SELECT g.id FROM games as g LEFT JOIN gamepalyers as gp ON gp.gameid=g.id WHERE gp.name = '"+PlayerA+"' OR gp.name = '"+PlayerB+"'"; if( mysql_real_query( Connection, QSelectUnscored.c_str( ), QSelectUnscored.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } else { MYSQL_RES *Result = mysql_store_result( Connection ); if( Result ) { vector<string> Row = MySQLFetchRow( Result ); while( !Row.empty( ) ) { UnscoredGames.push( UTIL_ToUInt32( Row[0] ) ); Row = MySQLFetchRow( Result ); } mysql_free_result( Result ); } else { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } cout << "found " << UnscoredGames.size( ) << "games to merge" << endl; string QDeletePlayers = "DELETE FROM w3mmd_elo_scores WHERE name = '"+PlayerA+"' OR name='"+PlayerB+"'"; string QDeletePlayers1 = "DELETE FROM scores WHERE name = '"+PlayerA+"' OR name='"+PlayerB+"'"; if( mysql_real_query( Connection, QDeletePlayers.c_str( ), QDeletePlayers.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( mysql_real_query( Connection, QDeletePlayers1.c_str( ), QDeletePlayers1.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } while( !UnscoredGames.empty( ) ) { uint32_t GameID = UnscoredGames.front( ); UnscoredGames.pop( ); // lowercase the name because there was a bug in GHost++ 13.3 and earlier that didn't automatically lowercase it when using MySQL string QSelectPlayers = "SELECT w3mmd_elo_scores.id, LOWER(gameplayers.name), spoofedrealm, flag, practicing, score FROM w3mmdplayers LEFT JOIN gameplayers ON gameplayers.gameid=w3mmdplayers.gameid AND LOWER(gameplayers.name)=LOWER(w3mmdplayers.name) LEFT JOIN w3mmd_elo_scores ON LOWER(w3mmd_elo_scores.name)=LOWER(gameplayers.name) AND server=spoofedrealm WHERE w3mmdplayers.category='" + MySQLEscapeString( Connection, Category ) + "' AND w3mmdplayers.gameid=" + UTIL_ToString( GameID ); if( mysql_real_query( Connection, QSelectPlayers.c_str( ), QSelectPlayers.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } else { MYSQL_RES *Result = mysql_store_result( Connection ); if( Result ) { cout << "gameid " << UTIL_ToString( GameID ) << " found" << endl; bool ignore = false; bool winner = false; uint32_t rowids[12]; string names[12]; string servers[12]; bool exists[12]; int num_players = 0; float player_ratings[12]; int player_teams[12]; int num_teams = 0; float team_ratings[12]; float team_winners[12]; int team_numplayers[12]; for( int i = 0; i < 12; i++ ) { team_ratings[i] = 0.0; team_numplayers[i] = 0; } vector<string> Row = MySQLFetchRow( Result ); while( Row.size( ) == 6 ) { // Row[0] = rowid // Row[1] = name // Row[2] = server // Row[3] = flag // Row[4] = practicing // Row[5] = score if( num_players >= 12 ) { cout << "gameid " << UTIL_ToString( GameID ) << " has more than 12 players, ignoring" << endl; ignore = true; break; } if( Row[3] == "drawer" ) { cout << "ignoring player [" << Row[1] << "|" << Row[2] << "] because they drew" << endl; continue; } if( Row[4] == "1" ) { cout << "ignoring player [" << Row[1] << "|" << Row[2] << "] because they were practicing" << endl; continue; } if( Row[3] == "winner" ) { // keep track of whether at least one player won or not since we shouldn't score the game if nobody won winner = true; // note: we pretend each player is on a different team (i.e. it was a free for all) // this is because the ELO algorithm requires that each team either all won or all lost as a group // however, the MMD system stores win/loss flags on a per player basis and doesn't constrain the flags based on team // another option is to throw an error when this is detected and ignore the game completely // at this point I'm not sure which option is more correct team_winners[num_players] = 1.0; } else team_winners[num_players] = 0.0; if( !Row[0].empty( ) ) rowids[num_players] = UTIL_ToUInt32( Row[0] ); else rowids[num_players] = 0; names[num_players] = Row[1]; servers[num_players] = Row[2]; if( !Row[5].empty( ) ) { exists[num_players] = true; player_ratings[num_players] = UTIL_ToFloat( Row[5] ); } else { cout << "new player [" << Row[1] << "|" << Row[2] << "] found" << endl; exists[num_players] = false; player_ratings[num_players] = 1000.0; } player_teams[num_players] = num_players; team_ratings[num_players] = player_ratings[num_players]; team_numplayers[num_players]++; num_players++; Row = MySQLFetchRow( Result ); } num_teams = num_players; mysql_free_result( Result ); if( !ignore ) { if( num_players == 0 ) cout << "gameid " << UTIL_ToString( GameID ) << " has no players or is the wrong category, ignoring" << endl; else if( !winner ) cout << "gameid " << UTIL_ToString( GameID ) << " has no winner, ignoring" << endl; else { cout << "gameid " << UTIL_ToString( GameID ) << " is calculating" << endl; float old_player_ratings[12]; memcpy( old_player_ratings, player_ratings, sizeof( float ) * 12 ); // team_ratings[0] /= team_numplayers[0]; // team_ratings[1] /= team_numplayers[1]; elo_recalculate_ratings( num_players, player_ratings, player_teams, num_teams, team_ratings, team_winners ); for( int i = 0; i < num_players; i++ ) { if( PlayerA != names[i] && PlayerB != names[i] ) { cout << "not a player to merge, skipping this player" << endl; break; } if( names[i] == PlayerB ) names[i] = PlayerA; cout << "player [" << names[i] << "|" << servers[i] << "] rating " << UTIL_ToString( (uint32_t)old_player_ratings[i] ) << " -> " << UTIL_ToString( (uint32_t)player_ratings[i] ) << endl; if( exists[i] ) { string EscName = MySQLEscapeString( Connection, names[i] ); string QUpdateScore = "UPDATE w3mmd_elo_scores SET score=" + UTIL_ToString( player_ratings[i], 2 ) + " WHERE id=" + UTIL_ToString( rowids[i] ); string Score = "UPDATE scores SET score=" + UTIL_ToString( player_ratings[i], 2 ) + " WHERE name=" + EscName; if( mysql_real_query( Connection, QUpdateScore.c_str( ), QUpdateScore.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( mysql_real_query( Connection, Score.c_str( ), Score.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } else { string EscCategory = MySQLEscapeString( Connection, Category ); string EscName = MySQLEscapeString( Connection, names[i] ); string EscServer = MySQLEscapeString( Connection, servers[i] ); string QInsertScore = "INSERT INTO w3mmd_elo_scores ( category, name, server, score ) VALUES ( '" + EscCategory + "', '" + EscName + "', '" + EscServer + "', " + UTIL_ToString( player_ratings[i], 2 ) + " )"; string Score = "INSERT INTO scores ( category, name, server, score ) VALUES( '" + EscCategory + "', '" + EscName + "', '" + EscServer + "', " + UTIL_ToString( player_ratings[i], 2 ) + " )"; if( mysql_real_query( Connection, QInsertScore.c_str( ), QInsertScore.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( mysql_real_query( Connection, Score.c_str( ), Score.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } } } } } else { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } } cout << "committing transaction" << endl; string QCommit = "COMMIT"; if( mysql_real_query( Connection, QCommit.c_str( ), QCommit.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "done" << endl; return 0; }
int main( int argc, char **argv ) { string CFGFile = "update_dota_elo.cfg"; if( argc > 1 && argv[1] ) CFGFile = argv[1]; CConfig CFG; CFG.Read( CFGFile ); string Server = CFG.GetString( "db_mysql_server", string( ) ); string Database = CFG.GetString( "db_mysql_database", "ghost" ); string User = CFG.GetString( "db_mysql_user", string( ) ); string Password = CFG.GetString( "db_mysql_password", string( ) ); int Port = CFG.GetInt( "db_mysql_port", 0 ); bool DontUpdateScoresToAdmins = CFG.GetInt("elo_dont_calculate_score_to_admins", 0) == 1 ? true : false; vector<string> AdminsList; AdminsList.clear(); cout << "connecting to database server" << endl; MYSQL *Connection = NULL; if( !( Connection = mysql_init( NULL ) ) ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } my_bool Reconnect = true; mysql_options( Connection, MYSQL_OPT_RECONNECT, &Reconnect ); if( !( mysql_real_connect( Connection, Server.c_str( ), User.c_str( ), Password.c_str( ), Database.c_str( ), Port, NULL, 0 ) ) ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "Checking Admins List" << endl; string QAdminsList = "SELECT name FROM admins;"; if( mysql_real_query( Connection, QAdminsList.c_str( ), QAdminsList.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } else { MYSQL_RES *Result = mysql_store_result( Connection ); if( Result ) { vector<string> Row = MySQLFetchRow( Result ); while( !Row.empty( ) ) { string name = Row[0]; transform( name.begin( ), name.end( ), name.begin( ), (int(*)(int))tolower ); AdminsList.push_back( name ); Row = MySQLFetchRow( Result ); } mysql_free_result( Result ); } else { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } cout << "beginning transaction" << endl; string QBegin = "BEGIN"; if( mysql_real_query( Connection, QBegin.c_str( ), QBegin.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "creating tables" << endl; string QCreate1 = "CREATE TABLE IF NOT EXISTS dota_elo_scores ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(15) NOT NULL, server VARCHAR(100) NOT NULL, score REAL NOT NULL )"; string QCreate2 = "CREATE TABLE IF NOT EXISTS dota_elo_games_scored ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, gameid INT NOT NULL )"; if( mysql_real_query( Connection, QCreate1.c_str( ), QCreate1.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( mysql_real_query( Connection, QCreate2.c_str( ), QCreate2.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "getting unscored games" << endl; queue<uint32_t> UnscoredGames; string QSelectUnscored = "SELECT id FROM games WHERE id NOT IN ( SELECT gameid FROM dota_elo_games_scored ) ORDER BY id"; if( mysql_real_query( Connection, QSelectUnscored.c_str( ), QSelectUnscored.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } else { MYSQL_RES *Result = mysql_store_result( Connection ); if( Result ) { vector<string> Row = MySQLFetchRow( Result ); while( !Row.empty( ) ) { UnscoredGames.push( UTIL_ToUInt32( Row[0] ) ); Row = MySQLFetchRow( Result ); } mysql_free_result( Result ); } else { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } cout << "found " << UnscoredGames.size( ) << " unscored games" << endl; while( !UnscoredGames.empty( ) ) { uint32_t GameID = UnscoredGames.front( ); UnscoredGames.pop( ); string QSelectPlayers = "SELECT dota_elo_scores.id, gameplayers.name, spoofedrealm, newcolour, winner, score FROM dotaplayers LEFT JOIN dotagames ON dotagames.gameid=dotaplayers.gameid LEFT JOIN gameplayers ON gameplayers.gameid=dotaplayers.gameid AND gameplayers.colour=dotaplayers.colour LEFT JOIN dota_elo_scores ON dota_elo_scores.name=gameplayers.name WHERE dotaplayers.gameid=" + UTIL_ToString( GameID ); if( mysql_real_query( Connection, QSelectPlayers.c_str( ), QSelectPlayers.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } else { MYSQL_RES *Result = mysql_store_result( Connection ); if( Result ) { cout << "gameid " << UTIL_ToString( GameID ) << " found" << endl; bool ignore = false; uint32_t rowids[10]; string names[10]; string servers[10]; bool exists[10]; int num_players = 0; float player_ratings[10]; int player_teams[10]; int num_teams = 2; float team_ratings[2]; float team_winners[2]; int team_numplayers[2]; team_ratings[0] = 0.0; team_ratings[1] = 0.0; team_numplayers[0] = 0; team_numplayers[1] = 0; vector<string> Row = MySQLFetchRow( Result ); while( Row.size( ) == 6 ) { if( num_players >= 10 ) { cout << "gameid " << UTIL_ToString( GameID ) << " has more than 10 players, ignoring" << endl; ignore = true; break; } uint32_t Winner = UTIL_ToUInt32( Row[4] ); if( Winner != 1 && Winner != 2 ) { cout << "gameid " << UTIL_ToString( GameID ) << " has no winner, ignoring" << endl; ignore = true; break; } else if( Winner == 1 ) { team_winners[0] = 1.0; team_winners[1] = 0.0; } else { team_winners[0] = 0.0; team_winners[1] = 1.0; } if( !Row[0].empty( ) ) rowids[num_players] = UTIL_ToUInt32( Row[0] ); else rowids[num_players] = 0; names[num_players] = Row[1]; transform( names[num_players].begin( ), names[num_players].end( ), names[num_players].begin( ), (int(*)(int))tolower ); servers[num_players] = Row[2]; if( !Row[5].empty( ) ) { exists[num_players] = true; player_ratings[num_players] = UTIL_ToFloat( Row[5] ); } else { cout << "new player [" << Row[1] << "] found" << endl; exists[num_players] = false; player_ratings[num_players] = 1000.0; } uint32_t Colour = UTIL_ToUInt32( Row[3] ); if( Colour >= 1 && Colour <= 5 ) { player_teams[num_players] = 0; team_ratings[0] += player_ratings[num_players]; team_numplayers[0]++; } else if( Colour >= 7 && Colour <= 11 ) { player_teams[num_players] = 1; team_ratings[1] += player_ratings[num_players]; team_numplayers[1]++; } else { cout << "gameid " << UTIL_ToString( GameID ) << " has a player with an invalid newcolour, ignoring" << endl; ignore = true; break; } num_players++; Row = MySQLFetchRow( Result ); } mysql_free_result( Result ); if( !ignore ) { if( num_players == 0 ) cout << "gameid " << UTIL_ToString( GameID ) << " has no players, ignoring" << endl; else if( team_numplayers[0] == 0 ) cout << "gameid " << UTIL_ToString( GameID ) << " has no Sentinel players, ignoring" << endl; else if( team_numplayers[1] == 0 ) cout << "gameid " << UTIL_ToString( GameID ) << " has no Scourge players, ignoring" << endl; else { cout << "gameid " << UTIL_ToString( GameID ) << " is calculating" << endl; float old_player_ratings[10]; memcpy( old_player_ratings, player_ratings, sizeof( float ) * 10 ); team_ratings[0] /= team_numplayers[0]; team_ratings[1] /= team_numplayers[1]; elo_recalculate_ratings( num_players, player_ratings, player_teams, num_teams, team_ratings, team_winners ); string QNullEloPoint = "UPDATE dotaplayers SET elopoint=0 WHERE gameid=" + UTIL_ToString( GameID ); if( mysql_real_query( Connection, QNullEloPoint.c_str( ), QNullEloPoint.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } vector<string> player_who_scored; player_who_scored.clear(); string QSelectPlayerPoint = "SELECT dp.id,gp.name FROM dotaplayers as dp LEFT JOIN gameplayers as gp ON gp.gameid=dp.gameid AND gp.colour=dp.colour LEFT JOIN dotagames as dg ON dg.gameid=dp.gameid LEFT JOIN games ON games.id=dp.gameid WHERE (gp.left > games.duration - 60 OR (gp.left < games.duration - 60 AND ((dg.winner=1 AND dp.newcolour>5) OR (dg.winner=2 AND dp.newcolour<6)))) AND dp.gameid="+UTIL_ToString( GameID ); if( mysql_real_query( Connection, QSelectPlayerPoint.c_str( ), QSelectPlayerPoint.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } else { MYSQL_RES *Result = mysql_store_result( Connection ); if( Result ) { vector<string> Row = MySQLFetchRow( Result ); while( !Row.empty( ) ) { string elopoint; elopoint = "0.0"; int player_id = -1; string cur_name; cur_name = Row[1]; transform( cur_name.begin( ), cur_name.end( ), cur_name.begin( ), (int(*)(int))tolower ); for (player_id = 0;player_id < 10; player_id++) if (names[player_id] == cur_name) break; if (player_id < 0) { cout << "[ELO] Error, player_id < 0" << endl; break; } if (DontUpdateScoresToAdmins) { for ( vector<string> :: iterator i = AdminsList.begin(); i != AdminsList.end(); i++) if ( (*i) == names[player_id] ) { player_ratings[player_id] = old_player_ratings[player_id]; break; } } elopoint = UTIL_FloatToString(player_ratings[player_id] - old_player_ratings[player_id]); string QUpdatePlayerPoint = "UPDATE dotaplayers SET elopoint="+elopoint+" WHERE gameid="+UTIL_ToString( GameID ) + " AND id=" + Row[0]; if( mysql_real_query( Connection, QUpdatePlayerPoint.c_str( ), QUpdatePlayerPoint.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( exists[player_id] ) { string QUpdateScore = "UPDATE dota_elo_scores SET score=" + UTIL_ToString( player_ratings[player_id], 2 ) + " WHERE id=" + UTIL_ToString( rowids[player_id] ); if( mysql_real_query( Connection, QUpdateScore.c_str( ), QUpdateScore.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } else { string EscName = MySQLEscapeString( Connection, names[player_id] ); string EscServer = MySQLEscapeString( Connection, servers[player_id] ); string QInsertScore = "INSERT INTO dota_elo_scores ( name, server, score ) VALUES ( '" + EscName + "', '" + EscServer + "', " + UTIL_ToString( player_ratings[player_id], 2 ) + " )"; if(mysql_real_query( Connection, QInsertScore.c_str( ), QInsertScore.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } player_who_scored.push_back(Row[1]); Row = MySQLFetchRow( Result ); } } mysql_free_result( Result ); } for( int i = 0; i < num_players; i++ ) { bool id_rating; id_rating = false; for (uint32_t cid=0;cid < player_who_scored.size(); cid++) if (player_who_scored[cid] == names[i]) { id_rating = true; break; } if (!id_rating) old_player_ratings[i] = player_ratings[i]; cout << "player [" << names[i] << "] rating " << UTIL_ToString( (uint32_t)old_player_ratings[i] ) << " -> " << UTIL_ToString( (uint32_t)player_ratings[i] ) << endl; } } } } else { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } string QInsertScored = "INSERT INTO dota_elo_games_scored ( gameid ) VALUES ( " + UTIL_ToString( GameID ) + " )"; if( mysql_real_query( Connection, QInsertScored.c_str( ), QInsertScored.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } } cout << "copying dota elo scores to scores table" << endl; string QCopyScores1 = "DELETE FROM scores WHERE category='dota_elo'"; string QCopyScores2 = "INSERT INTO scores ( category, name, server, score ) SELECT 'dota_elo', name, server, score FROM dota_elo_scores"; if( mysql_real_query( Connection, QCopyScores1.c_str( ), QCopyScores1.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } if( mysql_real_query( Connection, QCopyScores2.c_str( ), QCopyScores2.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "committing transaction" << endl; string QCommit = "COMMIT"; if( mysql_real_query( Connection, QCommit.c_str( ), QCommit.size( ) ) != 0 ) { cout << "error: " << mysql_error( Connection ) << endl; return 1; } cout << "done" << endl; return 0; }
int main(int argc, char* argv[]) { string cfgFile; try{ namespace po = boost::program_options; po::options_description generic("Generic options"); generic.add_options() ("version,v", "print version string") ("help,h", "help message") ("about,a", "about me") ; po::options_description config("Configuration"); config.add_options() ("config,c",po::value<string>(&cfgFile)->default_value("moreobs.cfg"),"config file") ; po::options_description cmdline_options; cmdline_options.add(generic).add(config); po::variables_map vm; po::store(po::parse_command_line(argc, argv, cmdline_options),vm); po::notify(vm); if (vm.count("help")) { cout << cmdline_options << "\n"; return 1; } if (vm.count("version")) { cout << "Version: " << "0.2.1079" << "\n"; return 1; } if (vm.count("about")) { cout<< "Waaagh!TV Client Simulation Server (personal)"<<endl; cout<< "Author: binux@CN" <<endl <<"Version: " <<"0.2.1079" <<endl << "Build: 2010-7-9"<<endl <<"This program is based on Waaagh!TV. All information about the protocol is guessing by looking at the network traffic. Thanks to guys for your useful programs."<<endl; return 1; } if (cfgFile!="moreobs.cfg" && vm.count("config")) { cout << "Using config file :" << cfgFile << endl; } } catch(boost::system::system_error& e) { DEBUG_Print(string("[MAIN]") + e.what() , DEBUG_LEVEL_ERROR); return 1; } //============================================================================================================ CConfig cfg; cfg.Read(cfgFile); debug_level = cfg.GetInt( "debug_level" , 99 ); gLogFile = cfg.GetString( "log", string( ) ); gLogMethod = cfg.GetInt( "logmethod", 1 ); if( !gLogFile.empty( ) ) { if( gLogMethod == 1 ) { // log method 1: open, append, and close the log for every message // this works well on Linux but poorly on Windows, particularly as the log file grows in size // the log file can be edited/moved/deleted while GHost++ is running } else if( gLogMethod == 2 ) { // log method 2: open the log on startup, flush the log for every message, close the log on shutdown // the log file CANNOT be edited/moved/deleted while GHost++ is running gLog = new ofstream( ); gLog->open( gLogFile.c_str( ), ios :: app ); } } CONSOLE_Print( "[MAIN] starting up" ); if( !gLogFile.empty( ) ) { if( gLogMethod == 1 ) CONSOLE_Print( "[MAIN] using log method 1, logging is enabled and [" + gLogFile + "] will not be locked" , DEBUG_LEVEL_MESSAGE ); else if( gLogMethod == 2 ) { if( gLog->fail( ) ) CONSOLE_Print( "[MAIN] using log method 2 but unable to open [" + gLogFile + "] for appending, logging is disabled" , DEBUG_LEVEL_WARN ); else CONSOLE_Print( "[MAIN] using log method 2, logging is enabled and [" + gLogFile + "] is now locked" , DEBUG_LEVEL_MESSAGE ); } } else CONSOLE_Print( "[MAIN] no log file specified, logging is disabled" , DEBUG_LEVEL_WARN); gMoreObs = new CMoreObs( &cfg ); //runing gMoreObs->Run(); //shutdown CONSOLE_Print( "[MAIN] shutting down", DEBUG_LEVEL_MESSAGE ); delete gMoreObs; gMoreObs = NULL; if( gLog ) { if( !gLog->fail( ) ) gLog->close( ); delete gLog; } return 0; }