diff --git a/booking.studygroups.inc b/booking.studygroups.inc new file mode 100644 index 0000000..e6902a0 --- /dev/null +++ b/booking.studygroups.inc @@ -0,0 +1,432 @@ +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); +} + +/** + * 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; + //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 = 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) + { + 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; + + //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) + { + 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; + + //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 attendee in the list + $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 + } //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; + +}