Freeciv-3.2
Loading...
Searching...
No Matches
voting.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <math.h>
19
20/* utility */
21#include "fcintl.h"
22#include "log.h"
23#include "support.h"
24
25/* common */
26#include "capability.h"
27#include "connection.h"
28#include "packets.h"
29#include "player.h"
30
31/* server */
32#include "commands.h"
33#include "console.h"
34#include <hand_gen.h> /* <> so looked from the build directory first. */
35#include "notify.h"
36#include "settings.h"
37#include "stdinhand.h"
38
39#include "voting.h"
40
43
44
45/**********************************************************************/
48int count_voters(const struct vote *pvote)
49{
50 int num_voters = 0;
51
54 num_voters++;
55 }
57
58 return num_voters;
59}
60
61/**********************************************************************/
64static void lsend_vote_new(struct conn_list *dest, struct vote *pvote)
65{
66 struct packet_vote_new packet;
67 struct connection *pconn;
68
69 if (pvote == NULL) {
70 return;
71 }
72
73 pconn = conn_by_number(pvote->caller_id);
74 if (pconn == NULL) {
75 return;
76 }
77
78 log_debug("lsend_vote_new %p (%d) --> %p", pvote, pvote->vote_no, dest);
79
80 packet.vote_no = pvote->vote_no;
81 sz_strlcpy(packet.user, pconn->username);
82 describe_vote(pvote, packet.desc, sizeof(packet.desc));
83
84 packet.percent_required = 100 * pvote->need_pc;
85 packet.flags = pvote->flags;
86
87 if (dest == NULL) {
88 dest = game.est_connections;
89 }
90
91 conn_list_iterate(dest, conn) {
92 if (!conn_can_see_vote(conn, pvote)) {
93 continue;
94 }
95 send_packet_vote_new(conn, &packet);
97}
98
99/**********************************************************************/
102static void lsend_vote_update(struct conn_list *dest, struct vote *pvote,
103 int num_voters)
104{
105 struct packet_vote_update packet;
106 struct connection *pconn;
107
108 if (pvote == NULL) {
109 return;
110 }
111
112 pconn = conn_by_number(pvote->caller_id);
113 if (pconn == NULL) {
114 return;
115 }
116
117 log_debug("lsend_vote_update %p (%d) --> %p", pvote, pvote->vote_no, dest);
118
119 packet.vote_no = pvote->vote_no;
120 packet.yes = pvote->yes;
121 packet.no = pvote->no;
122 packet.abstain = pvote->abstain;
123 packet.num_voters = num_voters;
124
125 if (dest == NULL) {
126 dest = game.est_connections;
127 }
128
129 conn_list_iterate(dest, aconn) {
131 continue;
132 }
135}
136
137/**********************************************************************/
140static void lsend_vote_remove(struct conn_list *dest, struct vote *pvote)
141{
142 struct packet_vote_remove packet;
143
144 if (!pvote) {
145 return;
146 }
147
148 packet.vote_no = pvote->vote_no;
149
150 if (dest == NULL) {
151 dest = game.est_connections;
152 }
153
154 conn_list_iterate(dest, pconn) {
157}
158
159/**********************************************************************/
162static void lsend_vote_resolve(struct conn_list *dest,
163 struct vote *pvote, bool passed)
164{
165 struct packet_vote_resolve packet;
166
167 if (!pvote) {
168 return;
169 }
170
171 packet.vote_no = pvote->vote_no;
172 packet.passed = passed;
173
174 if (dest == NULL) {
175 dest = game.est_connections;
176 }
177
178 conn_list_iterate(dest, pconn) {
180 continue;
181 }
184}
185
186/**********************************************************************/
189static void free_vote(struct vote *pvote)
190{
191 if (!pvote) {
192 return;
193 }
194
195 vote_cast_list_iterate(pvote->votes_cast, pvc) {
196 free(pvc);
198 vote_cast_list_destroy(pvote->votes_cast);
199 free(pvote);
200}
201
202/**********************************************************************/
205void remove_vote(struct vote *pvote)
206{
207 if (!vote_list || !pvote) {
208 return;
209 }
210
214}
215
216/**********************************************************************/
220{
221 if (!vote_list) {
222 return;
223 }
224
230}
231
232/**********************************************************************/
235bool vote_is_team_only(const struct vote *pvote)
236{
237 return pvote && (pvote->flags & VCF_TEAMONLY);
238}
239
240/**********************************************************************/
248bool conn_can_vote(const struct connection *pconn, const struct vote *pvote)
249{
252 return FALSE;
253 }
254
256 const struct player *pplayer, *caller_plr;
257
258 pplayer = conn_get_player(pconn);
260 if (!pplayer || !caller_plr
261 || !players_on_same_team(pplayer, caller_plr)) {
262 return FALSE;
263 }
264 }
265
266 return TRUE;
267}
268
269/**********************************************************************/
273 const struct vote *pvote)
274{
275 if (!pconn) {
276 return FALSE;
277 }
278
280 /* All is visible for global observer. */
281 return TRUE;
282 }
283
285 const struct player *pplayer, *caller_plr;
286
287 pplayer = conn_get_player(pconn);
289 if (!pplayer || !caller_plr
290 || !players_on_same_team(pplayer, caller_plr)) {
291 return FALSE;
292 }
293 }
294
295 return TRUE;
296}
297
298/**********************************************************************/
302{
303 if (!vote_list) {
304 return NULL;
305 }
306
308 if (pvote->vote_no == vote_no) {
309 return pvote;
310 }
312
313 return NULL;
314}
315
316/**********************************************************************/
319struct vote *get_vote_by_caller(const struct connection *caller)
320{
321 if (caller == NULL || !vote_list) {
322 return NULL;
323 }
324
326 if (pvote->caller_id == caller->id) {
327 return pvote;
328 }
330
331 return NULL;
332}
333
334/**********************************************************************/
338struct vote *vote_new(struct connection *caller,
339 const char *allargs,
340 int command_id)
341{
342 struct vote *pvote;
343 const struct command *pcmd;
344
345 if (!conn_can_vote(caller, NULL)) {
346 return NULL;
347 }
348
349 /* Cancel previous vote */
351
352 /* Make a new vote */
353 pvote = fc_malloc(sizeof(struct vote));
354 pvote->caller_id = caller->id;
355 pvote->command_id = command_id;
357
358 sz_strlcpy(pvote->cmdline, command_name(pcmd));
359 if (allargs != NULL && allargs[0] != '\0') {
360 sz_strlcat(pvote->cmdline, " ");
361 sz_strlcat(pvote->cmdline, allargs);
362 }
363
364 pvote->turn_count = 0;
365 pvote->votes_cast = vote_cast_list_new();
366 pvote->vote_no = ++vote_number_sequence;
367
369
370 pvote->flags = command_vote_flags(pcmd);
371 pvote->need_pc = (double) command_vote_percent(pcmd) / 100.0;
372
373 if (pvote->flags & VCF_NOPASSALONE) {
374 int num_voters = count_voters(pvote);
375 double min_pc = 1.0 / (double) num_voters;
376
377 if (num_voters > 1 && min_pc > pvote->need_pc) {
378 pvote->need_pc = MIN(0.5, 2.0 * min_pc);
379 }
380 }
381
383
384 return pvote;
385}
386
387/**********************************************************************/
391bool vote_would_pass_immediately(const struct connection *caller,
392 int command_id)
393{
394 struct vote virtual_vote;
395 const struct command *pcmd;
396
397 if (!conn_can_vote(caller, NULL)) {
398 return FALSE;
399 }
400
402 fc_assert(pcmd != NULL);
403 memset(&virtual_vote, 0, sizeof(virtual_vote));
405
406 if (virtual_vote.flags & VCF_NOPASSALONE) {
407 return FALSE;
408 }
409
410 virtual_vote.caller_id = caller->id;
411 return (((double) (command_vote_percent(pcmd)
412 * count_voters(&virtual_vote)) / 100.0) < 1.0);
413}
414
415/**********************************************************************/
420static void check_vote(struct vote *pvote)
421{
422 int num_cast = 0, num_voters = 0;
423 bool resolve = FALSE, passed = FALSE;
424 struct connection *pconn = NULL;
425 double yes_pc = 0.0, no_pc = 0.0, rem_pc = 0.0, base = 0.0;
426 int flags;
427 double need_pc;
428 char cmdline[MAX_LEN_CONSOLE_LINE];
429 const double MY_EPSILON = 0.000001;
430 const char *title;
431 const struct player *callplr;
432
433 if (!pvote) {
434 return;
435 }
436
437 pvote->yes = 0;
438 pvote->no = 0;
439 pvote->abstain = 0;
440
441 num_voters = count_voters(pvote);
442
443 vote_cast_list_iterate(pvote->votes_cast, pvc) {
444 if (!(pconn = conn_by_number(pvc->conn_id))
445 || !conn_can_vote(pconn, pvote)) {
446 continue;
447 }
448 num_cast++;
449
450 switch (pvc->vote_cast) {
451 case VOTE_YES:
452 pvote->yes++;
453 continue;
454 case VOTE_NO:
455 pvote->no++;
456 continue;
457 case VOTE_ABSTAIN:
458 pvote->abstain++;
459 continue;
460 case VOTE_NUM:
461 break;
462 }
463
464 log_error("Unknown vote cast variant: %d.", pvc->vote_cast);
465 pvote->abstain++;
467
468 flags = pvote->flags;
469 need_pc = pvote->need_pc;
470
471 /* Check if we should resolve the vote. */
472 if (num_voters > 0) {
473
474 /* Players that abstain essentially remove themselves from
475 * the voting pool. */
476 base = num_voters - pvote->abstain;
477
478 if (base > MY_EPSILON) {
479 yes_pc = (double) pvote->yes / base;
480 no_pc = (double) pvote->no / base;
481
482 /* The fraction of people who have not voted at all. */
483 rem_pc = (double) (num_voters - num_cast) / base;
484 }
485
486 if (flags & VCF_NODISSENT && no_pc > MY_EPSILON) {
487 resolve = TRUE;
488 }
489
490 if (!resolve) {
491 resolve = (/* We have enough yes votes. */
492 (yes_pc - need_pc > MY_EPSILON)
493 /* We have too many no votes. */
494 || (no_pc - 1.0 + need_pc > MY_EPSILON
495 || fabs(no_pc - 1.0 + need_pc) < MY_EPSILON)
496 /* We can't get enough no votes. */
497 || (no_pc + rem_pc - 1.0 + need_pc < -MY_EPSILON)
498 /* We can't get enough yes votes. */
499 || (yes_pc + rem_pc - need_pc < -MY_EPSILON
500 || fabs(yes_pc + rem_pc - need_pc) < MY_EPSILON));
501 }
502
503 /* Resolve if everyone voted already. */
504 if (!resolve && fabs(rem_pc) < MY_EPSILON) {
505 resolve = TRUE;
506 }
507
508 /* Resolve this vote if it has been around long enough. */
509 if (!resolve && pvote->turn_count > 1) {
510 resolve = TRUE;
511 }
512
513 /* Resolve this vote if everyone tries to abstain. */
514 if (!resolve && fabs(base) < MY_EPSILON) {
515 resolve = TRUE;
516 }
517 }
518
519 log_debug("check_vote flags=%d need_pc=%0.2f yes_pc=%0.2f "
520 "no_pc=%0.2f rem_pc=%0.2f base=%0.2f resolve=%d",
521 flags, need_pc, yes_pc, no_pc, rem_pc, base, resolve);
522
523 lsend_vote_update(NULL, pvote, num_voters);
524
525 if (!resolve) {
526 return;
527 }
528
529 passed = yes_pc - need_pc > MY_EPSILON;
530
531 if (passed && flags & VCF_NODISSENT) {
532 passed = fabs(no_pc) < MY_EPSILON;
533 }
534
536 const struct connection *caller;
537
538 /* TRANS: "Vote" as a process. Used as part of a sentence. */
539 title = _("Teamvote");
540 caller = vote_get_caller(pvote);
541 callplr = conn_get_player(caller);
542 } else {
543 /* TRANS: "Vote" as a process. Used as part of a sentence. */
544 title = _("Vote");
545 callplr = NULL;
546 }
547
548 if (passed) {
550 /* TRANS: "[Vote|Teamvote] 3 \"proposed change\" is ..." */
551 _("%s %d \"%s\" is passed %d to %d with "
552 "%d abstentions and %d who did not vote."),
553 title, pvote->vote_no, pvote->cmdline, pvote->yes,
554 pvote->no, pvote->abstain, num_voters - num_cast);
555 } else {
557 /* TRANS: "[Vote|Teamvote] 3 \"proposed change\" failed ..." */
558 _("%s %d \"%s\" failed with %d against, %d for, "
559 "%d abstentions and %d who did not vote."),
560 title, pvote->vote_no, pvote->cmdline, pvote->no,
561 pvote->yes, pvote->abstain, num_voters - num_cast);
562 }
563
564 lsend_vote_resolve(NULL, pvote, passed);
565
566 vote_cast_list_iterate(pvote->votes_cast, pvc) {
567 if (!(pconn = conn_by_number(pvc->conn_id))) {
568 log_error("Got a vote from a lost connection");
569 continue;
570 } else if (!conn_can_vote(pconn, pvote)) {
571 log_error("Got a vote from a non-voting connection");
572 continue;
573 }
574
575 switch (pvc->vote_cast) {
576 case VOTE_YES:
578 _("%s %d: %s voted yes."),
579 title, pvote->vote_no, pconn->username);
580 break;
581 case VOTE_NO:
583 _("%s %d: %s voted no."),
584 title, pvote->vote_no, pconn->username);
585 break;
586 case VOTE_ABSTAIN:
588 _("%s %d: %s chose to abstain."),
589 title, pvote->vote_no, pconn->username);
590 break;
591 default:
592 break;
593 }
595
596 /* Remove the vote before executing the command because it's the
597 * cause of many crashes due to the /cut command:
598 * - If the caller is the target.
599 * - If the target votes on this vote. */
600 sz_strlcpy(cmdline, pvote->cmdline);
602
603 if (passed) {
604 handle_stdin_input(NULL, cmdline);
605 }
606}
607
608/**********************************************************************/
611static struct vote_cast *vote_cast_find(struct vote *pvote, int conn_id)
612{
613 if (!pvote) {
614 return NULL;
615 }
616
617 vote_cast_list_iterate(pvote->votes_cast, pvc) {
618 if (pvc->conn_id == conn_id) {
619 return pvc;
620 }
622
623 return NULL;
624}
625
626/**********************************************************************/
629static struct vote_cast *vote_cast_new(struct vote *pvote)
630{
631 struct vote_cast *pvc;
632
633 if (!pvote) {
634 return NULL;
635 }
636
637 pvc = fc_malloc(sizeof(struct vote_cast));
638 pvc->conn_id = -1;
639 pvc->vote_cast = VOTE_ABSTAIN;
640
641 vote_cast_list_append(pvote->votes_cast, pvc);
642
643 return pvc;
644}
645
646/**********************************************************************/
649static void remove_vote_cast(struct vote *pvote, struct vote_cast *pvc)
650{
651 if (!pvote || !pvc) {
652 return;
653 }
654
655 vote_cast_list_remove(pvote->votes_cast, pvc);
656 free(pvc);
657 check_vote(pvote); /* Maybe can pass */
658}
659
660/**********************************************************************/
664 struct vote *pvote,
665 enum vote_type type)
666{
667 struct vote_cast *pvc;
668
669 if (!conn_can_vote(pconn, pvote)) {
670 return;
671 }
672
673 /* Try to find a previous vote */
674 if ((pvc = vote_cast_find(pvote, pconn->id))) {
675 pvc->vote_cast = type;
676 } else if ((pvc = vote_cast_new(pvote))) {
677 pvc->vote_cast = type;
678 pvc->conn_id = pconn->id;
679 } else {
680 /* Must never happen */
681 log_error("Failed to create a vote cast for connection %s.",
682 pconn->username);
683 return;
684 }
686}
687
688/**********************************************************************/
703
704/**********************************************************************/
707void voting_init(void)
708{
709 if (!vote_list) {
712 }
713}
714
715/**********************************************************************/
718void voting_turn(void)
719{
720 if (!vote_list) {
721 log_error("voting_turn() called before voting_init()");
722 return;
723 }
724
726 pvote->turn_count++;
729}
730
731/**********************************************************************/
734void voting_free(void)
735{
737 if (vote_list) {
739 vote_list = NULL;
740 }
741}
742
743/**********************************************************************/
748int describe_vote(struct vote *pvote, char *buf, int buflen)
749{
750 int ret = 0;
751
752 /* NB We don't handle votes with multiple flags here. */
753
754 if (pvote->flags & VCF_NODISSENT) {
756 /* TRANS: Describing a new vote that can only pass
757 * if there are no dissenting votes. */
758 _("%s (needs %0.0f%% and no dissent)."),
759 pvote->cmdline, MIN(100.0, pvote->need_pc * 100.0 + 1));
760 } else {
762 /* TRANS: Describing a new vote that can pass only if the
763 * given percentage of players votes 'yes'. */
764 _("%s (needs %0.0f%% in favor)."),
765 pvote->cmdline, MIN(100.0, pvote->need_pc * 100.0 + 1));
766 }
767
768 return ret;
769}
770
771/**********************************************************************/
775void handle_vote_submit(struct connection *pconn, int vote_no, int value)
776{
777 struct vote *pvote;
778 enum vote_type type;
779
780 log_debug("Got vote submit (%d %d) from %s.",
782
784 if (pvote == NULL) {
785 /* The client is out of synchronization: this vote is probably just
786 * resolved or cancelled. Not an error, let's just ignore the packet. */
787 log_verbose("Submit request for unknown vote_no %d from %s ignored.",
789 return;
790 }
791
792 if (value == 1) {
793 type = VOTE_YES;
794 } else if (value == -1) {
795 type = VOTE_NO;
796 } else if (value == 0) {
798 } else {
799 log_error("Invalid packet data for submit of vote %d "
800 "from %s ignored.", vote_no, conn_description(pconn));
801 return;
802 }
803
805}
806
807/**********************************************************************/
811{
812 if (NULL == vote_list
814 || NULL == pconn
816 return;
817 }
818
819 log_debug("Sending %s running votes to %s.",
820 only_team_votes ? "team" : "all", conn_description(pconn));
821
826 lsend_vote_new(pconn->self, pvote);
828 }
829 } else if (!only_team_votes) {
830 lsend_vote_new(pconn->self, pvote);
832 }
835}
836
837/**********************************************************************/
842{
843 if (NULL == vote_list
845 || NULL == pconn
846 || NULL == conn_get_player(pconn)) {
847 return;
848 }
849
850 log_debug("Sending remove info of the team votes to %s.",
852
857 }
860}
861
862/**********************************************************************/
867{
868 int num_voters;
869
870 if (vote_list == NULL || vote_list_size(vote_list) <= 0) {
871 return;
872 }
873
874 log_debug("Sending updated vote totals to conn_list %p", dest);
875
876 if (dest == NULL) {
877 dest = game.est_connections;
878 }
879
882 num_voters = count_voters(pvote);
883 lsend_vote_update(dest, pvote, num_voters);
886}
887
888/**********************************************************************/
891const struct connection *vote_get_caller(const struct vote *pvote)
892{
893 return conn_by_number(pvote->caller_id);
894}
const char * command_name(const struct command *pcommand)
Definition commands.c:746
int command_vote_percent(const struct command *pcommand)
Definition commands.c:818
const struct command * command_by_number(int i)
Definition commands.c:737
int command_vote_flags(const struct command *pcommand)
Definition commands.c:810
command_id
Definition commands.h:35
char * incite_cost
Definition comments.c:75
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:763
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:366
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:356
void connection_do_buffer(struct connection *pc)
Definition connection.c:324
bool conn_controls_player(const struct connection *pconn)
Definition connection.c:745
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:753
const char * conn_description(const struct connection *pconn)
Definition connection.c:474
struct connection * conn_by_number(int id)
Definition connection.c:421
enum cmdlevel conn_get_access(const struct connection *pconn)
Definition connection.c:775
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:336
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
#define MAX_LEN_CONSOLE_LINE
Definition console.h:19
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2931
#define _(String)
Definition fcintl.h:67
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
struct civ_game game
Definition game.c:62
const char * title
Definition repodlgs.c:1314
GType type
Definition repodlgs.c:1313
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
#define fc_malloc(sz)
Definition mem.h:34
void notify_team(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:345
int send_packet_vote_resolve(struct connection *pc, const struct packet_vote_resolve *packet)
int send_packet_vote_remove(struct connection *pc, const struct packet_vote_remove *packet)
int send_packet_vote_update(struct connection *pc, const struct packet_vote_update *packet)
int send_packet_vote_new(struct connection *pc, const struct packet_vote_new *packet)
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Definition player.c:1476
#define MIN(x, y)
Definition shared.h:55
bool handle_stdin_input(struct connection *caller, char *str)
Definition stdinhand.c:4429
struct conn_list * est_connections
Definition game.h:97
char user[MAX_LEN_NAME]
bv_plr_flags flags
Definition player.h:290
int conn_id
Definition voting.h:36
enum vote_type vote_cast
Definition voting.h:35
Definition voting.h:46
int vote_no
Definition voting.h:52
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
void send_running_votes(struct connection *pconn, bool only_team_votes)
Definition voting.c:810
static void lsend_vote_new(struct conn_list *dest, struct vote *pvote)
Definition voting.c:64
void send_remove_team_votes(struct connection *pconn)
Definition voting.c:841
int describe_vote(struct vote *pvote, char *buf, int buflen)
Definition voting.c:748
static void lsend_vote_remove(struct conn_list *dest, struct vote *pvote)
Definition voting.c:140
bool conn_can_vote(const struct connection *pconn, const struct vote *pvote)
Definition voting.c:248
static void check_vote(struct vote *pvote)
Definition voting.c:420
struct vote * vote_new(struct connection *caller, const char *allargs, int command_id)
Definition voting.c:338
bool vote_is_team_only(const struct vote *pvote)
Definition voting.c:235
void cancel_connection_votes(struct connection *pconn)
Definition voting.c:691
struct vote * get_vote_by_no(int vote_no)
Definition voting.c:301
int vote_number_sequence
Definition voting.c:42
bool vote_would_pass_immediately(const struct connection *caller, int command_id)
Definition voting.c:391
void send_updated_vote_totals(struct conn_list *dest)
Definition voting.c:866
void handle_vote_submit(struct connection *pconn, int vote_no, int value)
Definition voting.c:775
void voting_turn(void)
Definition voting.c:718
static void lsend_vote_resolve(struct conn_list *dest, struct vote *pvote, bool passed)
Definition voting.c:162
void clear_all_votes(void)
Definition voting.c:219
struct vote * get_vote_by_caller(const struct connection *caller)
Definition voting.c:319
void voting_init(void)
Definition voting.c:707
static void lsend_vote_update(struct conn_list *dest, struct vote *pvote, int num_voters)
Definition voting.c:102
static void free_vote(struct vote *pvote)
Definition voting.c:189
static struct vote_cast * vote_cast_find(struct vote *pvote, int conn_id)
Definition voting.c:611
void connection_vote(struct connection *pconn, struct vote *pvote, enum vote_type type)
Definition voting.c:663
struct vote_list * vote_list
Definition voting.c:41
const struct connection * vote_get_caller(const struct vote *pvote)
Definition voting.c:891
int count_voters(const struct vote *pvote)
Definition voting.c:48
static void remove_vote_cast(struct vote *pvote, struct vote_cast *pvc)
Definition voting.c:649
void remove_vote(struct vote *pvote)
Definition voting.c:205
void voting_free(void)
Definition voting.c:734
static struct vote_cast * vote_cast_new(struct vote *pvote)
Definition voting.c:629
bool conn_can_see_vote(const struct connection *pconn, const struct vote *pvote)
Definition voting.c:272
vote_type
Definition voting.h:26
@ VOTE_ABSTAIN
Definition voting.h:27
@ VOTE_YES
Definition voting.h:27
@ VOTE_NUM
Definition voting.h:27
@ VOTE_NO
Definition voting.h:27
#define vote_list_iterate_end
Definition voting.h:65
@ VCF_TEAMONLY
Definition voting.h:23
@ VCF_NOPASSALONE
Definition voting.h:21
@ VCF_NODISSENT
Definition voting.h:20
#define vote_cast_list_iterate(alist, pvc)
Definition voting.h:42
#define vote_list_iterate(alist, pvote)
Definition voting.h:63
#define vote_cast_list_iterate_end
Definition voting.h:44