The online racing simulator
LTWT: Live Teams Web Tracker
Hi!
After LWT wchich is easy (but maybe something will change with 0.4.0 version of PRISM) I will start working on LTWT.

Here is my problem. I can do everything but only when I have 1 server.
Can you help me with script that calculates positions for multi-server race.
First version of defining classes (but I will change if the change will help us) for cars is something like this:

<?php 
$classes 
= array('TBO' => 'FXO,XRT''STD' => 'XFG,XRG');
?>

or

<?php 
$classes 
= array('TBO' => array('FXO','XRT'), 'STD' => array('XFG','XRG'));
?>

I say the second one, it's easier to iterate over the second array then it is to have to parse the first.
Ok. Now we should take array for players but wchich data is needed and how to compare it. For example we have 4 servers and races didn't started at same time. Track is KY Oval. On 1,2 servers when people are crossing S-F line, on 3,4 servers people crosses SP1.
Comparing last registered times will not work. All data is saved in database. Splits, laps, pitstop have separate tables.
Why are you comparing times? Race classification is done by the number of laps completed in a given amount of distance or time, and then by the time taken by each team to complete those laps. Therefore, sort it on laps, then by the time taken to complete those laps, since each server's race start time.
Ok. I can select from DB data about last ETime in LAP packet and count laps. So we have now array:

<?php 
$racers 
= array('benten' => array(25150000'XFG'), 'boothy' => array(24149900'XRG'), 'Dygear' => array(25147800'FXO'));
?>

I will do some code in 1 hour so we can finish that today. I will not write all of the LTWT before 0.4.0 because Dygear said there will be big changes in API.
Quote from misiek08 :I will not write all of the LTWT before 0.4.0 because Dygear said there will be big changes in API.

Good idea, I'm still on the fence about some things, but I'll post the things I plan on chaging, and the things that have been changed from 0.3.0 to 0.3.1.
You said something about changing API and the plugin can not work. This system will use multi hosts and some other PRISM modules so it can be time wasting now.
I just found out my friends in the hospital, so after work I'm going to see him. It's going to be a long night.
I know how to do it but only with the same time of start. Can someone write an algorithm (script) in any programming lang for this? I will translate it to PHP but help me, please.
SQL:

SELECT * FROM results
ORDER BY lapsDone DESC, overallTime

C#

results.OrderByDescending(r => r.LapsDone).ThenBy(r => r.OverallTime);

Hmn, we have to include splits (because it's 5 sec interval, AJAX system). You did this if the table looks like
Quote :results { lfsw, name, lapsdone, overallTime, s1,s2,s3,car,pits}

lapsdone gets from the last packet and s1,2,3 too.
overalllTime is ETime from the last SPX or LAP packet.

EDIT: Chagned spX columns to sX columns - that are splits.
Both of the above are still valid for that result set, with or without the sector times. The sector times are just more data, it will not effect the way the data sorted.
I think he tries to figure out, how to compare two drivers if they are on different servers which started with a "big" timely difference. (big beeing 30 seconds?)

e.g.
Driver A on server A
Driver B on server B

The race on server A was started 10 seconds before the race on server B.
Driver A did 2 laps in 2 minutes.
Driver B did 2 laps in 1 minute 55 seconds.

The display on the website would display driver A in front of driver B for the short period of time between driver A finishing the second lap and driver B finishing the second lap because Driver A has a lap more.



The solution might be to store all events with a timestamp in the db and then only showing/sorting by events prior to now()-serverDifference.
Quote :SELECT *,IF(s1=0,1,0) as s1_isnull, IF(s2=0, 1, 0) as s2_isnull, IF(s3=0, 1, 0) as s3_isnull FROM results ORDER BY lapsdone DESC, s1 ASC, s2 ASC, s3 ASC, s1_isnull ASC, s2_isnull ASC, s3_isnull ASC

Did I miss something?
Quote from GeForz :I think he tries to figure out, how to compare two drivers if they are on different servers which started with a "big" timely difference. (big beeing 30 seconds?)

The last sever to start the session should be used as the chronometer for the over all session time. While server A will be ahead of server B, that would be ahead of server C you have to wait for server C to start before you can property start tracking race events between servers. You should use ETime in the packets to ensure that the data is synced correctly, therefor you should use ETime as the order mechanism for your sorting functions to ensure that the data in synced.

Quote from misiek08 :
SELECT *,IF(s1=0,1,0) as s1_isnull, IF(s2=0, 1, 0) as s2_isnull, IF(s3=0, 1, 0) as s3_isnull FROM results ORDER BY lapsdone DESC, s1 ASC, s2 ASC, s3 ASC, s1_isnull ASC, s2_isnull ASC, s3_isnull ASC

Did I miss something?

Not knowing what S1, S2 & S3 are, I could not really tell you. I would say that for each server must have it's own table. From there I would use a view of the these tables that would show information up to the last timestamp of the last server that started. From there, I would sort the information based on ETime.
s1,s2,s3 are split times.

EDIT:
overallTime is changed on LAP and SPX packet's so the ETime from last LAP packet (lapsdone) != overallTime
Wow, saving MCI's and NLP's could kill system because PHP can be blocked by connection php-mysql. But every other packet can be logged. I think you are going to make this view (code it) but when?
I can't do an ASYNCHRONOUS post to MySQL?
You can. I'll try my solution first and then you can do your. I will do it in 0.3.0 or in 0.3.1 but only if you will release it tomorrow before 15pm UTC
Any luck on this, would be cool to have
My official release maybe will be February or early March. (early means here early not 3 years later as for LFS)
Maybe someone will do it faster but I don't have so many time. I'll be testing first version in January on some league but this will be beta only.
yep and hopefully it works perfectly so you dont have to fix much
I wonna it too.
Code of beta version can you see below. It's working but there is still a lot of things to do.
Code of plugin:

<?php 
php

class ltwt2 extends Plugins {
    const 
NAME 'Test';
    const 
AUTHOR 'Misiek';
    const 
VERSION PHPInSimMod::VERSION;
    const 
DESCRIPTION 'Testing PRISM.';

    public 
$poss = array();
    public 
$misiek_plid 0;
    public 
$lapsdone = array();
    public 
$session 0;

    public function 
__construct() {
        require_once(
'includes/DB.class.php');
        
DB::gi()->query('SET NAMES utf8');
        
$this->registerPacket('save_to_db'ISP_SPXISP_LAPISP_PITISP_PLAISP_PENISP_FLGISP_NPLISP_REO);
        
$this->registerPacket('lap'ISP_LAP);
        
$this->registerPacket('spx'ISP_SPX);
        
$this->registerPacket('npl'ISP_NPL);
        
$this->registerPacket('npl'ISP_NPL);
        
$this->registerPacket('toc'ISP_TOC);
        
$this->createTimer('showMemoryUsage'30Timer::REPEAT);
        
error_reporting(E_ALL E_NOTICE);
    }

    public function 
showMemoryUsage() {
        echo 
'-------------------------------' PHP_EOL;
        echo 
'-------------------------------' PHP_EOL;
        echo 
'@memory_get_usage(): ' . @memory_get_usage() . PHP_EOL;
        echo 
'@memory_get_usage(true): ' . @memory_get_usage(true) . PHP_EOL;
        echo 
'@memory_get_peak_usage(): ' . @memory_get_peak_usage() . PHP_EOL;
        echo 
'@memory_get_peak_usage(true): ' . @memory_get_peak_usage(true) . PHP_EOL;
        echo 
'-------------------------------' PHP_EOL;
        echo 
'-------------------------------' PHP_EOL;
    }

// Convert LFS Time to minutes:seconds.ms string
    
public function sekdoczas($czas) {
        
$ret "";
        
$minutes intval(intval($czas 1000) / 60);
        if (
$minutes 0) {
            
$ret .= $minutes ':';
        }
        
$seconds bcmod(intval($czas 1000), 60);
        
$ret .= ( ($seconds 10) ? '0' $seconds $seconds) . '.';
        
$setne bcmod($czas1000);
        
$ret .= $setne;

        return 
$ret;
    }

    public function 
cpr($packet) {
        
$client $this->getClientByUCID($packet->UCID);
        if (
$client != NULL) {
            
/* Wpisz dane gracza do tabeli, zeby byly aktualne */
            
$query 'UPDATE {{table}}drivers SET nick = :nick WHERE id = :id';
            
$quer DB::gi()->prepare($query);
            
$quer->bindValue(':id'$client->driver_id);
            
$quer->bindValue(':nick'$this->lfs_codepage_convert($packet->PName));
            
$quer->execute();
        }
    }

    public function 
npl($packet) {
        
$client $this->getClientByPLID($packet->PLID);
        if (
$client != NULL) {
            
/* Pobierz dane gracza i zapisz w danych o klientach hosta */
            
$quer DB::gi()->prepare('SELECT * FROM drivers WHERE uname = :uname AND session = :session');
            
$quer->bindValue(':uname'$client->UName);
            
$quer->bindValue(':session'$this->session);
            
$quer->execute();
            
$driver $quer->fetch(PDO::FETCH_OBJ);
            unset(
$quer);
            
$client->driver_id $driver->id;
            
$client->driver $driver;

            
/* Ustaw w tabeli teams aktualnego kierowcę */
            
$quer DB::gi()->prepare('UPDATE teams SET online_driver = :driver WHERE team_nr = (SELECT team_nr from drivers WHERE uname = :uname) AND session = :session');
            
$quer->bindValue(':uname'$client->UName);
            
$quer->bindValue(':driver'$client->driver_id);
            
$quer->bindValue(':session'$this->session);
            
$quer->execute();
            unset(
$quer);
            
/* Pobierz dane zespołu i dopisz do danych gracza */
            
$quer2 DB::gi()->prepare('SELECT laps_done, ttime FROM teams WHERE team_nr = :team_nr AND session = :session');
            
$quer2->bindValue(':team_nr'$client->driver->team_nr);
            
$quer2->bindValue(':session'$this->session);
            
$quer2->execute();
            
$quer2 $quer2->fetch(PDO::FETCH_OBJ);
            
$client->laps_done $quer2->laps_done;
            
$client->ttime 0;
            
$client->ttime $quer2->ttime;
            unset(
$quer2);
            
/* Wpisz dane gracza do tabeli, zeby byly aktualne */
            
$query 'UPDATE {{table}}drivers SET nick = :nick, car = :car WHERE id = :id';
            
$quer DB::gi()->prepare($query);
            
$quer->bindValue(':id'$client->driver_id);
            
$quer->bindValue(':nick'$this->lfs_codepage_convert($packet->PName));
            
$quer->bindValue(':car'$packet->CName);
            
$quer->execute();
            unset(
$quer);
            echo 
'PName: ' $client->PName ' / UName: ' $client->UName ' / Car: ' $packet->car '/ PLID: ' $packet->PLID ' / UCID: ' $client->UCID PHP_EOL;
            echo 
'Team #: ' $client->driver->team_nr ' / Intake: ' $client->driver->rest_intake ' / Added mass: ' $client->driver->add_mass PHP_EOL;
        } else {
            echo 
'-------------------------------' PHP_EOL;
            echo 
'-------------------------------' PHP_EOL;
            echo 
'NIE MA: ' $client->UName PHP_EOL;
            echo 
'-------------------------------' PHP_EOL;
            echo 
'-------------------------------' PHP_EOL;
        }
    }

    public function 
toc($packet) {
        
/* Obsługa TOC, ktora kiedys zrobi sam PRISM */
        
$client $this->getClientByUCID($packet->NewUCID);
        
$client->players[] = $this->getClientByUCID($packet->OldUCID)->players[$packet->PLID];
        unset(
$this->getClientByUCID($packet->OldUCID)->players[$packet->PLID]);
        
$this->getPlayerByPLID($packet->PLID)->setUCID($packet->NewUCID);
        
/* Koniec obsługi TOC */
        
if ($client != NULL) {
            
/* Pobierz dane gracza i zapisz w danych o klientach hosta */
            
$quer DB::gi()->prepare('SELECT * FROM drivers WHERE uname = :uname AND session = :session');
            
$quer->bindValue(':uname'$client->UName);
            
$quer->bindValue(':session'$this->session);
            
$quer->execute();
            
$driver $quer->fetch(PDO::FETCH_OBJ);
            unset(
$quer);
            
$client->driver_id $driver->id;
            
$client->driver $driver;
            
/* Ustaw w tabeli teams aktualnego kierowcę */
            
$quer DB::gi()->prepare('UPDATE teams SET online_driver = :driver WHERE team_nr = (SELECT team_nr from drivers WHERE uname = :uname) AND session = :session');
            
$quer->bindValue(':uname'$client->UName);
            
$quer->bindValue(':driver'$client->driver_id);
            
$quer->bindValue(':session'$this->session);
            
$quer->execute();
            unset(
$quer);
            
/* Pobierz dane zespołu i dopisz do danych gracza */
            
$quer2 DB::gi()->prepare('SELECT laps_done, ttime FROM teams WHERE team_nr = :team_nr AND session = :session');
            
$quer2->bindValue(':team_nr'$client->driver->team_nr);
            
$quer2->bindValue(':session'$this->session);
            
$quer2->execute();
            
$quer2 $quer2->fetch(PDO::FETCH_OBJ);
            
$client->laps_done $quer2->laps_done 1;
            
$client->ttime 0;
            
$client->ttime $quer2->ttime;
            unset(
$quer2);
            
/* Wpisz dane gracza do tabeli, zeby byly aktualne */
            
$query 'UPDATE {{table}}drivers SET nick = :nick WHERE id = :id';
            
$quer DB::gi()->prepare($query);
            
$quer->bindValue(':id'$client->driver_id);
            
$quer->bindValue(':nick'$this->lfs_codepage_convert($client->PName));
            
$quer->execute();
            unset(
$quer);
            echo 
'PName: ' $client->PName ' / UName: ' $client->UName ' / PLID: ' $packet->PLID ' / UCID: ' $client->UCID PHP_EOL;
            echo 
'Team #: ' $client->driver->team_nr ' / Intake: ' $client->driver->rest_intake ' / Added mass: ' $client->driver->add_mass PHP_EOL;
        } else {
            echo 
'NIE MA: ' $client->UName PHP_EOL;
        }
    }

    public function 
lap($packet) {
        
$client $this->getClientByPLID($packet->PLID);
        
$laptime $packet->LTime;
        if(
$packet->LapsDone == 1){
            
$laptime $laptime $client->ttime;
        }
        if (
$client != NULL) {
            
$client->laps_done++;
            
$client->ttime $client->ttime $laptime;
            
$query 'UPDATE {{table}}laps SET ltime = :ltime, ttime = :ttime WHERE driver = :driver AND lap = :lap AND session = :session';
            
$quer DB::gi()->prepare($query);
            
$quer->bindValue(':driver'$client->driver_id);
            
$quer->bindValue(':ltime'$laptime);
            
$quer->bindValue(':ttime'$client->ttime);
            
$quer->bindValue(':lap'$client->laps_done);
            
$quer->bindValue(':session'$this->session);
            
$quer->execute();
            unset(
$quer);
            
$query 'UPDATE {{table}}teams SET laps_done = laps_done + 1, ttime = ttime + ' $laptime ', last_time = ' $laptime ' WHERE team_nr = :team';
            
$quer DB::gi()->prepare($query);
            
$quer->bindValue(':team'$client->driver->team_nr);
            
$quer->execute();

            unset(
$quer);
        }
    }

    public function 
spx($packet) {
        
$client $this->getClientByPLID($packet->PLID);
        if (
$client != NULL) {
            
$db_split 's' $packet->Split;
            if (
$packet->Split == 1) {
                
$query 'INSERT INTO {{table}}laps (driver, lap, session) VALUES(:driver, :lap, :session)';
                
$quer DB::gi()->prepare($query);
                
$quer->bindValue(':driver'$client->driver_id);
                
$lap $client->laps_done 1;
                
$quer->bindValue(':lap'$lap);
                
$quer->bindValue(':session'$this->session);
                
$quer->execute();
                unset(
$quer);
                unset(
$lap);
                
$query 'UPDATE {{table}}teams SET  s1 = \'0\', s2 = \'0\', s3 = \'0\', s4 = \'0\', last_time = \'0\' WHERE team_nr = :team_nr AND session = :session';
                
$quer DB::gi()->prepare($query);
                
$quer->bindParam(':team_nr'$client->driver->team_nrPDO::PARAM_INT);
                
$quer->bindParam(':session'$this->sessionPDO::PARAM_INT);
                
$quer->execute();
                unset(
$quer);
            }
            
$query 'UPDATE {{table}}laps SET  ' $db_split ' = :value WHERE lap = :lap AND driver = :driver AND session = :session';
            
$quer DB::gi()->prepare($query);
            
$quer->bindValue(':driver'$client->driver_id);
            
$quer->bindValue(':lap'$client->laps_done 1);
            
$quer->bindValue(':value'$packet->STime);
            
$quer->bindValue(':session'$this->session);
            
$quer->execute();
            unset(
$quer);
            
$query 'UPDATE {{table}}teams SET  ' $db_split ' = :value WHERE team_nr = :team_nr AND session = :session';
            
$quer DB::gi()->prepare($query);
            
$quer->bindValue(':value'$packet->STime);
            
$quer->bindValue(':team_nr'$client->driver->team_nr);
            
$quer->bindValue(':session'$this->session);
            
$quer->execute();
            unset(
$quer);
            unset(
$db_split);
            unset(
$query);
        }
    }

// Saves packets into db
    
public function save_to_db($packet) {
        
$save_str serialize($packet);
        
$query 'INSERT INTO {{table}}packets (time, data) VALUES(unix_timestamp(),:serialized)';
        
$quer DB::gi()->prepare($query);
        
$quer->bindValue(':serialized'$save_str);
        
$quer->execute();
        unset(
$quer);
        unset(
$save_str);
    }

    private function 
lfs_codepage_convert($str$conv_to 'UTF-8') {
        
$sets = array('L' => 'CP1252',
            
'G' => 'ISO-8859-7',
            
'C' => 'CP1251',
            
'E' => 'ISO-8859-2',
            
'T' => 'ISO-8859-9',
            
'B' => 'ISO-8859-13',
            
'J' => 'SJIS-win',
            
'S' => 'CP936',
            
'K' => 'CP949',
            
'H' => 'CP950');

        
$tr_ptrn = array("/\^d/""/\^s/""/\^c/""/\^a/""/\^q/""/\^t/""/\^l/""/\^r/""/\^v/");
        
$tr_ptrn_r = array("\\""/"":""*""?""\"""<"">""|");
        
$str preg_replace($tr_ptrn$tr_ptrn_r$str);

        
$newstr $tmp '';
        
$current_cp 'L';
        
$len strlen($str);
        for (
$i 0$i $len$i++) {
            if (
$str{$i} == '^' && isset($sets[$str{$i 1}]) && $str{$i 1} != "^") {
                if (
$tmp != '') {
                    
$newstr .= iconv($sets[$current_cp], $conv_to$tmp);  
                    
$tmp '';
                }
                
$current_cp $str{++$i};
            }
            
// Filter out every character below 0x20
            
else if (ord($str{$i}) > 31)
                
$tmp .= $str{$i};
        }
        if (
$tmp != '')
            
$newstr .= iconv($sets[$current_cp], $conv_to$tmp);  

        
// Final special char to convert - could not do that before codepage conversion
        
return str_replace('^^''^'$newstr);
    }

    
/*
      public function lap($packet){
      $nick = $this->getPlayerByPLID($packet->PLID)->PName;
      $nick = preg_replace('/\^[0-9A-Za-z]/','', $nick);
      # if($nick == 'Misiek')
      echo 'Nick: ', $nick, ' / Czas: ', @$this->sekdoczas($packet->LTime), ' / Ukonczone: ',$packet->LapsDone, PHP_EOL;
      } */
}

?>

Code to display live stats:

<?php 
php
ini_set
('display_errors'1);
error_reporting(E_ALL);
$title 'Live';
require_once 
'inc/DB.class.php';
/* connecting to DB, creating instance and setting utf */
DB::gi()->query('SET NAMES utf8');

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

### convert lfs time to stdClass object {hours, minutes, seconds, mili)

function lfs_time($time$mili true) {
    if (!
$mili) {
        
$time $time 1000;
    }
    
$return = new stdClass();
    
$return->hours floor($time 3600000);
    
$time $time - ($return->hours 3600000);
    
$return->minutes floor($time 60000);
    
$time $time - ($return->minutes 60000);
    
$return->seconds floor($time 1000);
    
$time $time - ($return->seconds 1000);
    if(
$time 100$time '0' $time;
    
$return->mili $time;
    return 
$return;
}

### convert lfs time to string H:i:s.ms

function lfs_time2string($time$mili true$hours false) {
    
$obj lfs_time($time);
    return ((
$hours) ? ($obj->hours ':') : '') . fillZero($obj->minutes) . ':' fillZero($obj->seconds) . (($mili) ? ('.' $obj->mili) : '');
}

### add 0 at the beginning of <10

function fillZero($where) {
    return (
$where 10) ? '0' $where $where;
}

### define colors for HTML-output ###

function lfs_getColorCode($col) {
    switch (
$col) {
        case 
: return "#000000";
        case 
: return "#ff0000";
        case 
: return "#00ff00";
        case 
: return "#ffff00";
        case 
: return "#0000ff";
        case 
: return "#ff00ff";
        case 
: return "#00ffff";
        case 
: return "#ffffff";
        case 
: return "#000000";
        case 
: return "#000000";
        default : return 
$col;
    }
}

### strip colors from names ###

function lfs_nameblank($name) {
    return 
stripslashes(preg_replace("/\^[0-9]/"""htmlspecialchars($name)));
}

### get colored names for HTML-output ###

function lfs_namecolored($name) {
    return 
stripslashes(preg_replace("/\^([0-9])(.[^\^]*)/e"'"<span style=\"color:".getColorCode($1).";\">$2</span>"'htmlspecialchars($name)));
}

/* L = Latin 1
 * G = Greek
 * C = Cyrillic
 * E = Central Europe
 * T = Turkish
 * B = Baltic
 * J = Japanese
 * S = Simplified Chinese
 * K = Korean
 * H = Traditional Chinese
 * 
 */
function lfs_codepage_convert($str$conv_to 'UTF-8') {
    
$sets = array('L' => 'CP1252',
        
'G' => 'ISO-8859-7',
        
'C' => 'CP1251',
        
'E' => 'ISO-8859-2',
        
'T' => 'ISO-8859-9',
        
'B' => 'ISO-8859-13',
        
'J' => 'SJIS-win',
        
'S' => 'CP936',
        
'K' => 'CP949',
        
'H' => 'CP950');

    
$tr_ptrn = array("/\^d/""/\^s/""/\^c/""/\^a/""/\^q/""/\^t/""/\^l/""/\^r/""/\^v/");
    
$tr_ptrn_r = array("\\""/"":""*""?""\"""<"">""|");
    
$str preg_replace($tr_ptrn$tr_ptrn_r$str);

    
$newstr $tmp '';
    
$current_cp 'L';
    
$len strlen($str);
    for (
$i 0$i $len$i++) {
        if (
$str{$i} == '^' && isset($sets[$str{$i 1}]) && $str{$i 1} != "^") {
            if (
$tmp != '') {
                
$newstr .= mb_convert_encoding($tmp$conv_to$sets[$current_cp]);
                
$tmp '';
            }
            
$current_cp $str{++$i};
        }
        
// Filter out every character below 0x20
        
else if (ord($str{$i}) > 31)
            
$tmp .= $str{$i};
    }
    if (
$tmp != '')
        
$newstr .= mb_convert_encoding($tmp$conv_to$sets[$current_cp]);

    
// Final special char to convert - could not do that before codepage conversion
    
return str_replace('^^''^'$newstr);
}

### get next position in class by car/carstype
function get_pos($car, &$classes){
    foreach(
$classes as $class){
        if(
in_array($car$class->cars)){
            
$class->pos++;
            return 
$class->pos 1;
        }
    }
}

### define colors for HTML-output ###
function getColorCode($col) {
    switch (
$col) {
        case 
: return "#000000";
        case 
: return "#ff0000";
        case 
: return "#00ff00";
        case 
: return "#ffff00";
        case 
: return "#0000ff";
        case 
: return "#ff00ff";
        case 
: return "#00ffff";
        case 
: return "#ffffff";
        case 
: return "#000000";
        case 
: return "#000000";
        default : return 
$col;
    }
}

$classes['XR3'] = 1;
$classes['FZ3'] = 1;
$classes['FX3'] = 1;
$classes['TBA'] = 1;
$classes['FZ5'] = 1;
$classes['RB4'] = 1;
$classes['XRG'] = 1;

/* $teamy_kierowcy = DB::gi()->prepare('
  SELECT
  (l.s1 + l.s2 + l.s3 + l.s4) AS splits_tog, l.s1, l.s2, l.s3, l.s4, l.ltime, l.lap,
  d.id as driver_id, d.nick, d.uname, d.admin, d.add_mass, d.rest_intake, d.flags, d.pla, d.country,
  t.id as team_id, t.team_nr, t.name, t.car, t.changes, t.penalty, t.dsq, t.online_driver, t.laps_done, t.ttime
  FROM (SELECT * FROM laps ORDER BY id DESC, lap DESC, ttime ASC) AS l
  LEFT JOIN drivers d ON(d.id = l.driver)
  LEFT JOIN teams t ON(t.team_nr = d.id_team)
  GROUP BY l.driver
  ORDER BY t.laps_done DESC, l.ttime ASC'); */
/* $teamy_kierowcy = DB::gi()->prepare('
  SELECT
  t.*,
  d.*,
  l.*
  FROM (SELECT * FROM laps GROUP BY driver ORDER BY lap) AS l LEFT JOIN drivers d ON d.id = l.driver LEFT JOIN teams t ON t.id = d.id_team'); */
$teamy_kierowcy DB::gi()->prepare('
    SELECT
    t.s1, t.s2, t.s3, t.s4, l.ltime, l.lap,
    d.id as driver_id, d.nick, d.uname, d.admin, d.car, d.add_mass, d.rest_intake, d.flags, d.pla, d.country,
    t.id as team_id, t.team_nr, t.name, t.car as class, t.changes, t.penalty, t.dsq, t.online_driver, t.laps_done, t.ttime,
    (SELECT ltime FROM laps WHERE driver = d.id ORDER BY id DESC LIMIT 1) AS ltime
    FROM teams t
    LEFT JOIN drivers d ON (d.id = t.online_driver)
    LEFT JOIN (SELECT * FROM laps GROUP BY driver ORDER BY lap) AS l ON(l.driver = d.id)
    ORDER BY t.laps_done DESC, t.ttime ASC, t.team_nr ASC'
);
$teamy_kierowcy->execute();
$teamy_kierowcy $teamy_kierowcy->fetchAll(PDO::FETCH_OBJ);

>?
xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
        <title>LFS Tracker - Misiek echo ($title && $title != '') ? '::' . $title : ''; </title>
        <meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
        <link rel="stylesheet" href="style_1.css" />
        <script type="text/javascript" src="js/jQuery.js"></script>
        <script type="text/javascript" src="js/jquery.tooltip.min.js"></script>
        <!--script type="text/javascript" src="js/jquery.color.js"></script>
        <script type="text/javascript" src="js/jquery.dump.js"></script>
        <script type="text/javascript" src="js/functions.js"></script>
        <script type="text/javascript" src="js/lang_pl.js"></script>
        <script type="text/javascript" src="js/main.js"></script-->
    </head>
    <body>
        <div id="top_menu">
            <div id="top_menu_inner"><ul class="inline_list" style="margin:0; list-style-type: none;">
                    <li><a href="index.php" class="full_white">Home</a></li>
                    <li><a href="best.php" class="full_white">Best laps</a></li>
                    <li><a href="teams_drivers.php" class="full_white">Teams & Drivers</a></li>
                    <li><a href="rescue.php" class="full_white">Rescue live progress</a></li>
                </ul></div>
        </div>
        <div id="cala_strona">
<!--div id="pitstopy">
    <div id="pitstopy_desc">Pitstopy:</div>
    <div id="pitstop_temp" style="display:none;">
        <div id="pitstop_dr_team"></div>
        <div id="pitstop"></div>
        <div id="opony"></div>
    </div>
</div-->
<center>
    <h1> This is 3rd round race progress...</h1>
    <div id="main_stat_table_div">
        <table id="main_stat_table">
            <tr id="main_stat_desc" class="main_stat_row">
                <td id="id_desc" class="first w_help" title="Position">Pos.</td>
                <td id="id_desc" class="first w_help" title="Team number">#</td>
                <td id="kierowca_desc" style="width: 150px">Driver</td>
                <td id="team_desc" style="width: 150px">Team</td>
                <td id="samochod_desc" class="w_help" title="Car">Car</td>
                <td id="split1_desc" class="w_help" title="Sector 1">S1</td>
                <td id="split2_desc" class="w_help" title="Sector 2">S2</td>
                <!--td id="split3_desc" class="w_help" title="Sector 3">S3</td-->
                <td id="czasokr_desc" class="w_help" title="Lap time">Lap time</td>
                <td id="okr_desc" class="w_help" title="Lap">Lap</td>
                <td id="najokr_desc" class="w_help" title="Best driver lap">Best driver lap</td>
                <!--td id="kara_desc" style="width: 20px">Penalty</td-->
                <td id="gap1_desc">Gap to 1st</td>
                <td id="gap2_desc">Gap</td>
            </tr>
            <!--<tr id="main_stat_1" class="main_stat_row">
                    <td id="id_1" class="first">1</td>
                    <td id="kierowca_1">Misiek 1</td>
                    <td id="team_1">Fast Racing 1</td>
                    <td id="samochod_1">FZR</td>
                    <td id="split1_1">26.39</td>
                    <td id="split2_1">1:02.12</td>
                    <td id="split3_1">--:--.--</td>
                    <td id="czasokr_1">1:48.23</td>
                    <td id="okr_1">2</td>
                    <td id="najokr_1">1:48.23 (1)</td>
                    <td id="kara_1" class="last">-</td>
            </tr> -->
            php
            if(count($teamy_kierowcy) > 0){
                $first_ttime = $teamy_kierowcy[0]->ttime;
                $last_ttime = $first_ttime;
            }
            $i = 1;
            foreach ($teamy_kierowcy as $team) {
                $class_pos = $i;
                if (array_key_exists($team->class, $classes)) {
                    $class_pos = $classes[$team->class];
                    $classes[$team->class]++;
                }
                $best_czas = DB::gi()->prepare('SELECT * FROM laps l WHERE driver = \'' . $team->online_driver . '\' AND ltime <> 3600000 AND ltime <> 0 ORDER BY ltime ASC LIMIT 1');
                $best_czas->execute();
                if ($best_czas2 = $best_czas->fetch(PDO::FETCH_OBJ)) {
                    $team->best_czas = lfs_time2string($best_czas2->ltime);
                    $team->best_nr = $best_czas2->lap;
                    $best_czas->closeCursor();
                } else {
                    $team->best_czas = '---------';
                    $team->best_nr = '--';
                }

                echo '<tr id="main_stat_' . $team->team_id . '" class="main_stat_row"> ';
                echo '<td id="poz_' . $team->team_id . '" class="first" title="' . $class_pos . ' in class ' . strtoupper($team->class) . '">' . $i . '</td> ';
                echo '<td id="id_' . $team->team_id . '" class="first">' . $team->team_nr . '</td> ';
                echo '<td id="kierowca_' . $team->team_id . '">' . lfs_namecolored($team->nick) . '<br />(' . $team->uname . ')</td> ';
                echo '<td id="team_' . $team->team_id . '">' . $team->name . '</td> ';
                echo '<td id="samochod_' . $team->team_id . '">' . strtoupper($team->car) . '<br />Class:' . strtoupper($team->class) . '</td> ';
                echo '<td id="split1_' . $team->team_id . '">' . lfs_time2string($team->s1) . '</td> ';
                echo '<td id="split2_' . $team->team_id . '">' . lfs_time2string($team->s2) . '</td> ';
                //echo '<td id="split3_' . $team->team_id . '">' . lfs_time2string($team->s3) . '</td> ';
                echo '<td id="czasokr_' . $team->team_id . '">' . lfs_time2string($team->ltime) . '</td> ';
                echo '<td id="okr_' . $team->team_id . '">' . ($team->laps_done + 1) . '</td> ';
                echo '<td id="najokr_' . $team->team_id . '">' . $team->best_czas . '<br />(' . $team->best_nr . ')</td> ';
                //echo '<td id="kara_' . $team->team_id . '" class="last">' . $team->penalty . '</td> ';
                //echo '<td id="ttime_' . $team->team_id . '" class="last">' . $team->ttime . '</td> ';
                echo '<td id="gap1_' . $team->team_id . '" class="last">' . lfs_time2string($team->ttime - $first_ttime) . '</td> ';
                echo '<td id="gap2_' . $team->team_id . '" class="last">' . lfs_time2string($team->ttime - $last_ttime) . '</td> ';
                echo '<td id="lapslink_' . $team->team_id . '" class="last"><a href="laps.php?t=' . $team->team_nr . '">Laps</a></td> ';
                echo '</tr>';
                $last_ttime = $team->ttime;
                $i++;
            }
            unset($best_czas);
            
        </table>
</center>
<!--table id="legenda">
    <tr>
        <th colspan="3">Legenda:</th>
    </tr>
    <tr>
        <td style="width:40px; background-color:#FFCC00;"> </td><td>Kierowca znajduje się w pitlane</td>
    </tr>
    <tr>
        <td style="width:40px; background-color:#FF0000;"> </td><td>Zespół nie uczestniczy w wyścigu</td>
    </tr>
</table>
</div>
<div id="komentarz">
<div>komentarz 1</div>
<div>komentarz 1</div>
<div>komentarz 1</div>
<div>komentarz 1</div>
<div>komentarz 1</div>
</div-->
<script type="text/javascript">
    setTimeout("window.location.reload()", 25000);
</script>
</div>
<!--div onclick="do_example()" style="clear:both">Teraz</div>

</div>
<div id="end"></div>

<div>
    <textarea id="kod"></textarea>

    <div id="eval_kod">Execute</div>
    <textarea id="debug"></textarea>
</div-->
<script type="text/javascript">
$('*').tooltip({track: true,
    delay: 0,
    showURL: false});
</script>
</body>
</html>
?>

DB.class:

<?php 
php
class DB extends PDO {

    private static 
$instance NULL;
    private 
$prefix;

    static public function 
gi() {
        if (
self::$instance == NULL) {
            try {
                
self::$instance = new DB('62.75.188.55','ltwt''officiale''ltwt''');
                
self::$instance->setAttribute(PDO::ATTR_ERRMODEPDO::ERRMODE_WARNING);
            } catch (
PDOException $e) {
                die(
'Error while connecting to DB: ' $e->getMessage());
            }
        }
        return 
self::$instance;
    }

    public function 
__construct($host$user$pass$name$prefix '') {
        
$this->prefix $prefix;
        
parent::__construct('mysql:dbname=' $name ';host=' $host$user$pass);
    }

    public function 
exec($query$file false$line false) {
        
$query str_replace('{{table}}'$this->prefix$query);
        return 
parent::exec($query);
    }

    public function 
query($query) {
        
$query str_replace('{{table}}'$this->prefix$query);

        return 
parent::query($query);
    }

    public function 
prepare($query) {
        
$query str_replace('{{table}}'$this->prefix$query);
        return 
parent:[:p]repare($query);
    }

}
?>

I think here are still good PHP programmers so maybe someone can edit it and make it better. @boothy is going to release tracker of MoE but I think it can take some time.
1

FGED GREDG RDFGDR GSFDG