/** * This is the handler for all things clubby, a club being a group of * players. Each club must have a unique name. It also handles elections * for various club positions. * @author Pinkfish * @started Sun Sep 27 03:35:42 EDT 1998 */ inherit "/obj/handlers/inherit/club_elected"; #define __CLUBS_H_NO_CLASSES #include <clubs.h> #include <broadcaster.h> #include <player_handler.h> #include <player_handler.h> // Special variables to control the club inner workings. private nosave mapping _discussion_items; #define CLUB_DISCUSS_FUNCTION_OBJECT 0 #define CLUB_DISCUSS_FUNCTION_FUNCTION 1 #define CLUB_DISCUSS_QUORUM_COMMITTEE 75 #define CLUB_DISCUSS_QUORUM_OPEN 25 private void add_club_discussion(int type, function func); protected int remove_discussion_item(string club_name, class discussion_idea item); private mixed club_discuss_new_position(int message, string club_name, class discussion_idea frog); private mixed club_discuss_position_name(int message, string club_name, class discussion_idea frog, string arg1, string arg2); private mixed club_discuss_position_remove(int message, string club_name, class discussion_idea frog, string arg1, string arg2); private mixed club_discuss_description(int message, string club_name, class discussion_idea frog); private mixed club_discuss_memo(int message, string club_name, class discussion_idea frog); private mixed club_discuss_secret(int message, string club_name, class discussion_idea frog); private mixed club_discuss_remove_member(int message, string club_name, class discussion_idea frog, string member); private mixed club_discuss_no_confidence(int message, string club_name, class discussion_idea frog, string arg1, string arg2); private mixed club_discuss_election(int message, string club_name, class discussion_idea frog, string arg1, string arg2); private mixed club_discuss_nomination(int message, string club_name, class discussion_idea frog, string arg1, string arg2); private mixed club_discuss_function(int message, string club_name, class discussion_idea frog, string arg1, string arg2); private mixed club_discuss_create_account(int message, string club_name, class discussion_idea frog, string arg1, string arg2); class discussion_idea query_discussion_item_by_type(string club_name, int type, class discussion_idea idea); protected mixed send_discuss_message(string club_name, int message, class discussion_idea item, string arg1, string arg2); protected void broadcast_discuss_message(string club_name, int message, string arg1, string arg2); int add_discussion_item(string club, int type, string added_by, string name, string info, string *choices, int time_to_finish, mixed extra_data); int setup_by_election(string club, string position, string info); int is_discuss_nominateable(string club_name, int id); void create() { _discussion_items = ([ ]); ::create(); add_club_discussion(CLUB_DISCUSS_NEW_POSITION, (: club_discuss_new_position :)); add_club_discussion(CLUB_DISCUSS_POSITION_NAME, (: club_discuss_position_name :)); add_club_discussion(CLUB_DISCUSS_POSITION_REMOVE, (: club_discuss_position_remove :)); add_club_discussion(CLUB_DISCUSS_DESCRIPTION, (: club_discuss_description :)); add_club_discussion(CLUB_DISCUSS_MEMO, (: club_discuss_memo :)); add_club_discussion(CLUB_DISCUSS_MEMBER_REMOVE, (: club_discuss_remove_member :)); add_club_discussion(CLUB_DISCUSS_SECRET_TYPE, (: club_discuss_secret :)); add_club_discussion(CLUB_DISCUSS_NO_CONFIDENCE, (: club_discuss_no_confidence :)); add_club_discussion(CLUB_DISCUSS_ELECTION, (: club_discuss_election :)); add_club_discussion(CLUB_DISCUSS_NOMINATION, (: club_discuss_nomination :)); add_club_discussion(CLUB_DISCUSS_FUNCTION, (: club_discuss_function :)); add_club_discussion(CLUB_DISCUSS_CREATE_ACCOUNT, (: club_discuss_create_account :)); } /* create() */ private void add_club_discussion(int type, function func) { _discussion_items[type] = func; } /* add_club_discussion() */ /** * This method is called when a discussion item is finished. It then * archives it or whatever else it wishes to do with the item * @param club_name the name of the club * @param item the text string of the finished item */ protected int archive_discussion_item(string club_name, string subject, string item) { if (is_elected_club(club_name)) { // Do some useful archiving. add_archive(club_name, subject, item); } } /* archive_discussion_item() */ /** * This is a special function to be used with the discuss items to * make sure that there is not another discussion item checking the * same name. * @param club_name the name of the club to check * @param position the position to check for * @return 1 if the position is being discussed as an item */ int is_discussion_position_valid(string club_name, string position) { class discussion_idea bing; position = lower_case(position); // Not already a position name. if (is_valid_position(club_name, position)) { return 0; } // Discussing it as a possible alternative name. do { bing = query_discussion_item_by_type(club_name, CLUB_DISCUSS_POSITION_NAME, bing); if (bing) { if (!undefinedp(bing->choices[position])) { return 0; } } } while (bing); // Discussing it as a new position type. do { bing = query_discussion_item_by_type(club_name, CLUB_DISCUSS_NEW_POSITION, bing); if (bing) { if (bing->information == position) { return 0; } } } while (bing); return 1; } /* is_discussion_position_valid() */ private mixed club_discuss_position_name(int message, string club_name, class discussion_idea frog, string arg1, string arg2) { string body; string position; int num; string old_pos; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* * The current position must be in the list of choices. Add * it if it is not.. Also make sure that none of the other * names are already positions in the club. */ if (!is_discussion_position_valid(club_name, frog->optional_data)) { return 0; } frog->choices = ([ CLUB_DISCUSS_YES_CHOICE : 0, CLUB_DISCUSS_NO_CHOICE : 0, CLUB_DISCUSS_ABSTAIN_CHOICE : 0 ]); if (!is_valid_position(club_name, frog->name)) { return 0; } return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : /* * Ok! Now we complete the position and tally up to find * which position is the best. */ body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The final votes for the discussion item to change the " "position " +frog->name + " to " + frog->optional_data + " is:\n"; foreach (position, num in frog->choices) { body += position + ": " + num + "\n"; } body += "\n"; if (frog->information) { body += frog->information + "\n"; } // Need to keep track of the old name since the change postion // call will modify the name in the structure. old_pos = frog->name; if (frog->choices[CLUB_DISCUSS_YES_CHOICE] > frog->choices[CLUB_DISCUSS_NO_CHOICE]) { change_position_name_in_club(club_name, frog->name, frog->optional_data); body += "Which means the position " + old_pos + " has been changed to " + frog->optional_data + ".\n"; } else { body += "Which means the position " + old_pos + " has not been changed to " + frog->optional_data + ".\n"; } do_mail_committee(club_name, "Results of changing the position " + frog->name, body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Voting on changing the position '" + frog->name + "' to '" + frog->optional_data + "'.\n"; if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Changing the position '" + frog->name + "'"; case CLUB_DISCUSS_MESSAGE_CHANGE_POSITION : if (frog->name == arg1) { frog->name = arg2; return 1; } return 0; case CLUB_DISCUSS_MESSAGE_REMOVE_POSITION : if (frog->name == arg1) { remove_discussion_item(club_name, frog); return 1; } return 0; } return 0; } /* club_discuss_position_name() */ private mixed club_discuss_position_remove(int message, string club_name, class discussion_idea frog, string arg1, string arg2) { string body; string position; int num; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* * The current position must be in the list of choices. Add * it if it is not.. Also make sure that none of the other * names are already positions in the club. */ if (!is_valid_position(club_name, frog->name)) { return 0; } if (is_basic_position(club_name, frog->name)) { return 0; } frog->choices = ([ CLUB_DISCUSS_YES_CHOICE : 0, CLUB_DISCUSS_NO_CHOICE : 0, CLUB_DISCUSS_ABSTAIN_CHOICE : 0 ]); return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : /* * Ok! Now we complete the position and tally up to find * which position is the best. */ body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The final votes for the discussion item " "to remove the position " + frog->name + " are:\n"; foreach (position, num in frog->choices) { body += position + ": " + num + "\n"; } body += "\n"; if (frog->information) { body += frog->information + "\n"; } if (frog->choices[CLUB_DISCUSS_YES_CHOICE] > frog->choices[CLUB_DISCUSS_NO_CHOICE]) { if (is_basic_position(club_name, frog->name)) { body += "Unable to remove the basic position " + frog->name + ".\n"; } else if (remove_position_in_club(club_name, frog->name)) { body += "Which means the position " + frog->name + " has been removed.\n"; } else { body += "Unable to remove the position " + frog->name + " for some reason, basic position or something?\n"; } } else { body += "Which means the position " + frog->name + " has not been removed.\n"; } do_mail_committee(club_name, "Results of removing the position " + frog->name, body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Voting on removing the position '" + frog->name + "'.\n"; if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Removing the position '" + frog->name + "'"; case CLUB_DISCUSS_MESSAGE_CHANGE_POSITION : if (frog->name == arg1) { frog->name = arg2; return 1; } return 0; case CLUB_DISCUSS_MESSAGE_REMOVE_POSITION : if (frog->name == arg1) { remove_discussion_item(club_name, frog); return 1; } return 0; } return 0; } /* club_discuss_position_remove() */ private mixed club_discuss_new_position(int message, string club_name, class discussion_idea frog) { string body; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* Make sure they only have a yes and no choice. */ frog->choices = ([ CLUB_DISCUSS_YES_CHOICE : 0, CLUB_DISCUSS_NO_CHOICE : 0, CLUB_DISCUSS_ABSTAIN_CHOICE : 0 ]); if (!is_discussion_position_valid(club_name, frog->name)) { return 0; } return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The vote for adding the position " + frog->name + " to the club " + query_club_name(club_name) + " has been completed and the results are " + frog->choices[CLUB_DISCUSS_YES_CHOICE] + " in favour, " + frog->choices[CLUB_DISCUSS_NO_CHOICE] + " against and " + frog->choices[CLUB_DISCUSS_ABSTAIN_CHOICE] + " abstaining.\n"; if (frog->information) { body += frog->information; } if (is_valid_position(club_name, frog->name)) { body += "\nUnfortunately " + frog->name + " is not a valid position. Vote forfited.\n"; do_mail_committee(club_name, "Results of adding " + frog->name, body); return 0; } if (frog->choices[CLUB_DISCUSS_YES_CHOICE] > frog->choices[CLUB_DISCUSS_NO_CHOICE]) { if (create_position_in_club(club_name, frog->name)) { body += "\nWhich means that the position " + frog->name + " has been created.\n"; setup_by_election(club_name, frog->name, frog->information); } else if (is_voting_in_progress(club_name)) { body += "\nWhich means we attempted to create the position " + frog->name + " but were prevented because " "voting is in progress?\n"; } else { body += "\nWhich means we attempted to create the position " + frog->name + " but were prevented for some reason.\n"; } } else { body += "\nWhich means that the position " + frog->name + " was not created.\n"; } do_mail_committee(club_name, "Results of adding " + frog->name, body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Voting on adding the position '" + frog->name + "' to the club.\n"; if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Adding the position '" + frog->name + "'"; } return 0; } /* club_discuss_position_name() */ private mixed club_discuss_description(int message, string club_name, class discussion_idea frog) { string body; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* See if there is already one of these going... */ if (query_discussion_item_by_type(club_name, CLUB_DISCUSS_DESCRIPTION, 0)) { return 0; } /* Make sure they only have a yes and no choice. */ frog->choices = ([ CLUB_DISCUSS_YES_CHOICE : 0, CLUB_DISCUSS_NO_CHOICE : 0, CLUB_DISCUSS_ABSTAIN_CHOICE : 0 ]); return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The vote for changing the description of the " + "club " + query_club_name(club_name) + " to:\n" + frog->information + "\nThe vote has been completed " "and the results are " + frog->choices[CLUB_DISCUSS_YES_CHOICE] + " in favour, " + frog->choices[CLUB_DISCUSS_NO_CHOICE] + " against and " + frog->choices[CLUB_DISCUSS_ABSTAIN_CHOICE] + " abstaining.\n"; if (frog->choices[CLUB_DISCUSS_YES_CHOICE] > frog->choices[CLUB_DISCUSS_NO_CHOICE]) { set_club_description(club_name, frog->information); body += "Which means the description has been changed.\n"; } else { body += "Which means the description has not been changed.\n"; } do_mail_committee(club_name, "Results of changing the description", body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Voting on changing the description of the club to:\n" + frog->information + "\n"; return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Changing the description"; } return 0; } /* club_discuss_description() */ private mixed club_discuss_secret(int message, string club_name, class discussion_idea frog) { string body; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* See if there is already one of these going... */ if (query_discussion_item_by_type(club_name, CLUB_DISCUSS_SECRET_TYPE, 0)) { return 0; } /* Make sure they only have a yes and no choice. */ frog->choices = ([ CLUB_DISCUSS_YES_CHOICE : 0, CLUB_DISCUSS_NO_CHOICE : 0, CLUB_DISCUSS_ABSTAIN_CHOICE : 0 ]); return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The vote for changing the club " + query_club_name(club_name) + " to "; if (query_club_secret(club_name)) { body += "an open club"; } else { body += "a secret club"; } body += " has been completed and the " "results are " + frog->choices[CLUB_DISCUSS_YES_CHOICE] + " in favour and " + frog->choices[CLUB_DISCUSS_NO_CHOICE] + " against with " + frog->choices[CLUB_DISCUSS_ABSTAIN_CHOICE] + " abstaining.\n\n"; if (frog->choices[CLUB_DISCUSS_YES_CHOICE] > frog->choices[CLUB_DISCUSS_NO_CHOICE]) { if (query_club_secret(club_name)) { reset_club_secret(club_name); body += "Which means the club is now open.\n"; } else { set_club_secret(club_name); body += "Which means the club is now secret.\n"; } } else { body += "Which means the club's secret flag has not been " "changed.\n"; } if (frog->information) { body += "\n" + frog->information; } do_mail_committee(club_name, "Results of changing the secret flag", body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : if (query_club_secret(club_name)) { body = "Voting on changing the club to be open.\n"; } else { body = "Voting on changing the club to be secret.\n"; } if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : if (query_club_secret(club_name)) { return "Changing the club to be open"; } else { return "Changing the club to be secret"; } } return 0; } /* club_discuss_secret() */ private mixed club_discuss_memo(int message, string club_name, class discussion_idea frog) { string body; string choice; int num; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* * A memo can have any fields. The verification is always * correct. */ return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : /* * Ok! Now we complete the position and tally up to find * which position is the best. */ body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The final votes for discussion memo '" + frog->name + "' were:\n"; foreach (choice, num in frog->choices) { body += choice + ": " + num + "\n"; } body += "\n" + frog->information; do_mail_committee(club_name, "Results of memo '" + frog->name + "'\n", body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Voting on the memo '" + frog->name + "'.\n"; if (stringp(frog->information)) { body += "\n" + frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Memo: " + frog->name; } return 0; } /* club_discuss_memo() */ private mixed club_discuss_remove_member(int message, string club_name, class discussion_idea frog, string member) { string body; class discussion_idea womble; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* See if there is already one of these going... */ frog->name = lower_case(frog->name); do { womble = query_discussion_item_by_type(club_name, CLUB_DISCUSS_MEMBER_REMOVE, womble); // Check to see if they are already being removed. if (womble && womble->name == frog->name) { return 0; } } while (womble); if (!is_member_of(club_name, frog->name)) { return 0; } /* Make sure they only have a yes and no choice. */ frog->choices = ([ CLUB_DISCUSS_YES_CHOICE : 0, CLUB_DISCUSS_NO_CHOICE : 0, CLUB_DISCUSS_ABSTAIN_CHOICE : 0 ]); return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The vote for changing removing the member " + frog->name + " from the club " + query_club_name(club_name) + " has been completed and the " "results are " + frog->choices[CLUB_DISCUSS_YES_CHOICE] + " in favour and " + frog->choices[CLUB_DISCUSS_NO_CHOICE] + " against with " + frog->choices[CLUB_DISCUSS_ABSTAIN_CHOICE] + " abstaining.\n\n"; if (frog->information) { body += frog->information; } if (frog->choices[CLUB_DISCUSS_YES_CHOICE] > frog->choices[CLUB_DISCUSS_NO_CHOICE]) { if (!is_member_of(club_name, frog->name)) { body += "Looks like someone beat us to removing them.\n"; } else { body += "Which means they have now been removed.\n"; remove_member(club_name, frog->name); } } else { body += "Which means no one has been removed.\n"; } do_mail_committee(club_name, "Results of removing the member", body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Voting on removing the member " + frog->name + ".\n"; if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Removing the member " + frog->name; case CLUB_DISCUSS_MESSAGE_REMOVE_MEMBER : if (frog->name == member) { // Remove this discussion item! return remove_discussion_item(club_name, frog); } return 0; } return 0; } /* club_discuss_remove_member() */ private mixed club_discuss_no_confidence(int message, string club_name, class discussion_idea frog, string arg1, string arg2) { string body; class discussion_idea womble; string real; string pos; if (!frog->name) { real = "all postions"; } else { real = frog->name; } switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* See if there is already one of these going... */ frog->name = lower_case(frog->name); do { womble = query_discussion_item_by_type(club_name, CLUB_DISCUSS_NO_CONFIDENCE, womble); // Check to see if they are already being removed. if (womble && womble->name == frog->name) { return 0; } } while (womble); if (!is_valid_position(club_name, frog->name) && frog->name) { return 0; } /* Make sure they only have a yes and no choice. */ frog->choices = ([ CLUB_DISCUSS_YES_CHOICE : 0, CLUB_DISCUSS_NO_CHOICE : 0, CLUB_DISCUSS_ABSTAIN_CHOICE : 0 ]); return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The vote for no confidence in " + real + " in the club " + query_club_name(club_name) + " has been completed and the " "results are " + frog->choices[CLUB_DISCUSS_YES_CHOICE] + " in favour and " + frog->choices[CLUB_DISCUSS_NO_CHOICE] + " against with " + frog->choices[CLUB_DISCUSS_ABSTAIN_CHOICE] + " abstaining.\n\n"; if (frog->choices[CLUB_DISCUSS_YES_CHOICE] > frog->choices[CLUB_DISCUSS_NO_CHOICE]) { if (!frog->name) { body += "Therefor we have removed everyone from the committee " "and started a new election.\n"; foreach (pos in query_valid_positions(club_name)) { catch(set_position_holder(club_name, pos, CLUB_UNKNOWN_MEMBER)); } start_election(club_name); } else if (is_valid_position(club_name, frog->name)) { set_position_holder(club_name, frog->name, CLUB_UNKNOWN_MEMBER); body += "Therefor we had set the position as vacant.\n"; } else { body += "The position in the club appears to have vanished!\n"; } } else { body += "Which means nothing has happened.\n"; } if (frog->information) { body += frog->information; } do_mail_committee(club_name, "Results of no confidence vote", body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Voting on confidence in the position " + real + ", a yes vote indicates that you are in favour of the " "no confidence vote.\n"; if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "No confidence in " + real; case CLUB_DISCUSS_MESSAGE_REMOVE_MEMBER : if (holds_position_of(club_name, frog->name, arg1) || holds_position_of(club_name, frog->name, CLUB_UNKNOWN_MEMBER)) { return remove_discussion_item(club_name, frog); } return 0; case CLUB_DISCUSS_MESSAGE_CHANGE_POSITION : if (frog->name == arg1) { frog->name = arg2; return 1; } return 0; case CLUB_DISCUSS_MESSAGE_REMOVE_POSITION : if (frog->name == arg1) { remove_discussion_item(club_name, frog); return 1; } return 0; } return 0; } /* club_discuss_no_confidence() */ private int is_nomination_or_election_being_discussed( string club_name, string pos_name ) { class discussion_idea womble; womble = 0; do { womble = query_discussion_item_by_type(club_name, CLUB_DISCUSS_ELECTION, womble); // Check to see if they are already being elected. if (womble && lower_case(womble->name) == lower_case(pos_name)) { return 1; } } while (womble); womble = 0; do { womble = query_discussion_item_by_type(club_name, CLUB_DISCUSS_NOMINATION, womble); // Check to see if they are already being nominated. if (womble && lower_case(womble->name) == lower_case(pos_name)) { return 1; } } while (womble); return 0; } /* is_nomination_or_election_discussed() */ private mixed club_discuss_nomination(int message, string club_name, class discussion_idea frog, string arg1, string arg2) { string body; string name; string *nom; string *nominated; int ret; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : // // Make the name correct. // frog->name = query_position_name(club_name, frog->name); /* See if there is already one of these going... */ if (is_nomination_or_election_being_discussed(club_name, frog->name)) { return 0; } if (!is_valid_position(club_name, frog->name)) { return 0; } if (is_election_in_progress(club_name) || is_nomination_in_progress(club_name)) { return 0; } /* Setup the nomination mapping. */ frog->choices = ([ ]); return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The vote for nominations for the position of " + frog->name + " in the club " + query_club_name(club_name) + " has been completed and the " "results are:\n"; nominated = ({ }); foreach (name, nom in frog->choices) { body += name + ": " + query_multiple_short(nom); if (member_array(name, nom) != -1 && sizeof(nom) >= 2) { body += " (accepted)\n"; nominated += ({ name }); } else { body += "\n"; } } if (frog->information) { body += frog->information; } if (sizeof(nominated)) { if (is_valid_position(club_name, frog->name)) { if (sizeof(nominated) != 1) { body += "Therefor we had added an election for " + query_multiple_short(nominated) + " .\n"; // // Do the addition in a call out, so we are removed first. // call_out((: add_discussion_item :), 0, club_name, CLUB_DISCUSS_ELECTION | CLUB_DISCUSS_OPEN | CLUB_DISCUSS_NO_QUORUM, CLUB_CONTROLLER_MEMBER, frog->name, frog->information, nominated, 7 * (24 * 60 * 60), 0); } else { body += "Only " + nominated[0] + " was nominated, so they are elected immediately.\n"; set_position_holder(club_name, frog->name, nominated[0]); } } else { body += "The position in the club appears to have vanished!\n"; } } else { if (is_valid_position(club_name, frog->name)) { body += "No one accepted their nomination, so nothing " "happened.\n"; // // Do the addition in a call out, so we are removed first. // call_out((: add_discussion_item :), 0, club_name, CLUB_DISCUSS_NOMINATION | CLUB_DISCUSS_OPEN | CLUB_DISCUSS_NO_QUORUM, frog->added_by, frog->name, frog->information, ({ }), 7 * (24 * 60 * 60), frog->optional_data); } else { body += "The position in the club appears to have vanished!\n"; } } do_mail_committee(club_name, "Results of nomination", body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Nominations for the position " + frog->name + ":\n"; foreach (name, nom in frog->choices) { body += name + ": " + query_multiple_short(nom); if (member_array(name, nom) != -1 && sizeof(nom) >= 2) { body += " (accepted)\n"; } else { body += "\n"; } } if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Nominations for " + frog->name; case CLUB_DISCUSS_MESSAGE_NOMINATION : if (is_member_of(club_name, arg1) && is_member_of(club_name, arg2)) { // Pass in the person nominated in the optional data. if (!frog->choices[arg2]) { frog->choices[arg2] = ({ arg1 }); return 1; } else if (member_array(arg1, frog->choices[arg2]) == -1) { frog->choices[arg2] += ({ arg1 }); return 1; } } return 0; case CLUB_DISCUSS_MESSAGE_WITHDRAW : if (frog->choices[arg1]) { map_delete(frog->choices, arg1); return 1; } return 0; case CLUB_DISCUSS_MESSAGE_REMOVE_MEMBER : // Check out to see if they have been nominated or nominated someone. if (frog->choices[arg1]) { map_delete(frog->choices, arg1); ret = 1; } foreach (name, nom in frog->choices) { if (member_array(arg1, nom) != -1) { frog->choices[name] = nom - ({ arg1 }); if (!sizeof(frog->choices[name])) { map_delete(frog->choices, name); } ret = 1; } } return ret; case CLUB_DISCUSS_MESSAGE_CHANGE_POSITION : if (frog->name == arg1) { frog->name = arg2; return 1; } return 0; case CLUB_DISCUSS_MESSAGE_TYPE : return CLUB_DISCUSS_MESSAGE_TYPE_NOMINATE; case CLUB_DISCUSS_MESSAGE_NOMINATION_QUERY : return frog->choices; case CLUB_DISCUSS_MESSAGE_REMOVE_POSITION : if (frog->name == arg1) { remove_discussion_item(club_name, frog); return 1; } return 0; } return 0; } /* club_discuss_nomination() */ private mixed club_discuss_election(int message, string club_name, class discussion_idea frog, string arg1, string arg2) { string body; string name; int num; int highest; string *voted; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : // // Make the name correct. // frog->name = query_position_name(club_name, frog->name); /* See if there is already one of these going... */ if (is_nomination_or_election_being_discussed(club_name, frog->name)) { return 0; } if (!is_valid_position(club_name, frog->name)) { return 0; } if (is_election_in_progress(club_name) || is_nomination_in_progress(club_name)) { return 0; } /* Make sure they only voting for people in the club. */ foreach (name, num in frog->choices) { frog->choices[name] = 0; if (!is_member_of(club_name, name)) { map_delete(frog->choices, name); } } if (!sizeof(frog->choices)) { return 0; } return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The vote the position of " + frog->name + " in the club " + query_club_name(club_name) + " has been completed and the " "results are:\n"; highest = 0; voted = ({ }); foreach (name, num in frog->choices) { body += name + ": " + num + "\n"; if (num > highest) { highest = num; voted = ({ name }); } else if (highest == num) { voted += ({ name }); } } if (frog->information) { body += frog->information; } if (sizeof(voted)) { if (is_valid_position(club_name, frog->name)) { if (sizeof(voted) == 1) { body += "Therefor " + voted[0] + " was elected to the position of " + frog->name + ".\n"; set_position_holder(club_name, frog->name, voted[0]); } else { body += "More than one person tied for the position, so " "the election has been added again.\n"; } } else { body += "The position in the club appears to have vanished!\n"; } } else { body += "No one voted for anyone, so nothing happened.\n"; } do_mail_committee(club_name, "Results of election", body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Election for the position of " + frog->name + ".\n"; if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Election for " + frog->name; case CLUB_DISCUSS_MESSAGE_REMOVE_MEMBER : if (!undefinedp(frog->choices[arg1])) { map_delete(frog->choices, arg1); return 1; } return 0; case CLUB_DISCUSS_MESSAGE_CHANGE_POSITION : if (frog->name == arg1) { frog->name = arg2; return 1; } return 0; case CLUB_DISCUSS_MESSAGE_REMOVE_POSITION : if (frog->name == arg1) { remove_discussion_item(club_name, frog); return 1; } return 0; } return 0; } /* club_discuss_election() */ private mixed club_discuss_function(int message, string club_name, class discussion_idea frog, string arg1, string arg2) { mixed ret; ret = call_other(frog->name[CLUB_DISCUSS_FUNCTION_OBJECT], frog->name[CLUB_DISCUSS_FUNCTION_FUNCTION], message, club_name, frog, arg1, arg2); if (message == CLUB_DISCUSS_MESSAGE_COMPLETE && stringp(ret)) { do_mail_committee(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, arg1, arg2), ret); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), ret); return 1; } return ret; } /* club_discuss_function() */ private mixed club_discuss_create_account(int message, string club_name, class discussion_idea frog, string arg1, string arg2) { string body; class discussion_idea womble; switch (message) { case CLUB_DISCUSS_MESSAGE_VERIFY : /* See if there is already one of these going... */ do { womble = query_discussion_item_by_type(club_name, CLUB_DISCUSS_CREATE_ACCOUNT, womble); // Check to see if the account is already being added. if (womble && womble->name == frog->name) { return 0; } } while (womble); frog->choices = ([ CLUB_DISCUSS_YES_CHOICE : 0, CLUB_DISCUSS_NO_CHOICE : 0, CLUB_DISCUSS_ABSTAIN_CHOICE : 0 ]); if (is_account_of(club_name, frog->name)) { return 0; } return 1; case CLUB_DISCUSS_MESSAGE_COMPLETE : body = "Hello!\n\nThe discussion item " "added at " + ctime(frog->time_added) + ", finished at " + ctime(time()) + " and added by " + frog->added_by + " has finished."; body += " The vote for adding the special account " + frog->name + " in the club " + query_club_name(club_name) + " has been completed and the " "results are " + frog->choices[CLUB_DISCUSS_YES_CHOICE] + " in favour, " + frog->choices[CLUB_DISCUSS_NO_CHOICE] + " against and " + frog->choices[CLUB_DISCUSS_ABSTAIN_CHOICE] + " abstaining.\n"; if (frog->choices[CLUB_DISCUSS_YES_CHOICE] > frog->choices[CLUB_DISCUSS_NO_CHOICE]) { if (create_account(club_name, frog->name)) { body += "Which means the special account " + frog->name + " has been created.\n"; } else { body += "Which means the special account " + frog->name + " was attempted to be created but had some problems.\n"; } } else { body += "Which means the special account " + frog->name + " has not been created.\n"; } if (frog->information) { body += frog->information; } do_mail_committee(club_name, "Results of creating account", body); archive_discussion_item(club_name, send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0), body); return 1; case CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION : body = "Creating the special account " + frog->name + ".\n"; if (frog->information) { body += frog->information; } return body; case CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION : return "Create special account " + frog->name; } return 0; } /* club_discuss_election() */ /** * This method figures out the discussion item for the club with the * given id. * @param club_name the name of the club * @param id the id of the discussion item * @return the found discussion item * @see add_discussion_item() */ class discussion_idea query_discussion_item(string club_name, int id) { class election_info frog; class discussion_idea bing; frog = (class election_info)query_elected_info(club_name); if (frog) { foreach (bing in frog->discussion) { if (bing->id == id) { return bing; } } } return 0; } /* query_discussion_item() */ /** * This method returns all the current discussion items for this * club. * @param club_name the name of the club to query the discussion items for * @return the list of current discussion items */ class discussion_idea* query_all_discussion_items(string club_name) { class election_info frog; frog = (class election_info)query_elected_info(club_name); if (frog) { return copy(frog->discussion); } return 0; } /* query_all_discussion_items() */ /** * This method returns a nice little description of the discussion item. * This is a very short description usable in lists and stuff. * @param club_name the name of the club * @param id the id of the discussion item * @return a short description of the item */ string query_discussion_item_short_description(string club_name, int id) { class discussion_idea bing; bing = query_discussion_item(club_name, id); if (bing) { if (_discussion_items[bing->discuss_type & CLUB_DISCUSS_TYPE_MASK]) { return send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, bing, 0, 0); } } return 0; } /* query_discuss_item_short_description() */ /** * This method returns a nice little description of the discussion item. * This is a longer description, useful in more places. * @param club_name the name of the club * @param id the id of the discussion item * @return a long description of the item */ string query_discussion_item_long_description(string club_name, int id) { class discussion_idea bing; bing = query_discussion_item(club_name, id); if (bing) { if (_discussion_items[bing->discuss_type & CLUB_DISCUSS_TYPE_MASK]) { return send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_LONG_DESCRIPTION, bing, 0, 0); } } return 0; } /* query_discuss_item_long_description() */ /** * This method checks to make sure the type of the discussion item * is valid. * @param type the type of the discussion item * @return 1 if it is valid, 0 if not */ int is_valid_discussion_item_type(int type) { if (_discussion_items[type & CLUB_DISCUSS_TYPE_MASK]) { return 1; } return 0; } /* is_valid_duscussion_item_type() */ /** * This method will add a discussion item to the table to be voted on. * @param club the club the item is being added to * @param type the type of the discussion item to be added * @param added_by who added the discussion item * @param name the name of the discussion item * @param choices the choices for the discussion item * @param time_to_finish the amount of time the election has to run * @param extra_data any optional data associated with the discussion idea * @return 1 if successfully added, 0 if not */ int add_discussion_item(string club, int type, string added_by, string name, string info, string *choices, int time_to_finish, mixed extra_data) { class discussion_idea bing; class election_info frog; int max_id; string choice; int i; // Allow the item to be added by the club contoller or the club itself. if (is_elected_club(club) && is_valid_discussion_item_type(type) && time_to_finish > 0 && (is_member_of(club, lower_case(added_by)) || added_by == CLUB_CONTROLLER_MEMBER || normalise_name(added_by) == normalise_name(club))) { /* Cool, then we can add this item. */ frog = (class election_info)query_elected_info(club); if (!pointerp(frog->discussion)) { frog->discussion = ({ }); } bing = new(class discussion_idea); max_id = 0; for (i = 0; i < sizeof(frog->discussion); i++) { if (frog->discussion[i]->id > max_id) { max_id = frog->discussion[i]->id; } } bing->id = max_id + 1; bing->time_added = time(); bing->time_finish = time() + time_to_finish; bing->discuss_type = type; bing->added_by = added_by; bing->name = name; bing->information = info; bing->choices = ([ ]); foreach (choice in choices) { bing->choices[lower_case(choice)] = 0; } bing->voted = ({ }); bing->optional_data = extra_data; /* Verify the data... */ if (send_discuss_message(club, CLUB_DISCUSS_MESSAGE_VERIFY, bing, 0, 0)) { frog->discussion += ({ bing }); set_club_changed(club); return 1; } return 0; } return 0; } /* add_discussion_item() */ /** * This method figures out the discussion item for the club with the * given type. It will also continue on a search from a last found item. * @param club_name the name of the club * @param type the type of the discussion item to find * @return the found discussion item * @see add_discussion_item() */ class discussion_idea query_discussion_item_by_type(string club_name, int type, class discussion_idea idea) { class election_info frog; class discussion_idea bing; int found; frog = (class election_info)query_elected_info(club_name); if (frog) { if (!idea) { found = 1; } foreach (bing in frog->discussion) { if (found) { if ((bing->discuss_type & CLUB_DISCUSS_TYPE_MASK) == type) { return bing; } } else if (bing == idea) { found = 1; } } } return 0; } /* query_discussion_item_by_type() */ /** * This method returns all the choices for this discussion item. * @param club_name the name of the club * @param id the id of the discussion item * @return an array of the valid set of choices, empty array on failure */ string *query_discussion_choices(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog) { return keys(frog->choices); } return ({ }); } /* is_valid_discussion_choice() */ /** * This method returns the person who added the discussion item. * @param club_name the name of the club * @param id the id of the discussion item * @return the name of the person who added the discussion item */ string query_discussion_added_by(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog && frog->added_by) { return frog->added_by; } return CLUB_UNKNOWN_MEMBER; } /* query_discussion_added_by() */ /** * This method returns the timeout time of the current discussion item. * @param club_name the name of the club * @param id the id of the discussion item * @return the time at which the dicussion item will finish */ int query_discussion_time_finish(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog) { return frog->time_finish; } return 0; } /* query_discussion_time_finish() */ /** * This method returns the timeout time of the current discussion item. * @param club_name the name of the club * @param id the id of the discussion item * @return the time at which the dicussion item will finish */ int query_discussion_time_added(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog) { return frog->time_finish; } return 0; } /* query_discussion_time_added() */ /** * This method returns the optional data of the discussion item. * @param club_name the name of the club * @param id the id of the discussion item * @return the optional data in the club */ mixed query_discussion_optional_data(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog) { return frog->optional_data; } return 0; } /* query_discussion_optional_data() */ /** * This method returns the nomination mapping for the discussion item * if it exists. The nomination mapping is of the format:<br> * <pre> * ([ * name : ({ nomated_by, nominated_by, ... }) * .. * ]) * </pre> * @param club_name the name of the club * @param id the id of the discussion item * @return the mapping as described above */ mapping query_discussion_nomination(string club_name, int id) { class discussion_idea frog; mapping stuff; frog = query_discussion_item(club_name, id); if (frog) { stuff = send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_NOMINATION_QUERY, frog, 0, 0); if (stuff) { return stuff; } return ([ ]); } return ([ ]); } /* query_discussion_nomination() */ /** * This method checks to see if the given nomination has already been * done. * @param club_name the name of the club * @param id the id of the discussion ite, * @param nominator the person doing the nomination * @param nominated the person being nominated * @return 1 if they are already nominated, 0 if not */ int is_discuss_person_nominated(string club_name, int id, string nominator, string nominated) { mapping bing; bing = query_discussion_nomination(club_name, id); if (bing[nominated]) { if (member_array(nominator, bing[nominated]) != -1) { return 1; } } return 0; } /* is_discuss_person_nominated() */ /** * This method checks to see if the discussion item is a committee only * item. * @param club_name the name of the club * @param id the id of the discussion item * @return 1 if it is a committee only item, 0 if it is open */ int is_committee_discussion_item(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog) { if (frog->discuss_type & CLUB_DISCUSS_OPEN) { return 0; } return 1; } return 0; } /* is_committee_discussion_item() */ /** * This method checks to see if the discussion item has no quorum * associated with it. * @param club_name the name of the club * @param id the id of the discussion item * @return 1 if it has no quorum, 0 if it is does */ int is_no_quorum_discussion_item(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog) { if (frog->discuss_type & CLUB_DISCUSS_NO_QUORUM) { return 1; } return 0; } return 0; } /* is_no_quorum_discussion_item() */ /** * This method checks to see if the discussion item is completed yet. * @param club_name the name of the club * @param id the id of the discussion item * @return 1 if the discussion item is finished * @see vote_for_discussion_item() */ int is_discussion_item_finished(string club_name, int id) { class discussion_idea frog; string *committee; frog = query_discussion_item(club_name, id); if (frog) { /* * If this is a committee only item, then if all the committee have * voted it is finished. */ if (is_committee_discussion_item(club_name, id)) { // Check to see if everyone has voted. committee = query_committee(club_name); if (committee && !sizeof(committee - frog->voted)) { return 1; } } // See if it has run to its completion time. if (frog->time_finish < time()) { return 1; } } return 0; } /* is_discussion_item_finished() */ /** * This method returns the number of people needed for quorum * in this discussion item. * @param club_name the name of the club to check for quorum * @param id the discussion item id * @return the number of people needed for quorum */ int query_discussion_item_quorum_number(string club_name, int id) { class discussion_idea bing; int num; bing = query_discussion_item(club_name, id); // No need for a quorum on this item. if (is_no_quorum_discussion_item(club_name, id)) { return 0; } else if (is_committee_discussion_item(club_name, id)) { /* Quorum is 75% of the (active) committee... */ num = sizeof(filter(query_committee(club_name), (: $1 != CLUB_UNKNOWN_MEMBER && PLAYER_HANDLER->test_active($1) :))); return (num * CLUB_DISCUSS_QUORUM_COMMITTEE / 100); } else { /* Only require 50% of the (active) general assembly to vote. */ num = sizeof(filter(query_members(club_name), (: $1 != CLUB_UNKNOWN_MEMBER && PLAYER_HANDLER->test_active($1, 1) :))); return (num * CLUB_DISCUSS_QUORUM_OPEN / 100); } return 0; } /* query_discussion_item_quorum_number() */ /** * This method returns the number of people who have voted for the * discussion item. * @param club_name the name of the club to check for quorum * @param id the discussion item id * @return the number of people who have voted */ int query_discussion_item_number_voted(string club_name, int id) { class discussion_idea bing; bing = query_discussion_item(club_name, id); if (bing) { return sizeof(bing->voted); } return 0; } /* query_discussion_item_quorum_number() */ /** * This method checks to see if quorum has been reached or not * for the club. * @param club_name the name of the club to check for quorum * @param id the discussion item id * @return 1 if quorum is reached, 0 if not */ int is_discussion_item_quorum(string club_name, int id) { class discussion_idea bing; int num; bing = query_discussion_item(club_name, id); if (bing) { num = query_discussion_item_quorum_number(club_name, id); if (sizeof(bing->voted) >= num) { return 1; } } return 0; } /* is_discussion_item_quorum() */ /** * This checks to see if the specified choice is a real discussion item * choice. * @param club_name the name of the club * @param id the id of the discussion item * @param choice the choice to check */ int is_valid_discussion_choice(string club_name, int id, string choice) { class discussion_idea frog; frog = query_discussion_item(club_name, id); choice = lower_case(choice); if (frog && !undefinedp(frog->choices[choice])) { return 1; } return 0; } /* is_valid_discussion_choice() */ /** * This method checks to see if the discussion item is a votable * item or not. * @param club_name the name of the club * @param id the id of the discussion item * @return 1 if it is votable, 0 if not */ int is_discuss_votable(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog) { if (send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_TYPE, frog, 0, 0) == CLUB_DISCUSS_MESSAGE_TYPE_VOTE) { return 1; } } return 0; } /* is_discuss_votable() */ /** * This method checks to see if the discussion item is a votable * item or not. * @param club_name the name of the club * @param id the id of the discussion item * @return 1 if it is votable, 0 if not */ int is_discuss_nominateable(string club_name, int id) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog) { if (send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_TYPE, frog, 0, 0) == CLUB_DISCUSS_MESSAGE_TYPE_NOMINATE) { return 1; } } return 0; } /* is_discuss_nominateable() */ /** * This method checks to see if the specified person can see the * discussion idea. * @param club_name the name of the club * @param id the id of the discussion idea * @param person the name of the person * @see vote_for_discussion_item() */ int can_reference_discussion_item(string club_name, int id, string person) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog && (!is_committee_discussion_item(club_name, id) || holds_any_position_of(club_name, person))) { return 1; } return 0; } /* can_reference_discussion_item() */ /** * This method checks to see if the specified person has already voted for * this discussion item. * @param club_name the name of the club * @param id the id of the discussion item * @param person the name of the person to check */ int has_voted_for_discussion_item(string club_name, int id, string person) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog && member_array(person, frog->voted) != -1) { return 1; } return 0; } /* has_voted_for_discussion_item() */ /** * This method sets up the discussion item as being voted by the * person specified. * @param club_name the name of the club * @param id the id of the discussion item * @param person the person doing the voting * @param choice the choices there are to vote on * @see add_discussion_item() */ int vote_for_discussion_item(string club_name, int id, string person, string choice) { class discussion_idea frog; frog = query_discussion_item(club_name, id); choice = lower_case(choice); if (frog && can_reference_discussion_item(club_name, id, person) && !has_voted_for_discussion_item(club_name, id, person) && is_valid_discussion_choice(club_name, id, choice) && is_discuss_votable(club_name, id)) { frog->choices[choice]++; frog->voted += ({ person }); set_club_changed(club_name); return 1; } return 0; } /* vote_for_discussion_item() */ /** * This message does the nomination thing for those discussion items * which accept nominations. * @param club_name the name of the club * @param id the id of the discussion item * @param nominator the person doing the nomination * @param nominated the person nominated */ int nominate_discussion_item(string club_name, int id, string nominator, string nominated) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog && is_member_of(club_name, nominator) && is_member_of(club_name, nominated) && is_discuss_nominateable(club_name, id)) { if (!is_creator_club(club_name) && PLAYER_HANDLER->test_creator(nominated)) { return 0; } if (send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_NOMINATION, frog, nominator, nominated)) { set_club_changed(club_name); return 1; } } return 0; } /* nominate_discussion_item() */ /** * This message does the withdraw thing for those discussion items * which accept nominations. * @param club_name the name of the club * @param id the id of the discussion item * @param withdraw the person being withdrawn */ int withdraw_discussion_item(string club_name, int id, string withdraw) { class discussion_idea frog; frog = query_discussion_item(club_name, id); if (frog && is_member_of(club_name, withdraw) && is_discuss_nominateable(club_name, id)) { if (send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_WITHDRAW, frog, withdraw, withdraw)) { set_club_changed(club_name); return 1; } } return 0; } /* withdraw_discussion_item() */ /** * This method removes a discussion item from the club. * @param club_name the name of the club to remove the discussion item * @param item the discusion item to remove * @return 1 on success, 0 on failure */ protected int remove_discussion_item(string club_name, class discussion_idea item) { class election_info bing; int i; bing = (class election_info)query_elected_info(club_name); if (bing) { for (i = 0; i < sizeof(bing->discussion); i++) { if (bing->discussion[i] == item) { bing->discussion = bing->discussion[0..i - 1] + bing->discussion[i + 1..]; set_club_changed(club_name); return 1; } } } return 0; } /* remove_discussion_item() */ /** * This method completes the discussion item. * @param club_name the name of the club * @param id the id of the discussion item * @return 1 if successful, 0 if not * @see add_discussion_item() */ int complete_discussion_item(string club_name, int id) { class discussion_idea frog; class election_info bing; int ret; frog = query_discussion_item(club_name, id); bing = (class election_info)query_elected_info(club_name); if (frog && is_discussion_item_finished(club_name, id)) { if (is_discussion_item_quorum(club_name, id)) { if (_discussion_items[frog->discuss_type & CLUB_DISCUSS_TYPE_MASK]) { send_broadcast_message(club_name, "Finished discussion item: " + send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_SHORT_DESCRIPTION, frog, 0, 0) + " see archives for results."); send_discuss_message(club_name, CLUB_DISCUSS_MESSAGE_COMPLETE, frog, 0, 0); } else { ret = -1; do_mail_committee(club_name, "Completed vote", "The completed vote on:\n" + "Discussion type " + (frog->discuss_type & CLUB_DISCUSS_TYPE_MASK) + " failed due to major internal messes.\n"); } } else { if (_discussion_items[frog->discuss_type & CLUB_DISCUSS_TYPE_MASK]) { do_mail_committee(club_name, "Completed vote", "The completed vote on:\n" + query_discussion_item_long_description(club_name, id) + "\n\nDid not have quorum, only " + sizeof(frog->voted) + " people voted.\n"); } else { do_mail_committee(club_name, "Completed vote", "The completed vote on:\n" + "Discussion type " + (frog->discuss_type & CLUB_DISCUSS_TYPE_MASK) + " failed due to major internal messes.\n"); } ret = -1; } remove_discussion_item(club_name, frog); //bing->discussion -= ({ frog }); //set_club_changed(club_name); } return ret; } /* complete_discussion_item() */ /** * This method sends a message to all the discussion items in the club * and then marks the club as changed if any of them return a non-zero * value. This is used for events like a member being removed of a * position being changed in name. * @param club_name the name of the club * @param message the message number * @param arg1 the first arguement * @param arg2 the second arguement */ protected mixed send_discuss_message(string club_name, int message, class discussion_idea item, string arg1, string arg2) { return evaluate(_discussion_items[item->discuss_type & CLUB_DISCUSS_TYPE_MASK], message, club_name, item, arg1, arg2); } /* send_discuss_message() */ /** * This method sends a message to all the discussion items in the club * and then marks the club as changed if any of them return a non-zero * value. This is used for events like a member being removed of a * position being changed in name. * @param club_name the name of the club * @param message the message number * @param arg1 the first arguement * @param arg2 the second arguement */ protected void broadcast_discuss_message(string club_name, int message, string arg1, string arg2) { class discussion_idea frog; class election_info bing; bing = (class election_info)query_elected_info(club_name); foreach (frog in bing->discussion) { if (send_discuss_message(club_name, message, frog, arg1, arg2)) { set_club_changed(club_name); } } } /* broadcast_discuss_message() */ /* * ----- Methods for checking changes to the club and reporting them to * ----- the discusion items */ /** * Catch the remove member calls and inform the system about them. * @ignore yes */ int remove_member(string name, string member) { if (::remove_member(name, member)) { if (is_elected_club(name)) { broadcast_discuss_message(name, CLUB_DISCUSS_MESSAGE_REMOVE_MEMBER, member, 0); } return 1; } return 0; } /* remove_member() */ /** * Catch the position change call and inform the system about it. * @ignore yes */ int change_position_name_in_club(string name, string position, string new_position) { if (::change_position_name_in_club(name, position, new_position)) { if (is_elected_club(name)) { broadcast_discuss_message(name, CLUB_DISCUSS_MESSAGE_CHANGE_POSITION, position, new_position); } return 1; } return 0; } /* change_position_name_in_club() */ /** * Catch the position removal things... * @ignore yes */ int remove_position_in_club(string name, string position) { if (::remove_position_in_club(name, position)) { if (is_elected_club(name)) { broadcast_discuss_message(name, CLUB_DISCUSS_MESSAGE_REMOVE_POSITION, position, 0); } return 1; } return 0; } /* remove_position_in_club() */ /** * Catch the position holder message and turn it into a nomination. * @ignore yes */ int set_position_holder(string club_name, string position, string person) { if (::set_position_holder(club_name, position, person)) { if (person == CLUB_UNKNOWN_MEMBER) { add_discussion_item(club_name, CLUB_DISCUSS_NOMINATION | CLUB_DISCUSS_NO_QUORUM | CLUB_DISCUSS_OPEN, CLUB_CONTROLLER_MEMBER, position, "Position became vacant.\n", ({ }), 7 * (24 * 60 * 60), 0); } return 1; } return 0; } /* set_position_holder() */ /** * Catch the start election thing and zap all currently running * by-elections. * @ignore yes */ int start_election(string name) { class discussion_idea womble; class election_info data; int type; if (::start_election(name)) { data = (class election_info)query_elected_info(name); foreach (womble in data->discussion) { type = womble->discuss_type & CLUB_DISCUSS_TYPE_MASK; if (type == CLUB_DISCUSS_NOMINATION || type == CLUB_DISCUSS_ELECTION) { remove_discussion_item(name, womble); set_club_changed(name); } } return 1; } return 0; } /* start_election() */ /** @ignore yes */ protected void check_elected_information(string name, string member, int startup) { class election_info data; class discussion_idea frog; string pos; ::check_elected_information(name, member, startup); data = (class election_info)query_elected_info(name); if (data) { foreach (frog in data->discussion) { if (is_discussion_item_finished(name, frog->id)) { complete_discussion_item(name, frog->id); set_club_changed(name); } else if (frog->discuss_type == CLUB_DISCUSS_NOMINATION || frog->discuss_type == CLUB_DISCUSS_ELECTION) { if (!is_election_in_progress(name) && !is_nomination_in_progress(name)) { frog->discuss_type |= CLUB_DISCUSS_OPEN | CLUB_DISCUSS_NO_QUORUM; set_club_changed(name); } else { remove_discussion_item(name, frog); } } } // // Check each position to see if we should start a by election // for it. // foreach (pos, member in data->positions) { if (member == CLUB_UNKNOWN_MEMBER && !is_election_in_progress(name) && !is_nomination_in_progress(name) && !is_nomination_or_election_being_discussed(name, pos)) { /* tell_creator("pinkfish", "Setting up by election for position " + pos + " in club " + name + ": " + member + "\n"); */ setup_by_election(name, pos, "Automatic after the position is declared " "vacant.\n"); set_club_changed(name); } } } } /* check_elected_information() */ /** * This method setups up a by-election for the specified position in the * club. * @param club the club to make a byelection in * @param position the position the byelection is for * @param info the information about the vote * @return 1 on success, 0 on failure */ int setup_by_election(string club, string position, string info) { // Check to make sure that we are not in the election or nomination // Phase right now. If we are too close to this phase we should // wait for the election to happen. return add_discussion_item(club, CLUB_DISCUSS_NOMINATION | CLUB_DISCUSS_OPEN | CLUB_DISCUSS_NO_QUORUM, CLUB_CONTROLLER_MEMBER, position, info, ({ }), 7 * 24 * 60 * 60, 0); } /* setup_by_election() */