std::vector<CDeterministicMNCPtr> CDeterministicMNList::CalculateQuorum(size_t maxSize, const uint256& modifier) const { auto scores = CalculateScores(modifier); // sort is descending order std::sort(scores.rbegin(), scores.rend(), [](const std::pair<arith_uint256, CDeterministicMNCPtr>& a, std::pair<arith_uint256, CDeterministicMNCPtr>& b) { if (a.first == b.first) { // this should actually never happen, but we should stay compatible with how the non deterministic MNs did the sorting return a.second->collateralOutpoint < b.second->collateralOutpoint; } return a.first < b.first; }); // take top maxSize entries and return it std::vector<CDeterministicMNCPtr> result; result.resize(std::min(maxSize, scores.size())); for (size_t i = 0; i < result.size(); i++) { result[i] = std::move(scores[i].second); } return result; }
void Game::Update() { // // If there is a real-world timer, update it if( m_winner == -1 && m_maxGameTime > 0 ) { m_maxGameTime -= SERVER_ADVANCE_PERIOD; m_maxGameTime = max( m_maxGameTime, 0 ); if( !m_gameTimeWarning && m_maxGameTime <= (10 * 60) && g_app->GetGame()->GetOptionValue("MaxGameRealTime") >= 10 ) { g_app->GetInterface()->ShowMessage( 0, 0, -1, LANGUAGEPHRASE("message_ten_minute_warning"), true ); m_gameTimeWarning = true; if( g_app->m_hidden ) { g_app->GetStatusIcon()->SetSubIcon( STATUS_ICON_TIMER ); g_app->GetStatusIcon()->SetCaption( LANGUAGEPHRASE("tray_icon_ten_minute_warning") ); } } } // Remove all remaining units and calculate total nukes when Defcon 3 hits int defcon = g_app->GetWorld()->GetDefcon(); if( defcon != m_lastKnownDefcon ) { if( !g_app->GetTutorial() || g_app->GetTutorial()->GetCurrentLevel() == 7 ) { if( defcon == 3 ) { for( int i = 0; i < g_app->GetWorld()->m_teams.Size(); ++i ) { Team *team = g_app->GetWorld()->m_teams[i]; team->m_unitCredits = 0; for( int j = 0; j < WorldObject::NumObjectTypes; ++j ) { team->m_unitsAvailable[j] = 0; } } CountNukes(); for( int i = 0; i < g_app->GetWorld()->m_teams.Size(); ++i ) { Team *team = g_app->GetWorld()->m_teams[i]; m_totalNukes[team->m_teamId] = m_nukeCount[team->m_teamId]; } EclRemoveWindow( "Side Panel" ); EclRemoveWindow( "Placement" ); } } m_lastKnownDefcon = defcon; } // // Has somebody won? if( m_winner == -1 ) { // // If the game is counting down... if( m_victoryTimer > 0 ) { m_victoryTimer -= SERVER_ADVANCE_PERIOD * g_app->GetWorld()->GetTimeScaleFactor(); m_victoryTimer = max( m_victoryTimer, 0 ); } m_recalcTimer -= SERVER_ADVANCE_PERIOD; if( m_recalcTimer <= 0 ) { m_recalcTimer = 3; // // Recalculate the scores CountNukes(); CalculateScores(); // // Look at nukes remaining // If there are few enough nukes, start the timer if( !m_lockVictoryTimer && m_victoryTimer < 0 ) { int totalNukeCount = 0; int totalMaxNukeCount = 0; int numTeams = g_app->GetWorld()->m_teams.Size(); for( int t = 0; t < numTeams; ++t ) { Team *team = g_app->GetWorld()->m_teams[t]; totalNukeCount += m_nukeCount[team->m_teamId]; totalMaxNukeCount += m_totalNukes[team->m_teamId]; } float averageNukeCount = totalNukeCount / (float) numTeams; float averageTotalCount = totalMaxNukeCount / (float) numTeams; float victoryNukeCount = averageTotalCount * GetOptionValue("VictoryTrigger") / 100.0f; if( averageNukeCount <= victoryNukeCount ) { m_victoryTimer = GetOptionValue("VictoryTimer"); m_victoryTimer *= 60; //to get it into minutes if( m_victoryTimer > 0 ) { g_app->GetInterface()->ShowMessage( 0, 0, -1, LANGUAGEPHRASE("message_victory_timer"), true ); g_soundSystem->TriggerEvent( "Interface", "DefconChange" ); if( g_app->m_hidden ) { g_app->GetStatusIcon()->SetSubIcon( STATUS_ICON_TIMER ); g_app->GetStatusIcon()->SetCaption( LANGUAGEPHRASE("tray_icon_victory_timer") ); } } } } // // If the countdown has finished // Declare the winner now! if( m_victoryTimer == 0 || m_maxGameTime == 0 ) { CalculateScores(); m_winner = -1; int winningScore = 0; for( int t = 0; t < g_app->GetWorld()->m_teams.Size(); ++t ) { Team *team = g_app->GetWorld()->m_teams[t]; int score = GetScore(team->m_teamId); g_app->GetClientToServer()->SendTeamScore( team->m_teamId, score ); if( score > winningScore ) { winningScore = score; m_winner = team->m_teamId; } } int numPlayers = g_app->GetWorld()->m_teams.Size(); char msg[128]; if( m_winner != -1 ) { strcpy(msg, LANGUAGEPHRASE("message_victory")); LPREPLACESTRINGFLAG( 'T', g_app->GetWorld()->GetTeam(m_winner)->GetTeamName(), msg ); if( m_winner == g_app->GetWorld()->m_myTeamId && numPlayers > 1 ) { } } else { strcpy(msg, LANGUAGEPHRASE("message_stalemate")); m_winner = 999; } strupr(msg); g_app->GetInterface()->ShowMessage( 0, 0, m_winner, msg, true ); g_app->GetMapRenderer()->m_renderEverything = true; for( int i = 0; i < g_app->GetWorld()->m_teams.Size(); ++i ) { g_app->GetWorld()->m_teams[i]->m_desiredGameSpeed = 0; } if( !EclGetWindow( "Stats" ) ) { EclRegisterWindow( new StatsWindow() ); } g_soundSystem->StopAllSounds( SoundObjectId(), "StartMusic StartMusic" ); g_soundSystem->TriggerEvent( "Interface", "GameOver" ); int specVisible = g_app->GetGame()->GetOptionValue("SpectatorChatChannel"); if( specVisible == 0 && g_app->GetWorld()->m_spectators.Size() ) { g_app->GetWorld()->AddChatMessage( -1, CHATCHANNEL_PUBLIC, LANGUAGEPHRASE("message_spectators_chat_players"), -1, false ); } } } } }