private function _createMessage($match, $messageType, $playerNames = null, $isHomeActive = TRUE)
 {
     if (!isset($this->_availableTexts[$messageType])) {
         return;
     }
     $texts = count($this->_availableTexts[$messageType]);
     $index = SimulationHelper::getMagicNumber(0, $texts - 1);
     $messageId = $this->_availableTexts[$messageType][$index];
     $players = '';
     if ($playerNames != null) {
         $players = implode(';', $playerNames);
     }
     $fromTable = $this->_websoccer->getConfig('db_prefix') . '_matchreport';
     $columns['match_id'] = $match->id;
     $columns['minute'] = $match->minute;
     $columns['message_id'] = $messageId;
     $columns['playernames'] = $players;
     $columns['active_home'] = $isHomeActive;
     $this->_db->queryInsert($columns, $fromTable);
 }
 private function createYouthPlayer($clubId, $scout, $country)
 {
     $firstName = $this->getItemFromFile(NAMES_DIRECTORY . "/" . $country . "/firstnames.txt");
     $lastName = $this->getItemFromFile(NAMES_DIRECTORY . "/" . $country . "/lastnames.txt");
     // strength computation (always compute since plug-ins might override scouting-success-flag)
     $minStrength = (int) $this->_websoccer->getConfig("youth_scouting_min_strength");
     $maxStrength = (int) $this->_websoccer->getConfig("youth_scouting_max_strength");
     $scoutFactor = $scout["expertise"] / 100;
     $strength = $minStrength + round(($maxStrength - $minStrength) * $scoutFactor);
     // consider random deviation
     $deviation = (int) $this->_websoccer->getConfig("youth_scouting_standard_deviation");
     $strength = $strength + SimulationHelper::getMagicNumber(0 - $deviation, $deviation);
     $strength = max($minStrength, min($maxStrength, $strength));
     // make sure that condigured boundaries are not violated
     // determine position
     if ($scout["speciality"] == "Torwart") {
         $positionProbabilities = array("Torwart" => 40, "Abwehr" => 30, "Mittelfeld" => 25, "Sturm" => 5);
     } elseif ($scout["speciality"] == "Abwehr") {
         $positionProbabilities = array("Torwart" => 10, "Abwehr" => 50, "Mittelfeld" => 30, "Sturm" => 10);
     } elseif ($scout["speciality"] == "Mittelfeld") {
         $positionProbabilities = array("Torwart" => 10, "Abwehr" => 15, "Mittelfeld" => 60, "Sturm" => 15);
     } elseif ($scout["speciality"] == "Sturm") {
         $positionProbabilities = array("Torwart" => 5, "Abwehr" => 15, "Mittelfeld" => 40, "Sturm" => 40);
     } else {
         $positionProbabilities = array("Torwart" => 15, "Abwehr" => 30, "Mittelfeld" => 35, "Sturm" => 20);
     }
     $position = SimulationHelper::selectItemFromProbabilities($positionProbabilities);
     $minAge = $this->_websoccer->getConfig("youth_scouting_min_age");
     $maxAge = $this->_websoccer->getConfig("youth_min_age_professional");
     $age = $minAge + SimulationHelper::getMagicNumber(0, abs($maxAge - $minAge));
     // create player
     $this->_db->queryInsert(array("team_id" => $clubId, "firstname" => $firstName, "lastname" => $lastName, "age" => $age, "position" => $position, "nation" => $country, "strength" => $strength), $this->_websoccer->getConfig("db_prefix") . "_youthplayer");
     // trigger event for plug-ins
     $event = new YouthPlayerScoutedEvent($this->_websoccer, $this->_db, $this->_i18n, $clubId, $scout["id"], $this->_db->getLastInsertedId());
     PluginMediator::dispatchEvent($event);
     // create success message
     $this->_websoccer->addFrontMessage(new FrontMessage(MESSAGE_TYPE_SUCCESS, $this->_i18n->getMessage("youthteam_scouting_success"), $this->_i18n->getMessage("youthteam_scouting_success_details", $firstName . " " . $lastName)));
 }
 /**
  * Computes a tackle between the player with ball and an opponent player who will be picked by this implementation.
  * Also triggers yellow/red cards, as well as injuries and penalties.
  * 
  * @see ISimulationStrategy::tackle()
  */
 public function tackle(SimulationMatch $match)
 {
     $player = $match->getPlayerWithBall();
     $opponentTeam = SimulationHelper::getOpponentTeam($player, $match);
     $targetPosition = $this->_opponentPositions[$player->position];
     $opponent = SimulationHelper::selectPlayer($opponentTeam, $targetPosition, null);
     // can win?
     $pWin[TRUE] = max(1, min(50 + $player->getTotalStrength($this->_websoccer, $match) - $opponent->getTotalStrength($this->_websoccer, $match), 99));
     $pWin[FALSE] = 100 - $pWin[TRUE];
     $result = SimulationHelper::selectItemFromProbabilities($pWin);
     foreach ($this->_observers as $observer) {
         $observer->onAfterTackle($match, $result ? $player : $opponent, $result ? $opponent : $player);
     }
     // player can keep the ball.
     if ($result == TRUE) {
         // opponent: yellow / redcard
         $pTackle['yellow'] = round(max(1, min(20, round((100 - $opponent->strengthTech) / 2))) * $this->_websoccer->getConfig('sim_cardsprobability') / 100);
         // prevent too many yellow-red cards
         if ($opponent->yellowCards > 0) {
             $pTackle['yellow'] = round($pTackle['yellow'] / 2);
         }
         $pTackle['red'] = 1;
         // if chances for yellow card is very high, then also chances for red card increased
         if ($pTackle['yellow'] > 15) {
             $pTackle['red'] = 3;
         }
         $pTackle['fair'] = 100 - $pTackle['yellow'] - $pTackle['red'];
         $tackled = SimulationHelper::selectItemFromProbabilities($pTackle);
         if ($tackled == 'yellow' || $tackled == 'red') {
             // player might have injury
             $pInjured[TRUE] = min(99, round((100 - $player->strengthFreshness) / 3 * $this->_websoccer->getConfig('sim_injuredprobability') / 100));
             $pInjured[FALSE] = 100 - $pInjured[TRUE];
             $injured = SimulationHelper::selectItemFromProbabilities($pInjured);
             $blockedMatches = 0;
             if ($injured) {
                 $maxMatchesInjured = (int) $this->_websoccer->getConfig('sim_maxmatches_injured');
                 $pInjuredMatches[1] = 5;
                 $pInjuredMatches[2] = 25;
                 $pInjuredMatches[3] = 30;
                 $pInjuredMatches[4] = 20;
                 $pInjuredMatches[5] = 5;
                 $pInjuredMatches[6] = 5;
                 $pInjuredMatches[7] = 5;
                 $pInjuredMatches[8] = 1;
                 $pInjuredMatches[9] = 1;
                 $pInjuredMatches[10] = 1;
                 $pInjuredMatches[11] = 1;
                 $pInjuredMatches[$maxMatchesInjured] = 1;
                 $blockedMatches = SimulationHelper::selectItemFromProbabilities($pInjuredMatches);
                 $blockedMatches = min($maxMatchesInjured, $blockedMatches);
             }
             foreach ($this->_observers as $observer) {
                 if ($tackled == 'yellow') {
                     $observer->onYellowCard($match, $opponent);
                 } else {
                     // number of blocked matches
                     $maxMatchesBlocked = (int) $this->_websoccer->getConfig('sim_maxmatches_blocked');
                     $minMatchesBlocked = min(1, $maxMatchesBlocked);
                     $blockedMatchesRedCard = SimulationHelper::getMagicNumber($minMatchesBlocked, $maxMatchesBlocked);
                     $observer->onRedCard($match, $opponent, $blockedMatchesRedCard);
                 }
                 if ($injured) {
                     $observer->onInjury($match, $player, $blockedMatches);
                     // select another player
                     $match->setPlayerWithBall(SimulationHelper::selectPlayer($player->team, PLAYER_POSITION_MIDFIELD));
                 }
             }
             // if player is a striker, he might be fouled within the goal room -> penalty
             if ($player->position == PLAYER_POSITION_STRIKER) {
                 $pPenalty[TRUE] = 10;
                 $pPenalty[FALSE] = 90;
                 if (SimulationHelper::selectItemFromProbabilities($pPenalty)) {
                     $this->foulPenalty($match, $player->team);
                 }
                 // fouls on all other player lead to a free kick
             } else {
                 // select player who will shoot
                 if ($player->team->freeKickPlayer != NULL) {
                     $freeKickScorer = $player->team->freeKickPlayer;
                 } else {
                     $freeKickScorer = SimulationHelper::selectPlayer($player->team, PLAYER_POSITION_MIDFIELD);
                 }
                 // get goaly influence
                 $goaly = SimulationHelper::selectPlayer(SimulationHelper::getOpponentTeam($freeKickScorer, $match), PLAYER_POSITION_GOALY, null);
                 $goalyInfluence = (int) $this->_websoccer->getConfig('sim_goaly_influence');
                 $shootReduction = round($goaly->getTotalStrength($this->_websoccer, $match) * $goalyInfluence / 100);
                 // do not consider position dependent shoot strength here
                 $shootStrength = $freeKickScorer->getTotalStrength($this->_websoccer, $match);
                 $pGoal[TRUE] = max(1, min($shootStrength - $shootReduction, 60));
                 $pGoal[FALSE] = 100 - $pGoal[TRUE];
                 $freeKickResult = SimulationHelper::selectItemFromProbabilities($pGoal);
                 foreach ($this->_observers as $observer) {
                     $observer->onFreeKick($match, $freeKickScorer, $goaly, $freeKickResult);
                 }
                 if ($freeKickResult) {
                     $this->_kickoff($match, $freeKickScorer);
                 } else {
                     $match->setPlayerWithBall($goaly);
                 }
             }
         }
         // player lost the ball
     } else {
         $match->setPlayerWithBall($opponent);
         // try a counterattack if player who lost the ball was an attacking player and if team is supposed to focus on counterattacks.
         if ($player->position == PLAYER_POSITION_STRIKER && $opponent->team->counterattacks) {
             // actual attempt depends also on tactic of other team
             $counterAttempt[TRUE] = $player->team->offensive;
             $counterAttempt[FALSE] = 100 - $counterAttempt[TRUE];
             if (SimulationHelper::selectItemFromProbabilities($counterAttempt)) {
                 // first pass to a striker if player is defender
                 if ($opponent->position == PLAYER_POSITION_DEFENCE) {
                     $match->setPlayerWithBall(SimulationHelper::selectPlayer($opponent->team, PLAYER_POSITION_STRIKER));
                 }
                 $this->shoot($match);
             }
         }
     }
     return $result;
 }
 /**
  * Simulates the specified match by the number of specified minutes.
  * 
  * @param SimulationMatch $match match to simulate.
  * @param int $minutes number of minutes to simuate.
  */
 public function simulateMatch(SimulationMatch $match, $minutes)
 {
     if ($match->minute == null) {
         $match->minute = 0;
     }
     // start the match
     if ($match->minute == 0) {
         foreach ($this->_observers as $observer) {
             $observer->onBeforeMatchStarts($match);
         }
     }
     // match might be completed already before simulation, e.g. when there is no formation provided
     if ($match->isCompleted) {
         $this->completeMatch($match);
         return;
     }
     // complete match if team has no players
     if (!$this->_hasPlayers($match->homeTeam) || !$this->_hasPlayers($match->guestTeam)) {
         $this->completeMatch($match);
         return;
     }
     for ($simMinute = 1; $simMinute <= $minutes; $simMinute++) {
         $match->minute = $match->minute + 1;
         if ($match->minute == 1) {
             $this->_simStrategy->kickoff($match);
         } else {
             SimulationHelper::checkAndExecuteSubstitutions($match, $match->homeTeam, $this->_observers);
             SimulationHelper::checkAndExecuteSubstitutions($match, $match->guestTeam, $this->_observers);
         }
         // execute next action
         $actionName = $this->_simStrategy->nextAction($match);
         $this->_simStrategy->{$actionName}($match);
         // increase minutes played
         $this->_increaseMinutesPlayed($match->homeTeam);
         $this->_increaseMinutesPlayed($match->guestTeam);
         // match ended?
         // two possibilities:
         // a. Normal matches end after regular time
         // b. if penalty shooting is enabled, play extension if there is no result after 90 minutes
         $lastMinute = 90 + SimulationHelper::getMagicNumber(1, 5);
         if ($match->penaltyShootingEnabled || $match->type == 'Pokalspiel') {
             // match ended after regular or extension time with a winner
             if (($match->minute == 91 || $match->minute == 121) && ($match->type != 'Pokalspiel' && $match->homeTeam->getGoals() != $match->guestTeam->getGoals() || $match->type == 'Pokalspiel' && !SimulationCupMatchHelper::checkIfExtensionIsRequired($this->_websoccer, $this->_db, $match))) {
                 $this->completeMatch($match);
                 break;
                 // no winner after extension time -> penalty shooting
             } elseif ($match->minute == 121 && ($match->type != 'Pokalspiel' && $match->homeTeam->getGoals() == $match->guestTeam->getGoals() || $match->type == 'Pokalspiel' && SimulationCupMatchHelper::checkIfExtensionIsRequired($this->_websoccer, $this->_db, $match))) {
                 $this->_simStrategy->penaltyShooting($match);
                 // we have a winner now
                 if ($match->type == 'Pokalspiel') {
                     // home team won
                     if ($match->homeTeam->getGoals() > $match->guestTeam->getGoals()) {
                         SimulationCupMatchHelper::createNextRoundMatchAndPayAwards($this->_websoccer, $this->_db, $match->homeTeam->id, $match->guestTeam->id, $match->cupName, $match->cupRoundName);
                         // guest team won
                     } else {
                         SimulationCupMatchHelper::createNextRoundMatchAndPayAwards($this->_websoccer, $this->_db, $match->guestTeam->id, $match->homeTeam->id, $match->cupName, $match->cupRoundName);
                     }
                 }
                 $this->completeMatch($match);
                 break;
             }
             // regular match
         } elseif ($match->minute >= $lastMinute) {
             $this->completeMatch($match);
             break;
         }
     }
 }
 /**
  * Selects a random player from specified team of specified position. If there is no player at the specified position available, take 
  * one from the next best position.
  * 
  * @param SimulationTeam $team target player's team
  * @param string $position target position
  * @param SimulationPlayer $excludePlayer exclude this player from possible selection.
  * @return SimulationPlayer the selected player.
  */
 public static function selectPlayer($team, $position, $excludePlayer = null)
 {
     $players = array();
     if (isset($team->positionsAndPlayers[$position])) {
         if ($excludePlayer == null || $excludePlayer->position != $position) {
             $players = $team->positionsAndPlayers[$position];
             // filter excludePlayer
         } else {
             foreach ($team->positionsAndPlayers[$position] as $player) {
                 if ($player->id !== $excludePlayer->id) {
                     $players[] = $player;
                 }
             }
         }
     }
     $noOfPlayers = count($players);
     // no player at this position, take next best position
     if ($noOfPlayers < 1) {
         if ($position == PLAYER_POSITION_STRIKER) {
             return self::selectPlayer($team, PLAYER_POSITION_MIDFIELD, $excludePlayer);
         } else {
             if ($position == PLAYER_POSITION_MIDFIELD) {
                 return self::selectPlayer($team, PLAYER_POSITION_DEFENCE, $excludePlayer);
             } else {
                 if ($position == PLAYER_POSITION_DEFENCE) {
                     return self::selectPlayer($team, PLAYER_POSITION_GOALY, $excludePlayer);
                 }
             }
         }
         // if no goaly available, get just next available player in order to avoid infinite loop
         foreach ($team->positionsAndPlayers as $pposition => $pplayers) {
             foreach ($pplayers as $player) {
                 if ($player->id !== $excludePlayer->id) {
                     return $player;
                 }
             }
         }
     }
     $player = $players[SimulationHelper::getMagicNumber(0, $noOfPlayers - 1)];
     return $player;
 }