62 struct packet_vote_new packet;
65 if (pvote ==
nullptr) {
70 if (pconn ==
nullptr) {
76 packet.vote_no = pvote->
vote_no;
80 packet.percent_required = 100 * pvote->
need_pc;
81 packet.flags = pvote->
flags;
83 if (dest ==
nullptr) {
92 send_packet_vote_new(conn, &packet);
103 struct packet_vote_update packet;
106 if (pvote ==
nullptr) {
111 if (pconn ==
nullptr) {
117 packet.vote_no = pvote->
vote_no;
118 packet.yes = pvote->
yes;
119 packet.no = pvote->
no;
120 packet.abstain = pvote->
abstain;
121 packet.num_voters = num_voters;
123 if (dest ==
nullptr) {
132 send_packet_vote_update(aconn, &packet);
142 struct packet_vote_remove packet;
148 packet.vote_no = pvote->
vote_no;
150 if (dest ==
nullptr) {
164 struct packet_vote_resolve packet;
170 packet.vote_no = pvote->
vote_no;
171 packet.passed = passed;
173 if (dest ==
nullptr) {
182 send_packet_vote_resolve(pconn, &packet);
258 const struct player *pplayer, *caller_plr;
262 if (!pplayer || !caller_plr
275 const struct vote *pvote)
287 const struct player *pplayer, *caller_plr;
291 if (!pplayer || !caller_plr
311 if (pvote->vote_no ==
vote_no) {
331 if (pvote->caller_id == caller->
id) {
364 if (allargs !=
nullptr && allargs[0] !=
'\0') {
380 double min_pc = 1.0 / qMax(
static_cast<double>(num_voters), 1.0);
382 if (num_voters > 1 && min_pc > pvote->
need_pc) {
399 struct vote virtual_vote;
408 memset(&virtual_vote, 0,
sizeof(virtual_vote));
429 int num_cast = 0, num_voters = 0;
430 bool resolve =
false, passed =
false;
432 double yes_pc = 0.0, no_pc = 0.0, rem_pc = 0.0,
base = 0.0;
436 const double MY_EPSILON = 0.000001;
438 const struct player *callplr;
458 switch (pvc->vote_cast) {
472 qCritical(
"Unknown vote cast variant: %d.", pvc->vote_cast);
481 if (num_voters > 0) {
486 if (
base > MY_EPSILON) {
487 yes_pc =
static_cast<double>(pvote->
yes) /
base;
488 no_pc =
static_cast<double>(pvote->
no) /
base;
491 rem_pc =
static_cast<double>(num_voters - num_cast) /
base;
500 (yes_pc - need_pc > MY_EPSILON)
502 || (no_pc - 1.0 + need_pc > MY_EPSILON
503 || fabs(no_pc - 1.0 + need_pc) < MY_EPSILON)
505 || (no_pc + rem_pc - 1.0 + need_pc < -MY_EPSILON)
507 || (yes_pc + rem_pc - need_pc < -MY_EPSILON
508 || fabs(yes_pc + rem_pc - need_pc) < MY_EPSILON));
512 if (!resolve && fabs(rem_pc) < MY_EPSILON) {
522 if (!resolve && fabs(
base) < MY_EPSILON) {
527 log_debug(
"check_vote flags=%d need_pc=%0.2f yes_pc=%0.2f "
528 "no_pc=%0.2f rem_pc=%0.2f base=%0.2f resolve=%d",
529 flags, need_pc, yes_pc, no_pc, rem_pc,
base, resolve);
537 passed = yes_pc - need_pc > MY_EPSILON;
540 passed = fabs(no_pc) < MY_EPSILON;
547 title =
_(
"Teamvote");
559 _(
"%s %d \"%s\" is passed %d to %d with "
560 "%d abstentions and %d who did not vote."),
562 pvote->
abstain, num_voters - num_cast);
566 _(
"%s %d \"%s\" failed with %d against, %d for, "
567 "%d abstentions and %d who did not vote."),
569 pvote->
abstain, num_voters - num_cast);
577 qCritical(
"Got a vote from a lost connection");
580 qCritical(
"Got a vote from a non-voting connection");
584 switch (pvc->vote_cast) {
587 _(
"%s %d: %s voted yes."), title, pvote->
vote_no,
592 _(
"%s %d: %s voted no."), title, pvote->
vote_no,
597 _(
"%s %d: %s chose to abstain."), title, pvote->
vote_no,
653 vote_cast_list_append(pvote->
votes_cast, pvc);
663 if (!pvote || !pvc) {
667 vote_cast_list_remove(pvote->
votes_cast, pvc);
692 qCritical(
"Failed to create a vote cast for connection %s.",
734 qCritical(
"voting_turn() called before voting_init()");
774 _(
"%s (needs %0.0f%% and no dissent)."), pvote->
cmdline,
780 _(
"%s (needs %0.0f%% in favor)."), pvote->
cmdline,
800 if (pvote ==
nullptr) {
803 qDebug(
"Submit request for unknown vote_no %d from %s ignored.",
vote_no,
810 }
else if (value == -1) {
812 }
else if (value == 0) {
815 qCritical(
"Invalid packet data for submit of vote %d "
835 log_debug(
"Sending %s running votes to %s.",
846 }
else if (!only_team_votes) {
866 log_debug(
"Sending remove info of the team votes to %s.",
892 log_debug(
"Sending updated vote totals to conn_list %p", dest);
894 if (dest ==
nullptr) {
const char * command_name(const struct command *pcommand)
Return name of the command.
int command_vote_percent(const struct command *pcommand)
Returns the vote percent required for this command to pass in a vote.
const struct command * command_by_number(int i)
Return command by its number.
int command_vote_flags(const struct command *pcommand)
Returns a bit-wise combination of all vote flags set for this command.
void conn_list_do_unbuffer(struct conn_list *dest)
Convenience functions to unbuffer a list of connections.
struct player * conn_get_player(const struct connection *pconn)
Returns the player that this connection is attached to, or nullptr.
const char * conn_description(const struct connection *pconn, bool is_private)
° Return pointer to static string containing a description for this ° connection, based on pconn->nam...
void conn_list_do_buffer(struct conn_list *dest)
Convenience functions to buffer a list of connections.
void connection_do_buffer(struct connection *pc)
Turn on buffering, using a counter so that calls may be nested.
bool conn_controls_player(const struct connection *pconn)
Returns TRUE if the given connection is attached to a player which it also controls (i....
bool conn_is_global_observer(const struct connection *pconn)
Returns TRUE if the given connection is a global observer.
struct connection * conn_by_number(int id)
Find connection by id, from game.all_connections.
enum cmdlevel conn_get_access(const struct connection *pconn)
Returns the current access level of the given connection.
void connection_do_unbuffer(struct connection *pc)
Turn off buffering if internal counter of number of times buffering was turned on falls to zero,...
#define conn_list_iterate(connlist, pconn)
#define conn_list_iterate_end
#define MAX_LEN_CONSOLE_LINE
static void base(QVariant data1, QVariant data2)
Action "Build Base" for choice dialog.
const struct ft_color ftc_vote_abstain
const struct ft_color ftc_vote_failed
const struct ft_color ftc_vote_yes
const struct ft_color ftc_vote_no
const struct ft_color ftc_vote_passed
#define fc_assert(condition)
#define log_debug(message,...)
void notify_team(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Sends a message to all players on pplayer's team.
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Return TRUE if players are in the same team.
bool handle_stdin_input(struct connection *caller, char *str)
Main entry point for "command input".
struct conn_list * est_connections
char username[MAX_LEN_NAME]
struct vote_cast_list * votes_cast
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
#define sz_strlcpy(dest, src)
#define sz_strlcat(dest, src)
void send_running_votes(struct connection *pconn, bool only_team_votes)
Sends a packet_vote_new to pconn for every currently running votes.
static void lsend_vote_new(struct conn_list *dest, struct vote *pvote)
Tell clients that a new vote has been created.
void send_remove_team_votes(struct connection *pconn)
Sends a packet_vote_remove to pconn for every currently running team vote 'pconn' can see.
int describe_vote(struct vote *pvote, char *buf, int buflen)
Fills the supplied buffer with a string describing the given vote.
struct vote * vote_new(struct connection *caller, const char *allargs, int command_id)
Create and return a newly allocated vote for the command with id 'command_id' and all arguments in th...
static void lsend_vote_remove(struct conn_list *dest, struct vote *pvote)
Tell clients that the given vote no longer exists.
void voting_turn()
Check running votes.
bool conn_can_vote(const struct connection *pconn, const struct vote *pvote)
A user cannot vote if: is not connected access level < basic isn't a player the vote is a team vote a...
const struct connection * vote_get_caller(const struct vote *pvote)
Returns the connection that called this vote.
static void check_vote(struct vote *pvote)
Check if we satisfy the criteria for resolving a vote, and resolve it if these critera are indeed met...
bool vote_is_team_only(const struct vote *pvote)
Returns TRUE if this vote is a "teamvote".
void cancel_connection_votes(struct connection *pconn)
Cancel the votes of a lost or a detached connection.
bool vote_would_pass_immediately(const struct connection *caller, int command_id)
Return whether the vote would pass immediately when the caller will vote for.
void send_updated_vote_totals(struct conn_list *dest)
Sends a packet_vote_update to every conn in dest.
void voting_free()
Free all memory used by this module.
void handle_vote_submit(struct connection *pconn, int vote_no, int value)
Handle a vote submit packet sent from a client.
static void lsend_vote_resolve(struct conn_list *dest, struct vote *pvote, bool passed)
Tell clients that the given vote resolved.
static struct vote_cast * vote_cast_find(struct vote *pvote, int conn_id)
Find the vote cast for the user id conn_id in a vote.
static void lsend_vote_update(struct conn_list *dest, struct vote *pvote, int num_voters)
Send updated status information about the given vote.
static void free_vote(struct vote *pvote)
Free all memory used by the vote structure.
void connection_vote(struct connection *pconn, struct vote *pvote, enum vote_type type)
Make the given connection vote 'type' on 'pvote', and check the vote.
static struct vote_cast * vote_cast_new(struct vote *pvote)
Return a new vote cast.
struct vote_list * vote_list
struct vote * get_vote_by_caller(const struct connection *caller)
Returns the vote called by 'caller', or nullptr if none exists.
int count_voters(const struct vote *pvote)
Helper function that returns the current number of eligible voters.
void clear_all_votes()
Remove all votes.
static void remove_vote_cast(struct vote *pvote, struct vote_cast *pvc)
Remove a vote cast.
void voting_init()
Initialize data structures used by this module.
void remove_vote(struct vote *pvote)
Remove the given vote and send a vote_remove packet to clients.
struct vote * get_vote_by_no(int vote_no)
Returns the vote with vote number 'vote_no', or nullptr.
bool conn_can_see_vote(const struct connection *pconn, const struct vote *pvote)
Usually, all users can see, except in the team vote case.
#define vote_list_iterate_end
#define vote_cast_list_iterate(alist, pvc)
#define vote_list_iterate(alist, pvote)
#define vote_cast_list_iterate_end