/**
  * 
  * @param WebSoccer $websoccer request context.
  * @param DbConnection $db database connection-
  * @param I18n $i18n messages context.
  * @param string $jobId Job ID as defined at jobs.xml.
  * @param $errorOnAlreadyRunning boolean TRUE if error shall occur on init time when an instance of this job is already running.
  */
 function __construct(WebSoccer $websoccer, DbConnection $db, I18n $i18n, $jobId, $errorOnAlreadyRunning = TRUE)
 {
     $this->_websoccer = $websoccer;
     $this->_db = $db;
     $this->_i18n = $i18n;
     $this->_id = $jobId;
     $xmlConfig = $this->getXmlConfig();
     // check if another instance is running (consider timeout of 5 minutes)
     if ($errorOnAlreadyRunning) {
         $initTime = (int) $xmlConfig->attributes()->inittime;
         $now = $websoccer->getNowAsTimestamp();
         $timeoutTime = $now - 5 * 60;
         if ($initTime > $timeoutTime) {
             throw new Exception('Another instance of this job is already running.');
         }
         $this->replaceAttribute('inittime', $now);
     }
     $interval = (int) $xmlConfig->attributes()->interval;
     $this->_interval = $interval * 60;
     ignore_user_abort(TRUE);
     // run possibly forever
     set_time_limit(0);
     // enable garbage collection (in case it is disabled by default)
     gc_enable();
 }
 /**
  * Creates badge assignment.
  *
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @param int $userId ID of user.
  * @param int $badgeId ID od badge.
  */
 public static function awardBadge(WebSoccer $websoccer, DbConnection $db, $userId, $badgeId)
 {
     $badgeUserTable = $websoccer->getConfig('db_prefix') . '_badge_user';
     // create assignment
     $db->queryInsert(array('user_id' => $userId, 'badge_id' => $badgeId, 'date_rewarded' => $websoccer->getNowAsTimestamp()), $badgeUserTable);
     // notify lucky user
     NotificationsDataService::createNotification($websoccer, $db, $userId, 'badge_notification', null, 'badge', 'user', 'id=' . $userId);
 }
 /**
  * Marks user as absent, makes his teams managable by deputy and sends deputy notification about it.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @param int $userId ID of user who is absent.
  * @param int $deputyId ID of user's deputy during absence.
  * @param int $days Number of days to be absent.
  */
 public static function makeUserAbsent(WebSoccer $websoccer, DbConnection $db, $userId, $deputyId, $days)
 {
     // create absence record
     $fromDate = $websoccer->getNowAsTimestamp();
     $toDate = $fromDate + 24 * 3600 * $days;
     $db->queryInsert(array('user_id' => $userId, 'deputy_id' => $deputyId, 'from_date' => $fromDate, 'to_date' => $toDate), $websoccer->getConfig('db_prefix') . '_userabsence');
     // update manager reference of managed teams
     $db->queryUpdate(array('user_id' => $deputyId, 'user_id_actual' => $userId), $websoccer->getConfig('db_prefix') . '_verein', 'user_id = %d', $userId);
     // create notification for deputy
     $user = UsersDataService::getUserById($websoccer, $db, $userId);
     NotificationsDataService::createNotification($websoccer, $db, $deputyId, 'absence_notification', array('until' => $toDate, 'user' => $user['nick']), 'absence', 'user');
 }
 /**
  * Securely calls an action. Before the actual call, this handler will validate all parameters defined at the module.xml
  * and check the user permissions.
  * 
  * @param WebSoccer $website Current WebSoccer context.
  * @param DbConnection $db Data base connection.
  * @param I18n $i18n Messages context.
  * @param string $actionId ID of action to validate and execute.
  * @return string|NULL ID of page to display after the execution of this action or NULL if the current page shall be displayed.
  * @throws Exception if action could not be found, a double-submit occured, access is denied, controller could not be found 
  * or if the executed controller has thrown an Exception.
  */
 public static function handleAction(WebSoccer $website, DbConnection $db, I18n $i18n, $actionId)
 {
     if ($actionId == NULL) {
         return;
     }
     // check double-submit
     if (isset($_SESSION[DOUBLE_SUBMIT_CHECK_SESSIONKEY_ACTIONID]) && $_SESSION[DOUBLE_SUBMIT_CHECK_SESSIONKEY_ACTIONID] == $actionId && isset($_SESSION[DOUBLE_SUBMIT_CHECK_SESSIONKEY_TIME]) && $_SESSION[DOUBLE_SUBMIT_CHECK_SESSIONKEY_TIME] + DOUBLE_SUBMIT_CHECK_SECONDS > $website->getNowAsTimestamp()) {
         throw new Exception($i18n->getMessage('error_double_submit'));
     }
     $actionConfig = json_decode($website->getAction($actionId), true);
     $actionXml = ModuleConfigHelper::findModuleConfigAsXmlObject($actionConfig['module']);
     // check permissions
     $user = $website->getUser();
     // is admin action
     if (strpos($actionConfig['role'], 'admin') !== false) {
         if (!$user->isAdmin()) {
             throw new AccessDeniedException($i18n->getMessage('error_access_denied'));
         }
     } else {
         // all other actions
         $requiredRoles = explode(',', $actionConfig['role']);
         if (!in_array($user->getRole(), $requiredRoles)) {
             throw new AccessDeniedException($i18n->getMessage('error_access_denied'));
         }
     }
     // validate parameters
     $params = $actionXml->xpath('//action[@id = "' . $actionId . '"]/param');
     $validatedParams = array();
     if ($params) {
         $validatedParams = self::_validateParameters($params, $website, $i18n);
     }
     $controllerName = $actionConfig['controller'];
     // handle premium actions
     if (isset($actionConfig['premiumBalanceMin']) && $actionConfig['premiumBalanceMin']) {
         return self::_handlePremiumAction($website, $db, $i18n, $actionId, $actionConfig['premiumBalanceMin'], $validatedParams, $controllerName);
     }
     $actionReturn = self::_executeAction($website, $db, $i18n, $actionId, $controllerName, $validatedParams);
     // create log entry
     if (isset($actionConfig['log']) && $actionConfig['log'] && $website->getUser()->id) {
         ActionLogDataService::createOrUpdateActionLog($website, $db, $website->getUser()->id, $actionId);
     }
     return $actionReturn;
 }
 /**
  * Creates a new action log for the specified user and deletes old ones.
  * If there is already a recent log for the same action, it will onl update the timestamp.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @param int $userId ID of user.
  * @param string $actionId Action name.
  */
 public static function createOrUpdateActionLog(WebSoccer $websoccer, DbConnection $db, $userId, $actionId)
 {
     $fromTable = $websoccer->getConfig('db_prefix') . '_useractionlog';
     // delete old entries of user (entries which are older than 20 days)
     $deleteTimeThreshold = $websoccer->getNowAsTimestamp() - 24 * 3600 * 20;
     $db->queryDelete($fromTable, 'user_id = %d AND created_date < %d', array($userId, $deleteTimeThreshold));
     // check if action has been triggered within the last X minutes. If so, just update timestamp rather than filling DB unnecessary.
     $timeThreshold = $websoccer->getNowAsTimestamp() - 30 * 60;
     $result = $db->querySelect('id', $fromTable, 'user_id = %d AND action_id = \'%s\' AND created_date >= %d ORDER BY created_date DESC', array($userId, $actionId, $timeThreshold), 1);
     $lastLog = $result->fetch_array();
     $result->free();
     // update last log
     if ($lastLog) {
         $db->queryUpdate(array('created_date' => $websoccer->getNowAsTimestamp()), $fromTable, 'id = %d', $lastLog['id']);
         // create new log
     } else {
         $db->queryInsert(array('user_id' => $userId, 'action_id' => $actionId, 'created_date' => $websoccer->getNowAsTimestamp()), $fromTable);
     }
 }
 /**
  * Checks whether a new random event is due for the specified user and executes it.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @param int $userId ID of user.
  */
 public static function createEventIfRequired(WebSoccer $websoccer, DbConnection $db, $userId)
 {
     // is feature enabled?
     $eventsInterval = (int) $websoccer->getConfig('randomevents_interval_days');
     if ($eventsInterval < 1) {
         return;
     }
     // user must manage at least one team
     $result = $db->querySelect('id', $websoccer->getConfig('db_prefix') . '_verein', 'user_id = %d AND status = \'1\'', $userId);
     $clubIds = array();
     while ($club = $result->fetch_array()) {
         $clubIds[] = $club['id'];
     }
     $result->free();
     if (!count($clubIds)) {
         return;
     }
     // select radomly one of the user's teams
     $clubId = $clubIds[array_rand($clubIds)];
     // do not create an event within first 24 hours of registration
     $now = $websoccer->getNowAsTimestamp();
     $result = $db->querySelect('datum_anmeldung', $websoccer->getConfig('db_prefix') . '_user', 'id = %d', $userId, 1);
     $user = $result->fetch_array();
     $result->free();
     if ($user['datum_anmeldung'] >= $now - 24 * 3600) {
         return;
     }
     // is a new event due? check occurance of latest event for user
     $result = $db->querySelect('occurrence_date', $websoccer->getConfig('db_prefix') . '_randomevent_occurrence', 'user_id = %d ORDER BY occurrence_date DESC', $userId, 1);
     $latestEvent = $result->fetch_array();
     $result->free();
     if ($latestEvent && $latestEvent['occurrence_date'] >= $now - 24 * 3600 * $eventsInterval) {
         return;
     }
     // create and execute an event occurence
     self::_createAndExecuteEvent($websoccer, $db, $userId, $clubId);
     // delete old occurences. Delete those which are older than 10 intervals.
     // In general, only the latest 10 occurences should remain.
     if ($latestEvent) {
         $deleteBoundary = $now - 24 * 3600 * 10 * $eventsInterval;
         $db->queryDelete($websoccer->getConfig('db_prefix') . '_randomevent_occurrence', 'user_id = %d AND occurrence_date < %d', array($userId, $deleteBoundary));
     }
 }
 /**
  * Creates a new unseen notification about any event which shall catch the user's attention.
  * 
  * @param WebSoccer $websoccer application context.
  * @param DbConnection $db DB connection.
  * @param int $userId ID of notification receiver.
  * @param string $messageKey key of message to display. Can contain place holders in form of {myplaceholder}.
  * @param array $messageData values of placeholder as an assoc. array. Array keys are message place holders.
  * @param string $type Optional. Type of notification as a string ID. Can be used for displaying icons or similar in the view layer.
  * @param string $targetPageId Optional. ID of page to which a link shall be targetting.
  * @param string $targetPageQueryString Optional. Query string to append to the target page link.
  * @param int $teamId Optional. ID of team to which this notification is assigned.
  */
 public static function createNotification(WebSoccer $websoccer, DbConnection $db, $userId, $messageKey, $messageData = null, $type = null, $targetPageId = null, $targetPageQueryString = null, $teamId = null)
 {
     $columns = array('user_id' => $userId, 'eventdate' => $websoccer->getNowAsTimestamp(), 'message_key' => $messageKey);
     if ($messageData != null) {
         $columns['message_data'] = json_encode($messageData);
     }
     if ($type != null) {
         $columns['eventtype'] = $type;
     }
     if ($targetPageId != null) {
         $columns['target_pageid'] = $targetPageId;
     }
     if ($targetPageQueryString != null) {
         $columns['target_querystr'] = $targetPageQueryString;
     }
     if ($teamId != null) {
         $columns['team_id'] = $teamId;
     }
     $db->queryInsert($columns, $websoccer->getConfig('db_prefix') . '_notification');
 }
 /**
  * Simulates youth matches. They are executed differently from normal matches sinc they have a different structure
  * and other simulation observers.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB conncetion.
  * @param int $maxMatchesToSimulate Maximum number of matches to simulate.
  */
 public static function simulateOpenYouthMatches(WebSoccer $websoccer, DbConnection $db, $maxMatchesToSimulate)
 {
     // is feature enabled at the moment?
     if (!$websoccer->getConfig('youth_enabled')) {
         return;
     }
     $simulator = new Simulator($db, $websoccer);
     // observer stores results
     $simulator->attachObserver(new YouthMatchDataUpdateSimulatorObserver($websoccer, $db));
     // ceate match report items on events
     $simulator->getSimulationStrategy()->attachObserver(new YouthMatchReportSimulationObserver($websoccer, $db));
     // get matches to simulate
     $result = $db->querySelect('*', $websoccer->getConfig('db_prefix') . '_youthmatch', 'simulated != \'1\' AND matchdate <= %d ORDER BY matchdate ASC', $websoccer->getNowAsTimestamp(), $maxMatchesToSimulate);
     while ($matchinfo = $result->fetch_array()) {
         $match = self::_createMatch($websoccer, $db, $matchinfo);
         if ($match != null) {
             $simulator->simulateMatch($match, 100);
             // let garbage collector free memory before script execution by removing all references to objects
             $match->cleanReferences();
             unset($match);
         }
     }
     $result->free();
 }
 private static function createTransaction(WebSoccer $websoccer, DbConnection $db, $team, $teamId, $amount, $subject, $sender)
 {
     // ignore transaction if team is without user and option is enabled
     if (!$team["user_id"] && $websoccer->getConfig("no_transactions_for_teams_without_user")) {
         return;
     }
     // create transaction
     $fromTable = $websoccer->getConfig("db_prefix") . "_konto";
     $columns["verein_id"] = $teamId;
     $columns["absender"] = $sender;
     $columns["betrag"] = $amount;
     $columns["datum"] = $websoccer->getNowAsTimestamp();
     $columns["verwendung"] = $subject;
     $db->queryInsert($columns, $fromTable);
     // update team budget
     $newBudget = $team["team_budget"] + $amount;
     $updateColumns["finanz_budget"] = $newBudget;
     $fromTable = $websoccer->getConfig("db_prefix") . "_verein";
     $whereCondition = "id = %d";
     $parameters = $teamId;
     $db->queryUpdate($updateColumns, $fromTable, $whereCondition, $parameters);
 }
 /**
  * Provides users who are currently online.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @param int $startIndex Fetch start index.
  * @param int $entries_per_page Number of rows to fetch.
  * @return array list of users who are currently online.
  */
 public static function getOnlineUsers(WebSoccer $websoccer, DbConnection $db, $startIndex, $entries_per_page)
 {
     $timeBoundary = $websoccer->getNowAsTimestamp() - 15 * 60;
     $columns["U.id"] = "id";
     $columns["nick"] = "nick";
     $columns["email"] = "email";
     $columns["U.picture"] = "picture";
     $columns["lastonline"] = "lastonline";
     $columns["lastaction"] = "lastaction";
     $columns["c_hideinonlinelist"] = "hideinonlinelist";
     $columns["C.id"] = "team_id";
     $columns["C.name"] = "team_name";
     $columns["C.bild"] = "team_picture";
     $limit = $startIndex . "," . $entries_per_page;
     $fromTable = $websoccer->getConfig("db_prefix") . "_user AS U";
     $fromTable .= " LEFT JOIN " . $websoccer->getConfig("db_prefix") . "_verein AS C ON C.user_id = U.id";
     $whereCondition = "U.status = 1 AND lastonline >= %d GROUP BY id ORDER BY lastonline DESC";
     $result = $db->querySelect($columns, $fromTable, $whereCondition, $timeBoundary, $limit);
     $users = array();
     while ($user = $result->fetch_array()) {
         $user["picture"] = self::getUserProfilePicture($websoccer, $user["picture"], $user["email"]);
         $users[] = $user;
     }
     $result->free();
     return $users;
 }
 /**
  * Creates a payment log entry and credits premium balance according to available price options.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB Connection.
  * @param int $userId ID of user to credit for.
  * @param number $amount Real money amount that has been registered. Will be stored with multiplied by 100, in order to store float numbers as integers.
  * @param string $subject Subject id for premium statement. Usually ID of action which triggered the payment.
  * @throws Exception if either the amount is <= 0 or if no price option is available for the specified amount.
  */
 public static function createPaymentAndCreditPremium(WebSoccer $websoccer, DbConnection $db, $userId, $amount, $subject)
 {
     if ($amount <= 0) {
         throw new Exception('Illegal amount: ' . $amount);
     }
     $realAmount = $amount * 100;
     // create payment statement
     $db->queryInsert(array('user_id' => $userId, 'amount' => $realAmount, 'created_date' => $websoccer->getNowAsTimestamp()), $websoccer->getConfig('db_prefix') . '_premiumpayment');
     // get premium amount to credit
     $priceOptions = explode(',', $websoccer->getConfig('premium_price_options'));
     if (count($priceOptions)) {
         foreach ($priceOptions as $priceOption) {
             $optionParts = explode(':', $priceOption);
             $realMoney = trim($optionParts[0]);
             $realMoneyAmount = $realMoney * 100;
             $premiumMoney = trim($optionParts[1]);
             // credit amount and end here
             if ($realAmount == $realMoneyAmount) {
                 self::creditAmount($websoccer, $db, $userId, $premiumMoney, $subject);
                 return;
             }
         }
     }
     // if reached here, no price option has been found for this amount
     throw new Exception('No price option found for amount: ' . $amount);
 }
 /**
  * Removes open match requests which cannot be approved any more because match would start to later otherwise.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  */
 public static function deleteInvalidOpenMatchRequests(WebSoccer $websoccer, DbConnection $db)
 {
     $timeBoundary = $websoccer->getNowAsTimestamp() + $websoccer->getConfig("youth_matchrequest_accept_hours_in_advance");
     $db->queryDelete($websoccer->getConfig("db_prefix") . "_youthmatch_request", "matchdate <= %d", $timeBoundary);
 }
 /**
  * Counts number of players who are currently available on the transfer market.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @param string $positionFilter position ID as in DB table.
  * @return int number of found players. 0 if no players found.
  */
 public static function countPlayersOnTransferList(WebSoccer $websoccer, DbConnection $db, $positionFilter = null)
 {
     $columns = 'COUNT(*) AS hits';
     $fromTable = $websoccer->getConfig('db_prefix') . '_spieler AS P';
     $whereCondition = 'P.status = 1 AND P.transfermarkt = 1 AND P.transfer_ende > %d';
     $parameters[] = $websoccer->getNowAsTimestamp();
     if ($positionFilter != null) {
         $whereCondition .= ' AND P.position = \'%s\'';
         $parameters[] = $positionFilter;
     }
     $result = $db->querySelect($columns, $fromTable, $whereCondition, $parameters);
     $players = $result->fetch_array();
     $result->free();
     if (isset($players['hits'])) {
         return $players['hits'];
     }
     return 0;
 }
 /**
  * Generates new players for a specified team.
  * 
  * @param WebSoccer $websoccer Application context
  * @param DbConnection $db DB connection
  * @param int $teamId ID of team to generate players for. If 0, then players will be generated for transfer market.
  * @param int $age age of players in years.
  * @param int $ageDeviation maximum deviation of age in years.
  * @param int $salary salary per match.
  * @param int $contractDuration contract duration in number of matches.
  * @param array $strengths assoc. array of strength values. Keys are: strength, technique, stamina, freshness, satisfaction
  * @param array $positions assoc array of positions and number of players to generate for each position. Key=abbreviated positions as in DB.
  * @param int $maxDeviation maximum deviation in strength.
  * @param sring|NULL $nationality optional. Nationality of player.If not provided, it is taken from club.
  * @throws Exception if generation failed.
  */
 public static function generatePlayers(WebSoccer $websoccer, DbConnection $db, $teamId, $age, $ageDeviation, $salary, $contractDuration, $strengths, $positions, $maxDeviation, $nationality = NULL)
 {
     if (strlen($nationality)) {
         $country = $nationality;
     } else {
         // get country from team
         $fromTable = $websoccer->getConfig('db_prefix') . '_verein AS T';
         $fromTable .= ' INNER JOIN ' . $websoccer->getConfig('db_prefix') . '_liga AS L ON L.id = T.liga_id';
         $result = $db->querySelect('L.land AS country', $fromTable, 'T.id = %d', $teamId);
         $league = $result->fetch_array();
         $result->free();
         if (!$league) {
             throw new Exception('illegal team ID');
         }
         $country = $league['country'];
     }
     $firstNames = self::_getLines(FILE_FIRSTNAMES, $country);
     $lastNames = self::_getLines(FILE_LASTNAMES, $country);
     // map main position to parent position
     $mainPositions['T'] = 'Torwart';
     $mainPositions['LV'] = 'Abwehr';
     $mainPositions['IV'] = 'Abwehr';
     $mainPositions['RV'] = 'Abwehr';
     $mainPositions['LM'] = 'Mittelfeld';
     $mainPositions['ZM'] = 'Mittelfeld';
     $mainPositions['OM'] = 'Mittelfeld';
     $mainPositions['DM'] = 'Mittelfeld';
     $mainPositions['RM'] = 'Mittelfeld';
     $mainPositions['LS'] = 'Sturm';
     $mainPositions['MS'] = 'Sturm';
     $mainPositions['RS'] = 'Sturm';
     // create players for all positions
     foreach ($positions as $mainPosition => $numberOfPlayers) {
         for ($playerNo = 1; $playerNo <= $numberOfPlayers; $playerNo++) {
             $playerAge = $age + self::_getRandomDeviationValue($ageDeviation);
             $time = strtotime('-' . $playerAge . ' years', $websoccer->getNowAsTimestamp());
             $birthday = date('Y-m-d', $time);
             $firstName = self::_getItemFromArray($firstNames);
             $lastName = self::_getItemFromArray($lastNames);
             self::_createPlayer($websoccer, $db, $teamId, $firstName, $lastName, $mainPositions[$mainPosition], $mainPosition, $strengths, $country, $playerAge, $birthday, $salary, $contractDuration, $maxDeviation);
         }
     }
 }
 /**
  * Provides number of future matches in that the specified team is involved in.
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @param int $teamId ID of team
  * @return int number of next matches to play.
  */
 public static function countNextMatches(WebSoccer $websoccer, DbConnection $db, $teamId)
 {
     $columns = "COUNT(*) AS hits";
     $fromTable = $websoccer->getConfig("db_prefix") . "_spiel";
     $result = $db->querySelect($columns, $fromTable, "(home_verein = %d OR gast_verein = %d) AND datum > %d", array($teamId, $teamId, $websoccer->getNowAsTimestamp()));
     $matches = $result->fetch_array();
     $result->free();
     if (isset($matches["hits"])) {
         return $matches["hits"];
     }
     return 0;
 }
 private static function getBonusSumFromBuildings(WebSoccer $websoccer, DbConnection $db, $attributeName, $teamId)
 {
     $dbPrefix = $websoccer->getConfig('db_prefix');
     $result = $db->querySelect('SUM(' . $attributeName . ') AS attrSum', $dbPrefix . '_buildings_of_team INNER JOIN ' . $dbPrefix . '_stadiumbuilding ON id = building_id', 'team_id = %d AND construction_deadline < %d', array($teamId, $websoccer->getNowAsTimestamp()));
     $resArray = $result->fetch_array();
     $result->free();
     if ($resArray) {
         return $resArray['attrSum'];
     }
     return 0;
 }
 /**
  * Gets matches to simulate, registers simulation obervers, creates internal data model (loading data from the database)
  * and eventually calls the Simulator. After simulation, it stores the current state.
  * Additionally, it triggers also youth matches simulation, in case maximum number of matches has not exceeded yet.
  * 
  * @param WebSoccer $websoccer request context.
  * @param DbConnection $db database connection.
  */
 public static function simulateOpenMatches(WebSoccer $websoccer, DbConnection $db)
 {
     $simulator = new Simulator($db, $websoccer);
     // add creating match report texts
     $strategy = $simulator->getSimulationStrategy();
     $simulationObservers = explode(',', $websoccer->getConfig('sim_simulation_observers'));
     foreach ($simulationObservers as $observerClassName) {
         $observerClass = trim($observerClassName);
         if (strlen($observerClass)) {
             $strategy->attachObserver(new $observerClass($websoccer, $db));
         }
     }
     $simulatorObservers = explode(',', $websoccer->getConfig('sim_simulator_observers'));
     foreach ($simulatorObservers as $observerClassName) {
         $observerClass = trim($observerClassName);
         if (strlen($observerClass)) {
             $simulator->attachObserver(new $observerClass($websoccer, $db));
         }
     }
     // find and execute open matches
     $fromTable = $websoccer->getConfig('db_prefix') . '_spiel AS M';
     $fromTable .= ' INNER JOIN ' . $websoccer->getConfig('db_prefix') . '_verein AS HOME_T ON HOME_T.id = M.home_verein';
     $fromTable .= ' INNER JOIN ' . $websoccer->getConfig('db_prefix') . '_verein AS GUEST_T ON GUEST_T.id = M.gast_verein';
     $fromTable .= ' LEFT JOIN ' . $websoccer->getConfig('db_prefix') . '_aufstellung AS HOME_F ON HOME_F.match_id = M.id AND HOME_F.verein_id = M.home_verein';
     $fromTable .= ' LEFT JOIN ' . $websoccer->getConfig('db_prefix') . '_aufstellung AS GUEST_F ON GUEST_F.match_id = M.id AND GUEST_F.verein_id = M.gast_verein';
     $columns['M.id'] = 'match_id';
     $columns['M.spieltyp'] = 'type';
     $columns['M.home_verein'] = 'home_id';
     $columns['M.gast_verein'] = 'guest_id';
     $columns['M.minutes'] = 'minutes';
     $columns['M.soldout'] = 'soldout';
     $columns['M.elfmeter'] = 'penaltyshooting';
     $columns['M.pokalname'] = 'cup_name';
     $columns['M.pokalrunde'] = 'cup_roundname';
     $columns['M.pokalgruppe'] = 'cup_groupname';
     $columns['M.stadion_id'] = 'custom_stadium_id';
     $columns['M.player_with_ball'] = 'player_with_ball';
     $columns['M.prev_player_with_ball'] = 'prev_player_with_ball';
     $columns['M.home_tore'] = 'home_goals';
     $columns['M.gast_tore'] = 'guest_goals';
     $columns['M.home_offensive'] = 'home_offensive';
     $columns['M.home_setup'] = 'home_setup';
     $columns['M.home_noformation'] = 'home_noformation';
     $columns['M.home_longpasses'] = 'home_longpasses';
     $columns['M.home_counterattacks'] = 'home_counterattacks';
     $columns['M.home_morale'] = 'home_morale';
     $columns['M.home_freekickplayer'] = 'home_freekickplayer';
     $columns['M.gast_offensive'] = 'guest_offensive';
     $columns['M.guest_noformation'] = 'guest_noformation';
     $columns['M.gast_setup'] = 'guest_setup';
     $columns['M.gast_longpasses'] = 'guest_longpasses';
     $columns['M.gast_counterattacks'] = 'guest_counterattacks';
     $columns['M.gast_morale'] = 'guest_morale';
     $columns['M.gast_freekickplayer'] = 'guest_freekickplayer';
     $columns['HOME_F.id'] = 'home_formation_id';
     $columns['HOME_F.offensive'] = 'home_formation_offensive';
     $columns['HOME_F.setup'] = 'home_formation_setup';
     $columns['HOME_F.longpasses'] = 'home_formation_longpasses';
     $columns['HOME_F.counterattacks'] = 'home_formation_counterattacks';
     $columns['HOME_F.freekickplayer'] = 'home_formation_freekickplayer';
     $columns['HOME_T.name'] = 'home_name';
     $columns['HOME_T.nationalteam'] = 'home_nationalteam';
     $columns['HOME_T.interimmanager'] = 'home_interimmanager';
     $columns['HOME_T.captain_id'] = 'home_captain_id';
     $columns['GUEST_T.nationalteam'] = 'guest_nationalteam';
     $columns['GUEST_T.name'] = 'guest_name';
     $columns['GUEST_T.captain_id'] = 'guest_captain_id';
     $columns['GUEST_T.interimmanager'] = 'guest_interimmanager';
     for ($playerNo = 1; $playerNo <= 11; $playerNo++) {
         $columns['HOME_F.spieler' . $playerNo] = 'home_formation_player' . $playerNo;
         $columns['HOME_F.spieler' . $playerNo . '_position'] = 'home_formation_player_pos_' . $playerNo;
         $columns['GUEST_F.spieler' . $playerNo] = 'guest_formation_player' . $playerNo;
         $columns['GUEST_F.spieler' . $playerNo . '_position'] = 'guest_formation_player_pos_' . $playerNo;
         if ($playerNo <= 5) {
             $columns['HOME_F.ersatz' . $playerNo] = 'home_formation_bench' . $playerNo;
             $columns['GUEST_F.ersatz' . $playerNo] = 'guest_formation_bench' . $playerNo;
         }
     }
     // substitutions
     for ($subNo = 1; $subNo <= 3; $subNo++) {
         // will be used for initial creation
         $columns['HOME_F.w' . $subNo . '_raus'] = 'home_formation_sub' . $subNo . '_out';
         $columns['HOME_F.w' . $subNo . '_rein'] = 'home_formation_sub' . $subNo . '_in';
         $columns['HOME_F.w' . $subNo . '_minute'] = 'home_formation_sub' . $subNo . '_minute';
         $columns['HOME_F.w' . $subNo . '_condition'] = 'home_formation_sub' . $subNo . '_condition';
         $columns['HOME_F.w' . $subNo . '_position'] = 'home_formation_sub' . $subNo . '_position';
         // will be used for loading from state
         $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.home_w' . $subNo . '_position'] = 'home_sub_' . $subNo . '_position';
         $columns['GUEST_F.w' . $subNo . '_raus'] = 'guest_formation_sub' . $subNo . '_out';
         $columns['GUEST_F.w' . $subNo . '_rein'] = 'guest_formation_sub' . $subNo . '_in';
         $columns['GUEST_F.w' . $subNo . '_minute'] = 'guest_formation_sub' . $subNo . '_minute';
         $columns['GUEST_F.w' . $subNo . '_condition'] = 'guest_formation_sub' . $subNo . '_condition';
         $columns['GUEST_F.w' . $subNo . '_position'] = 'guest_formation_sub' . $subNo . '_position';
         $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';
         $columns['M.gast_w' . $subNo . '_position'] = 'guest_sub_' . $subNo . '_position';
     }
     $columns['GUEST_F.id'] = 'guest_formation_id';
     $columns['GUEST_F.offensive'] = 'guest_formation_offensive';
     $columns['GUEST_F.setup'] = 'guest_formation_setup';
     $columns['GUEST_F.longpasses'] = 'guest_formation_longpasses';
     $columns['GUEST_F.counterattacks'] = 'guest_formation_counterattacks';
     $columns['GUEST_F.freekickplayer'] = 'guest_formation_freekickplayer';
     $whereCondition = 'M.berechnet != \'1\' AND M.blocked != \'1\' AND M.datum <= %d ORDER BY M.datum ASC';
     $parameters = $websoccer->getNowAsTimestamp();
     $interval = (int) $websoccer->getConfig('sim_interval');
     $maxMatches = (int) $websoccer->getConfig('sim_max_matches_per_run');
     $result = $db->querySelect($columns, $fromTable, $whereCondition, $parameters, $maxMatches);
     $matchesSimulated = 0;
     $lockArray = array('blocked' => '1');
     $unlockArray = array('blocked' => '0');
     $matchTable = $websoccer->getConfig('db_prefix') . '_spiel';
     while ($matchinfo = $result->fetch_array()) {
         // lock record
         $db->queryUpdate($lockArray, $matchTable, 'id = %d', $matchinfo['match_id']);
         $match = null;
         if ($matchinfo['minutes'] < 1) {
             $match = self::createInitialMatchData($websoccer, $db, $matchinfo);
         } else {
             $match = SimulationStateHelper::loadMatchState($websoccer, $db, $matchinfo);
         }
         if ($match != null) {
             $simulator->simulateMatch($match, $interval);
             SimulationStateHelper::updateState($websoccer, $db, $match);
         }
         // let garbage collector free memory before script execution by removing all references to objects
         $match->cleanReferences();
         unset($match);
         // unlock record
         $db->queryUpdate($unlockArray, $matchTable, 'id = %d', $matchinfo['match_id']);
         $matchesSimulated++;
     }
     $result->free();
     // Simulate youth matches
     $maxYouthMatchesToSimulate = $maxMatches - $matchesSimulated;
     if ($maxYouthMatchesToSimulate) {
         YouthMatchSimulationExecutor::simulateOpenYouthMatches($websoccer, $db, $maxYouthMatchesToSimulate);
     }
 }
 private static function _transferPlayer(WebSoccer $websoccer, DbConnection $db, $playerId, $targetClubId, $targetUserId, $currentUserId, $currentClubId, $amount, $exchangePlayer1 = 0, $exchangePlayer2 = 0)
 {
     $db->queryUpdate(array("verein_id" => $targetClubId, "vertrag_spiele" => $websoccer->getConfig("transferoffers_contract_matches")), $websoccer->getConfig("db_prefix") . "_spieler", "id = %d", $playerId);
     // create log
     $db->queryInsert(array("bid_id" => 0, "datum" => $websoccer->getNowAsTimestamp(), "spieler_id" => $playerId, "seller_user_id" => $currentUserId, "seller_club_id" => $currentClubId, "buyer_user_id" => $targetUserId, "buyer_club_id" => $targetClubId, "directtransfer_amount" => $amount, "directtransfer_player1" => $exchangePlayer1, "directtransfer_player2" => $exchangePlayer2), $websoccer->getConfig("db_prefix") . "_transfer");
 }
 /**
  * Provides stadium construction orders which are due (i.e. deadline is in the past).
  * 
  * @param WebSoccer $websoccer Application context.
  * @param DbConnection $db DB connection.
  * @return array list of construction orders incl. builder's reliability and user ID.
  */
 public static function getDueConstructionOrders(WebSoccer $websoccer, DbConnection $db)
 {
     $fromTable = $websoccer->getConfig("db_prefix") . "_stadium_construction AS C";
     $fromTable .= " INNER JOIN " . $websoccer->getConfig("db_prefix") . "_stadium_builder AS B ON B.id = C.builder_id";
     $fromTable .= " INNER JOIN " . $websoccer->getConfig("db_prefix") . "_verein AS T ON T.id = C.team_id";
     $result = $db->querySelect("C.*, T.user_id AS user_id, B.reliability AS builder_reliability", $fromTable, "C.deadline <= %d", $websoccer->getNowAsTimestamp());
     $orders = array();
     while ($order = $result->fetch_array()) {
         $orders[] = $order;
     }
     $result->free();
     return $orders;
 }
 /**
  * Provides clubs in order of league table criteria.
  * Additionally updates league history at first time of user session.
  * 
  * @param WebSoccer $websoccer Application Context
  * @param DbConnection $db DB connection
  * @param int $leagueId league ID
  * @return array array of teams, ordered by table criteria.
  */
 public static function getTeamsOfLeagueOrderedByTableCriteria(WebSoccer $websoccer, DbConnection $db, $leagueId)
 {
     // get current season
     $result = $db->querySelect('id', $websoccer->getConfig('db_prefix') . '_saison', 'liga_id = %d AND beendet = \'0\' ORDER BY name DESC', $leagueId, 1);
     $season = $result->fetch_array();
     $result->free();
     $fromTable = $websoccer->getConfig('db_prefix') . '_verein AS C';
     $fromTable .= ' LEFT JOIN ' . $websoccer->getConfig('db_prefix') . '_user AS U ON C.user_id = U.id';
     $fromTable .= ' LEFT JOIN ' . $websoccer->getConfig('db_prefix') . '_leaguehistory AS PREVDAY ON (PREVDAY.team_id = C.id AND PREVDAY.matchday = (C.sa_spiele - 1)';
     if ($season) {
         $fromTable .= ' AND PREVDAY.season_id = ' . $season['id'];
     }
     $fromTable .= ')';
     $columns = array();
     $columns['C.id'] = 'id';
     $columns['C.name'] = 'name';
     $columns['C.sa_punkte'] = 'score';
     $columns['C.sa_tore'] = 'goals';
     $columns['C.sa_gegentore'] = 'goals_received';
     $columns['(C.sa_tore - C.sa_gegentore)'] = 'goals_diff';
     $columns['C.sa_siege'] = 'wins';
     $columns['C.sa_niederlagen'] = 'defeats';
     $columns['C.sa_unentschieden'] = 'draws';
     $columns['C.sa_spiele'] = 'matches';
     $columns['C.bild'] = 'picture';
     $columns['U.id'] = 'user_id';
     $columns['U.nick'] = 'user_name';
     $columns['U.email'] = 'user_email';
     $columns['U.picture'] = 'user_picture';
     $columns['PREVDAY.rank'] = 'previous_rank';
     // order by
     $whereCondition = 'C.liga_id = %d AND C.status = \'1\' ORDER BY score DESC, goals_diff DESC, wins DESC, draws DESC, goals DESC, name ASC';
     $parameters = $leagueId;
     $teams = array();
     // shall update league history? DO this only every 10 minutes
     $now = $websoccer->getNowAsTimestamp();
     $updateHistory = FALSE;
     if ($season && (!isset($_SESSION['leaguehist']) || $_SESSION['leaguehist'] < $now - 600)) {
         $_SESSION['leaguehist'] = $now;
         $updateHistory = TRUE;
         $queryTemplate = 'REPLACE INTO ' . $websoccer->getConfig('db_prefix') . '_leaguehistory ';
         $queryTemplate .= '(team_id, season_id, user_id, matchday, rank) ';
         $queryTemplate .= 'VALUES (%d, ' . $season['id'] . ', %s, %d, %d);';
     }
     $result = $db->querySelect($columns, $fromTable, $whereCondition, $parameters);
     $rank = 0;
     while ($team = $result->fetch_array()) {
         $rank++;
         $team['user_picture'] = UsersDataService::getUserProfilePicture($websoccer, $team['user_picture'], $team['user_email'], 20);
         $teams[] = $team;
         // update history
         if ($updateHistory && $team['matches']) {
             $userId = $team['user_id'] ? $team['user_id'] : 'DEFAULT';
             $query = sprintf($queryTemplate, $team['id'], $userId, $team['matches'], $rank);
             $db->executeQuery($query);
         }
     }
     $result->free();
     return $teams;
 }
 public static function getLastMatch(WebSoccer $websoccer, DbConnection $db)
 {
     // where
     $whereCondition = 'M.berechnet = 1 AND (HOME.user_id = %d OR GUEST.user_id = %d) AND M.datum < %d ORDER BY M.datum DESC';
     $parameters = array($websoccer->getUser()->id, $websoccer->getUser()->id, $websoccer->getNowAsTimestamp());
     return self::_getMatchSummaryByCondition($websoccer, $db, $whereCondition, $parameters);
 }
 public static function getTransactionsBetweenUsers(WebSoccer $websoccer, DbConnection $db, $user1, $user2)
 {
     $columns = 'COUNT(*) AS number';
     $fromTable = $websoccer->getConfig('db_prefix') . '_transfer';
     $whereCondition = 'datum >= %d AND (seller_user_id = %d AND buyer_user_id = %d OR seller_user_id = %d AND buyer_user_id = %d)';
     $parameters = array($websoccer->getNowAsTimestamp() - 30 * 3600 * 24, $user1, $user2, $user2, $user1);
     $result = $db->querySelect($columns, $fromTable, $whereCondition, $parameters);
     $transactions = $result->fetch_array();
     $result->free();
     if (isset($transactions['number'])) {
         return $transactions['number'];
     }
     return 0;
 }
예제 #23
0
/**
 * Writes a log statement into the entity log file.
 * 
 * @param WebSoccer $websoccer application context.
 * @param string $type edit|delete
 * @param string $username name of admin who executed an action.
 * @param string $entity name of affacted entity.
 * @param string $entityValue string value which identifies the entity item.
 */
function logAdminAction(WebSoccer $websoccer, $type, $username, $entity, $entityValue)
{
    $userIp = getenv('REMOTE_ADDR');
    $message = $websoccer->getFormattedDatetime($websoccer->getNowAsTimestamp()) . ';' . $username . ';' . $userIp . ';' . $type . ';' . $entity . ';' . $entityValue;
    $file = BASE_FOLDER . '/generated/entitylog.php';
    $fw = new FileWriter($file, FALSE);
    $fw->writeLine($message);
    $fw->close();
}