id_t Voting::duplicated(const Vote &vote) const { const auto pit(chanidx.equal_range(vote.get_chan_name())); for(auto it(pit.first); it != pit.second; ++it) { const auto id(it->second); const auto vit(votes.find(id)); if(vit == votes.end()) continue; const auto &existing(*vit->second); if(vote.get_id() == existing.get_id()) continue; if(vote.get_type() != existing.get_type()) continue; if(!boost::iequals(vote.get_issue(),existing.get_issue())) continue; return existing.get_id(); }; return 0; }
void Render( int realX, int realY, bool highlighted, bool clicked ) { Image *img = g_resource->GetImage( "gui/tick.bmp" ); Vote *vote = g_app->GetWorld()->m_votingSystem.LookupVote(m_voteId); if( vote && vote->m_result == Vote::VoteUnknown ) { Team *myTeam = g_app->GetWorld()->GetMyTeam(); if( vote->GetRequiredAllianceId() == myTeam->m_allianceId ) { g_renderer->SetBlendMode( Renderer::BlendModeAdditive ); g_renderer->RectFill( realX, realY, m_w, m_h, Colour(100,100,100,50) ); if( highlighted || clicked ) { g_renderer->RectFill( realX, realY, m_w, m_h, Colour(100,100,100,150) ); g_renderer->Blit( img, realX+8, realY+2, 15, 15, Colour(255,255,255,20) ); } if( vote->GetCurrentVote( myTeam->m_teamId ) == m_vote ) { g_renderer->RectFill( realX, realY, m_w, m_h, Colour(100,100,100,150) ); g_renderer->Blit( img, realX+8, realY+2, 15, 15, White ); } g_renderer->Rect( realX, realY, m_w, m_h, Colour(100,100,100,100) ); g_renderer->SetBlendMode( Renderer::BlendModeNormal ); } } }
//Displays the votes of the candidate selected from the combo box void CountDialog::on_search_by_cand_combo_currentIndexChanged(int index) { ui->votes_list->clear(); int size = count->get_candidates().size(); QList<Vote *> votes; int votes_size = 0; QCoreApplication::processEvents(); //It's a candidate if (index > 0 && index <= size) { votes = count->get_candidates().at(index-1)->get_total_votes(); votes_size = votes.size(); Vote *v; VoteListItem *item; for (int j = votes_size-1; j >= 0; j--) { v = votes[j]; item = new VoteListItem(v); item->setText(QString::number(v->get_id())); ui->votes_list->addItem(item); } } //It's the non-transferable not effectives else if (index == size+1) display_non_transferable_votes(); //It should be blank else { ui->votes_list->clear(); } }
void MouseUp() { Vote *vote = g_app->GetWorld()->m_votingSystem.LookupVote(m_voteId); if( vote && vote->m_result == Vote::VoteUnknown ) { Team *myTeam = g_app->GetWorld()->GetMyTeam(); if( vote->GetRequiredAllianceId() == myTeam->m_allianceId ) { g_app->GetClientToServer()->CastVote( myTeam->m_teamId, m_voteId, m_vote ); } } }
void CountDialog::display_non_transferable_votes() { QList<Vote *> nonTs = count->get_nonTransferable_votes_not_effective(); int nonTs_size = nonTs.size(); Vote *v; VoteListItem *item; for (int i = 0; i < nonTs_size; i++) { v = nonTs[i]; item = new VoteListItem(v); item->setText(QString::number(v->get_id())); ui->votes_list->addItem(item); } }
void Voting::call_finish(Vote &vote) noexcept try { vote.finish(); } catch(const std::exception &e) { std::stringstream err; err << "An internal error occurred in Vote::finish(): " << e.what() << "."; std::cerr << "[Voting]: \033[1;31m" << err.str() << "\033[0m" << std::endl; const auto &chans(get_chans()); if(chans.has(vote.get_chan_name())) { Chan &chan(vote.get_chan()); chan << err.str() << chan.flush; } }
void Voting::valid_motion(const Vote &vote) { const auto &cfg(vote.get_cfg()); const auto &user(vote.get_user()); const auto &chan(vote.get_chan()); valid_limits(vote,chan,user); if(!speaker(cfg,chan,user)) throw Exception("You are not able to create votes on this channel."); if(!enfranchised(cfg,chan,user)) throw Exception("You are not yet enfranchised in this channel."); if(!qualified(cfg,chan,user)) throw Exception("You have not been participating enough to start a vote."); const auto now(time(nullptr)); if(cfg.has("limit.motion")) { const auto limit(secs_cast(cfg["limit.motion"])); const Vdb::Terms query { Vdb::Term { "ended", ">=", lex_cast(now - limit) }, Vdb::Term { "issue", "==", vote.get_issue() }, Vdb::Term { "type", "==", vote.get_type() }, Vdb::Term { "chan", "==", chan.get_name() }, }; if(!vdb.query(query,1).empty()) throw Exception("This vote was made within the last ") << secs_cast(limit) << ". Try again later."; } const Adoc reasons(cfg.get_child("limit.reason",Adoc{})); reasons.for_each([this,&chan,&vote,&now] (const std::string &reason, const std::string &limit_str) { if(reason.size() > 64 || !isalpha(reason)) throw Exception("Malformed reason key given in limit.reason"); const auto limit(secs_cast(limit_str)); const Vdb::Terms query { Vdb::Term { "reason", "==", reason }, Vdb::Term { "ended", ">=", lex_cast(now - limit) }, Vdb::Term { "issue", "==", vote.get_issue() }, Vdb::Term { "type", "==", vote.get_type() }, Vdb::Term { "chan", "==", chan.get_name() }, }; if(!vdb.query(query,1).empty()) throw Exception("This vote failed with the reason '") << reason << "' within the last " << secs_cast(limit) << ". Try again later."; }); }
//Finds the vote by id chosen form the list void CountDialog::on_search_by_vote_id_btn_clicked() { bool vote_found = false; QString id_string = ui->search_by_vote_id_spinbox->text(); if (id_string != "" && id_string != "0") { int id = id_string.toInt(); int size = count->get_candidates().size(); QList<Vote *> votes; int votes_size = 0; for (int y = 0; y < size; y++) { votes = count->get_candidates().at(y)->get_total_votes(); votes_size = votes.size(); Vote *v; VoteListItem *item; for (int j = votes_size-1; j >= 0; j--) { v = votes[j]; if (v->get_id() == id) { vote_found = true; ui->votes_list->clear(); item = new VoteListItem(v); item->setText(QString::number(v->get_id())); ui->votes_list->addItem(item); } } } QList<Vote *> nonTs = count->get_nonTransferable_votes_not_effective(); int nonTs_size = nonTs.size(); for (int i = 0; i < nonTs_size; i++) { Vote *v = nonTs[i]; if (v->get_id() == id) { vote_found = true; ui->votes_list->clear(); VoteListItem *item = new VoteListItem(v); item->setText(QString::number(v->get_id())); ui->votes_list->addItem(item); } } if (ui->votes_list->count() == 0) { vote_found = false; } } //If vote doesn't exist, display message box telling the user. if (!vote_found) { QMessageBox box; box.setText("Invalid vote id"); box.exec(); } }
void Voting::valid_limits_type(const Vote &vote, const Chan &chan, const User &user, const Adoc &cfg) { using limits = std::numeric_limits<uint8_t>; if(vote.get_type() == "appeal") return; if(vote.get_type() == "trial") return; auto typcnt(0); for_each(chan,user,[&typcnt,&vote] (const Vote &active) { typcnt += active.get_type() == vote.get_type(); }); if(typcnt > cfg.get<uint8_t>("limit.type",limits::max())) throw Exception("Too many active votes of this type started by you on this channel."); }
void VotingSystem::Update() { if( g_app->GetGame()->m_winner != -1 ) { return; } m_updateTimer += SERVER_ADVANCE_PERIOD; if( m_updateTimer >= 1 ) { m_updateTimer = 0; for( int i = 0; i < m_votes.Size(); ++i ) { if( m_votes.ValidIndex(i) ) { Vote *vote = m_votes[i]; if( vote->m_result == Vote::VoteUnknown ) { vote->m_timer -= 1; int required = vote->GetVotesRequired(); int yes, no, abstain; vote->GetCurrentVote( &yes, &no, &abstain ); if( yes >= required ) { vote->Finish( Vote::VoteYes ); } else if( no >= required || abstain == 0 || vote->m_timer <= 0 ) { vote->Finish( Vote::VoteNo ); } } } } } }
void Voting::valid_limits(const Vote &vote, const Chan &chan, const User &user) { using limits = std::numeric_limits<uint8_t>; if(user.is_myself() || chan.users.mode(user).has('o')) return; const auto &cfg(vote.get_cfg()); if(count(chan) > cfg.get<uint8_t>("limit.active",limits::max())) throw Exception("Too many active votes for this channel."); if(count(chan,user) > cfg.get<uint8_t>("limit.user",limits::max())) throw Exception("Too many active votes started by you on this channel."); valid_limits_type(vote,chan,user,cfg); }
void Voting::cancel(Vote &vote, const Chan &chan, const User &user) { if(user.get_acct() != vote.get_user_acct()) throw Exception() << "You can't cancel a vote by " << vote.get_user_acct() << "."; if(vote.total() > 1) throw Exception("You can't cancel after someone else has voted."); const auto &cfg(vote.get_cfg()); if(!cfg.get("cancel",true)) throw Exception("You can't cancel votes of this type."); vote.cancel(); del(vote.get_id()); }
void AlliancesWindow::Update() { // // Build a list of all teams; LList<Team *> teams; for( int i = 0; i < g_app->GetWorld()->m_teams.Size(); ++i ) { Team *team = g_app->GetWorld()->m_teams[i]; teams.PutData( team ); } // // Now put the other teams in, in alliance order int currentIndex = 0; while( teams.Size() > 0 ) { Team *baseTeam = teams[0]; m_teamOrder[currentIndex] = baseTeam->m_teamId; ++currentIndex; teams.RemoveData(0); for( int i = 0; i < teams.Size(); ++i ) { Team *possibleAlly = teams[i]; if( possibleAlly->m_allianceId == baseTeam->m_allianceId ) { m_teamOrder[currentIndex] = possibleAlly->m_teamId; ++currentIndex; teams.RemoveData(i); --i; } } } // // Are there any votes we can see? for( int i = 0; i < MAX_TEAMS; ++i ) { m_votes[i] = -1; } currentIndex = 0; for( int i = 0; i < g_app->GetWorld()->m_votingSystem.m_votes.Size(); ++i ) { if( g_app->GetWorld()->m_votingSystem.m_votes.ValidIndex(i) ) { Vote *vote = g_app->GetWorld()->m_votingSystem.m_votes[i]; if( vote->m_result == Vote::VoteUnknown && vote->CanSeeVote( g_app->GetWorld()->m_myTeamId ) ) { m_votes[currentIndex] = i; ++currentIndex; } } } // // Make sure we are the right size m_h = 120 + g_app->GetWorld()->m_teams.Size() * 42; m_h += currentIndex * 45; if( currentIndex > 0 ) m_h += 10; m_h = max(m_h, 300 ); GetButton("Close")->m_y = m_h - 25; }
void Render( int realX, int realY, bool highlighted, bool clicked ) { AlliancesWindow *parent = (AlliancesWindow *)m_parent; int voteId = parent->m_votes[m_voteIndex]; Vote *vote = g_app->GetWorld()->m_votingSystem.LookupVote( voteId ); Team *myTeam = g_app->GetWorld()->GetMyTeam(); if( vote ) { g_renderer->RectFill( realX, realY, m_w, m_h, Colour(10,10,50,200) ); Colour borderCol(255,255,255,100); if( highlighted || clicked ) { borderCol.m_a = 255; g_renderer->RectFill( realX, realY, m_w, m_h, Colour(100,100,150,100) ); } g_renderer->Rect( realX, realY, m_w, m_h, borderCol ); switch( vote->m_voteType ) { case Vote::VoteTypeJoinAlliance: if( myTeam->m_teamId == vote->m_createTeamId ) { char *allianceName = g_app->GetWorld()->GetAllianceName(vote->m_voteData); g_renderer->TextSimple( realX+10, realY+5, White, 14, LANGUAGEPHRASE("dialog_you_requested_alliance_1") ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_you_requested_alliance_2") ); LPREPLACESTRINGFLAG( 'A', allianceName, caption ); g_renderer->TextSimple( realX+10, realY+20, White, 14, caption ); } else { Team *team = g_app->GetWorld()->GetTeam( vote->m_createTeamId ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_requested_alliance_1") ); LPREPLACESTRINGFLAG( 'T', team->m_name, caption ); g_renderer->TextSimple( realX+10, realY+5, White, 15, caption ); g_renderer->TextSimple( realX+10, realY+20, White, 15, LANGUAGEPHRASE("dialog_requested_alliance_2") ); } break; case Vote::VoteTypeKickPlayer: { Team *kickTeam = g_app->GetWorld()->GetTeam(vote->m_voteData); if( myTeam->m_teamId == vote->m_createTeamId ) { g_renderer->TextSimple( realX+10, realY+5, White, 15, LANGUAGEPHRASE("dialog_you_requested_kick_1") ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_you_requested_kick_2") ); LPREPLACESTRINGFLAG( 'T', kickTeam->m_name, caption ); g_renderer->TextSimple( realX+10, realY+20, White, 15, caption ); } else { Team *team = g_app->GetWorld()->GetTeam( vote->m_createTeamId ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_requested_kick_1") ); LPREPLACESTRINGFLAG( 'T', team->m_name, caption ); g_renderer->TextSimple( realX+10, realY+5, White, 15, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_requested_kick_2") ); LPREPLACESTRINGFLAG( 'T', kickTeam->m_name, caption ); g_renderer->TextSimple( realX+10, realY+20, White, 15, caption ); } break; } } int yes, no, abstain; vote->GetCurrentVote( &yes, &no, &abstain ); g_renderer->Text( realX + 190, realY + 12, White, 17, "%ds", int(vote->m_timer) ); g_renderer->TextSimple( realX + m_w - 70, realY + 5, White, 10, LANGUAGEPHRASE("dialog_vote_yes") ); g_renderer->TextSimple( realX + m_w - 70, realY + 15, White, 10, LANGUAGEPHRASE("dialog_vote_no") ); g_renderer->TextSimple( realX + m_w - 70, realY + 25, White, 10, LANGUAGEPHRASE("dialog_vote_abstain") ); g_renderer->Text( realX + m_w - 20, realY + 5, White, 10, "%d", yes ); g_renderer->Text( realX + m_w - 20, realY + 15, White, 10, "%d", no ); g_renderer->Text( realX + m_w - 20, realY + 25, White, 10, "%d", abstain ); } }
void VotingWindow::Render( bool _hasFocus ) { InterfaceWindow::Render( _hasFocus ); Vote *vote = g_app->GetWorld()->m_votingSystem.LookupVote(m_voteId); if( vote ) { Team *myTeam = g_app->GetWorld()->GetMyTeam(); switch( vote->m_voteType ) { case Vote::VoteTypeJoinAlliance: if( myTeam->m_teamId == vote->m_createTeamId ) { char *allianceName = g_app->GetWorld()->GetAllianceName(vote->m_voteData); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+30, White, 20, LANGUAGEPHRASE("dialog_you_requested_alliance_1") ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_you_requested_alliance_2") ); LPREPLACESTRINGFLAG( 'A', allianceName, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+50, White, 20, caption ); } else if( myTeam->m_allianceId == vote->m_voteData ) { Team *team = g_app->GetWorld()->GetTeam( vote->m_createTeamId ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_requested_alliance_1") ); LPREPLACESTRINGFLAG( 'T', team->m_name, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+30, White, 20, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+50, White, 20, LANGUAGEPHRASE("dialog_requested_alliance_2") ); } break; case Vote::VoteTypeKickPlayer: { Team *kickTeam = g_app->GetWorld()->GetTeam(vote->m_voteData); if( myTeam->m_teamId == vote->m_createTeamId ) { g_renderer->TextCentreSimple( m_x+m_w/2, m_y+30, White, 20, LANGUAGEPHRASE("dialog_you_requested_kick_1") ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_you_requested_kick_2") ); LPREPLACESTRINGFLAG( 'T', kickTeam->m_name, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+50, White, 20, caption ); } else if( myTeam->m_allianceId == kickTeam->m_allianceId && myTeam->m_teamId != kickTeam->m_teamId ) { Team *team = g_app->GetWorld()->GetTeam( vote->m_createTeamId ); char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_requested_kick_1") ); LPREPLACESTRINGFLAG( 'T', team->m_name, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+30, White, 20, caption ); sprintf( caption, LANGUAGEPHRASE("dialog_requested_kick_2") ); LPREPLACESTRINGFLAG( 'T', kickTeam->m_name, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y+50, White, 20, caption ); } break; } } g_renderer->SetFont( "kremlin" ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + 90, White, 20, LANGUAGEPHRASE("dialog_vote_yes") ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + 120, White, 20, LANGUAGEPHRASE("dialog_vote_no") ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + 150, White, 20, LANGUAGEPHRASE("dialog_vote_abstain") ); g_renderer->SetFont(); int yes, no, abstain; vote->GetCurrentVote( &yes, &no, &abstain ); g_renderer->Text( m_x + m_w - 40, m_y + 90, White, 20, "%d", yes ); g_renderer->Text( m_x + m_w - 40, m_y + 120, White, 20, "%d", no ); g_renderer->Text( m_x + m_w - 40, m_y + 150, White, 20, "%d", abstain ); if( vote->m_result == Vote::VoteUnknown ) { char caption[512]; sprintf( caption, LANGUAGEPHRASE("dialog_vote_seconds_to_vote") ); LPREPLACEINTEGERFLAG( 'S', (int) vote->m_timer, caption ); g_renderer->TextCentreSimple( m_x + m_w/2, m_y + m_h - 70, White, 15, caption ); int votesRequired = vote->GetVotesRequired(); sprintf( caption, LANGUAGEPHRASE("dialog_vote_number_votes_required") ); LPREPLACEINTEGERFLAG( 'V', votesRequired, caption ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y + m_h - 50, White, 15, caption ); } else if( vote->m_result == Vote::VoteYes ) { g_renderer->SetFont( "kremlin" ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y + m_h - 70, White, 30, LANGUAGEPHRASE("dialog_vote_succeeded") ); g_renderer->SetFont(); } else if( vote->m_result == Vote::VoteNo ) { g_renderer->SetFont( "kremlin" ); g_renderer->TextCentreSimple( m_x+m_w/2, m_y + m_h - 70, White, 30, LANGUAGEPHRASE("dialog_vote_failed") ); g_renderer->SetFont(); } } }