<?php
/* vim: set noexpandtab tabstop=2 softtabstop=2 shiftwidth=2: */

/**
 * Chat plugin.
 * Shows new/online Dedimania world records and their relations on the
 * current track.
 * Created by Xymph
 *
 * Dependencies: requires plugin.dedimania.php, plugin.checkpoints.php
 *               used by plugin.dedimania.php
 */

Aseco::addChatCommand('helpdedi', 'Displays info about the Dedimania records system');
Aseco::addChatCommand('dedihelp', 'Displays info about the Dedimania records system');
Aseco::addChatCommand('dedirecs', 'Displays all Dedimania records on current track');
if (!INHIBIT_RECCMDS) {
	Aseco::addChatCommand('dedinew', 'Shows newly driven Dedimania records');
	Aseco::addChatCommand('dedilive', 'Shows Dedimania records of online players');
	Aseco::addChatCommand('dedipb', 'Shows your Dedimania personal best on current track');
	Aseco::addChatCommand('dedifirst', 'Shows first Dedimania record on current track');
	Aseco::addChatCommand('dedilast', 'Shows last Dedimania record on current track');
	Aseco::addChatCommand('dedinext', 'Shows next better Dedimania record to beat');
	Aseco::addChatCommand('dedidiff', 'Shows your difference to first Dedimania record');
	Aseco::addChatCommand('dedirange', 'Shows difference first to last Dedimania record');
}
Aseco::addChatCommand('dedicps', 'Sets Dedimania record checkspoints tracking');
Aseco::addChatCommand('dedistats', 'Displays Dedimania track statistics');
Aseco::addChatCommand('dedisectms', 'Displays all Dedimania records\' sector times');

function chat_dedihelp($aseco, $command) { chat_helpdedi($aseco, $command); }
function chat_helpdedi($aseco, $command) {

	// compile & display help message
	$header = 'Dedimania information:';
	$data = array();
	$data[] = array('{#dedimsg}Dedimania$g is an online World Records database for {#black}all');
	$data[] = array('TrackMania games.  See its official site at:');
	$data[] = array('{#black}$l[http://www.dedimania.com/SITE/]http://www.dedimania.com/SITE/$l$g and the records database:');
	$data[] = array('{#black}$l[http://www.dedimania.com/tm2stats/?do=stat]http://www.dedimania.com/tm2stats/?do=stat$l$g .');
	$data[] = array();
	$data[] = array('Dedimania records are stored per game (TM2, TMF, etc)');
	$data[] = array('and mode (TimeAttack, Rounds, etc) and shared between');
	$data[] = array('all servers that operate with Dedimania support.');
	$data[] = array();
	$data[] = array('The available Dedimania commands are similar to local');
	$data[] = array('record commands:');
	$data[] = array('{#black}/dedirecs$g, {#black}/dedinew$g, {#black}/dedilive$g, {#black}/dedipb$g, {#black}/dedicps$g, {#black}/dedistats$g,');
	$data[] = array('{#black}/dedifirst$g, {#black}/dedilast$g, {#black}/dedinext$g, {#black}/dedidiff$g, {#black}/dedirange$g');
	$data[] = array();
	$data[] = array('See the {#black}/helpall$g command for detailed descriptions.');

	// display ManiaLink message
	display_manialink($command['author']->login, $header, array('Icons64x64_1', 'TrackInfo', -0.01), $data, array(0.95), 'OK');
}  // chat_helpdedi

function chat_dedirecs($aseco, $command) {
	global $dedi_db;

	$player = $command['author'];
	$login = $player->login;
	$dedi_recs = $dedi_db['Challenge']['Records'];

	// split params into array
	$arglist = explode(' ', strtolower(preg_replace('/ +/', ' ', $command['params'])));

	// process optional relations commands
	if ($arglist[0] == 'help') {
		$header = '{#black}/dedirecs <option>$g shows Dedimania records and relations:';
		$help = array();
		$help[] = array('...', '{#black}help',
		                'Displays this help information');
		$help[] = array('...', '{#black}pb',
		                'Shows your personal best on current track');
		$help[] = array('...', '{#black}new',
		                'Shows newly driven records');
		$help[] = array('...', '{#black}live',
		                'Shows records of online players');
		$help[] = array('...', '{#black}first',
		                'Shows first ranked record on current track');
		$help[] = array('...', '{#black}last',
		                'Shows last ranked record on current track');
		$help[] = array('...', '{#black}next',
		                'Shows next better ranked record to beat');
		$help[] = array('...', '{#black}diff',
		                'Shows your difference to first ranked record');
		$help[] = array('...', '{#black}range',
		                'Shows difference first to last ranked record');
		$help[] = array();
		$help[] = array('Without an option, the normal records list is displayed.');

		// display ManiaLink message
		display_manialink($login, $header, array('Icons64x64_1', 'TrackInfo', -0.01), $help, array(1.2, 0.05, 0.3, 0.85), 'OK');
		return;
	}
	elseif ($arglist[0] == 'pb') {
		chat_dedipb($aseco, $command);
		return;
	}
	elseif ($arglist[0] == 'new') {
		chat_dedinew($aseco, $command);
		return;
	}
	elseif ($arglist[0] == 'live') {
		chat_dedilive($aseco, $command);
		return;
	}
	elseif ($arglist[0] == 'first') {
		chat_dedifirst($aseco, $command);
		return;
	}
	elseif ($arglist[0] == 'last') {
		chat_dedilast($aseco, $command);
		return;
	}
	elseif ($arglist[0] == 'next') {
		chat_dedinext($aseco, $command);
		return;
	}
	elseif ($arglist[0] == 'diff') {
		chat_dedidiff($aseco, $command);
		return;
	}
	elseif ($arglist[0] == 'range') {
		chat_dedirange($aseco, $command);
		return;
	}

	if (!$total = count($dedi_recs)) {
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors('{#server}> {#error}No Dedimania records found!'), $login);
		return;
	}
	$maxrank = max($dedi_db['ServerMaxRank'], $player->dedirank);

	// display ManiaLink window
	$head = 'Current TOP ' . $maxrank . ' Dedimania Records:';
	$msg = array();
	$lines = 0;
	$player->msgs = array();
	// reserve extra width for $w tags
	$extra = ($aseco->settings['lists_colornicks'] ? 0.2 : 0);
	if ($dedi_db['ShowRecLogins'])
		$player->msgs[0] = array(1, $head, array(1.2+$extra, 0.1, 0.45+$extra, 0.4, 0.25), array('BgRaceScore2', 'Podium'));
	else
		$player->msgs[0] = array(1, $head, array(0.8+$extra, 0.1, 0.45+$extra, 0.25), array('BgRaceScore2', 'Podium'));

	// create list of records
	for ($i = 0; $i < $total; $i++) {
		$cur_record = $dedi_recs[$i];
		$nick = $cur_record['NickName'];
		if (!$aseco->settings['lists_colornicks'])
			$nick = stripColors($nick);
		if ($dedi_db['ShowRecLogins']) {
			$msg[] = array(str_pad($i+1, 2, '0', STR_PAD_LEFT) . '.',
			               '{#black}' . $nick,
			               '{#login}' . $cur_record['Login'],
			               ((isset($cur_record['NewBest']) && $cur_record['NewBest']) ? '{#black}': '') .
			               ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                $cur_record['Best'] : formatTime($cur_record['Best'])));
		} else {
			$msg[] = array(str_pad($i+1, 2, '0', STR_PAD_LEFT) . '.',
			               '{#black}' . $nick,
			               ((isset($cur_record['NewBest']) && $cur_record['NewBest']) ? '{#black}': '') .
			               ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                $cur_record['Best'] : formatTime($cur_record['Best'])));
		}
		if (++$lines > 14) {
			$player->msgs[] = $msg;
			$lines = 0;
			$msg = array();
		}
	}
	// add if last batch exists
	if (!empty($msg))
		$player->msgs[] = $msg;

	// display ManiaLink message
	display_manialink_multi($player);
}  // chat_dedirecs


/*
 * Universal function to generate list of Dedimania records for current track.
 * Called by chat_dedinew, chat_dedilive, endMap & beginMap (plugin.dedimania.php).
 * Show to a player if $login defined, otherwise show to all players.
 * $mode = 0 (only new), 1 (top-8 & online players at start of track),
 *         2 (top-6 & online during track), 3 (top-8 & new at end of track)
 * In modes 1/2/3 the last Dedimania record is also shown
 * top-8 is configurable via $dedi_db['ShowMinRecs']; top-6 is ShowMinRecs-2
 */
function show_dedirecs($aseco, $name, $uid, $dedi_recs, $login, $mode, $window) {
	global $dedi_db, $dedi_debug;

	$records = '$n';  // use narrow font

	if ($dedi_debug > 2)
		$aseco->console_text('show_dedirecs - dedi_recs' . CRLF . print_r($dedi_recs, true));

	// check for records
	if (!isset($dedi_recs) || ($total = count($dedi_recs)) == 0) {
		$totalnew = -1;
	} else {
		// check whether to show range
		if ($dedi_db['ShowRecsRange']) {
			// get the first & last Dedimania records
			$first = $dedi_recs[0];
			$last = $dedi_recs[$total-1];
			// compute difference between records
			if ($aseco->server->gameinfo->mode != Gameinfo::STNT) {
				$diff = $last['Best'] - $first['Best'];
				$sec = floor($diff/1000);
				$ths = $diff - ($sec * 1000);
			} else {  // Stunts
				$diff = $first['Best'] - $last['Best'];
			}
		}

		// get list of online players
		$players = array();
		foreach ($aseco->server->players->player_list as $pl) {
			$players[] = $pl->login;
		}

		// collect new records and records by online players
		$totalnew = 0;

		// go through each record
		for ($i = 0; $i < $total; $i++) {
			$cur_record = $dedi_recs[$i];

			// if the record is new then display it
			if (isset($cur_record['NewBest']) && $cur_record['NewBest']) {
				$totalnew++;
				$record_msg = formatText($aseco->getChatMessage('RANKING_RECORD_NEW_ON'),
				                         $i+1,
				                         stripColors($cur_record['NickName']),
				                         ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
				                          $cur_record['Best'] : formatTime($cur_record['Best'])));
				// always show new record
				$records .= $record_msg;
			} else {
				// check if player is online
				if (in_array($cur_record['Login'], $players) /* && $cur_record['Game'] == $aseco->server->getGame() */ ) {
					$record_msg = formatText($aseco->getChatMessage('RANKING_RECORD_ON'),
					                         $i+1,
					                         stripColors($cur_record['NickName']),
					                         ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
					                          $cur_record['Best'] : formatTime($cur_record['Best'])));
					// check if last Dedimania record
					if ($mode != 0 && $i == $total-1) {
						$records .= $record_msg;
					}
					// check if always show (start of/during track)
					elseif ($mode == 1 || $mode == 2) {
						$records .= $record_msg;
					}
					else {
						// show record if < ShowMinRecs (end of track)
						if ($mode == 3 && $i < $dedi_db['ShowMinRecs']) {
							$records .= $record_msg;
						}
					}
				} else {
					$record_msg = formatText($aseco->getChatMessage('RANKING_RECORD'),
					                         $i+1,
					                         stripColors($cur_record['NickName']),
					                         ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
					                          $cur_record['Best'] : formatTime($cur_record['Best'])));
					// check if last Dedimania record
					if ($mode != 0 && $i == $total-1) {
						$records .= $record_msg;
					}
					// show offline record if < ShowMinRecs-2 (during track)
					elseif (($mode == 2 && $i < $dedi_db['ShowMinRecs']-2) ||
					// show offline record if < ShowMinRecs (start/end of track)
					        (($mode == 1 || $mode == 3) && $i < $dedi_db['ShowMinRecs'])) {
						$records .= $record_msg;
					}
				}
			}
		}
	}

	// define wording of the ranking message
	switch ($mode) {
	case 0:
		$timing = 'during';
		break;
	case 1:
		$timing = 'before';
		break;
	case 2:
		$timing = 'during';
		break;
	case 3:
		$timing = 'after';
		break;
	}

	// hyperlink track name
	$name = stripColors($name);
	$name = '$l[http://www.dedimania.com/tm2stats/?do=stat&Show=RECORDS&RecOrder3=RANK-ASC&UId=' . $uid . ']' . $name . '$l';

	// define the ranking message
	if ($totalnew > 0) {
		$message = formatText($dedi_db['Messages']['RANKING_NEW'][0],
		                      $name, $timing, $totalnew);
	}
	elseif ($totalnew == 0 && $records != '$n') {
		// check whether to show range
		if ($dedi_db['ShowRecsRange']) {
			$message = formatText($dedi_db['Messages']['RANKING_RANGE'][0],
			                      $name, $timing,
			                      ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                       $diff : sprintf("%d.%03d", $sec, $ths)));
		} else {
			$message = formatText($dedi_db['Messages']['RANKING'][0],
			                      $name, $timing);
		}
	}
	elseif ($totalnew == 0 && $records == '$n') {
		$message = formatText($dedi_db['Messages']['RANKING_NONEW'][0],
		                      $name, $timing);
	}
	else {  // $totalnew == -1
		$message = formatText($dedi_db['Messages']['RANKING_NONE'][0],
		                      $name, $timing);
	}

	// append the records if any
	if ($records != '$n') {
		$records = substr($records, 0, strlen($records)-2);  // strip trailing ", "
		$message .= LF . $records;
	}

	// show to player or all
	if ($login) {
		// strip 1 leading '>' to indicate a player message instead of system-wide
		$message = str_replace('{#server}>> ', '{#server}> ', $message);
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login);
	} else {
		if ($window == 2 && function_exists('send_window_message'))
			send_window_message($aseco, $message, ($mode == 3));
		else
			$aseco->client->query('ChatSendServerMessage', $aseco->formatColors($message));
	}
}  // show_dedirecs

function chat_dedinew($aseco, $command) {
	global $dedi_db;

	// show only newly driven records
	show_dedirecs($aseco, $aseco->server->map->name, $aseco->server->map->uid, $dedi_db['Challenge']['Records'], $command['author']->login, 0, 0);
}  // chat_dedinew

function chat_dedilive($aseco, $command) {
	global $dedi_db;

	// show online & ShowMinRecs-2 records
	show_dedirecs($aseco, $aseco->server->map->name, $aseco->server->map->uid, $dedi_db['Challenge']['Records'], $command['author']->login, 2, 0);
}  // chat_dedilive

function chat_dedipb($aseco, $command) {
	global $dedi_db;

	$login = $command['author']->login;
	$dedi_recs = $dedi_db['Challenge']['Records'];

	$found = false;
	// find Dedimania record
	for ($i = 0; $i < count($dedi_recs); $i++) {
		$rec = $dedi_recs[$i];
		if ($rec['Login'] == $login /* && $rec['Game'] == $aseco->server->getGame() */ ) {
			$score = $rec['Best'];
			$rank = $i;
			$found = true;
			break;
		}
	}

	if ($found) {
		$message = formatText($dedi_db['Messages']['PB'][0],
		                      ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
		                       $score : formatTime($score)), $rank+1);
		$message = $aseco->formatColors($message);
		$aseco->client->query('ChatSendServerMessageToLogin', $message, $login);
	} else {
		$message = $dedi_db['Messages']['PB_NONE'][0];
		$message = $aseco->formatColors($message);
		$aseco->client->query('ChatSendServerMessageToLogin', $message, $login);
	}
}  // chat_dedipb

function chat_dedifirst($aseco, $command) {
	global $dedi_db;

	$dedi_recs = $dedi_db['Challenge']['Records'];

	if (!empty($dedi_recs)) {
		// get the first Dedimania record
		$record = $dedi_recs[0];

		// show chat message
		$message = formatText($dedi_db['Messages']['FIRST_RECORD'][0])
		         . formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
		                                             1,
		                                             stripColors($record['NickName']),
		                                             ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
		                                              $record['Best'] : formatTime($record['Best'])));

		$message = substr($message, 0, strlen($message)-2);  // strip trailing ", "
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $command['author']->login);
	} else {
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors('{#server}> {#error}No Dedimania records found!'), $command['author']->login);
	}
}  // chat_dedifirst

function chat_dedilast($aseco, $command) {
	global $dedi_db;

	$dedi_recs = $dedi_db['Challenge']['Records'];

	if ($total = count($dedi_recs)) {
		// get the last Dedimania record
		$record = $dedi_recs[$total-1];

		// show chat message
		$message = formatText($dedi_db['Messages']['LAST_RECORD'][0])
		         . formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
		                                             $total,
		                                             stripColors($record['NickName']),
		                                             ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
		                                              $record['Best'] : formatTime($record['Best'])));

		$message = substr($message, 0, strlen($message)-2);  // strip trailing ", "
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $command['author']->login);
	} else {
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors('{#server}> {#error}No Dedimania records found!'), $command['author']->login);
	}
}  // chat_dedilast

function chat_dedinext($aseco, $command) {
	global $dedi_db;

	$login = $command['author']->login;
	$dedi_recs = $dedi_db['Challenge']['Records'];

	if ($total = count($dedi_recs)) {
		$found = false;
		// find Dedimania record
		for ($i = 0; $i < $total; $i++) {
			$rec = $dedi_recs[$i];
			if ($rec['Login'] == $login /* && $rec['Game'] == $aseco->server->getGame() */ ) {
				$rank = $i;
				$found = true;
				break;
			}
		}

		if ($found) {
			// get current and next better Dedimania records
			$nextrank = ($rank > 0 ? $rank-1 : 0);
			$record = $dedi_recs[$rank];
			$next = $dedi_recs[$nextrank];

			// compute difference to next record
			if ($aseco->server->gameinfo->mode != Gameinfo::STNT) {
				$diff = $record['Best'] - $next['Best'];
				$sec = floor($diff/1000);
				$ths = $diff - ($sec * 1000);
			} else {  // Stunts mode
				$diff = $next['Best'] - $record['Best'];
			}

			// show chat message
			$message1 = formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
			                                              $rank+1,
			                                              stripColors($record['NickName']),
			                                              ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                                               $record['Best'] : formatTime($record['Best'])));
			$message1 = substr($message1, 0, strlen($message1)-2);  // strip trailing ", "
			$message2 = formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
			                                              $nextrank+1,
			                                              stripColors($next['NickName']),
			                                              ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                                               $next['Best'] : formatTime($next['Best'])));
			$message2 = substr($message2, 0, strlen($message2)-2);  // strip trailing ", "
			$message = formatText($dedi_db['Messages']['DIFF_RECORD'][0],
			                      $message1, $message2,
			                      ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                       $diff : sprintf("%d.%03d", $sec, $ths)));

			$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login);
		} else {
			// look for unranked time instead
			$order = ($aseco->server->gameinfo->mode == Gameinfo::STNT ? 'DESC' : 'ASC');
			$query = 'SELECT Score FROM rs_times
			          WHERE PlayerId=' . $command['author']->id . ' AND
			                MapId=' . $aseco->server->map->id . '
			          ORDER BY Score ' . $order . ' LIMIT 1';
			$result = mysql_query($query);
			if (mysql_num_rows($result) > 0) {
				$unranked = mysql_fetch_object($result);
				$found = true;
			}
			mysql_free_result($result);

			if ($found) {
				// get the last Dedimania record
				$last = $dedi_recs[$total-1];

				// compute difference to next record
				if ($aseco->server->gameinfo->mode != Gameinfo::STNT) {
					$sign = ($unranked->Score < $last['Best'] ? '-' : '');
					$diff = abs($unranked->Score - $last['Best']);
					$sec = floor($diff/1000);
					$ths = $diff - ($sec * 1000);
				} else {  // Stunts mode
					$diff = $last['Best'] - $unranked->Score;
				}

				// show chat message
				$message1 = formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
				                                              'PB',
				                                              stripColors($command['author']->nickname),
				                                              ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
				                                               $unranked->Score : formatTime($unranked->Score)));
				$message1 = substr($message1, 0, strlen($message1)-2);  // strip trailing ", "
				$message2 = formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
				                                              $total,
				                                              stripColors($last['NickName']),
				                                              ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
				                                               $last['Best'] : formatTime($last['Best'])));
				$message2 = substr($message2, 0, strlen($message2)-2);  // strip trailing ", "
				$message = formatText($dedi_db['Messages']['DIFF_RECORD'][0],
				                      $message1, $message2,
				                      ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
				                       $diff : sprintf("%s%d.%03d", $sign, $sec, $ths)));

				$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login);
			} else {
				$message = '{#server}> {#error}You don\'t have Dedimania a record on this track yet... use {#highlite}$i/dedilast';
				$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login);
			}
		}
	} else {
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors('{#server}> {#error}No Dedimania records found!'), $login);
	}
}  // chat_dedinext

function chat_dedidiff($aseco, $command) {
	global $dedi_db;

	$login = $command['author']->login;
	$dedi_recs = $dedi_db['Challenge']['Records'];

	if ($total = count($dedi_recs)) {
		$found = false;
		// find Dedimania record
		for ($i = 0; $i < $total; $i++) {
			$rec = $dedi_recs[$i];
			if ($rec['Login'] == $login /* && $rec['Game'] == $aseco->server->getGame() */ ) {
				$rank = $i;
				$found = true;
				break;
			}
		}

		if ($found) {
			// get current and first Dedimania records
			$record = $dedi_recs[$rank];
			$first = $dedi_recs[0];

			// compute difference to first record
			if ($aseco->server->gameinfo->mode != Gameinfo::STNT) {
				$diff = $record['Best'] - $first['Best'];
				$sec = floor($diff/1000);
				$ths = $diff - ($sec * 1000);
			} else {  // Stunts mode
				$diff = $first['Best'] - $record['Best'];
			}

			// show chat message
			$message1 = formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
			                                              $rank+1,
			                                              stripColors($record['NickName']),
			                                              ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                                               $record['Best'] : formatTime($record['Best'])));
			$message1 = substr($message1, 0, strlen($message1)-2);  // strip trailing ", "
			$message2 = formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
			                                              1,
			                                              stripColors($first['NickName']),
			                                              ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                                               $first['Best'] : formatTime($first['Best'])));
			$message2 = substr($message2, 0, strlen($message2)-2);  // strip trailing ", "
			$message = formatText($dedi_db['Messages']['DIFF_RECORD'][0],
			                      $message1, $message2,
			                      ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
			                       $diff : sprintf("%d.%03d", $sec, $ths)));

			$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login);
		} else {
			$message = '{#server}> {#error}You don\'t have a Dedimania record on this track yet... use {#highlite}$i/dedilast';
			$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $login);
		}
	} else {
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors('{#server}> {#error}No Dedimania records found!'), $login);
	}
}  // chat_dedidiff

function chat_dedirange($aseco, $command) {
	global $dedi_db;

	$dedi_recs = $dedi_db['Challenge']['Records'];

	if ($total = count($dedi_recs)) {
		// get the first & last Dedimania records
		$first = $dedi_recs[0];
		$last = $dedi_recs[$total-1];

		// compute difference between records
		if ($aseco->server->gameinfo->mode != Gameinfo::STNT) {
			$diff = $last['Best'] - $first['Best'];
			$sec = floor($diff/1000);
			$ths = $diff - ($sec * 1000);
		} else {  // Stunts mode
			$diff = $first['Best'] - $last['Best'];
		}

		// show chat message
		$message1 = formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
		                                              1,
		                                              stripColors($first['NickName']),
		                                              ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
		                                               $first['Best'] : formatTime($first['Best'])));
		$message1 = substr($message1, 0, strlen($message1)-2);  // strip trailing ", "
		$message2 = formatText($aseco->getChatMessage('RANKING_RECORD_NEW'),
		                                              $total,
		                                              stripColors($last['NickName']),
		                                              ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
		                                               $last['Best'] : formatTime($last['Best'])));
		$message2 = substr($message2, 0, strlen($message2)-2);  // strip trailing ", "
		$message = formatText($dedi_db['Messages']['DIFF_RECORD'][0],
		                      $message1, $message2,
		                      ($aseco->server->gameinfo->mode == Gameinfo::STNT ?
		                       $diff : sprintf("%d.%03d", $sec, $ths)));

		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message), $command['author']->login);
	} else {
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors('{#server}> {#error}No Dedimania records found!'), $command['author']->login);
	}
}  // chat_dedirange

function chat_dedicps($aseco, $command) {
	global $dedi_db, $checkpoints;  // from plugin.checkpoints.php

	$login = $command['author']->login;

	if ($aseco->settings['display_checkpoints']) {
		if (isset($checkpoints[$login]) && $checkpoints[$login]->loclrec != -1) {
			// set Dedimania checkpoints tracking
			$param = $command['params'];
			if (strtolower($param) == 'off') {
				$checkpoints[$login]->dedirec = -1;
				$message = '{#server}> {#dedimsg}Dedimania checkpoints tracking: {#highlite}OFF';
			}
			elseif ($param == '') {
				$checkpoints[$login]->dedirec = 0;
				$message = '{#server}> {#dedimsg}Dedimania checkpoints tracking: {#highlite}ON {#dedimsg}(your own or the last record)';
			}
			elseif (is_numeric($param) && $param > 0 && $param <= $dedi_db['MaxRecords']) {
				$checkpoints[$login]->dedirec = intval($param);
				$message = '{#server}> {#dedimsg}Dedimania checkpoints tracking record: {#highlite}' . $checkpoints[$login]->dedirec;
			}
			else {
				$message = '{#server}> {#error}No such Dedimania record {#highlite}$i ' . $param;
			}
		} else {
			$message = '{#server}> {#error}You must first enable checkpoints tracking with {#highlite}$i /cps';
		}
	} else {
		$message = '{#server}> {#error}Dedimania checkpoints tracking permanently disabled by server';
	}
	// show chat message
	$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors($message) , $login);
}  // chat_dedicps

function chat_dedistats($aseco, $command) {
	global $dedi_db;

	$login = $command['author']->login;

	// compile & display stats message
	$header = 'Dedimania Stats: {#black}' . stripColors($aseco->server->map->name);
	$stats = array();
	$stats[] = array('Server MaxRank', '{#black}' . $dedi_db['ServerMaxRank']);
	$stats[] = array('Your MaxRank', '{#black}' . $command['author']->dedirank);
	$stats[] = array();
	$stats[] = array('UID', '{#black}' . $dedi_db['Challenge']['UId']);
	$stats[] = array('Total Races', '{#black}' . $dedi_db['Challenge']['TotalRaces']);
	$stats[] = array('Total Players', '{#black}' . $dedi_db['Challenge']['TotalPlayers']);
	$stats[] = array('Avg. Players', '{#black}' . ($dedi_db['Challenge']['TotalRaces'] > 0 ? round($dedi_db['Challenge']['TotalPlayers'] / $dedi_db['Challenge']['TotalRaces'], 2) : 0));
	$stats[] = array();
	$stats[] = array('               {#black}$l[http://dedimania.com/tm2stats/?do=stat&RecOrder3=RANK-ASC&UId=' . $dedi_db['Challenge']['UId'] . '&Show=RECORDS]View all Dedimania records for this track$l');

	// display ManiaLink message
	display_manialink($login, $header, array('Icons64x64_1', 'Maximize', -0.01), $stats, array(1.0, 0.3, 0.7), 'OK');
}  // chat_dedistats

function chat_dedisectms($aseco, $command) {
	global $dedi_db;

	$player = $command['author'];
	$login = $player->login;
	$dedi_recs = $dedi_db['Challenge']['Records'];

	if (!$total = count($dedi_recs)) {
		$aseco->client->query('ChatSendServerMessageToLogin', $aseco->formatColors('{#server}> {#error}No Dedimania records found!'), $login);
		return;
	}
	$maxrank = max($dedi_db['ServerMaxRank'], $player->dedirank);
	$cpscnt = count(explode(',', $dedi_recs[0]['Checks']));

	// display ManiaLink window
	$head = 'Current TOP ' . $maxrank . ' Dedimania Sector Times (' . $cpscnt . '):';
	$cpsmax = 12;
	// compute widths
	$width = 0.1 + 0.18 + min($cpscnt, $cpsmax) * 0.1 + ($cpscnt > $cpsmax ? 0.06 : 0.0);
	if ($width < 1.0) $width = 1.0;
	$widths = array($width, 0.1, 0.18);
	for ($i = 0; $i < min($cpscnt, $cpsmax); $i++)
		$widths[] = 0.1; // cp
	if ($cpscnt > $cpsmax)
		$widths[] = 0.06;

	$msg = array();
	$lines = 0;
	$player->msgs = array();
	$player->msgs[0] = array(1, $head, $widths, array('BgRaceScore2', 'Podium'));

	// create list of records
	for ($i = 0; $i < $total; $i++) {
		$cur_record = $dedi_recs[$i];
		$cpsrec = explode(',', $cur_record['Checks']);
		$line = array();
		$line[] = str_pad($i+1, 2, '0', STR_PAD_LEFT) . '.';
		$line[] = ((isset($cur_record['NewBest']) && $cur_record['NewBest']) ? '{#black}' : '')
		          . formatTime($cur_record['Best']);
		// append up to $cpsmax sector times
		if (!empty($cpsrec)) {
			$j = 1;
			$pr = 0;
			foreach ($cpsrec as $cp) {
				$line[] = '$n' . formatTime($cp - $pr);
				$pr = $cp;
				if (++$j > $cpsmax) {
					if ($cpscnt > $cpsmax) $line[] = '+';
					break;
				}
			}
		}
		$msg[] = $line;
		if (++$lines > 14) {
			$player->msgs[] = $msg;
			$lines = 0;
			$msg = array();
		}
	}
	// add if last batch exists
	if (!empty($msg))
		$player->msgs[] = $msg;

	// display ManiaLink message
	display_manialink_multi($player);
}  // chat_dedisectms
?>
