Specify the number of leader or helper sessions for each attendee. Note that this will overwrite the previous value.

"); $session_count = array(); $session_count['0'] = 0; $session_count['1'] = 1; $session_count['2'] = 2; $session_count['3'] = 3; $session_count['4'] = 4; $session_count['5'] = 5; $form['booking-leadhelp-count'] = array( '#type' => 'select', '#title' => t('Set Number of Sessions'), '#required' => TRUE, '#default_value' => '0', '#options' => $session_count, ); $header = array ( 'booking_nid' => array('data' => t('Booking ID')), 'booking_name' => array('data' => t('Name')), 'booking_gender' => array('data' => t('Gender')), 'booking_baptised' => array('data' => t('Baptised?')), 'booking_age' => array('data' => t('Age at start of event')), 'booking_lead_sessions' => array('data' => t('Number of groups to lead currently')), 'booking_help_sessions' => array('data' => t('Number of groups to help currently')), ); $result = db_query("SELECT * FROM {booking_person} p left outer join {booking_leadhelp_list} l on p.nid = l.booking_node_id WHERE p.booking_event_id = :eid ORDER BY p.booking_gender DESC, p.booking_dob, p.booking_baptised", array(':eid' => $event->eid)); foreach($result as $data) { $options[$data->nid] = array ( 'booking_nid' => l(t('!id', array('!id' => $data->nid)), t('node/!id', array('!id' => $data->nid))), 'booking_name' => $data->booking_firstname . " " . $data->booking_lastname, 'booking_gender' => $data->booking_gender == 'M' ? 'Male' : 'Female', 'booking_baptised' => $data->booking_baptised == 'Y' ? 'Yes' : 'No', 'booking_age' => _booking_avg_age($data->booking_dob, 1, $event->booking_event_start), 'booking_lead_sessions' => $data->booking_total_lead === NULL ? '0' : $data->booking_total_lead, 'booking_help_sessions' => $data->booking_total_help === NULL ? '0' : $data->booking_total_help, ); } $form['table'] = array ( '#type' => 'tableselect', '#header' => $header, '#options' => $options, '#empty' => t('No attendees found.'), ); $form['submit-leader'] = array ( '#type' => 'submit', '#value' => t('Set Leader'), ); $form['submit-helper'] = array ( '#type' => 'submit', '#value' => t('Set Helper'), ); return array ( 'first_para' => array ( '#type' => 'markup', '#markup' => $prefix, ), 'form' => $form, ); } /** * Process the submission for number of study group sessions to lead/help */ function booking_available_leadhelp_select_form_submit($form, &$form_state) { global $event; $counter = 0; $checkboxes = $form_state['values']['table']; $session_count = $form_state['values']['booking-leadhelp-count']; foreach($checkboxes as $key => $value) { if (is_numeric($key) && $value != 0) { //watchdog('booking', 'Checking !nid for entry in the booking_leadhelp_list table', array ('!nid' => $key)); //check if an entry already exists for this person in the booking_leadhelp_list table $person = db_query("SELECT person.booking_node_id " . "FROM {booking_leadhelp_list} person " . "WHERE booking_node_id = :nid", array(':nid' => $key)) ->fetchObject(); if ($form_state['values']['op'] == 'Set Leader') { watchdog('booking', 'Setting group leader count to !count for !nid', array ('!count' => $session_count, '!nid' => $key)); if ($person) { //run an update db_update('booking_leadhelp_list') ->fields(array ( 'booking_total_lead' => $session_count, 'booking_available_lead' => $session_count, )) ->condition('booking_node_id', $key) ->execute(); } else { //run an insert db_insert('booking_leadhelp_list') ->fields(array( 'booking_eventid' => $event->eid, 'booking_node_id' => $key, 'booking_total_lead' => $session_count, 'booking_available_lead' => $session_count, 'booking_total_help' => 0, 'booking_available_help' => 0, )) ->execute(); } } elseif ($form_state['values']['op'] == 'Set Helper') { watchdog('booking', 'Setting group helper count to !count for !nid', array ('!count' => $session_count, '!nid' => $key)); if ($person) { //run an update db_update('booking_leadhelp_list') ->fields(array ( 'booking_total_help' => $session_count, 'booking_available_help' => $session_count, )) ->condition('booking_node_id', $key) ->execute(); } else { //run an insert db_insert('booking_leadhelp_list') ->fields(array( 'booking_eventid' => $event->eid, 'booking_node_id' => $key, 'booking_total_lead' => 0, 'booking_available_lead' => 0, 'booking_total_help' => $session_count, 'booking_available_help' => $session_count, )) ->execute(); } } $counter++; } } drupal_set_message("Defined leader/helper numbers for $counter people.", 'status', FALSE); watchdog('booking', "Defined leader/helper numbers for $counter people."); } /** * Function for defining the number of study group sessions * Note: This is hard-coded for now in the install file */ /** * Function to correctly clone an associative array storing objects * Taken from http://stackoverflow.com/questions/1532618/is-there-a-function-to-make-a-copy-of-a-php-array-to-another */ function clone_array($copied_array) { return array_map(function($element) { return ( ((is_array($element)) ? call_user_func(__FUNCTION__, $element) : ((is_object($element)) ? clone $element : $element ) ) ); }, $copied_array); } //taken from http://stackoverflow.com/questions/4102777/php-random-shuffle-array-maintaining-key-value function shuffle_assoc($list) { if (!is_array($list)) return $list; $keys = array_keys($list); shuffle($keys); $random = array(); foreach ($keys as $key) { $random[$key] = $list[$key]; } return $random; } /** * Function for calculating who belongs to which study group */ function booking_studygroups_calculate() { global $event; $attendees = array(); $working_list = array(); //consider using a lock as per https://api.drupal.org/api/drupal/includes!lock.inc/group/lock/7 //select all the attendees booked in $query = db_query("SELECT * FROM {booking_person} p left outer join {booking_leadhelp_list} l on p.nid = l.booking_node_id WHERE p.booking_event_id = :eid AND p.booking_status = 1", array(':eid' => $event->eid)); $attendees = $query->fetchAllAssoc('nid'); //iterate over the attendee associative array and add some fields foreach ($attendees as $person) { //flag that indicates processed or not $person->processed = 0; //field that indicates the session id the person is assigned to $person->session = 0; $person->is_leader = 0; $person->is_helper = 0; //convert NULLs into zero $person->booking_total_lead = $person->booking_total_lead === NULL ? '0' : $person->booking_total_lead; $person->booking_available_lead = $person->booking_available_lead === NULL ? '0' : $person->booking_available_lead; $person->booking_total_help = $person->booking_total_help === NULL ? '0' : $person->booking_total_help; $person->booking_available_help = $person->booking_available_help === NULL ? '0' : $person->booking_available_help; } //watchdog('booking', "Attendee list: @info", array('@info' => var_export($attendees, TRUE))); //select all the study groups for this event id $studygroups = db_query("SELECT * FROM {booking_studygroup_list} WHERE booking_eventid = :eid", array(':eid' => $event->eid)); //iterate over each study group (eg Monday Tuesday Wednesday etc) foreach ($studygroups as $group) { drupal_set_message(t('Processing study group !group.', array('!group' => $group->booking_studygroup_descrip))); //create a temporary copy of the attendee list to work with for this study group $working_list = array(); $working_list = shuffle_assoc(clone_array($attendees)); //set up the iterator $obj = new ArrayObject( $working_list ); $it = $obj->getIterator(); //reset the iterator to starting position $it->rewind(); //watchdog('booking', "Attendee list: @info", array('@info' => var_export($attendees, TRUE))); //watchdog('booking', "Attendee list working copy: @info", array('@info' => var_export($working_list, TRUE))); $session_id = 1; $rewound = FALSE; $leader_found = FALSE; $helper_found = FALSE; while (true) { //if we're at the end of the attendee list, go back to the start if (! $it->valid() ) { if ($rewound == TRUE) { watchdog('booking', "Already rewound once."); //we've already gone back to the start once, don't do it again break; } else { watchdog('booking', "Rewinding to start of attendee list."); $it->rewind(); $rewound = TRUE; } } //check if we have reached the total number of sessions required if ($session_id > $group->booking_num_group_sessions) { break; } //check if we can increment the session count if ($leader_found == TRUE && $helper_found == TRUE) { $session_id++; $leader_found = FALSE; $helper_found = FALSE; } //get the current attendee element $current = $it->current(); //watchdog('booking', 'Attendee before leader check has id !id.', array('!id' => $it->key())); //check if this attendee is a leader if ($current->processed == 0 && $current->booking_available_lead > 0 && $leader_found == FALSE) { drupal_set_message(t('Found available leader with id !id for session !session.', array('!id' => $it->key(), '!session' => $session_id))); $leader_found = TRUE; //assign leader to session and mark as processed in the temporary attendee list $current->session = $session_id; $current->processed = 1; $current->is_leader = 1; //decrement the number of available leading positions for this user in our master copy of the attendee list $attendees[$it->key()]->booking_available_lead = $attendees[$it->key()]->booking_available_lead - 1; //Check for spouse of leader, allocate to this group also if ($current->booking_partner_id > 0) { //add the spouse to the same session and mark as processed in the temporary attendee list drupal_set_message(t('Assigning spouse (id !spouse) of id !id to session !session.', array('!id' => $it->key(), '!session' => $session_id, '!spouse' => $current->booking_partner_id))); $spouse = $working_list[$current->booking_partner_id]; $spouse->session = $session_id; $spouse->processed = 1; } } //check if this attendee is a helper elseif ($current->processed == 0 && $current->booking_available_help > 0 && $helper_found == FALSE) { drupal_set_message(t('Found available helper with id !id for session !session.', array('!id' => $it->key(), '!session' => $session_id))); $helper_found = TRUE; //assign leader to session and mark as processed in the temporary attendee list $current->session = $session_id; $current->processed = 1; $current->is_helper = 1; //decrement the number of available helping positions for this user in our master copy of the attendee list $attendees[$it->key()]->booking_available_help = $attendees[$it->key()]->booking_available_help - 1; //Check for spouse of helper, allocate to this group also if ($current->booking_partner_id > 0) { //add the spouse to the same session and mark as processed in the temporary attendee list drupal_set_message(t('Assigning spouse (id !spouse) of id !id to session !session.', array('!id' => $it->key(), '!session' => $session_id, '!spouse' => $current->booking_partner_id))); $spouse = $working_list[$current->booking_partner_id]; $spouse->session = $session_id; $spouse->processed = 1; } } //otherwise go to the next one else { $it->next(); } } //reset the iterator to starting position $it->rewind(); //iterate over the attendee list while ( $it->valid() ) { //go to the first unprocessed attendee while ($it->current()->processed == 1) { drupal_set_message(t('Person with id !id has already been processed earlier.', array('!id' => $it->key()))); $it->next(); //double check we didn't run out of people right here if (! $it->valid() ) { drupal_set_message("Ran out of attendees to process."); break; } } //iterate over the session list //for ($i = 1; $i <= $group->booking_num_group_sessions; $i++) for ($i = 1; $i <= 16; $i++) { //check we have attendees left if (! $it->valid() ) { drupal_set_message("Ran out of attendees to process."); break; } //get the current attendee element $current = $it->current(); //assign this attendee to this session if unprocessed so far if ($current->processed == 0) { drupal_set_message(t('Assigning person with id !id to session !session.', array('!id' => $it->key(), '!session' => $i))); $current->session = $i; $current->processed = 1; //check if the attendee was married if ($current->booking_partner_id > 0) { //add the spouse to the same session and mark as processed in the temporary attendee list drupal_set_message(t('Assigning spouse (id !spouse) of id !id to session !session.', array('!id' => $it->key(), '!session' => $i, '!spouse' => $current->booking_partner_id))); $spouse = $working_list[$current->booking_partner_id]; $spouse->session = $i; $spouse->processed = 1; } } //move to the next unprocessed attendee in the list while ($it->valid() && $it->current()->processed == 1) $it->next(); } //finished looping through session list } //finished looping through attendees for this study group //iterate over the attendee list and write to the database the session they're assigned to //use the multi-insert query type at https://drupal.org/node/310079 //TODO: a check to update existing records rather than inserting new ones $query = db_insert('booking_studygroup_mapping')->fields(array('booking_eventid', 'booking_node_id', 'booking_studygroup_id', 'booking_session_id', 'booking_is_leader', 'booking_is_helper')); foreach($working_list as $person) { $record = array( 'booking_eventid' => $event->eid, 'booking_node_id' => $person->nid, 'booking_studygroup_id' => $group->sid, 'booking_session_id' => $person->session, 'booking_is_leader' => $person->is_leader, 'booking_is_helper' => $person->is_helper, ); $query->values($record); } $query->execute(); } //finished processing study groups //watchdog('booking', "Attendee list final version: @info", array('@info' => var_export($attendees, TRUE))); } /** * Function for viewing who belongs to which study group */ function booking_studygroups_view() { global $event; }