示例#1
0
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))));
}
示例#2
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 );

	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;
}
示例#3
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;
}
示例#6
0
文件: main.cpp 项目: binux/moreobs
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;
}