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; }