/**
  * Generates a new formation for the specified team, which will be directly stored both in the database and in the internal model.
  * 
  * It is a 4-4-2 formation. It always selects the freshest players of the team.
  * 
  * @param WebSoccer $websoccer request context.
  * @param DbConnection $db database connection.
  * @param SimulationTeam $team Team that needs a new formation.
  * @param int $matchId match id.
  */
 public static function generateNewFormationForTeam(WebSoccer $websoccer, DbConnection $db, SimulationTeam $team, $matchId)
 {
     // get all players (prefer the freshest players)
     $columns['id'] = 'id';
     $columns['position'] = 'position';
     $columns['position_main'] = 'mainPosition';
     $columns['vorname'] = 'firstName';
     $columns['nachname'] = 'lastName';
     $columns['kunstname'] = 'pseudonym';
     $columns['w_staerke'] = 'strength';
     $columns['w_technik'] = 'technique';
     $columns['w_kondition'] = 'stamina';
     $columns['w_frische'] = 'freshness';
     $columns['w_zufriedenheit'] = 'satisfaction';
     if ($websoccer->getConfig('players_aging') == 'birthday') {
         $ageColumn = 'TIMESTAMPDIFF(YEAR,geburtstag,CURDATE())';
     } else {
         $ageColumn = 'age';
     }
     $columns[$ageColumn] = 'age';
     // get players from usual team
     if (!$team->isNationalTeam) {
         $fromTable = $websoccer->getConfig('db_prefix') . '_spieler';
         $whereCondition = 'verein_id = %d AND verletzt = 0 AND gesperrt = 0 AND status = 1 ORDER BY w_frische DESC';
         $parameters = $team->id;
         $result = $db->querySelect($columns, $fromTable, $whereCondition, $parameters);
     } else {
         // national team: take best players of nation
         $columnsStr = '';
         $firstColumn = TRUE;
         foreach ($columns as $dbName => $aliasName) {
             if (!$firstColumn) {
                 $columnsStr = $columnsStr . ', ';
             } else {
                 $firstColumn = FALSE;
             }
             $columnsStr = $columnsStr . $dbName . ' AS ' . $aliasName;
         }
         $nation = $db->connection->escape_string($team->name);
         $dbPrefix = $websoccer->getConfig('db_prefix');
         $queryStr = '(SELECT ' . $columnsStr . ' FROM ' . $dbPrefix . '_spieler WHERE nation = \'' . $nation . '\' AND position = \'Torwart\' ORDER BY w_staerke DESC, w_frische DESC LIMIT 1)';
         $queryStr .= ' UNION ALL (SELECT ' . $columnsStr . ' FROM ' . $dbPrefix . '_spieler WHERE nation = \'' . $nation . '\' AND position = \'Abwehr\' ORDER BY w_staerke DESC, w_frische DESC LIMIT 4)';
         $queryStr .= ' UNION ALL (SELECT ' . $columnsStr . ' FROM ' . $dbPrefix . '_spieler WHERE nation = \'' . $nation . '\' AND position = \'Mittelfeld\' ORDER BY w_staerke DESC, w_frische DESC LIMIT 4)';
         $queryStr .= ' UNION ALL (SELECT ' . $columnsStr . ' FROM ' . $dbPrefix . '_spieler WHERE nation = \'' . $nation . '\' AND position = \'Sturm\' ORDER BY w_staerke DESC, w_frische DESC LIMIT 2)';
         $result = $db->executeQuery($queryStr);
     }
     $lvExists = FALSE;
     $rvExists = FALSE;
     $lmExists = FALSE;
     $rmExists = FALSE;
     $ivPlayers = 0;
     $zmPlayers = 0;
     while ($playerinfo = $result->fetch_array()) {
         $position = $playerinfo['position'];
         // generate a 4-4-2 formation
         if ($position == PLAYER_POSITION_GOALY && isset($team->positionsAndPlayers[PLAYER_POSITION_GOALY]) && count($team->positionsAndPlayers[PLAYER_POSITION_GOALY]) == 1 || $position == PLAYER_POSITION_DEFENCE && isset($team->positionsAndPlayers[PLAYER_POSITION_DEFENCE]) && count($team->positionsAndPlayers[PLAYER_POSITION_DEFENCE]) >= 4 || $position == PLAYER_POSITION_MIDFIELD && isset($team->positionsAndPlayers[PLAYER_POSITION_MIDFIELD]) && count($team->positionsAndPlayers[PLAYER_POSITION_MIDFIELD]) >= 4 || $position == PLAYER_POSITION_STRIKER && isset($team->positionsAndPlayers[PLAYER_POSITION_STRIKER]) && count($team->positionsAndPlayers[PLAYER_POSITION_STRIKER]) >= 2) {
             continue;
         }
         $mainPosition = $playerinfo['mainPosition'];
         //prevent double LV/RV/LM/RM
         if ($mainPosition == 'LV') {
             if ($lvExists) {
                 $mainPosition = 'IV';
                 $ivPlayers++;
                 if ($ivPlayers == 3) {
                     $mainPosition = 'RV';
                     $rvExists = TRUE;
                 }
             } else {
                 $lvExists = TRUE;
             }
         } elseif ($mainPosition == 'RV') {
             if ($rvExists) {
                 $mainPosition = 'IV';
                 $ivPlayers++;
                 if ($ivPlayers == 3) {
                     $mainPosition = 'LV';
                     $lvExists = TRUE;
                 }
             } else {
                 $rvExists = TRUE;
             }
         } elseif ($mainPosition == 'IV') {
             $ivPlayers++;
             if ($ivPlayers == 3) {
                 if (!$rvExists) {
                     $mainPosition = 'RV';
                     $rvExists = TRUE;
                 } else {
                     $mainPosition = 'LV';
                     $lvExists = TRUE;
                 }
             }
         } elseif ($mainPosition == 'LM') {
             if ($lmExists) {
                 $mainPosition = 'ZM';
                 $zmPlayers++;
             } else {
                 $lmExists = TRUE;
             }
         } elseif ($mainPosition == 'RM') {
             if ($rmExists) {
                 $mainPosition = 'ZM';
                 $zmPlayers++;
             } else {
                 $rmExists = TRUE;
             }
         } elseif ($mainPosition == 'LS' || $mainPosition == 'RS') {
             $mainPosition = 'MS';
         } elseif ($mainPosition == 'ZM') {
             $zmPlayers++;
             if ($zmPlayers > 2) {
                 $mainPosition = 'DM';
             }
         }
         $player = new SimulationPlayer($playerinfo['id'], $team, $position, $mainPosition, 3.0, $playerinfo['age'], $playerinfo['strength'], $playerinfo['technique'], $playerinfo['stamina'], $playerinfo['freshness'], $playerinfo['satisfaction']);
         if (strlen($playerinfo['pseudonym'])) {
             $player->name = $playerinfo['pseudonym'];
         } else {
             $player->name = $playerinfo['firstName'] . ' ' . $playerinfo['lastName'];
         }
         $team->positionsAndPlayers[$player->position][] = $player;
         SimulationStateHelper::createSimulationRecord($websoccer, $db, $matchId, $player);
     }
     $result->free();
 }
 /**
  * Loads the simulation state (statistics, players, results, etc.) from the database and builds the internal model
  * for continuing the match simulation.
  * 
  * @param WebSoccer $websoccer application context.
  * @param DbConnection $db database connection.
  * @param array $matchinfo match data from match database table.
  * @return SimulationMatch loaded match, ready for simulation.
  */
 public static function loadMatchState(WebSoccer $websoccer, DbConnection $db, $matchinfo)
 {
     $homeTeam = new SimulationTeam($matchinfo['home_id']);
     $guestTeam = new SimulationTeam($matchinfo['guest_id']);
     self::loadTeam($websoccer, $db, $matchinfo['match_id'], $homeTeam);
     self::loadTeam($websoccer, $db, $matchinfo['match_id'], $guestTeam);
     $homeTeam->setGoals($matchinfo['home_goals']);
     $homeTeam->offensive = $matchinfo['home_offensive'];
     $homeTeam->isNationalTeam = $matchinfo['home_nationalteam'];
     $homeTeam->isManagedByInterimManager = $matchinfo['home_interimmanager'];
     $homeTeam->noFormationSet = $matchinfo['home_noformation'];
     $homeTeam->setup = $matchinfo['home_setup'];
     $homeTeam->name = $matchinfo['home_name'];
     $homeTeam->longPasses = $matchinfo['home_longpasses'];
     $homeTeam->counterattacks = $matchinfo['home_counterattacks'];
     $homeTeam->morale = $matchinfo['home_morale'];
     $guestTeam->setGoals($matchinfo['guest_goals']);
     $guestTeam->offensive = $matchinfo['guest_offensive'];
     $guestTeam->isNationalTeam = $matchinfo['guest_nationalteam'];
     $guestTeam->isManagedByInterimManager = $matchinfo['guest_interimmanager'];
     $guestTeam->noFormationSet = $matchinfo['guest_noformation'];
     $guestTeam->setup = $matchinfo['guest_setup'];
     $guestTeam->name = $matchinfo['guest_name'];
     $guestTeam->longPasses = $matchinfo['guest_longpasses'];
     $guestTeam->counterattacks = $matchinfo['guest_counterattacks'];
     $guestTeam->morale = $matchinfo['guest_morale'];
     $match = new SimulationMatch($matchinfo['match_id'], $homeTeam, $guestTeam, $matchinfo['minutes']);
     $match->type = $matchinfo['type'];
     $match->penaltyShootingEnabled = $matchinfo['penaltyshooting'];
     $match->isSoldOut = $matchinfo['soldout'];
     $match->cupName = $matchinfo['cup_name'];
     $match->cupRoundName = $matchinfo['cup_roundname'];
     $match->cupRoundGroup = $matchinfo['cup_groupname'];
     $match->isAtForeignStadium = $matchinfo['custom_stadium_id'] ? TRUE : FALSE;
     //get and set player with ball
     if ($matchinfo['player_with_ball'] && isset(self::$_addedPlayers[$matchinfo['player_with_ball']])) {
         $match->setPlayerWithBall(self::$_addedPlayers[$matchinfo['player_with_ball']]);
     }
     if ($matchinfo['prev_player_with_ball'] && isset(self::$_addedPlayers[$matchinfo['prev_player_with_ball']])) {
         $match->setPreviousPlayerWithBall(self::$_addedPlayers[$matchinfo['prev_player_with_ball']]);
     }
     // set free kick takers
     if ($matchinfo['home_freekickplayer'] && isset(self::$_addedPlayers[$matchinfo['home_freekickplayer']])) {
         $homeTeam->freeKickPlayer = self::$_addedPlayers[$matchinfo['home_freekickplayer']];
     }
     if ($matchinfo['guest_freekickplayer'] && isset(self::$_addedPlayers[$matchinfo['guest_freekickplayer']])) {
         $guestTeam->freeKickPlayer = self::$_addedPlayers[$matchinfo['guest_freekickplayer']];
     }
     // substitutions
     for ($subNo = 1; $subNo <= 3; $subNo++) {
         if ($matchinfo['home_sub_' . $subNo . '_out'] && isset(self::$_addedPlayers[$matchinfo['home_sub_' . $subNo . '_in']]) && isset(self::$_addedPlayers[$matchinfo['home_sub_' . $subNo . '_out']])) {
             $sub = new SimulationSubstitution($matchinfo['home_sub_' . $subNo . '_minute'], self::$_addedPlayers[$matchinfo['home_sub_' . $subNo . '_in']], self::$_addedPlayers[$matchinfo['home_sub_' . $subNo . '_out']], $matchinfo['home_sub_' . $subNo . '_condition'], $matchinfo['home_sub_' . $subNo . '_position']);
             $homeTeam->substitutions[] = $sub;
         }
         if ($matchinfo['guest_sub_' . $subNo . '_out'] && isset(self::$_addedPlayers[$matchinfo['guest_sub_' . $subNo . '_in']]) && isset(self::$_addedPlayers[$matchinfo['guest_sub_' . $subNo . '_out']])) {
             $sub = new SimulationSubstitution($matchinfo['guest_sub_' . $subNo . '_minute'], self::$_addedPlayers[$matchinfo['guest_sub_' . $subNo . '_in']], self::$_addedPlayers[$matchinfo['guest_sub_' . $subNo . '_out']], $matchinfo['guest_sub_' . $subNo . '_condition'], $matchinfo['guest_sub_' . $subNo . '_position']);
             $guestTeam->substitutions[] = $sub;
         }
     }
     // reset cache
     self::$_addedPlayers = null;
     return $match;
 }
    for ($subNo = 1; $subNo <= 3; $subNo++) {
        $columns["M.home_w" . $subNo . "_raus"] = "home_sub_" . $subNo . "_out";
        $columns["M.home_w" . $subNo . "_rein"] = "home_sub_" . $subNo . "_in";
        $columns["M.home_w" . $subNo . "_minute"] = "home_sub_" . $subNo . "_minute";
        $columns["M.home_w" . $subNo . "_condition"] = "home_sub_" . $subNo . "_condition";
        $columns["M.gast_w" . $subNo . "_raus"] = "guest_sub_" . $subNo . "_out";
        $columns["M.gast_w" . $subNo . "_rein"] = "guest_sub_" . $subNo . "_in";
        $columns["M.gast_w" . $subNo . "_minute"] = "guest_sub_" . $subNo . "_minute";
        $columns["M.gast_w" . $subNo . "_condition"] = "guest_sub_" . $subNo . "_condition";
    }
    $result = $db->querySelect($columns, $fromTable, "M.id = %d", $matchId);
    $matchinfo = $result->fetch_array();
    $result->free();
    // init default simulation strategry in order to include dependend constants. Yeah, refactor this once having to much time...
    $dummyVar = new DefaultSimulationStrategy($website);
    $matchModel = SimulationStateHelper::loadMatchState($website, $db, $matchinfo);
    // compute audience
    if ($website->getRequestParameter("computetickets")) {
        SimulationAudienceCalculator::computeAndSaveAudience($website, $db, $matchModel);
    }
    if ($matchinfo["type"] == "Pokalspiel") {
        SimulationCupMatchHelper::checkIfExtensionIsRequired($website, $db, $matchModel);
    }
    // complete match
    $observer = new DataUpdateSimulatorObserver($website, $db);
    $observer->onMatchCompleted($matchModel);
    // show success message
    echo createSuccessMessage($i18n->getMessage("match_manage_complete_success"), "");
}
echo "<h3><a href=\"" . $website->getInternalUrl("team", "id=" . $match["match_home_id"]) . "\" target=\"_blank\">" . escapeOutput($match["match_home_name"]) . "</a> - <a href=\"" . $website->getInternalUrl("team", "id=" . $match["match_guest_id"]) . "\" target=\"_blank\">" . escapeOutput($match["match_guest_name"]) . "</a></h3>";
echo "<div class=\"well\">" . $i18n->getMessage("match_manage_complete_intro") . "</div>";
 public static function addPlayers(WebSoccer $websoccer, DbConnection $db, SimulationTeam $team, $matchinfo, $columnPrefix)
 {
     $fromTable = $websoccer->getConfig('db_prefix') . '_spieler';
     $columns['verein_id'] = 'team_id';
     $columns['nation'] = 'nation';
     $columns['position'] = 'position';
     $columns['position_main'] = 'mainPosition';
     $columns['position_second'] = 'secondPosition';
     $columns['vorname'] = 'firstName';
     $columns['nachname'] = 'lastName';
     $columns['kunstname'] = 'pseudonym';
     $columns['w_staerke'] = 'strength';
     $columns['w_technik'] = 'technique';
     $columns['w_kondition'] = 'stamina';
     $columns['w_frische'] = 'freshness';
     $columns['w_zufriedenheit'] = 'satisfaction';
     $columns['st_spiele'] = 'matches_played';
     if ($websoccer->getConfig('players_aging') == 'birthday') {
         $ageColumn = 'TIMESTAMPDIFF(YEAR,geburtstag,CURDATE())';
     } else {
         $ageColumn = 'age';
     }
     $columns[$ageColumn] = 'age';
     $whereCondition = 'id = %d AND verletzt = 0';
     // player must not be blocked
     if ($team->isNationalTeam) {
         $whereCondition .= ' AND gesperrt_nationalteam = 0';
     } elseif ($matchinfo['type'] == 'Pokalspiel') {
         $whereCondition .= ' AND gesperrt_cups = 0';
     } elseif ($matchinfo['type'] != 'Freundschaft') {
         $whereCondition .= ' AND gesperrt = 0';
     }
     $positionMapping = SimulationHelper::getPositionsMapping();
     $addedPlayers = 0;
     for ($playerNo = 1; $playerNo <= 11; $playerNo++) {
         $playerId = $matchinfo[$columnPrefix . '_formation_player' . $playerNo];
         $mainPosition = $matchinfo[$columnPrefix . '_formation_player_pos_' . $playerNo];
         $result = $db->querySelect($columns, $fromTable, $whereCondition, $playerId);
         $playerinfo = $result->fetch_array();
         $result->free();
         // is player still in team?
         if (isset($playerinfo['team_id']) && $playerinfo['team_id'] == $team->id || $team->isNationalTeam && $playerinfo['nation'] == $team->name) {
             $position = $positionMapping[$mainPosition];
             $strength = $playerinfo['strength'];
             // player becomes weaker: wrong position
             if ($playerinfo['position'] != $position && $playerinfo['mainPosition'] != $mainPosition && $playerinfo['secondPosition'] != $mainPosition) {
                 $strength = round($strength * (1 - $websoccer->getConfig('sim_strength_reduction_wrongposition') / 100));
                 // player becomes weaker: secondary position
             } elseif (strlen($playerinfo['mainPosition']) && $playerinfo['mainPosition'] != $mainPosition && ($playerinfo['position'] == $position || $playerinfo['secondPosition'] == $mainPosition)) {
                 $strength = round($strength * (1 - $websoccer->getConfig('sim_strength_reduction_secondary') / 100));
             }
             $player = new SimulationPlayer($playerId, $team, $position, $mainPosition, 3.0, $playerinfo['age'], $strength, $playerinfo['technique'], $playerinfo['stamina'], $playerinfo['freshness'], $playerinfo['satisfaction']);
             if (strlen($playerinfo['pseudonym'])) {
                 $player->name = $playerinfo['pseudonym'];
             } else {
                 $player->name = $playerinfo['firstName'] . ' ' . $playerinfo['lastName'];
             }
             $team->positionsAndPlayers[$player->position][] = $player;
             SimulationStateHelper::createSimulationRecord($websoccer, $db, $matchinfo['match_id'], $player);
             $addedPlayers++;
             // is player the team captain?
             if ($matchinfo[$columnPrefix . '_captain_id'] == $playerId) {
                 self::computeMorale($player, $playerinfo['matches_played']);
             }
             // is player free kick taker?
             if ($matchinfo[$columnPrefix . '_formation_freekickplayer'] == $playerId) {
                 $team->freeKickPlayer = $player;
             }
         }
     }
     // generate new formation if formation is invalid
     if ($addedPlayers < 11 && $websoccer->getConfig('sim_createformation_on_invalidsubmission')) {
         // delete existing invalid formation
         $db->queryDelete($websoccer->getConfig('db_prefix') . '_spiel_berechnung', 'spiel_id = %d AND team_id = %d', array($matchinfo['match_id'], $team->id));
         $team->positionsAndPlayers = array();
         // generate a new one
         SimulationFormationHelper::generateNewFormationForTeam($websoccer, $db, $team, $matchinfo['match_id']);
         $team->noFormationSet = TRUE;
         return;
     }
     // bench
     for ($playerNo = 1; $playerNo <= 5; $playerNo++) {
         $playerId = $matchinfo[$columnPrefix . '_formation_bench' . $playerNo];
         $result = $db->querySelect($columns, $fromTable, $whereCondition, $playerId);
         $playerinfo = $result->fetch_array();
         $result->free();
         // is player still in team?
         if (isset($playerinfo['team_id']) && $playerinfo['team_id'] == $team->id || $team->isNationalTeam && $playerinfo['nation'] == $team->name) {
             $player = new SimulationPlayer($playerId, $team, $playerinfo['position'], $playerinfo['mainPosition'], 3.0, $playerinfo['age'], $playerinfo['strength'], $playerinfo['technique'], $playerinfo['stamina'], $playerinfo['freshness'], $playerinfo['satisfaction']);
             if (strlen($playerinfo['pseudonym'])) {
                 $player->name = $playerinfo['pseudonym'];
             } else {
                 $player->name = $playerinfo['firstName'] . ' ' . $playerinfo['lastName'];
             }
             $team->playersOnBench[$playerId] = $player;
             SimulationStateHelper::createSimulationRecord($websoccer, $db, $matchinfo['match_id'], $player, TRUE);
         }
     }
 }