Commit 6af854ff authored by saviola's avatar saviola
Browse files

First commit of the XAseco plugin file.

parents
<?php
/**
* (X)Aseco Train Statistics version 0.8
*
*
* This plugin collects train statistics for each player on each map on a per
* map basis.
*
* Changelog:
*
* Version 0.8:
*
* - renamed plugin file to plugin.xts.php
* - exported commented out chat functionality into chat.xts.php
* - enabled XTS in time attack and team mode
*
* Version 0.6:
* - second testing release, backend implemented, write-only approach
*
* Version 0.5:
* - first tesing release, no data storage backend implemented, everything stored in ram
* - each time a player finishes, his time is being saved
* - each time a player fails (resigns), an internal counter is incremented
* - only activated in round-based modes
*/
/*
* Constants and configuration
*/
// defines which messages will be send to the console
define('XTS_LOG_LEVEL', 3);
/*
* Tiny logging facility.
*/
class XtsLogger
{
const ERROR = 5;
const WARNING = 4;
const NOTICE = 3;
const NORMAL = 2;
const VERBOSE = 1;
const DEBUG = 0;
public static $logLevels = array('DEBUG', 'VERBOSE', 'NORMAL', 'NOTICE', 'WARNING', 'ERROR');
/**
* Logs given message to given level. It is displayed in the console if the given level is higher or equal to the XTS_LOG_LEVEL
* value.
*/
public static function log($message, $level = self::NORMAL)
{
$prefix = 'XTS'.($level != self::NORMAL ? '['.self::$logLevels[$level].']' : '').': ';
if ($level >= XTS_LOG_LEVEL)
{
Xts::$aseco->console_text($prefix.$message);
//Xts::$aseco->client->queryIgnoreResult('ChatSendServerMessage', Xts::$aseco->formatColors($prefix.$message));
}
}
}
class XtsRecord
{
public $checkpoint = null;
public $fails = 0;
public $idChallenge = 0;
public $idPlayer = 0;
public $login = null;
public $times = array();
public function __construct($login, $idChallenge = null)
{
$this->idPlayer = Xts::$aseco->getPlayerId($login);
$this->login = $login;
$this->idChallenge = $idChallenge;
}
/**
* Merge two records of the same challenge
* TODO: compare challenges
*/
public function mergeInto(XtsRecord $record)
{
$this->fails += $record->fails;
$this->times += $record->times;
return $this;
}
/**
* Returns current statistics
*/
public function getStats()
{
$countFinish = count($this->times);
$countOverall = $this->fails+$countFinish;
return 'Count: '.$countOverall.
', fails: '.$this->fails.' ('.round($this->fails/$countOverall*100).'%)'.
', average: '.formatTime(round(array_sum($this->times)/$countFinish));
}
/**
* Registers checkpoint $index for this user to check whether s/he failed
*/
public function registerCheckpoint($index)
{
$this->checkpoint = $index;
return $this;
}
/**
* Registers fail
*/
public function registerFail()
{
$this->fails++;
$this->checkpoint = null;
}
// Registers time for player
public function registerTime($time)
{
$this->times[] = $time;
$this->checkpoint = null;
}
}
class Xts
{
/**
* Reference to aseco object
*/
public static $aseco = null;
protected $_challenge = null;
protected $_data = array();
protected $_dataClean = array();
protected static $_instance = null;
protected function __construct(Aseco $aseco)
{
$this->_aseco = $aseco;
$this->setChallenge();
}
/**
* Loads overall statistics for $login on current challenge
*
* This method is currently not used
*/
public function fetchStats($login)
{
return null;
$record = $this->getRecord($login);
$query = 'SELECT * FROM xts WHERE PlayerId = "'.$record->idPlayer.'" AND ChallengeId = "'.$record->idChallenge.'"';
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
return $row;
}
/**
* Returns current challenge
*/
public function getChallenge()
{
if (null === $this->_challenge)
{
$this->setChallenge();
}
return $this->_challange;
}
public static function getInstance()
{
if (null === self::$_instance)
{
self::$_instance = new Xts(self::$aseco);
}
return self::$_instance;
}
/**
* Retrieves and possibly creates record
*/
public function getRecord($login)
{
// if player is new, create record
if (!isset($this->_data[$login]))
{
XtsLogger::log('Creating new record: '.$login, XtsLogger::DEBUG);
$this->_data[$login] = new XtsRecord($login, $this->getChallenge()->id);
}
$record = $this->_data[$login];
return $record;
}
/*
* Saves record in $_dataClean or merges it into existing record
*/
public function saveRecords($login = null)
{
$data = array();
if (null != $login)
{
$data = array($this->_data[$login]);
unset($this->_data[$login]);
}
else
{
$data = $this->_data;
$this->_data = array();
}
$challengeId = Xts::$aseco->getChallengeId(Xts::$aseco->server->challenge->uid);
XtsLogger::log('Saving record for '.($login ? $login : 'all'). ' on map '.$challengeId, XtsLogger::DEBUG);
foreach ($data as $record)
{
// Skip if no data available
if (!$record->times) continue;
$query = 'INSERT INTO xts (PlayerId, ChallengeId, Mode, Times, Count) '.
'VALUES ('.$record->idPlayer.','.$challengeId.','. (int) checkStatus(Xts::$aseco).',"'.implode(',', $record->times).'",'.
(count($record->times)+$record->fails).')';
$result = mysql_query($query);
if (false === $result)
{
XtsLogger::log('Error inserting data into database. Query: '.$query, XtsLogger::ERROR);
}
}
}
/**
* Sets current challenge
*/
public function setChallenge(Challenge $challenge = null)
{
// If no challenge was given, try to find out current challenge
if (null === $challenge)
{
$challenge = self::$aseco->server->challenge;
}
XtsLogger::log('New challenge: '.$challenge->id.', old challenge: '.$this->_challenge->id, XtsLogger::DEBUG);
if (null != $this->_challenge && $this->_challenge->id != $challenge->id && !empty($this->_data))
{
XtsLogger::log('Saving records...', XtsLogger::DEBUG);
$this->saveRecords();
}
$this->_challenge = $challenge;
}
}
Aseco::registerEvent('onCheckpoint', 'xtsCheckpointReached');
//Aseco::registerEvent('onEndRound', 'xtsEndRound');
Aseco::registerEvent('onNewChallenge', 'xtsNewChallenge');
Aseco::registerEvent('onPlayerFinish', 'xtsFinished');
Aseco::registerEvent('onPlayerDisconnect', 'xtsPlayerDisconnects');
Aseco::registerEvent('onStartup', 'xtsInit');
//Aseco::registerEvent('onEndRace', 'xtsEndRace');
/**
* Checks whether a supported mode is activated.
*/
function checkStatus($aseco)
{
return in_array($aseco->server->gameinfo->mode, array(0, 1, 2, 5)) ? $aseco->server->gameinfo->mode : false;
}
/**
* Registers each checkpoint for each player, to notice players giving up
*/
function xtsCheckpointReached($aseco, $params)
{
if (false === checkStatus($aseco)) return;
$xts = Xts::getInstance();
list($playerUid, $login, $time, $score, $index) = $params;
$xts->getRecord($login)->registerCheckpoint($index);
}
/**
* When the current challenge ends, all data is stored in the database
*/
function xtsEndRace($aseco, $challenge)
{
//global $xts;
//$xts->endRace($challenge);
}
/**
* When a round ends, player data is stored in the $xts object
*/
function xtsEndRound($aseco)
{
//global $xts;
//$xts->endRound();
}
/**
* When a player finishes, his record is saved
*/
function xtsFinished($aseco, $record)
{
if (false === checkStatus($aseco)) return;
$xts = Xts::getInstance();
$xtsRecord = $xts->getRecord($record->player->login);
if (0 == $record->score)
{
// Didn't reach first checkpoint? Well, then never mind, no fail.
if (null === $xtsRecord->checkpoint) return;
$xtsRecord->registerFail();
XtsLogger::log('Player failed: '.$record->player->login. ', fails: '.$xtsRecord->fails, XtsLogger::DEBUG);
return;
}
$xtsRecord->registerTime($record->score);
}
/**
* Initializes XTS
*/
function xtsInit($aseco)
{
Xts::$aseco = $aseco;
XtsLogger::log($aseco, 'Starting.', XtsLogger::DEBUG);
}
/**
* When a new challenge is loaded, the $xts object is notified
*/
function xtsNewChallenge($aseco, $challenge)
{
if (false === checkStatus($aseco)) return;
Xts::getInstance()->setChallenge($challenge);
}
/**
* When a player disconnects, his current dara are stored in the database
*/
function xtsPlayerDisconnects($aseco, $player)
{
if (false === checkStatus($aseco)) return;
XtsLogger::log('Player disconnecting: '.$player->login, XtsLogger::DEBUG);
Xts::getInstance()->saveRecords($player->login);
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment