Exemplo n.º 1
0
 /**
  * Add all the links for a division to the menu.
  */
 function _addDivisionMenuItems($division, $league, $id = null, $name = null)
 {
     Configure::load("sport/{$league['sport']}");
     if ($id) {
         $path = array(__('Leagues', true), $name);
     } else {
         $path = array(__('Leagues', true));
     }
     if (!array_key_exists('league_name', $division)) {
         Division::_addNames($division, $league);
     }
     $is_coordinator = in_array($division['id'], $this->UserCache->read('DivisionIDs'));
     $is_manager = $this->is_manager && in_array($league['affiliate_id'], $this->UserCache->read('ManagedAffiliateIDs'));
     if (array_key_exists('Division', $league)) {
         $division_count = count($league['Division']);
     } else {
         $division_count = $this->requestAction(array('controller' => 'leagues', 'action' => 'division_count'), array('named' => array('league' => $league['id'])));
     }
     if ($division_count == 1) {
         $this->_addMenuItem($division['league_name'], array('controller' => 'leagues', 'action' => 'view', 'league' => $league['id']), $path);
         $path[] = $division['league_name'];
     } else {
         $this->_addMenuItem($league['name'], array('controller' => 'leagues', 'action' => 'view', 'league' => $league['id']), $path);
         $path[] = $league['name'];
         if (!empty($division['name'])) {
             $this->_addMenuItem($division['name'], array('controller' => 'divisions', 'action' => 'view', 'division' => $division['id']), $path);
             $path[] = $division['name'];
         }
     }
     $this->_addMenuItem(__('Schedule', true), array('controller' => 'divisions', 'action' => 'schedule', 'division' => $division['id']), $path);
     $this->_addMenuItem(__('Standings', true), array('controller' => 'divisions', 'action' => 'standings', 'division' => $division['id']), $path);
     if ($this->is_logged_in) {
         if ($division['schedule_type'] != 'competition') {
             $this->_addMenuItem(__('Scores', true), array('controller' => 'divisions', 'action' => 'scores', 'division' => $division['id']), $path);
         }
         if (League::hasStats($league)) {
             $this->_addMenuItem(__('Stats', true), array('controller' => 'divisions', 'action' => 'stats', 'division' => $division['id']), $path);
         }
     }
     if ($this->is_admin || $is_manager || $is_coordinator) {
         $this->_addMenuItem(__('Add Games', true), array('controller' => 'schedules', 'action' => 'add', 'division' => $division['id']), array_merge($path, array('Schedule')));
         if ($division['schedule_type'] != 'competition') {
             $this->_addMenuItem(__('Approve scores', true), array('controller' => 'divisions', 'action' => 'approve_scores', 'division' => $division['id']), $path);
         }
         if ($division_count == 1) {
             $this->_addMenuItem(__('Edit', true), array('controller' => 'leagues', 'action' => 'edit', 'league' => $league['id']), $path);
         } else {
             $this->_addMenuItem(__('Edit', true), array('controller' => 'divisions', 'action' => 'edit', 'division' => $division['id']), $path);
         }
         $this->_addMenuItem(sprintf(__('%s distribution', true), __(Configure::read('sport.field_cap'), true)), array('controller' => 'divisions', 'action' => 'fields', 'division' => $division['id']), $path);
         $this->_addMenuItem(sprintf(__('%s availability', true), __(Configure::read('sport.field_cap'), true)), array('controller' => 'divisions', 'action' => 'slots', 'division' => $division['id']), $path);
         $this->_addMenuItem(__('Status report', true), array('controller' => 'divisions', 'action' => 'status', 'division' => $division['id']), $path);
         if (Configure::read('scoring.allstars') && $division['allstars'] != 'never') {
             $this->_addMenuItem(__('All stars', true), array('controller' => 'divisions', 'action' => 'allstars', 'division' => $division['id']), $path);
         }
         $this->_addMenuItem(__('Captain emails', true), array('controller' => 'divisions', 'action' => 'emails', 'division' => $division['id']), $path);
         if (League::hasSpirit($league)) {
             $this->_addMenuItem(__('Spirit Report', true), array('controller' => 'divisions', 'action' => 'spirit', 'division' => $division['id']), $path);
             $this->_addMenuItem(__('Download', true), array('controller' => 'divisions', 'action' => 'spirit', 'division' => $division['id'], 'ext' => 'csv'), array_merge($path, array('Spirit Report')));
         }
         $this->_addMenuItem(__('Adjust seeds', true), array('controller' => 'divisions', 'action' => 'seeds', 'division' => $division['id']), $path);
     }
     if ($this->is_admin) {
         $this->_addMenuItem(__('Add coordinator', true), array('controller' => 'divisions', 'action' => 'add_coordinator', 'division' => $division['id']), $path);
     }
     // Some items are only applicable depending on league configuration
     if (!empty($division['schedule_type'])) {
         $league_obj = $this->_getComponent('LeagueType', $division['schedule_type'], $this);
         $league_obj->addMenuItems($division, $path, $is_coordinator || $is_manager);
     }
 }
Exemplo n.º 2
0
 /**
  * Take what is currently known about the game, and finalize it.
  * If we have:
  * 	0) no scores entered
  * 		- forfeit game as 0-0 tie
  * 		- give poor spirit to both
  * 	1) one score entered
  * 		- use single score as final
  * 		- give full spirit to entering team, assigned spirit, less
  * 		  some configurable penalty, to non-entering team.
  * 	2) two scores entered, not agreeing
  * 		- send email to the coordinator(s).
  *  3) two scores entered, agreeing
  *  	- scores are entered as provided, as are spirit values.
  */
 function _finalizeGame($game)
 {
     // Initialize data to be saved
     $data = array('Game' => array('id' => $game['Game']['id'], 'status' => 'normal'));
     if (League::hasSpirit($game['Division']['League'])) {
         $spirit_obj = $this->_getComponent('Spirit', $game['Division']['League']['sotg_questions'], $this);
     }
     $home_entry = $this->Game->_get_score_entry($game, $game['Game']['home_team']);
     $away_entry = $this->Game->_get_score_entry($game, $game['Game']['away_team']);
     if ($home_entry && $away_entry) {
         if ($this->Game->_score_entries_agree($home_entry, $away_entry)) {
             $data['Game']['status'] = $home_entry['status'];
             if ($home_entry['status'] == 'normal') {
                 // No default.  Just finalize score.
                 $data['Game']['home_score'] = $home_entry['score_for'];
                 $data['Game']['away_score'] = $home_entry['score_against'];
                 $data['Game']['home_carbon_flip'] = $home_entry['home_carbon_flip'];
             }
             $data['Game']['approved_by'] = APPROVAL_AUTOMATIC;
         } else {
             // Maybe send a notification email to the convener
             // TODO: Do this on a recurring basis, every few days, instead of just once
             if (empty($game['ScoreMismatchEmail'])) {
                 $this->set(compact('game'));
                 if ($this->_sendMail(array('to' => $game['Division'], 'subject' => 'Score entry mismatch', 'template' => 'score_entry_mismatch', 'sendAs' => 'both'))) {
                     $this->Game->ScoreMismatchEmail->create();
                     $this->Game->ScoreMismatchEmail->save(array('type' => 'email_score_mismatch', 'game_id' => $game['Game']['id']));
                 }
             }
             return __('This score doesn\'t agree with the one your opponent submitted. Because of this, the score will not be posted until your coordinator approves it. Alternately, whichever coach or captain made an error can edit their submission.', true);
         }
     } else {
         if ($home_entry && !$away_entry) {
             $data['Game']['status'] = $home_entry['status'];
             switch ($home_entry['status']) {
                 case 'home_default':
                     if (isset($spirit_obj)) {
                         $this->_spiritTeams($game['Game']['home_team'], $game['Game']['away_team'], $data);
                         $this->_spiritMerge($game['Game']['home_team'], $spirit_obj->defaulted(), $data);
                     }
                     break;
                 case 'away_default':
                     if (isset($spirit_obj)) {
                         $this->_spiritTeams($game['Game']['home_team'], $game['Game']['away_team'], $data);
                         $this->_spiritMerge($game['Game']['home_team'], $spirit_obj->expected(), $data);
                     }
                     break;
                 case 'normal':
                     $data['Game']['home_score'] = $home_entry['score_for'];
                     $data['Game']['away_score'] = $home_entry['score_against'];
                     $data['Game']['home_carbon_flip'] = $home_entry['home_carbon_flip'];
                     if (isset($spirit_obj)) {
                         $this->_spiritTeams($game['Game']['home_team'], $game['Game']['away_team'], $data);
                         $this->_spiritMerge($game['Game']['home_team'], $spirit_obj->expected(), $data);
                     }
                     break;
                 default:
                     $data['Game']['home_score'] = $data['Game']['away_score'] = null;
                     break;
             }
             if (isset($spirit_obj) && !in_array($home_entry['status'], Configure::read('unplayed_status'))) {
                 $penalty = Configure::read('scoring.missing_score_spirit_penalty');
                 $data['SpiritEntry'][$game['Game']['away_team']] = array('id' => $game['SpiritEntry'][$game['Game']['away_team']]['id'], 'entered_sotg' => max(0, $game['SpiritEntry'][$game['Game']['away_team']]['entered_sotg'] - $penalty), 'score_entry_penalty' => -$penalty);
             }
             $data['Game']['approved_by'] = APPROVAL_AUTOMATIC_HOME;
             $this->_remindTeam($game, $game['AwayTeam'], $game['HomeTeam'], 'score_approval', 'notification of score approval', false);
         } else {
             if (!$home_entry && $away_entry) {
                 $data['Game']['status'] = $away_entry['status'];
                 switch ($away_entry['status']) {
                     case 'away_default':
                         if (isset($spirit_obj)) {
                             $this->_spiritTeams($game['Game']['away_team'], $game['Game']['home_team'], $data);
                             $this->_spiritMerge($game['Game']['away_team'], $spirit_obj->defaulted(), $data);
                         }
                         break;
                     case 'home_default':
                         if (isset($spirit_obj)) {
                             $this->_spiritTeams($game['Game']['away_team'], $game['Game']['home_team'], $data);
                             $this->_spiritMerge($game['Game']['away_team'], $spirit_obj->expected(), $data);
                         }
                         break;
                     case 'normal':
                         $data['Game']['home_score'] = $away_entry['score_against'];
                         $data['Game']['away_score'] = $away_entry['score_for'];
                         $data['Game']['home_carbon_flip'] = $away_entry['home_carbon_flip'];
                         if (isset($spirit_obj)) {
                             $this->_spiritTeams($game['Game']['away_team'], $game['Game']['home_team'], $data);
                             $this->_spiritMerge($game['Game']['away_team'], $spirit_obj->expected(), $data);
                         }
                         break;
                 }
                 if (isset($spirit_obj) && !in_array($away_entry['status'], Configure::read('unplayed_status'))) {
                     $penalty = Configure::read('scoring.missing_score_spirit_penalty');
                     $data['SpiritEntry'][$game['Game']['home_team']] = array('id' => $game['SpiritEntry'][$game['Game']['home_team']]['id'], 'entered_sotg' => max(0, $game['SpiritEntry'][$game['Game']['home_team']]['entered_sotg'] - $penalty), 'score_entry_penalty' => -$penalty);
                 }
                 $data['Game']['approved_by'] = APPROVAL_AUTOMATIC_AWAY;
                 $this->_remindTeam($game, $game['HomeTeam'], $game['AwayTeam'], 'score_approval', 'notification of score approval', false);
             } else {
                 if (!$home_entry && !$away_entry) {
                     // TODO: don't do automatic forfeit yet.  Make it per-league configurable
                     return __('No score entry found for either team; cannot finalize this game.', true);
                 }
             }
         }
     }
     // Possibly adjust the score if the game status changed
     $this->_adjustScoreAndRatings($game, $data);
     if (!$this->Game->saveAll($data)) {
         return __('Could not successfully save game results.', true);
     }
     // Delete score entries
     $this->Game->ScoreEntry->deleteAll(array('game_id' => $game['Game']['id']));
     $this->_updateDependencies($game, $data['Game']['home_score'] > $data['Game']['away_score']);
     Cache::delete("division/{$game['Division']['id']}/standings", 'long_term');
     Cache::delete("division/{$game['Division']['id']}/schedule", 'long_term');
     Cache::delete('league/' . $this->Game->Division->league($game['Division']['id']) . '/standings', 'long_term');
     Cache::delete('league/' . $this->Game->Division->league($game['Division']['id']) . '/schedule', 'long_term');
     return true;
 }
Exemplo n.º 3
0
 function submit_score()
 {
     $id = $this->_arg('slot');
     if (!$id) {
         $this->Session->setFlash(sprintf(__('Invalid %s', true), __('game slot', true)), 'default', array('class' => 'info'));
         $this->redirect('/');
     }
     $this->GameSlot->contain(array('Game' => array('HomeTeam', 'HomePoolTeam' => 'DependencyPool', 'Division' => 'League'), 'Field' => array('Facility' => 'Region')));
     $gameSlot = $this->GameSlot->read(null, $id);
     if (!$gameSlot) {
         $this->Session->setFlash(sprintf(__('Invalid %s', true), __('game slot', true)), 'default', array('class' => 'info'));
         $this->redirect('/');
     }
     if (empty($gameSlot['Game'])) {
         $this->Session->setFlash(__('This game slot has no games associated with it.', true), 'default', array('class' => 'info'));
         $this->redirect('/');
     }
     $game = $gameSlot['Game'][0];
     if ($game['Division']['schedule_type'] != 'competition') {
         $this->Session->setFlash(__('You can only enter scores for multiple games in "competition" divisions.', true), 'default', array('class' => 'info'));
         $this->redirect('/');
     }
     if (Game::_is_finalized($game)) {
         $this->Session->setFlash(__('Games in this slot have already been finalized.', true), 'default', array('class' => 'info'));
         $this->redirect('/');
     }
     $end_time = strtotime("{$gameSlot['GameSlot']['game_date']} {$gameSlot['GameSlot']['display_game_end']}") + Configure::read('timezone.adjust') * 60;
     if ($end_time - 60 * 60 > time()) {
         $this->Session->setFlash(__('That game has not yet occurred!', true), 'default', array('class' => 'info'));
         $this->redirect('/');
     }
     // We need this in a couple of places
     if (League::hasSpirit($game['Division']['League'])) {
         $spirit_obj = $this->_getComponent('Spirit', $game['Division']['League']['sotg_questions'], $this);
     }
     $this->Configuration->loadAffiliate($gameSlot['Field']['Facility']['Region']['affiliate_id']);
     Configure::load("sport/{$game['Division']['League']['sport']}");
     $ratings_obj = $this->_getComponent('Ratings', $game['Division']['rating_calculator'], $this);
     $this->set(compact('gameSlot'));
     if (!empty($this->data)) {
         $teams = $games = $incidents = $errors = array();
         $unplayed = in_array($this->data['Game']['status'], Configure::read('unplayed_status'));
         // We could put these as hidden fields in the form, but we'd need to
         // validate them against the values from the URL anyway, so it's
         // easier to just set them directly here.
         // We use the team_id as the array index, here and in the views,
         // because order matters, and this is a good way to ensure that
         // the correct data gets into the correct form.
         foreach ($gameSlot['Game'] as $i => $game) {
             if (!array_key_exists($game['home_team'], $this->data['Game'])) {
                 $errors[$game['home_team']]['home_score'] = 'Scores must be entered for all teams.';
             } else {
                 $details = $this->data['Game'][$game['home_team']];
                 if ($unplayed) {
                     $score = $rating = null;
                 } else {
                     $score = $details['home_score'];
                     $rating = $ratings_obj->calculateRatingsChange($details['home_score']);
                     $teams[$game['home_team']] = array('id' => $game['home_team'], 'rating' => $game['HomeTeam']['rating'] + $rating, 'seed' => 0);
                 }
                 $games[$game['home_team']] = array('id' => $game['id'], 'status' => $this->data['Game']['status'], 'home_score' => $score, 'rating_points' => $rating, 'approved_by' => $this->UserCache->currentId());
                 if ($details['incident']) {
                     $incidents[$game['home_team']] = array('game_id' => $game['id'], 'team_id' => $game['home_team'], 'type' => $details['type'], 'details' => $details['details'], 'game' => $game);
                 }
             }
         }
         if (!empty($errors)) {
             $this->GameSlot->Game->validationErrors = $errors;
         } else {
             $transaction = new DatabaseTransaction($this->GameSlot);
             if ($this->GameSlot->Game->saveAll($games, array('validate' => 'first'))) {
                 if (Configure::read('scoring.incident_reports') && !empty($incidents)) {
                     if (!$this->GameSlot->Game->Incident->saveAll($incidents, array('validate' => 'first'))) {
                         $this->Session->setFlash(sprintf(__('The %s could not be saved. Please correct the errors below and try again.', true), __('incident data', true)), 'default', array('class' => 'warning'));
                         return;
                     }
                 }
                 // TODO: Replace this with a call to GamesController::_adjustScoreAndRatings, which will
                 // need to be moved to a shared location and adjusted to handle competition differences.
                 // For now, all that function does that this doesn't is stats, and we have no idea how
                 // stats might play out in competition divisions, so this will suffice.
                 $this->GameSlot->Game->Division->Team->saveAll($teams);
                 $transaction->commit();
                 foreach ($gameSlot['Game'] as $i => $game) {
                     Cache::delete("division/{$game['Division']['id']}/standings", 'long_term');
                     Cache::delete("division/{$game['Division']['id']}/schedule", 'long_term');
                     Cache::delete('league/' . $this->GameSlot->Game->Division->league($game['Division']['id']) . '/standings', 'long_term');
                     Cache::delete('league/' . $this->GameSlot->Game->Division->league($game['Division']['id']) . '/schedule', 'long_term');
                 }
                 $resultMessage = __('Scores have been saved and game results posted.', true);
                 $resultClass = 'success';
                 // TODO: Check for changes to the incident text to avoid sending a duplicate email,
                 // and we probably want to change the text of the email slightly to let the recipient
                 // know that it's an update instead of a new incident.
                 // TODO: Combine code from here and games controller?
                 $incidentMessage = '';
                 if (Configure::read('scoring.incident_reports')) {
                     $addr = Configure::read('email.incident_report_email');
                     foreach ($incidents as $incident) {
                         $this->set(array('incident' => $incident, 'game' => $incident['game'], 'division' => $incident['game']['Division'], 'slot' => $gameSlot['GameSlot'], 'field' => $gameSlot['Field'], 'home_team' => $incident['game']['HomeTeam']));
                         if ($this->_sendMail(array('to' => "Incident Manager <{$addr}>", 'replyTo' => $this->UserCache->read('Person.email_formatted'), 'subject' => "Incident report: {$incident['type']}", 'template' => 'incident_report', 'sendAs' => 'html'))) {
                             // TODO: Maybe send the incident report before saving data, and add in a column for
                             // whether it was sent, thus allowing the cron to attempt to re-send it?
                             $incidentMessage = ' ' . __('Your incident report details have been sent for handling.', true);
                         } else {
                             App::import('Helper', 'Html');
                             $html = new HtmlHelper();
                             $link = $html->link($addr, "mailto:{$addr}");
                             $incidentMessage = ' ' . sprintf(__('There was an error sending your incident report details. Please send them to %s to ensure proper handling.', true), $link);
                             $resultClass = 'warning';
                         }
                     }
                 }
                 $resultMessage .= $incidentMessage;
                 if ($resultMessage) {
                     $this->Session->setFlash($resultMessage, 'default', array('class' => $resultClass));
                 }
                 $this->redirect('/');
             } else {
                 $this->Session->setFlash(sprintf(__('The %s could not be saved. Please correct the errors below and try again.', true), __('scores', true)), 'default', array('class' => 'warning'));
             }
         }
     }
 }