View Full Version : PHP4/5 - LFSWorldSDK, class for stats retrieval
Dygear
1st October 2006, 21:32
After alot of time, and some blood (punching the screen, wall, and myself [once I realized how bad of a programmer I am], sweat (Man, it's freaking hot), and tears (mainly due to me punching myself) the latest stable release is done. That means you and me can start to have to have some fun with this. It's fully compatible with the current version of LFSWorld (1.3 at the time of writing). Keep in mind there have been some changes to the syntax of some of the functions. Mainly due to the fact that it now allows for arrays, other then that, it should just be a little faster then the one your running right now (With any luck).
Well, you know the drill, if you should happen to see anything wrong, shoot me a PM, or just reply to this topic with the bugs you've found.
Most Current Release (1.5) (http://lfsworldsdk.cvs.sourceforge.net/*checkout*/lfsworldsdk/lfsworldsdk/lfsworldsdk.php).
And you could include it, or just add this to the bottom :
<?php
include('lfsworldsdk.php');
echo '<!-- get_hl --><p />';
print_r($SDK->get_hl(array('Dygear', 'filur', 'Victor', 'glyphon')));
echo '<!-- get_ch --><p />';
print_r($SDK->get_ch(array('000', '230', '420', '630'), array('MRT', 'FOX', 'FO8', 'BF1')));
echo '<!-- get_wr --><p />';
print_r($SDK->get_wr());
echo '<!-- get_pb --><p />';
print_r($SDK->get_pb(array('Dygear', 'filur', 'Victor', 'glyphon')));
echo '<!-- get_fuel --><p />';
print_r($SDK->get_fuel(array('Dygear', 'filur', 'Victor', 'glyphon')));
echo '<!-- get_pst --><p />';
print_r($SDK->get_pst(array('Dygear', 'filur', 'Victor', 'glyphon')));
echo '<!-- get_host --><p />';
print_r($SDK->get_hosts());
echo '<!-- get_teams --><p />';
print_r($SDK->get_teams());
echo '<!-- get_hl_log --><p />';
print_r($SDK->get_hl_log());
# echo '<!-- get_progress --><p />';
// print_r($SDK->get_progress('^1(^3FM^1) ^4OvaL ^1JuNkIeS!'));
?>
minimax
1st October 2006, 21:41
Can i ask what it is lol
zeugnimod
1st October 2006, 21:52
I have the same question. :confused:
the_angry_angel
1st October 2006, 22:24
Its a higher level API to query LFSWorld.
Nice work Dygear and filur :) I'll have a shufti tomorrow :D
Dygear
2nd October 2006, 00:49
That is right now, just the core of it. I'll add things like converting time into a more human readable form. The url encoded team string and so on. But first I must finish the core. There are some issues with host, and I'm not totaly sure what they all are. Saying that they sould be done faily soon, when in the next day or two.
St4Lk3R
2nd October 2006, 07:19
great work you guys. truely awesome.
PS: I'd like to help if needed and given the chance.
CrazyICE
2nd October 2006, 11:25
really coOL :D
traxxion
2nd October 2006, 12:18
Probably another dumb question by me, but Im gonna ask anyway.
Am I the only one who gets this:
Parse error: parse error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /var/www/html/includes/custom/LFSWorldSDK.php on line 15
error?
filur
2nd October 2006, 12:30
error?
You're probably running php 4, which fails at declaring variables as private (php5+). This code doesn't really need php 5 and i think Dygear will remove the php 5 specifics.
traxxion
2nd October 2006, 13:04
You're probably running php 4, which fails at declaring variables as private (php5+). This code doesn't really need php 5 and i think Dygear will remove the php 5 specifics.
I thought that! Looking forward to the php4 version then :)
Dygear
5th October 2006, 02:57
PHP4 :
http://lfsworldsdk.cvs.sourceforge.net/lfsworldsdk/PHP4/LFSWorldSDK.php?revision=1.1
PaulC2K
5th October 2006, 03:03
Kickass!
If it wasnt for the fact that the Mercury site has been up & down like a streetwalkers undergarments today, i'd have given a thumbs up on whatever appeared, and then probably asked a whole heap of questions about wtf it all means and whatnot :D
PaulC2K
5th October 2006, 03:17
If at first you dont succeed, find another server to go mess up!
http://www.qazwert.com/LFS_SDK.php
Parse error: parse error, unexpected T_NEW in /home2/qazwert/public_html/LFS_SDK.php on line 175
:(
edit: PHP version = 4.4.1
filur
5th October 2006, 07:08
parse error, unexpected T_NEW ...
If you're looking for assistance you'll need to make the source visible, that error message says pretty much nothing.
Rename the file to .txt or make another script containing ..
<?php
highlight_file('problem_file.php');
?>
traxxion
5th October 2006, 07:33
I get the same as Paul.
Parse error: parse error, unexpected T_NEW in /var/www/html/includes/custom/LFSWorldSDK.php on line 175
Haven't changed anything from the original file so line 175 is this one:
Throw New Exception($str);
filur
5th October 2006, 08:12
PHP4 issue again, updated and hopefully works now.
http://prdownloads.sourceforge.net/lfsworldsdk/lfsworldsdk-php4-cvs20061005.zip?download
traxxion
5th October 2006, 08:23
PHP4 issue again, updated and hopefully works now.
http://prdownloads.sourceforge.net/lfsworldsdk/lfsworldsdk-php4-cvs20061005.zip?download
Thanks for the quick service filur, awesome :thumb: . Works fine now! Off to play around a bit with it --->
:D
OldBloke
5th October 2006, 10:13
Am I right in thinking that the place to add the idkey is ...
function __construct($IdKey = 'xxxxxxxxx', $TarPited = False, $Version = '1.2')
However, when I do this I get the following error ....
Warning: gzuncompress() [function.gzuncompress]: data error in LFSWorldSDK.php on line 86
Am I missing something?
filur
5th October 2006, 10:28
Am I missing something?
Looks like you're using the version Dygear links to in the first post, if so, try the most recent one (http://prdownloads.sourceforge.net/lfsworldsdk/lfsworldsdk-php4-cvs20061005.zip?download) instead.
OldBloke
5th October 2006, 10:48
Looks like you're using the version Dygear links to in the first post, if so, try the most recent one (http://prdownloads.sourceforge.net/lfsworldsdk/lfsworldsdk-php4-cvs20061005.zip?download) instead.
Yep. Now working fine.
I'm used to getting the latest version from the first post ;)
D34N0
5th October 2006, 15:13
Great work.. This will make life easier in my next incarnation of the Team Setup Station.:thumb:
Thanks
Dean
Dygear
5th October 2006, 21:41
Awsome, glad it's getting used, and thanks filur for fixing it! I was at work, and missed it all. Happy to see I picked a awsome co-author :). If you use the program for anything do let us know about it. I myself am going to remake the SimFIA website with this bad boy!
PaulC2K
5th October 2006, 21:54
Dygear/filur :
Dont suppose either of you could point me in the direction of how you then use this information, ie now that info is pulled, how would it be seperated to be usable?
Take the HL example, you get:
Array ( [id_hl] => 1205 [track] => 420 [car] => BF1 [time] => 104250 [flags_hlaps] => 1614 )
... amongst other HL info, how would i go about picking out peices so i can specify say:
$id = 1205
$track = 420
$car = BF1
$time = 104250
$flags_hlaps = 1614
I know little more than how to get stuff to & from a db, so thats what i plan to do with all this info, show it into a db, cronjob it as frequently as it might require updating, and pull any results from within the db, it just works easier for me in the future.
Love the fact that you've included the examples for each type of stat were likely to require :D
Dygear
5th October 2006, 22:39
The SDK comes with a built in way of finding hot laps. While I wanted to keep in more bare bones. I thought it would be better, and faster to just simply have it in one function.
<?php
// Include LFSWorldSDK so that you can use it the functions.
include('LFSWorldSDK.php');
$SDK = new LFSWorldSDK;
// So to get the data you wanted from LFSWorld, you would run this :
$data = $SDK->get_hl('PaulC2K', '420', 'BF1');
// Now we have an array in $data, to use this information we could just assign it to a variable like so :
$id = $data['id'];
$track = $data['track'];
$car = $data['car'];
$time = $data['time'];
$flags_hlaps = $data['flags_hlaps'];
// The question now becomes why? Why read the value of $data into separate entities, when they are allready distinguable in the first place? You could just do this :
echo 'Driver PaulC2K set a time of ' . $data['time'] . ' on track ' . $data['track'] . ' in the ' . $data['car'] . ', man he\'s quick!';
// Or use complex strings like this :
echo "Driver PaulC2K set a time of {$data['time']} on track {$data['track']} in the {$data['car']}, man he's quick!";
?>
Now as for your SQL code, something like this would work :
<?php
include('LFSWorldSDK.php');
$SDK = new LFSWorldSDK;
$racer = 'PaulC2K';
$track = '420';
$car = 'BF1';
$hl = $SDK->get_hl($racer, $track, $car);
if (count($hl) != 0) {
mysql_connect($hostname, $username, $password);
@mysql_select_db($database) or die('Unable to select database');
mysql_query("INSERT INTO hotlaps VALUES ('','{$racer}','{$hl['track']}','{$hl['car']}','{$hl['time']}','{$hl['flags_hlaps']}'");
mysql_close();
}
else
die('No HotLaps Returned!');
?>
jscorrea
21st October 2006, 05:01
Hi,
Look this:
include "LFSWorldSDK.php";
$LFSWorld = new LFSWorldSDK;
$user = 'jscorrea';
$stats = $LFSWorld->get_stats($user);
echo $stats[distance] == "" ? "no user" :"ok";
echo $stats[online] == 0? "OFFLINE" : "ONLINE";
This is the right way to show if the user exists?
In my case i have user im my database and the code below dont work:
include "LFSWorldSDK.php";
$LFSWorld = new LFSWorldSDK;
$user = $a["uname"];
$stats = $LFSWorld->get_stats($user);
echo $stats[distance] == "" ? "no user" :"ok";
echo $stats[online] == 0? "OFFLINE" : "ONLINE";
$a["uname"] return in my site a username.
The error is:
LFSWorld error: $str
Regards.
JS
Dygear
21st October 2006, 08:13
In the next version of this (comming soon I might add) we are going to compress the querys for a few good reasons. One, if you have premium stats, it saves you money. Two, if you get uncompressed data then you know it's an error and as such the file could throw a warning out to you via the trigger_error (http://www.php.net/manual/en/function.trigger-error.php) function. As ever, it will be up to the user of the SDK to catch these errors.
PaulC2K
24th October 2006, 09:17
Got quite a few bits n peices done with this SDK, one which is almost finished but just needs some touching up, but mostly just little bits n peices but i wouldnt have been able to do any of it without the SDK :)
One thing thats just been pointed out to me:
When pulling the WR holders list, XRT @ 000 is 'Svemirko Joca' however only 'Svemirko' is given. Im not sure if this would be possible to fix... just tried what i thought might work, and it seems okay :D
addition to LFSWorldSDK.php function get_wr()
$result[] = array(
'id_wr' => $fragment[0],
'track' => $fragment[1],
'car' => $fragment[2],
'time' => $fragment[3],
'flags_hlaps' => $fragment[4],
'racername' => $fragment[5],
'racername2' => $fragment[6]
and then
$racername = $data['racername']." ".$data['racername2'];
Works a treat, wasnt sure if it'd throw a wobbler looking for a 6th peice of info when 99.9% of them dont have one.
filur
24th October 2006, 10:19
$result[] = array(
'id_wr' => $fragment[0],
'track' => $fragment[1],
'car' => $fragment[2],
'time' => $fragment[3],
'flags_hlaps' => $fragment[4],
'racername' => preg_replace('/(.+\s){5}/U', '', implode(' ', $fragment))
);
Should work for any number of spaces in usernames.
Dygear
25th October 2006, 01:02
filur, you rock dude! Oh and nice they put a spell check in the new version of firefox!
Dygear
26th October 2006, 09:50
Just a quick heads up for you all, version 1.3 is going to be uploaded to you all very soon so that you can use it. It fixes some bugs found in the last version, such as the error message 'LFSWorld Error : $str' now it will return that error string for you to deal with. Might change that behaviour in the future.
Big fix on the get_wr, hotlap_chart functions. They should now return the correct name for racername. Also I've modded the get_hl, and get_pb functions to make use of the same function set as the other two. Keeps the code nice and homogeneous.
Dygear
29th October 2006, 08:36
Updated the link at the top of page.
Dygear
8th November 2006, 09:22
There will be an update for this VERY soon that will have proper 1.3 support. I had a working version, but ... as I just reformatted my hard drive, I neglected to backup that one file. Sorry for the delay.
Dygear
9th November 2006, 14:53
Due to CVS issues, here is the code ... I'll attempt to upload the code to the CVS when I get back from work.
<?php
class LFSWorldSDK {
var $ps;
var $idkey;
var $version;
var $lasthit;
var $action;
var $racer;
var $track;
var $car;
var $control;
var $log_filter;
var $lines;
var $starttime;
var $format;
var $c;
function LFSWorldSDK($IdKey, $Premium = false, $Version = '1.3') {
$this->ps = $Premium;
$this->idkey = $IdKey;
$this->version= $Version;
$this->lasthit= 0;
$this->query = null;
}
function make_query_string() {
$vars = array();
foreach ($this->get_option_set() as $key => $item) {
$vars[$key] = "{$key}={$item}";
}
foreach ($this->get_request_vars() as $key => $item) {
$vars[$key] = "{$key}={$item}";
}
return 'http://www.lfsworld.net/pubstat/get_stat2.php?' . implode('&', $vars);
}
function get_option_set() {
return array(
'version' => $this->version,
'idk' => $this->idkey,
'ps' => $this->ps,
);
}
function get_request_vars() {
return array(
'action' => $this->action,
'racer' => urlencode($this->racer),
'car' => $this->car,
'track' => $this->track,
'control' => $this->control,
'log_filter' => $this->log_filter,
'lines' => $this->lines,
'starttime' => $this->starttime,
'format' => $this->format,
'c' => $this->c,
);
}
function get_query_results() {
if ($this->ps == TRUE || time() - $this->lasthit > 5) {
$this->lasthit = time();
if ($str = file_get_contents($this->make_query_string())) {
if ($this->c == 1) {
$tmpfile = tmpfile();
if (file_put_contents($tmpfile, $str)) {
$gz = gzopen($tmpfile, "rb");
$str = gzpassthru($gz);
gzclose($tmpfile);
return preg_replace("/\n$/", "", $str);
}
}
elseif ($this->c == 2)
return preg_replace("/\n$/", "", gzuncompress($str));
elseif ($this->c == 3)
return preg_replace("/\n$/", "", gzinflate($str));
else {
if (count(explode("\n", $str)) == 1)
return preg_replace("/\n$/", "", $str); // Don't Ask Don't Tell.
else
return preg_replace("/\n$/", "", $str);
}
}
}
else {
sleep(1);
return $this->get_query_results();
}
}
function get_hl($racer, $track = NULL, $car = NULL) {
$this->action = 'hl';
$this->racer = $racer;
foreach (explode("\n", $this->get_query_results()) as $line => $data) {
preg_match_all('/(.+)\s(.+)\s(.+)\s(.+)\s(.+)\s(.+)\s(.+)\s(.+)/U', $data, $fragment);
$iteration = array(
'id_hl' => $fragment[1][0],
'track' => $fragment[2][0],
'car' => $fragment[3][0],
'split1' => $fragment[4][0],
'split2' => $fragment[5][0],
'split3' => $fragment[6][0],
'time' => $fragment[7][0],
'flags_hlaps' => $fragment[8][0]
);
if ($track != NULL || $car != NULL) {
if ($iteration['track'] == $track && $car == NULL)
$result[] = $iteration;
if ($iteration['car'] == $car && $track == NULL)
$result[] = $iteration;
if ($iteration['track'] == $track && $iteration['car'] == $car)
return $iteration;
}
else
$result[] = $iteration;
}
return $result;
}
function get_pb($racer, $track = NULL, $car = NULL) {
$this->action = 'pb';
$this->racer = $racer;
foreach (explode("\n", $this->get_query_results()) as $line => $data) {
preg_match_all('/(.+)\s(.+)\s(.+)\s(.+)/U', $data, $fragment);
$iteration = array(
'track' => $fragment[1][0],
'car' => $fragment[2][0],
'time' => $fragment[3][0],
'lapcount' => $fragment[4][0]
);
if ($track != NULL || $car != NULL) {
if ($iteration['track'] == $track && $car == NULL)
$result[] = $iteration;
if ($iteration['car'] == $car && $track == NULL)
$result[] = $iteration;
if ($iteration['track'] == $track && $iteration['car'] == $car)
return $iteration;
}
else
$result[] = $iteration;
}
return $result;
}
function get_stats($racer) {
$this->action = 'pst';
$this->racer = $racer;
$data = explode("\n", $this->get_query_results());
$result = array(
'distance' => $data[0],
'fuel' => $data[1],
'laps' => $data[2],
'hosts' => $data[3],
'wins' => $data[4],
'second' => $data[5],
'third' => $data[6],
'finished' => $data[7],
'quals' => $data[8],
'pole' => $data[9],
'credits' => $data[10],
'drags' => $data[11],
'dragwins' => $data[12],
'online' => $data[13],
'hostname' => $data[14],
'time' => $data[15],
'track' => $data[16],
'car' => $data[17],
);
return $result;
}
function hotlap_chart($track, $car, $control = NULL) {
$this->action = 'ch';
$this->track = $track;
$this->car = $car;
if ($control != NULL)
$this->control = $control;
foreach (explode("\n", $this->get_query_results()) as $line => $data) {
preg_match_all('/(.+)\s(.+)\s(.+)\s(.+)\s(.+)\s(.+?)/U', $data, $fragment);
$result[] = array(
'split1' => $fragment[1][0],
'split2' => $fragment[2][0],
'split3' => $fragment[3][0],
'time' => $fragment[4][0],
'flags_hlaps' => $fragment[5][0],
'racername' => $fragment[6][0]
);
}
return $result;
}
function get_wr() {
$this->action = 'wr';
foreach (explode("\n", $this->get_query_results()) as $line => $data) {
preg_match_all('/(.+)\s(.+)\s(.+)\s(.+)\s(.+)\s(.+)\s(.+)\s(.+?)/U', $data, $fragment);
$result[] = array(
'id_wr' => $fragment[1][0],
'track' => $fragment[2][0],
'car' => $fragment[3][0],
'split1' => $fragment[4][0],
'split2' => $fragment[5][0],
'split3' => $fragment[6][0],
'time' => $fragment[7][0],
'flags_hlaps' => $fragment[8][0],
'racername' => $fragment[9][0]
);
}
return $result;
}
function get_hosts() {
$this->action = 'hosts';
$string = $this->get_query_results();
$result = array();
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$NumberOfRacers = @unpack("c", substr($string, $pointer + 52, 1));
$NumberOfRacers = $NumberOfRacers[1];
$NumberOfRacersLen = $NumberOfRacers * 24;
$PointerPast = $NumberOfRacersLen + 53;
$result[$i] = array();
if (($result[$i] = @unpack("a32hostname/A4tmlt/A4tcrm/icars/irules/claps/cqual/cspare1/cspare2/cnrofracers/a{$NumberOfRacersLen}racernames", substr($string, $pointer, $PointerPast)))) {
$result[$i]['racernames'] = preg_split("/\\0/", $result[$i]['racernames'], -1, PREG_SPLIT_NO_EMPTY);
$result[$i]['tmlt'] = unpack("ctype/cmain/a1letter/ctestId", $result[$i]['tmlt']);
$result[$i]['tcrm'] = unpack("ctrack/cconfig/creversed/cmax", $result[$i]['tcrm']);
}
else
unset($result[$i]);
$pointer += $PointerPast;
}
return $result;
}
function get_teams() {
$this->action = 'teams';
$string = $this->get_query_results();
$result = array();
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$infoLen = @unpack("S", substr($string, $pointer + 298, 2));
$infoLen = $infoLen[1];
$nrMembers = @unpack("S", substr($string, $pointer + 300 + $infoLen, 2));
$nrMembers = $nrMembers[1] * 24;
$PointerPast = 302 + $infoLen + $nrMembers;
$result[$i] = array();
if (($result[$i] = @unpack("a128team/a6tag/a32country/a128url/Ibits/Sinfo_len/a{$infoLen}info/Snr_members/a{$nrMembers}members", substr($string, $pointer, $PointerPast)))) {
$result[$i]['members'] = preg_split("/\\0/", $result[$i]['members'], -1, PREG_SPLIT_NO_EMPTY);
$result[$i]['info'] = urldecode($result[$i]['info']);
}
else
unset($result[$i]);
$pointer += $PointerPast;
}
return $result;
}
function get_hlog($log_filter = NULL, $lines = NULL, $control = NULL, $starttime = NULL) {
$this->action = 'hl_log';
$this->format = 3;
if ($log_filter != NULL)
$this->log_filter = $log_filter;
if ($lines != NULL && $lines >= 1 && $lines <= 150)
$this->lines = $lines;
if ($control != NULL)
$this->control = $control;
if ($starttime != NULL)
$this->starttime = $starttime;
$string = $this->get_query_results();
$result = array();
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$result[$i] = array();
if (($result[$i] = @unpack("itime/a24racer/a32country/A4tcrc/i4split/Spos/Sflags/iid_hl", substr($string, $pointer, 88)))) {
$result[$i]['tcrc'] = unpack("ctrack/cconfig/creversed/ccar", $result[$i]['tcrc']);
}
else
unset($result[$i]);
$pointer += 88;
}
return $result;
}
}
?>
Dygear
10th November 2006, 05:37
Issues, feedback, comments or anything?
SkyNet
10th November 2006, 07:25
I see nobody is replying...well i dl'ed the sdk and the updated code and will give it a go when i get back from work. Thanks dygear ;)
filur
10th November 2006, 20:54
Updated CVS with Dygears code for the pubstat changes and released a new .rar, http://prdownloads.sourceforge.net/lfsworldsdk/lfsworldsdk-php4-cvs20061110.rar?download
SkyNet
10th November 2006, 22:14
Hm i'm no programer so i would appreciate if you could help me around this...When i try to get my pb's it just says "Laps: 0" and if i try get my hotlaps it says "Array ( [id_hl] => [track] => [car] => [split1] => [split2] => [split3] => [time] => [flags_hlaps] => )"
And since 1.3 you must use your pubstats id...where do i put it?
filur
10th November 2006, 22:39
since 1.3 you must use your pubstats id...where do i put it?
The id key is passed to the object at creation, it is actually required.
$object = new LFSWorldSDK('id key goes here');if i try get my hotlaps it says "Array ( [id_hl] => [track] => [car] => ...
Arrays can be seen as collections of variable<->value pairs, to access the value of a variable, you use:
$the_array['variable_name'];
A simple way to iterate thru the entire array:
$hotlaps = get_hl('filur');
foreach ($hotlaps as $lap) {
echo $lap['track'].' in '.$lap['car'].': '.$lap['time'].'<br />';
}
More info on arrays in PHP:
http://php.net/manual/en/language.types.array.php
http://php.net/manual/en/ref.array.php
paXton
11th November 2006, 13:11
Hi!
Updated CVS with Dygears code for the pubstat changes and released a new .rar, http://prdownloads.sourceforge.net/lfsworldsdk/lfsworldsdk-php4-cvs20061110.rar?download
perhaps, the id_key should be mentioned it the "examples/get_XXX.php".
Keep up the good work. :thumb:
I like the SDK...
paXton
Dygear
12th November 2006, 00:55
I don't think we've updated the examples part of it as of 1.0. I'm going to have to do that later :).
HorsePower
12th November 2006, 14:18
Just a little question: Someone had this gzuncompress-error with an older version of LFSWorldSDK.
Warning: gzuncompress(): data error in ...
ATM, I'm also programming a little script, and I also get this message from the 3rd time on I query LFSW (10 sec between queries).
I use this code (for example for WR's):
gzuncompress(file_get_contents("http://lfsworld.net/pubstat/get_stat2.php?version=1.3&action=wr&c=2&idk=".$this->id_key));
How can I fix it? Any help appreciated! Thanks in advance!
SkyNet
12th November 2006, 18:05
Hey thanks i got it working.
All the tracks are in three digit numbers, how do i know which is which? I only know that 000 is blackwood.
And then how do i rename them their real names, so that it would show me "Blackwood GP" instead of "000".
HorsePower
12th November 2006, 18:21
Explained here:
http://www.lfsforum.net/showthread.php?t=14480
filur
12th November 2006, 20:49
Warning: gzuncompress(): data error in ...
ATM, I'm also programming a little script, and I also get this message from the 3rd time on I query LFSW (10 sec between queries).
I use this code (for example for WR's):
gzuncompress(file_get_contents("http://lfsworld.net/pubstat/get_stat2.php?version=1.3&action=wr&c=2&idk=".$this->id_key));
How can I fix it? Any help appreciated! Thanks in advance!
if ($gzstr = file_get_contents(' ... ')) {
if ($str = @gzuncompress($gzstr))
/* it's all good. */
else
/* it's most likely an error message in plain text ($gzstr). */
}
else
/* can't get output. */
HorsePower
12th November 2006, 21:22
Thanks very much! Will test that soon. :)
HorsePower
13th November 2006, 10:27
Ok, implemented it. The error message I get is
"can't reload this page that quickly after another"
Is this a PHP problem, or a Apache problem (I'm using XAMPP at my localhost to test my work).
I mean, as far as I understood, I can use pubstat every 5 seconds. But also if I wait 10 seconds between queries I get this message every single time from the 2rd query in a row on. :scratchch
EDIT: In fact, I get this error from the 2nd query on.
EDIT: And even with 120 seconds between queries. Must be a PHP/Apache problem, right?
filur
13th November 2006, 10:33
... as far as I understood, I can use pubstat every 5 seconds. But also if I wait 10 seconds between queries I get this message every single time from the 3rd query ...
Make sure you're not running something else that's querying pubstats, as it's limited per IP. Can't see how it could technically be caused by Apache or PHP.
Edit: maybe it's also limited by id-key, if you're using the same key from separate locations. (?)
HorsePower
13th November 2006, 10:53
I found this post, http://www.lfsforum.net/showthread.php?p=68428#post68428
He can solve his problem by using the 5-second interval. Strange. 120 seconds don't work for me.
And I have no other processes grabbing LFSW. We have a homepage, which will query LFSW at maximum every 60 seconds, but only if someones klicking on it. And that are only up to 30 people per day. And this page uses a different ID-Key.
Anyway, thanks for you comments. This is off-topic here. If I can't solve the problem, I maybe post elsewhere.
EDIT: Yet a last note here: It works for uncompressed LFSW-output. Now I'm really confused.
filur
13th November 2006, 11:43
I found this post [...] He can solve his problem by using the 5-second interval. Strange. 120 seconds don't work for me [...] EDIT: Yet a last note here: It works for uncompressed LFSW-output. Now I'm really confused.
I run alot of pubstat stuff, everything compressed (gzcompress), everything on 5s. tarpit. Tried running the script from command line?
HorsePower
13th November 2006, 13:28
Nope. How? And what's different there?
The only change I have to make is to remove the &c=2 and the gzuncompress stuff. :shrug:
filur
13th November 2006, 14:05
Nope. How? And what's different there?
You could basically find out if the webserver or anything in that environment is causing the problem.
php.exe -f path/to/file.php
http://www.php.net/manual/en/features.commandline.php
Dygear
13th November 2006, 14:47
Eh, I don't think this is a apache error. The question you should ask your self is, is there any other part of the script that is not using that function? From what I can see, I don't think you have a function setup for this. Try a setup like this . . .
<?php
function get_lfsw_data($query_str) {
sleep(5);
if ($gzstr = file_get_contents('http://lfsworld.net/pubstat/get_stat2.php?version=1.3&c=2'.$query_str)) {
if ($str = @gzuncompress($gzstr))
return $str;
else
die($gzstr);
} else {
return -1;
}
}
echo get_lfsw_data('&action=wr&idk=".$this->id_key);
?>
I would do it this way, I'm not fully sure how your doing it by yourself. Also note that sleep(5) some times returns the error of 'not enough time between querys' so you might want to bump it up to 6 seconds.
HorsePower
13th November 2006, 18:58
I'm stunned. :Eyecrazy:
It works, basically with your function. But as hard as I try, I can see no difference (in principle) to my old code. The only change is that now there is this extra function that does the querying.
Maybe I just have overseen something. :smileypul
function get_lfsw_data($query_str) {
sleep(6);
$query = "http://lfsworld.net/pubstat/get_stat2.php?version=1.3".$query_str."&c=2&idk=".$this->id_key;
if ($gzstr = file_get_contents($query)) {
if ($str = @gzuncompress($gzstr)){
return $str;
}else{
die($gzstr);
}
} else {
return "";
}
}
filur
14th November 2006, 05:14
It works, basically with your function. But as hard as I try, I can see no difference (in principle) to my old code. The only change is that now there is this extra function that does the querying.
There are some oddities in PHP, sometimes it doesn't work as line-by-line as you'd expect, might've found one of those. :)
HorsePower
16th November 2006, 11:18
To wrap this off-topic discussion up, I just want to say that everything is working fine now. Just as you guys here I have written some kind of SDK, basically a class covering some helpful functions for querying LFSW.
Furthermore I have written another class, called 'tracker', which uses the class above to get all HLs, PBs and WRs of a set of mates and stores them into a MySQL DB. There are some functions for a formatted output in a table.
The result can be seen here (http://hot.german-gamers-club.de/?id=17&lang=1).
There are still some things to implement or some bug fixes to make, I guess.
Anyway, I will write a bit of documentation for all my stuff and release it on our homepage (or even somewhere here) in the near future. Maybe you guys are also interested in this tracker stuff.
Again, I want to thank you for the kind help here. :thumb:
BTW: I don't want to compete with you guys. I believe your SDK is much more stable, bug free and runs on a wider range of platforms, since I really haven't cared much about compatibility and I'm not a PHP expert. :shrug:
MikeB
16th November 2006, 11:28
Hey, i am trying to get the list of teams. But it seems the parsing is going wrong. I already added some output to show me the raw string returned from lfsworld and this looks good. But there is something going wrong with the unpack stuff which i dont really understand (beeing a php noob :))
Does anyone experience the same problems?
To be a bit more clear - i am using this small script derived from your examples:
function teams_test() {
global $LFSWorld;
$teams = $LFSWorld->get_teams();
echo "<p>Starting teams list</p>\n";
foreach ($teams as $this_team) {
echo "-----------------------------------------\n";
echo "Team: {$this_team['team']} ({$this_team['tag']}) \n\n";
echo "Members: {$this_team['nr_members']} \n";
echo "Website: {$this_team['url']} \n\n";
}
echo "<p>Finished teams list</p>\n";
}
It is not related to tarpitting or my UserID. Other things i tried (get pbs/hotlaps etc.) work fine.
Dygear
17th November 2006, 00:23
Hey, i am trying to get the list of teams. But it seems the parsing is going wrong. I already added some output to show me the raw string returned from lfsworld and this looks good. But there is something going wrong with the unpack stuff which i dont really understand (beeing a php noob :))
Does anyone experience the same problems?
To be a bit more clear - i am using this small script derived from your examples:
It is not related to tarpitting or my UserID. Other things i tried (get pbs/hotlaps etc.) work fine.
I'll look into this in a moment. . . I've got some SimFIA stuff to do right now. Could you tell me what version of the script your running?
MikeB
17th November 2006, 09:38
I'll look into this in a moment. . . I've got some SimFIA stuff to do right now. Could you tell me what version of the script your running?
The file says:
@version $Id: LFSWorldSDK.php,v 1.4 2006/11/10 20:38:36 lur Exp $
And the package name is "lfsworldsdk-php4-cvs20061110".
Thanks :nod:
Dygear
17th November 2006, 23:35
$teams = $LFSWorld->get_teams();
echo "<p>Starting teams list</p>\n";
foreach ($teams as $this_team) {
echo "-----------------------------------------\n";
echo "Team: {$this_team['team']} ({$this_team['tag']}) \n\n";
echo "Members: {$this_team['nr_members']} \n";
echo "Website: {$this_team['url']} \n\n";
}
echo "<p>Finished teams list</p>\n";
Seems that when you place it inside a function like that, it simply will not work. I'm running 5.2.0 on my test box (and production box) and the issue remains. I would simpley extend the lfsworld class with your own functions.
filur
18th November 2006, 00:35
I would simpley extend the lfsworld class with your own functions.
Just to clarify as this sounds hopelessly complex for someone who's new to it.
Instead of wrapping actions into a function like MikeB did in the example a few posts above, a much cleaner and actually simpler method is extending lfsworldsdk.
include 'lfsworldsdk.php';
class MyLFSWorld extends LFSWorldSDK {
function teams_test() {
$teams = $this->get_teams();
echo "<p>Starting teams list</p>\n";
foreach ($teams as $this_team) {
echo "-----------------------------------------\n";
echo "Team: {$this_team['team']} ({$this_team['tag']}) \n\n";
echo "Members: {$this_team['nr_members']} \n";
echo "Website: {$this_team['url']} \n\n";
}
echo "<p>Finished teams list</p>\n";
}
}
By doing this you are effectively copying the entire function set from lfsworldsdk and adding the teams_test function to it. The passing around of $LFSWorld is replaced with $this, $this is always a reference to the object itself when working with code inside a class.
Finally you would use your class instead of lfsworldsdk when creating the object:
//$LFSWorld = new LFSWorldSDK();
$LFSWorld = new MyLFSWorld();
$LFSWorld->teams_test();
Anarchi-H
18th November 2006, 14:55
$teams = $LFSWorld->get_teams();
echo "<p>Starting teams list</p>\n";
foreach ($teams as $this_team) {
echo "-----------------------------------------\n";
echo "Team: {$this_team['team']} ({$this_team['tag']}) \n\n";
echo "Members: {$this_team['nr_members']} \n";
echo "Website: {$this_team['url']} \n\n";
}
echo "<p>Finished teams list</p>\n";
Seems that when you place it inside a function like that, it simply will not work. I'm running 5.2.0 on my test box (and production box) and the issue remains. I would simpley extend the lfsworld class with your own functions.
Your code to decompress c=1 doesn't work (on my box at least), and is a bit nasty anyway.
This works just as well...
return gzinflate(substr($str, 10));
I can't replicate the error you and MikeB are talking about so I can't offer any solutions. However, scope should not matter. It doesn't matter if you are in calling from a function or a global scope, the code should still behave the same. (For reference I'm running Apache 2.0.59 w/ PHP5.2.0)
Extending LFSWorldSDK in that manner is very bad design form and could just be a work around to a more serious issue.
filur
18th November 2006, 18:08
Extending LFSWorldSDK in that manner is very bad design form and could just be a work around to a more serious issue.
What makes it bad design?
Anarchi-H
19th November 2006, 02:54
What makes it bad design?
Misuse of inheritance and in the specific example, mixing (business) logic with presentation. A quote from the great wiki itself in the 'Common Mistakes' section.
Object-oriented programming (http://en.wikipedia.org/wiki/Object-oriented_programming#Common_mistakes)
Overuse of inheritance when composition or aggregation may be more appropriate. It has been suggested that training materials over-emphasizes inheritance, perhaps because it is easier to illustrate than the alternatives.
In this case, aggregation would be more appropriate if you are going to extend it with OO.
I understand it is difficult to to explain the concept of a class to new coders, let alone the difference between ways of extending them but education is key and in this case it is showing new coders the wrong way to do it.
The code doesn't work in that configuration for a reason. It may not be your fault, it may be a PHP bug, but regardless it is your responsibility as the developers to find it, and even more so if you can replicate it!
You wouldn't expect Scawen to say "It just doesnt work, here is what you'll have to do instead".
Sorry for the lecture, but you did ask :p
filur
19th November 2006, 04:25
Misuse of inheritance and in the specific example, mixing (business) logic with presentation. [...] In this case, aggregation would be more appropriate if you are going to extend it with OO.
While i do agree on mixing code with presentation, i would suggest pretty much anything to avoid passing the object around as a global variable.
I guess by misuse of inheritance you're saying inheritance is in this case completely unecessary, if so i would basically agree. However, attempting to explain classes, objects and association or how to use runkit doesn't really fit in this thread. Extending the class is an easy neatness fix, and in my opinion quite a good introduction to objects and classes in PHP. If there's enough interest i'm sure the manual and google would do a better job of teaching object orientation then i could. :)
You wouldn't expect Scawen to say "It just doesnt work, here is what you'll have to do instead".
I would expect Scawen to say "until i fix the black screen bug, don't start LFS in fullscreen" (might've been windowed). ;)
Anarchi-H
19th November 2006, 05:12
While i do agree on mixing code with presentation, i would suggest pretty much anything to avoid passing the object around as a global variable.
I guess by misuse of inheritance you're saying inheritance is in this case completely unecessary, if so i would basically agree. ...
Not quite; if I were to aggregate an instance of LFSWorld to MyLFSWorld it would look like this;
<?php
class MyLFSWorld
{
var $LFSWorld = null;
function MyLFSWorld($idk)
{
$this->LFSWorld =& new LFSWorldSDK($idk);
}
}
?>
I'm not sure where you got the idea of global from :x
The definition of an aggregation is when one object belongs to another, and this owned object will be created and destroyed with/by the owning object.
As you can see, it is a minor departure from inheritance, but an important one because you no longer have to worry about namespace clashes between the base lib and the "extended" functionality, and (with PHP5) you don't have to worry about them accidentally accessing a protected var. (Not that this applies here :))
I would expect Scawen to say "until i fix the black screen bug, don't start LFS in fullscreen" (might've been windowed). ;)
Fair play, but I bet it would be high on his list :thumb:
filur
19th November 2006, 07:15
I'm not sure where you got the idea of global from :x
From the code i used in my example, the code that was being discussed by MikeB and Dygear.
As you can see, it is a minor departure from inheritance
Actually, i see it as something completely different. :)
MikeB
19th November 2006, 10:06
Ahem, before this evolves to some flamewar maybe some background to my question :-)
Basically i am currently playing around with the pubstats and just wanted to test the different methods your SDK is offering. Having studied computer science and about 5 years of C++ experience in full depth in my job I have quite some knowledge of object orientation and the related paradigms :-)
So i totally agree that my code sample using global vars sucks :) So please do not take it as a serious approach for anything useful - i really just played with your SDK methods (and PHP in general).
(Now back to topic :D)
Having said that, i would agree with Anarchi:
However, scope should not matter. It doesn't matter if you are in calling from a function or a global scope, the code should still behave the same. As i said i have no experience with PHP sof ar. I am using php5 as installed by my ISP. Is there anything useful i could do to help track this error down?
St4Lk3R
19th November 2006, 11:09
As i said i have no experience with PHP sof ar. I am using php5 as installed by my ISP. Is there anything useful i could do to help track this error down?
You can in fact. First thing you can do is try to replace
global $LFSWorld;
by
global &$LFSWorld;
Else PHP could try to create a copy of the $LFSWorld object instead of passing a reference to it to the function.
If this does not work, try giving $LFSWorld as a parameter to your function:
function get_lfsw_teams(&$LFSWorld) {
// ...
}
$LFSWorld = new LFSWorldSDK($idk);
get_lfsw_teams(&$LFSWorld);
This should work in every case.
Greets
filur
19th November 2006, 12:11
.. PHP could try to create a copy of the $LFSWorld object instead of passing a reference to it to the function.
PHP5 should AFAIK always pass objects by reference.
St4Lk3R
20th November 2006, 11:23
PHP5 should AFAIK always pass objects by reference.
PHP 5 does, but PHP 4 may want to do bad things with the objects.
bdshan
24th November 2006, 19:52
I just started playing around with this SDK. I noticed that when I get my PBs all the lapcounts are wrong. I looked at the data recieved back from world and it is correct, but when reading the results return by the function they are wrong. For example 43 becomes 4, 167 becomes 1. Has anyone else noticed this?
I should note that I changed the pubstats version to 1.3 from 1.2 and added my ident key. I got the same results both when using compressed and uncompress LFSWorld queries.
MikeB
29th November 2006, 14:12
I just started playing around with this SDK. I noticed that when I get my PBs all the lapcounts are wrong. I looked at the data recieved back from world and it is correct, but when reading the results return by the function they are wrong. For example 43 becomes 4, 167 becomes 1. Has anyone else noticed this?
I should note that I changed the pubstats version to 1.3 from 1.2 and added my ident key. I got the same results both when using compressed and uncompress LFSWorld queries.
I got exactly the same problem. I resolved it using a simple "explode" statement instead of regex matching - i did not investigate further but I suppose filur/dygear had some reason to use regex instead of explode?
I am currently at work, i can post the change this evening if you need it.
bdshan
29th November 2006, 14:43
Thanks for the offer, MikeB. I know that explode will work. I currently use it in my implementation. I was looking at integrating the SDK so I wouldn't need to rewrite all those same functions myself.
I am completely clueless when it comes to regex, so I was hoping filur or dygear would give an explaination of why they use the regex and what it is doing.
filur
29th November 2006, 15:31
Only bit of regex i can think of was added to grab usernames with any number of spaces, discussed earlier in this thread. A limited explode is probably a better option.
bdshan
29th November 2006, 15:38
Filur, indulge me if you will. What does
preg_match_all('/(.+)\s(.+)\s(.+)\s(.+)/U', $data, $fragment);
do? This line is the only line in the PB function that I don't understand. And forgive me I have not looked up the preg_match function in the PHP manual.
filur
29th November 2006, 15:47
Filur, indulge me if you will. What does
preg_match_all('/(.+)\s(.+)\s(.+)\s(.+)/U', $data, $fragment);
do? This line is the only line in the PB function that I don't understand. And forgive me I have not looked up the preg_match function in the PHP manual.
It matches any character the least possible amount of times until it stumbles upon a whitespace character, four times, then it matches any character until there's nothing more to match. The parenthesis creates subpatterns / submatches which end up as entries in the $fragment array.
Result should be the same as explode(' ', $string, 5);
Dygear
2nd December 2006, 13:36
Awe! I missed the great discussion! Sorry all, I've been doing a lot of work, did not even have thanksgiving off. Anyway, back on subject. I think a simple redo of all of this would be nice. filur has wanted to get a pure php 5 version of this out for some time. I'd like to update the current php 4 version quite alot so that it works better. Seems I've not put alot of testing into it, or as much as I should of.
Dygear
7th December 2006, 10:23
<?php
// Copyright 2006 Mark 'Dygear' Tomlin & Mikael 'filur' Forsberg
// Verison 1.5.beta (UNI)
class LFSWorldSDK {
function LFSWorldSDK($idk, $ver = 1.3, $pre = false) {
$this->ps = $pre;
$this->idk = $idk;
$this->version = $ver;
}
function make_query($qryStr) {
return file_get_contents("http://www.lfsworld.net/pubstat/get_stat2.php?version={$this->version}&idk={$this->idk}&ps={$this->ps}{$qryStr}");
}
function get_hl($racer) {
foreach (explode("\n", $this->make_query("&action=hl&racer={$racer}")) as $line => $data)
list($result[$line]['id_hl'], $result[$line]['track'], $result[$line]['car'], $result[$line]['split1'], $result[$line]['split2'], $result[$line]['split3'], , $result[$line]['time'], $result[$line]['flags_hlaps']) = split(' ', $data, 8);
return $result;
}
function get_pb($racer) {
foreach (explode("\n", $this->make_query("&action=pb&racer={$racer}")) as $line => $data)
list($result[$line]['track'], $result[$line]['car'], $result[$line]['time'], $result[$line]['lapcount']) = split(' ', $data, 4);
return $result;
}
function get_ch($track, $car, $control = null) {
foreach (explode("\n", $this->make_query("&action=ch&track={$track}&car={$car}&control={$control}")) as $line => $data)
list($result[$line]['split1'], $result[$line]['split2'], $result[$line]['split3'], $result[$line]['time'], $result[$line]['flags_hlaps'], $result[$line]['racername']) = split(' ', $data, 6);
return $result;
}
function get_wr() {
foreach (explode("\n", $this->make_query("&action=wr")) as $line => $data)
list($result[$line]['id_wr'], $result[$line]['track'], $result[$line]['car'], $result[$line]['split1'], $result[$line]['split2'], $result[$line]['split3'], $result[$line]['time'], $result[$line]['flags_hlaps'], $result[$line]['racername']) = split(' ', $data, 9);
return $result;
}
function get_pst($racer) {
list($result['distance'], $result['fuel'], $result['laps'], $result['hosts'], $result['wins'], $result['second'], $result['third'], $result['finished'], $result['quals'], $result['pole'], $result['online'], $result['drags'], $result['drag'], $result['online'], $result['hostname'], $result['time'], $result['track'], $result['car']) = split("\n", $this->make_query("&action=pst&racer={$racer}"), 19);
return $result;
}
function get_hosts() {
$string = $this->make_query("&action=hosts");
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$NumberOfRacers = @unpack("c", substr($string, $pointer + 52, 1));
$NumberOfRacers = $NumberOfRacers[1];
$NumberOfRacersLen = $NumberOfRacers * 24;
$PointerPast = $NumberOfRacersLen + 53;
$result[$i] = array();
if (($result[$i] = @unpack("a32hostname/A4tmlt/A4tcrm/icars/irules/claps/cqual/cspare1/cspare2/cnrofracers/a{$NumberOfRacersLen}racernames", substr($string, $pointer, $PointerPast)))) {
$result[$i]['racernames'] = preg_split("/\\0/", $result[$i]['racernames'], -1, PREG_SPLIT_NO_EMPTY);
$result[$i]['tmlt'] = unpack("ctype/cmain/a1letter/ctestId", $result[$i]['tmlt']);
$result[$i]['tcrm'] = unpack("ctrack/cconfig/creversed/cmax", $result[$i]['tcrm']);
}
else
unset($result[$i]);
$pointer += $PointerPast;
}
return $result;
}
function get_teams() {
$string = $this->make_query("&action=teams");
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$infoLen = @unpack("S", substr($string, $pointer + 298, 2));
$infoLen = $infoLen[1];
$nrMembers = @unpack("S", substr($string, $pointer + 300 + $infoLen, 2));
$nrMembers = $nrMembers[1] * 24;
$PointerPast = 302 + $infoLen + $nrMembers;
$result[$i] = array();
if (($result[$i] = @unpack("a128team/a6tag/a32country/a128url/Ibits/Sinfo_len/a{$infoLen}info/Snr_members/a{$nrMembers}members", substr($string, $pointer, $PointerPast)))) {
$result[$i]['members'] = preg_split("/\\0/", $result[$i]['members'], -1, PREG_SPLIT_NO_EMPTY);
$result[$i]['info'] = urldecode($result[$i]['info']);
}
else
unset($result[$i]);
$pointer += $PointerPast;
}
return $result;
}
function get_hl_log($log_filter = 4, $lines = 150, $control = null, $starttime = 0) {
$string = $this->make_query("&action=hl_log&log_filter={$log_filter}&lines={$lines}&control={$control}&starttime={$starttime}&format=3");
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$result[$i] = array();
if (($result[$i] = @unpack("itime/a24racer/a32country/A4tcrc/i4split/Spos/Sflags/iid_hl", substr($string, $pointer, 88))))
$result[$i]['tcrc'] = unpack("ctrack/cconfig/creversed/ccar", $result[$i]['tcrc']);
else
unset($result[$i]);
$pointer += 88;
}
return $result;
}
}
?>
This should be faster as it does not rely on preg for it's string parsing in all cases.
This is not directly compatible with the older versions due to the fact that I've changed around the order of the args for the entry function.
Dygear
8th December 2006, 05:09
Preamble
I'd like to point out that code IS BETA, and as such I'm going to be building on it, alot. By alot, I mean to the level where you only need one function from the SDK to get just the data you need. I also plan on adding some support files to facilitate functions that would allow you to make queries like so :
From my brain to your server
$SDK->get_pb('Dygear', 'BL1', 'BF1');
I know, I know, woop-de-do. I can use the short name for the track, oh but there's so much more planed . . .
$SDK->get_pb('filur', array('BL1', 'FE4', 'KY3', '661'), array('S-S', '-FOX'));
Notice that I'm going to be getting all of filur's pbs on Blackwood GP, Fern Bay Black, Kyoto GP Long, and Aston North Reverse with the S-S class of cars minus the FOX. Now this is not code that I've made ... yet, but this is what is planed.
HorsePower
See what you started HorsePower? I just have to one up ya man, and this is the best way I know how, to out program ya. BTW, I still think your program is slick, I would love to run it, but I can't bring myself to. I might find something in your code that makes me want to use it. And I'd really like this project to be from my brain (and filur's brain) to your computer.
The Keep It Simple Stupid Paradox.
I build on the original LFSWorldSDK with the idea that it should not do more then was needed, but I was missing the point. It, as is, is nothing more then an API to facilitate easy access to the LFS World Repository. I wanted to keep it simple on the LFSWorldSDK side so it would be as lean, and thus fast. But there is the issue, people who are using this product really want something to do it all, they really want an SDK. I've failed to provide that up to this point. It's not filur's fault, he was pushing me in the direction of a full on do it all SDK but I stopped him and said K.I.S.S. The issue with K.I.S.S is that it's anything but simple for the guy who has to make the data do it's little work out. They where not really gaining anything from the SDK other then a nice way to connect and get data from the LFSWorld website. Pointless.
Design ideas
This is what I'm planing, 1 file for each current function of the SDK. The core file will still be called LFSWorldSDK and will do all of the query work, it will also be the entry point for the SDK as is right now in 1.5.Beta. 1.5.Beta is dead, I'm not going to be doing any more work on it. The next step is 2.0, what 1.0 should of been, and what filur has always wanted. A real SDK. It will do it all. One line queries to get the data you need. Directory Structure Looks Like This (Tentative), and the
LFSWorldSDK.php // LFSWorldSDK Entry Point (You Include This File, It Includes The Rest).
support_core.php // Home to things like support arrays with info on what is equal to what.
action_hl.php // Hot Lap query code.
action_pb.php // Personal Best query code.
action_ch.php // CHart query code.
action_wr.php // World Record query code.
action_pst.php // Personal STatistics query code.
action_hosts.php // Hosts query code.
action_teams.php // Teams query code.
action_hl_log.php // Hot Lap Log query code.
File(s) are only going to be included if you use that function.
HorsePower
8th December 2006, 11:00
HorsePower
See what you started HorsePower? I just have to one up ya man, and this is the best way I know how, to out program ya. BTW, I still think your program is slick, I would love to run it, but I can't bring myself to. I might find something in your code that makes me want to use it. And I'd really like this project to be from my brain (and filur's brain) to your computer.
Hehe. :D I really would like if you bring your work to the next level.
And if you have a really weak moment, and decide to implement my tracker into your SDK, I would love it. :nod:
Anarchi-H
8th December 2006, 13:34
Your design ideas are very similar to how PPF is architectured but I no longer have time to update it since taking a full time PHP developer position. :(
Rather than going to waste, perhaps it can be of some use to you, even if you don't use the code directly.
PPF is architectured like this ...
Tailored Interfaces
Simple implementation specific interfaces for an end programmer to use that will provide an easy way to 'do it all' without compromising the core code. (Only the SimpleInterface is implemented at present which provides a very similar API to LFSWorldSDK)
Generic Interface
This handles all requests to the 'providers' (explained below). It takes care of default params, caching, handling the request etc. It is completely isolated from a specific provider so that if multiple sources for LFSWorld data pop up in the future then only a new provider needs to be written.
Providers
The base provider handles the HTTP request, decompression and error checking. The sub-providers take care of the parsing and (like in your ideas) are each in their own file.
CacheProviders
Cache providers provide different means of caching. There is currently a file based cacher and an sql based cacher (only works with hosts atm because the other providers need pre-insert and post-select callbacks writing for them.
Lookups
The lookups provide a means of translation between common formats that LFSWorld uses, and that someone using PPF might need. i.e. convert XFG->XF Gti or 000 -> Blackwood GP
Utils
These are small bits of code that perform useful functions. For example, there is an extremely optimized Colour and Charset parser with output callbacks so that only a callback needs to be written for a new kind of output. (CSS & HTML ones exist already)
Other functions include ones to decompress LFSWorld data, check for LFSWorld errors and make LFSJoin/Join2LFS compatible links.A quick overview of how these fit together looks like this...
User creates TailoredInterface (which extends GenericInterface)
User calls a 'do it all' method on the TailoredInterface
TailoredInterface creates provider instance
TailoredInterface creates cache provider instance
TailoredInterface does pre-request magic
TailoredInterface calls GenericInterface to make a data request and passes provider & cache objects to GenericInterface
GenericInterface checks with provider that all params are set
GenericInterface checks with cache to see if a valid entry exists
Assuming no cache entry, GenericInterface calls provider to get data
Provider makes request to LFSWorld
Provider decompresses data and checks for errors
Provider returns data to Generic Interface
Generic interface passes returned data to cacher
Cacher stores data
Generic Interface returns data to TailoredInterface
TailoredInterface does post-request magic (display and such)
The End
If any of that interests you, feel free to pm me for further explanation.
If not then maybe someone else might find use it.
filur
8th December 2006, 14:45
I've looked at PPF twice i think, but as i can't stand PEAR i've never tried it.
My own design is something like ..
Wrapper creates Query instance.
Wrapper passes Query instance to Engine.
Engine grabs request details from Query, performs request and decompression.
Engine passes raw result to Query.
Engine calls interfaced methods in Query.
Query formats itself.
Engine returns Query (result) to Wrapper
Wrapper returns Query (result) to User.
The stuff i've written is highly object oriented, meaning you won't get hotlap flags returned as "517", you'll get something like ..
HotlapFlags Object {
bits => 517
gearblip => TRUE
gearcut => FALSE
...
__toString() => 'w gb ac'
}
.. etc.
Typical use would be something like ..
$wrapper = new LFSWorldSDK($idkey, $compression);
$hotlaps = $wrapper->getHotlaps('filur');
foreach ($hotlaps as $lap)
echo $lap->track.' '.$lap->car.' @ '.$lap->laptime.'<br />';
print_r($hotlaps->_asArray());
echo $hotlaps->getSingleLap('BL1', 'LX6')->laptime;
I've also got Resources which are pretty similar to Lookups, mine are collections of static methods:
$readable = LFSWLaptime::getTrimReadableTime($integer_laptime) ;
$car_fullname = LFSWCars::getCarName($car);
Where, for example, getCarName() always returns the full name whether you call it with car bits or the abbreviation (or the full name, even).
This will of course not run under PHP4 at all, has __toString() design issues with some versions of PHP5, but should hopefully run as intended on PHP6. :) I am however writing it under PHP5, and it works good enough. Currently backing this thing (http://www.liveforspeed.se/?view=memberpages&read=memberpages__pb_rank) with no issues thus far. :)
Anarchi-H
8th December 2006, 17:27
I've looked at PPF twice i think, but as i can't stand PEAR i've never tried it.
Sounds good, although watch out for speed issues on the charts if you are creating objects for each record. My initial solution was entirely OO but I found it to be much slower than arrays for the dataset with so many objects, even on PHP5. (Unless the charts output has changed; it's been a while since I tested)
PPF will run under PHP4 (>4.2.0 I think, although maybe 4.3), and fair point about PEAR. It's pretty crap but is only used for HTTP_Request (because fopen can't do timeouts and I couldn't be arsed to write my own HTTP client) and Cache_lite for the file cache.
Files that require PEAR are (IIRC) ppf/caches/lfsworldfilecache.php && ppf/providers/lfsw/baseprovider.php ... possibly some hackish variable poking and stuff in the sub-providers.
It would be pretty easy to port it to other libs since there aren't that many references made to PEAR specifics.
Yeah, anyway, point wasn't in the architecture; that was just provided so that you might be able to find the stuff you want. You can rip it apart and mangle it about as much as suits you, or just use a single line of code if it is useful.
I forgot to mention, ignore the license. I'm essentially opening this up for a free for all so no credit or anything silly is required.
filur
8th December 2006, 17:49
... watch out for speed issues on the charts if you are creating objects for each record.
It'll be slow(er), no doubt. :) Hopefully countered a bit by ease of use.
... about PEAR. It's pretty crap but is only used for HTTP_Request (because fopen can't do timeouts and I couldn't be arsed to write my own HTTP client) and Cache_lite for the file cache.
I think there's one or more .ini settings for socket timeouts, but i can see why you'd use PEAR stuffies. I'd probably be a PEAR user myself if the contents weren't distributed thru and / or relied on PEAR. :)
Anarchi-H
8th December 2006, 18:02
I think there's one or more .ini settings for socket timeouts, but i can see why you'd use PEAR stuffies. I'd probably be a PEAR user myself if the contents weren't distributed thru and / or relied on PEAR. :)
There is indeed but I wanted it to be compatible with shared hosts.
I'm far from a PEAR user. They just happened to be on hand when I did the prelims.
Dygear
10th December 2006, 23:07
@filur
I like your code, and it does do alot, but I don't like how it seems to much like Java or C#. It also has issues in the areas such as no, and I do mean NO, support for the PHP4 people out there. So that pretty much makes it a goner. Other then that, really it's sweet.
@Anarchi-H
I would think in a more required files point of view, then an extras point of view. I'd like it if each file could be used by itself as a parser, or a fetcher, or even a helper.
Name:LFSWorldSDK.php
Type:Fetcher
This file simple makes contact with LFSWorld and get's the data from it, uncompressing the data if necessary. This file would also contain the prototypes for the parsers and throw a warning if that function (by the file not being there) is not available. I'd like to point out, that it's not meant to be used with out all of the files, but if the user should use it that way, then I must have something in place that will stop a program halt in that case.
Name:LFSDataConvert.php
Type:Helper
This is not a required file, but if you don't have it, it will not be able to convent things like 'BL1' or 'Blackwood GP' into '000', or 'BMW SAUBER' into 'BF1'.
Name:action_hl.php
Type:Paser
Name:action_pb.php
Type:Paser
Name:action_ch.php
Type:Paser
Name:action_wr.php
Type:Paser
Name:action_pst.php
Type:Paser
Name:action_hosts.php
Type:Paser
Name:action_teams.php
Type:Paser
Name:action_hl_log.php
Type:Paser
This is pretty much what I am thinking. No file is needed, but all files would help. I have four days I've given myself to program this, starting on my birthday (Dec 16th) but it should only take me two days. filur, it looks like I'm making the PHP4 version again. If you want to do the PHP5 (more OOP less panzyness) version in a concurrent manner along with me, that would be cool. If not that's fine.
filur
10th December 2006, 23:16
filur, it looks like I'm making the PHP4 version again. If you want to do the PHP5 (more OOP less panzyness) version in a concurrent manner along with me, that would be cool. If not that's fine.
Sure, i'll just go rewrite it like 8 more times. :)
Or maybe I should just fill the cvs with whatever i've got and actually try to finish it. :)
Edit: btw, i like the (your) new ideas.
Dygear
11th December 2006, 06:55
Sure, i'll just go rewrite it like 8 more times. :)
Or maybe I should just fill the cvs with whatever i've got and actually try to finish it. :)
Edit: btw, i like the (your) new ideas.
@filur
Yea, they are kinda stolen from yourself are'ent they.
@all
Now if only I had the sense to listen to him in the first place :).
Anarchi-H
11th December 2006, 12:31
Not quite sure I get what you mean, but if you are planning what I think you are planning, then it's very similar to PPF.
You could include just one of the providers and it would in turn require the base provider, but apart from that it could be used stand alone. I think that is what you are planning isn't it?
The only difference I see is that in PPF the fetcher resides in an inherited base provider class where as yours resides alone.
...unless you were going for the procedural approach and by 'requiring' the files they executed automatically. Still, similar approach, different implementation.
Dygear
13th December 2006, 07:52
You could include just one of the providers and it would in turn require the base provider, but apart from that it could be used stand alone. I think that is what you are planning isn't it?
Not quite, the 'providers' or parsers only require the string they need to parse, they are stand alone completely. The core of it could be used stand alone just to get data from LFS World, as it would handle all of the compression stuff, and just return the string. If you wanted to use one of the functions as part of the SDK the files need to be there in order for it to work, or it will raise an error and return a FALSE.
Jonas8431
13th December 2006, 14:29
Hi, so guys how does it (LFSWorldSDK) look like?, not in codes just in one of webpages or a pic. thanks
filur
13th December 2006, 17:34
Hi, so guys how does it (LFSWorldSDK) see?, not in codes just in one of webpages or a pic. thanks
If i'm not mistaken, you're asking for an example of what LFSWorldSDK looks like when used on a webpage? Simple answer is it doesn't look like anything at all. It works sort of like database communication functions, hopefully letting you grab the information you want and present it in the way you want to.
LFSWorldSDK creates no page output whatsoever, it only helps gather data so you can create the page yourself.
Dygear
19th December 2006, 20:51
Hi, so guys how does it (LFSWorldSDK) look like?, not in codes just in one of webpages or a pic. thanks
http://www.SimFIA.com/
MaKaKaZo
20th April 2007, 18:03
So, is there anything like an official last version of LFSWorldSDK? A friend of mine handed it to me, and googling for it I found a sourceforge site where the last versión i found was actually older to the one my friend gave me. Is there an official site for it? And what is the last version?
Thnx for this work, it really helps ;)
Dygear
24th April 2007, 05:33
So, is there anything like an official last version of LFSWorldSDK? A friend of mine handed it to me, and googling for it I found a sourceforge site where the last versión i found was actually older to the one my friend gave me. Is there an official site for it? And what is the last version?
Thnx for this work, it really helps ;)
http://lfsworldsdk.cvs.sourceforge.net/lfsworldsdk/lfsworldsdk/
Look at the 1.2 file, it's the most update to date one. (lfsworldsdk.php not the LFSWorldSDK.php)
Dygear
26th April 2007, 09:12
So ... what do ya guys think? Any info, bugs, or anything would be nice. Feedback, I need feedback!
the_angry_angel
26th April 2007, 09:36
Nothing of use. I do have a bug where by it will occasionally throw warnings about not enough bytes for unpack to run properly (yet it's clearly getting results), but I've not had the opportunity to find out why it's telling me that yet. I'm in the process of moving my server, so the script currently hasn't been running for the last few days.
Dygear
26th April 2007, 10:04
Nothing of use. I do have a bug where by it will occasionally throw warnings about not enough bytes for unpack to run properly (yet it's clearly getting results), but I've not had the opportunity to find out why it's telling me that yet. I'm in the process of moving my server, so the script currently hasn't been running for the last few days.
Funny, I could of swore I fixed that! You should be getting that in the hosts list. I'll double check that function.
... well I can't right now, we just got a 911 call ... I'll check it in an hour or so.
Dygear
26th April 2007, 13:29
Simple fix, change this:
a32hostname/a4tmlt/a4tcrm/icars/irules/claps/cqual/cspare1/cspare2/cnrofracers/a{$NumberOfRacersLen}racernames
to this:
a32hostname/A4tmlt/a4tcrm/icars/irules/claps/cqual/cspare1/cspare2/cnrofracers/a{$NumberOfRacersLen}racernames
Yeah, it turns out it throws a hissy fit more times with the lowercase a then with the uppercase A. *srugs*. One line fix.
Huh, tcrm wants an lower case a while tmlt wants an upper case A. Oh joy! This get's fun from time to time. :D
Dygear
26th April 2007, 13:58
Fix one of my fixes. Will update the cvs once I get out of work (Or I get out of school [about 12 hours from now]). But yeah, this is proof! I really do eat my own dog food.
Dygear
27th April 2007, 05:06
CVS updated to fix some of the more major errors:
Fixed Hosts Unpack Error.
Fixed Incorrect Amount of HL being returned (one two few).
Fixed Incorrect Amount of PB being returned (one two few).
Fixed Incorrect Amount of CH being returned (one two few).
Fixed Incorrect Amount of WR being returned (one two few).
Fixed Incorrect Amount of PST being returned (one two few).
Megin
28th June 2007, 08:07
Hello,
i don't know if i'm at the right place, but i ask u:
I want to make website for spliting racers into divisions by hotlaps from LFSWorld. I find Live for Speed Pubstats S2 v1.3 i can get chart of hotlaps for track and car.
But i don't know how to pick some racers and divide them to 2 or more divisions? I think that i have to use your php script, but i don't know how. Coud u give me some advices? Thank u very much for answers.
Edit: i read something about it and i know that i have to place on web LFSWorldSDK.php from post #1 and than i have to create another php file with that script what i want. Am i right?
Dygear
29th June 2007, 22:30
Download this one. (http://lfsworldsdk.cvs.sourceforge.net/*checkout*/lfsworldsdk/lfsworldsdk/lfsworldsdk.php). (Ver 1.5). If you need any more help just post here.
Megin
1st July 2007, 11:03
Download this one. (http://lfsworldsdk.cvs.sourceforge.net/*checkout*/lfsworldsdk/lfsworldsdk/lfsworldsdk.php?revision=1.3). (Ver 1.5). If you need any more help just post here.
Thanx a lot for that, i place it on my website and i tried it, but i have some problems... i write u PM, because in errors it shows my IDK.
St4Lk3R
1st July 2007, 19:46
Download this one. (http://lfsworldsdk.cvs.sourceforge.net/*checkout*/lfsworldsdk/lfsworldsdk/lfsworldsdk.php?revision=1.3). (Ver 1.5). If you need any more help just post here.
little hint... leave away the ?revision param, and it will afaik always display the HEAD revision. this could be useful for the first post especially.
Dygear
2nd July 2007, 00:30
Thanks for the tip St4Lk3R.
Megin
2nd July 2007, 08:23
I put your lfsworldsdk.php at another web: http://www.komora.sk/lfs/lfsworldsdk.php
Could u check it? I'm not sure if it works properly? I was thinking, that it pick up and show only hotlap from Dygear and filur, but it shows quite big list of... many parameters....
Dygear
2nd July 2007, 23:06
That's what your meant to see. That's an array filled with the information you requested. You can then use that to build your (web) application.
Megin
3rd July 2007, 07:55
Ok, i see.... i left in lfsworldsdk.php only this (from print part of script): print_r($SDK->get_ch(array('621'), array('XFR')));
http://www.komora.sk/lfs/lfsworldsdk.php
It print array with hotlaps from combo AS National Revision - XFR. I think that i need another php script to pick up certain racers from that list. :shrug: Could u please explain me, or better give me an expample how i pick up for example me: Megin and another one: Ondrejko from that list of hotlaps?That will be wery useful for me :nod:
filur
3rd July 2007, 20:28
require 'lfsworldsdk.php';
$SDK = new LFSWorldSDK('idkey goes here');
function some_function_name($SDK, $track, $car, $racers) {
$chart = $SDK->get_ch(array($track), array($car));
$ret = array();
foreach ($chart[$track][$car] as $key => $item) {
if (in_array($item['racername'], $racers)) {
$ret[] = $item;
$sort[] = $item['time'];
}
}
array_multisort($sort, SORT_ASC, $ret);
return $ret;
}
$drivers = array('Megin',
'Ondrejko',
'dime_miki',
'BenjiMC');
$table = some_function_name($SDK, 621, 'XFR', $drivers);
foreach ($table as $p => $driver)
echo ($p + 1), '. ', $driver['racername'], '<br />', PHP_EOL;
Dygear
4th July 2007, 06:00
Brings a tear to my eye filur.
Say it with me now "Heeessssssssssssssss baaaaaaaaaaaaaackkkkkkkkkkk!"
Megin
4th July 2007, 13:16
Thank u guys a lot :), it finaly works :thumb:.
Now i try modify that myself - add there time of drivers and divide them to division (when i pick up more drivers). So i hope it will be without big problems, if not.... i ask here, becouse PRO like U always know.... :nod:
Dygear
20th August 2007, 00:45
... amongst other HL info, how would i go about picking out peices so i can specify say:
$id = 1205
$track = 420
$car = BF1
$time = 104250
$flags_hlaps = 1614
I found an awesome function that will do what you asked. (Turn an array into tokens / variables that you can use.)
foreach($sdk->hl('Dygear') as $item)
extract($item, EXTR_OVERWRITE);
PaulC2K
20th August 2007, 21:43
I found an awesome function that will do what you asked. (Turn an array into tokens / variables that you can use.)
foreach($sdk->hl('Dygear') as $item)
extract($item, EXTR_OVERWRITE);
LOL
5th October 2006, 22:54 :razz: :thumb:
Cant say your not committed to answering any questions asked no matter how long ago they were asked!
Havent actually made use of the SDK for quite some time :(, did our teams update for xmas and never got round to updating the SDK powered scripts (though i still plan to) but that should come in handy when i figure out what it might have been that I needed to do what i was asking about :D
Cheers.
Dygear
21st August 2007, 06:14
I always fell bad when I don't have an answer to question, and I found that one line fix and that rocks.
MikeB
28th August 2007, 18:37
Hi Dygear,
i have a problem with the SDK :)
Please check the following code:
<?php
require_once("scripts/LFSWorldSDK.php5");
$id_key = "<my key>";
$use_premium = FALSE;
$SDK = new LFSWorldSDK($id_key, $use_premium);
// Test "Lord Of Death"
print_r($SDK->get_pb('Lord Of Death'));
?>
I always get an empty array. But if you check lfsworld (http://www.lfsworld.net/?win=stats&racer=Lord%20Of%20Death)you see he has quite some pbs stored.
Any idea?
(I am using version 1.5)
EDIT: As some motivation for you :) :
Yesterday i launched my TeamStats page in the german lfs forum with great feedback. I am using lfsworldSDK as the backend to retrieve the stats of the drivers and store it with MySQL. Check it out here: http://teamstats.m-bauer.org. If all goes well i will also announce it "officially" here in the forum. But i want to clear most bugs before :)
Thank you :)
bdshan
28th August 2007, 19:41
I didn't check the LFSWorldSDK, but you may want to check if the get_pb function does a urlencode on the racer value. Since Lord of Death contains spaces you need to urlencode it.
MikeB
28th August 2007, 19:56
I didn't check the LFSWorldSDK, but you may want to check if the get_pb function does a urlencode on the racer value. Since Lord of Death contains spaces you need to urlencode it.
DOH, sometimes it is so easy :) But to correct you, it only works with "rawurlencode()" (where spaces are converted to "%20" instead of "+").
Thanks very much!
Dygear
29th August 2007, 03:52
Yeah, I'll consider urlencodeing the racer name in the next version.
(Although, I would not call the base compleat, it's done.)
Thanks to bdshan for the help, with the help.
Bismarck
29th August 2007, 19:56
Hi Dygear,
dont know whether it was mentioned before, but in function get_pst() you use 2 times $result['online'] . I think it should be one times for $result['online_status] and one times for $result['online_credits].
So in the next version you can change it. :thumb:
Dygear
29th August 2007, 22:36
My, I messed up that one quite well. Yeah, I did not even notice that one.
Megin
20th September 2007, 08:42
Hello, i'm back with another problem. this is example:
<?php
require 'lfsworldsdk.php';
$SDK = new LFSWorldSDK('idkey goes here');
function some_function_name($SDK, $track, $car, $racers) {
$chart = $SDK->get_ch(array($track), array($car));
$ret = array();
foreach ($chart[$track][$car] as $key => $item) {
if (in_array($item['racername'], $racers)) {
$ret[] = $item;
$sort[] = $item['time'];
}
}
array_multisort($sort, SORT_ASC, $ret);
return $ret;
}
$drivers = array('Megin',
'BIGMAN',
'eraser_svk'
);
$table = some_function_name($SDK, '000', 'RB4', $drivers);
foreach ($table as $p => $driver)
echo ($p + 1), '. ', $driver['racername'], '<br />', PHP_EOL;
?>
it make order by hotlaps, on BL1 with RB4 but i don't know how i can add for drivers specific car (TBO class)
Megin - FXO
BIGMAN - RB4
eraser_svk - RB4
and make order with this specific combos :shrug:
Could u correct this example? Thanx a lot
bdshan
20th September 2007, 11:48
How about altering the driver array to be an associative array
$drivers = array('Megin'=>'FXO',
'BIGMAN'=>'RB4',
'eraser_svk'=>'RB4'
);
Then in your function use the array keys for the driver and the value as the car.
function some_function_name($SDK, $track, $racers)
Just a quick thought off the top of my head.
Megin
20th September 2007, 16:05
I try something like that but it didn't work, some modifing of my example will be useful
Dygear
28th September 2007, 13:51
Your on the right path grasshopper. I cleaned up your code, but made not changes.
<?php
require_once('lfsworldsdk.php');
$SDK = new LFSWorldSDK('idkey goes here');
function some_function_name($track, $car, $racers) {
global $SDK;
$chart = $SDK->get_ch($track, $car);
$ret = array();
foreach ($chart[$track][$car] as $key => $item) {
if (in_array($item['racername'], $racers)) {
$ret[] = $item;
$sort[] = $item['time'];
}
}
array_multisort($sort, SORT_ASC, $ret);
return $ret;
}
$drivers = array(
'Megin',
'BIGMAN',
'eraser_svk'
);
$table = some_function_name($SDK, '000', 'RB4', $drivers);
foreach ($table as $p => $driver) {
echo ($p + 1), '. ', $driver['racername'], '<br />', PHP_EOL;
}
?>
Megin
4th October 2007, 11:15
So, i have this:
<?php
require 'lfsworldsdk.php';
$SDK = new LFSWorldSDK('idkey goes here');
function triedicka($SDK, $track, $car, $racers) {
$chart = $SDK->get_ch(array($track), array($car));
$ret = array();
foreach ($chart[$track][$car] as $key => $item) {
if (in_array($item['racername'], $racers)) {
$ret[] = $item;
$sort[] = $item['time'];
}
}
array_multisort($sort, SORT_ASC, $ret);
return $ret;
}
$driversfxo = array(
'Atti Honyi (SK)',
'Megin'
);
$table1 = triedicka($SDK, '000', 'FXO', $driversfxo);
$driversrb4 = array(
'Sisolak',
'eraser_svk'
);
sleep(5);
$table2 = triedicka($SDK, '000', 'RB4', $driversrb4);
$driversxrt = array(
'Ghost_CZ',
'BIGMAN'
);
sleep(5);
$table3 = triedicka($SDK, '000', 'XRT', $driversxrt);
$all = array_merge($table1, $table2, $table3);
//--------------- how sort $all ?
echo "<BR>FXO:<br/>";
foreach ($table1 as $p1 => $driver1) {
echo ($p + 1), '. ', $driver1['racername'],' - ', $driver1['time'], '<br/>', PHP_EOL;
}
echo "<BR>RB4:<br/>";
foreach ($table2 as $p2 => $driver2) {
echo ($p + 1), '. ', $driver2['racername'],' - ', $driver2['time'], '<br/>', PHP_EOL;
}
echo "<BR>XRT:<br/>";
foreach ($table3 as $p3 => $driver3) {
echo ($p + 1), '. ', $driver3['racername'],' - ', $driver3['time'], '<br/>', PHP_EOL;
}
echo "<BR>ALL:<br/>";
foreach ($all as $p => $driver) {
echo ($p + 1), '. ', $driver['racername'],' - ', $driver['time'], '<br/>', PHP_EOL;
}
?>
U can see that $all is undorted. ($all is join array of arrays of drivers with xrt, rb4 and xrt) How to sort $all? Probably i have to create new function like function tiedicka. I try it but failed :-(
Dygear: sorry but your cleaned code in sort function din't work as well :-(
filur
4th October 2007, 13:16
Try this.
require 'lfsworldsdk.php';
$SDK = new LFSWorldSDK('idkey goes here');
function some_function_name($SDK, $racers) {
static $charts = array();
$ret = $sort = array();
foreach ($racers as $racername => $combo) {
$c = &$charts[$combo['track']][$combo['car']];
if (FALSE == isset($c)) {
sleep(5);
$c = $SDK->get_ch(array($combo['track']), array($combo['car']));
}
foreach ($c[$combo['track']][$combo['car']] as $key => $item) {
if ($item['racername'] == $racername) {
$ret[] = array_merge($item, $combo);
$sort[] = $item['time'];
}
}
}
array_multisort($sort, SORT_ASC, $ret);
return $ret;
}
function disptime($t) {
return date('i:s', ((int) $t / 1000)) . '.' . $t % 1000;
}
$drivers = array
(
'Atti Honyi (SK)' => array('track' => '000', 'car' => 'FXO'),
'Megin' => array('track' => '000', 'car' => 'FXO'),
'Sisolak' => array('track' => '000', 'car' => 'RB4'),
'eraser_svk' => array('track' => '000', 'car' => 'RB4'),
'Ghost_CZ' => array('track' => '000', 'car' => 'XRT'),
'BIGMAN' => array('track' => '000', 'car' => 'XRT')
);
$table = some_function_name($SDK, $drivers);
foreach ($table as $p => $driver)
echo ($p + 1), '. ', $driver['racername'], ' ', $driver['car'], ' ', disptime($driver['time']), '<br />', PHP_EOL;
Megin
5th October 2007, 11:42
That's the solution of my problem! Great. Works excelent. Thanx a lot. :thumb:
Dygear
27th October 2007, 10:28
And here is One Point Six, 1.6 with a new feature and a long awaited bug fix.
Notes:
* New Function, get_progress($host).
* Return Value Change in get_pst($racer).
* Online Bug Fixed, Only Returns One Online.
* First Online now Called Credits.
* Second Online, the online status, remains as Online.
<?php
$SDK = new LFSWorldSDK('idk', true);
/*
** Live For Speed World SDK, easily find what you need from the World of Live For Speed.
**
** @package LFSWorldSDK
** @since 2007-10-27 06:30
** @author Mark 'Dygear' Tomlin
** @coauthor Mikael 'filur' Forsberg
** @license MIT License (http://opensource.org/licenses/mit-license.php)
** @copyright Copyright (C) 2006, Mark 'Dygear' Tomlin & Mikael 'filur' Forsberg.
** @version 1.6
*/
class LFSWorldSDK {
function LFSWorldSDK($idk, $ps = false) {
$this->ps = $ps;
$this->idk = $idk;
$this->version = 1.3;
}
function make_query($qryStr, $file = 'get_stat2.php') {
return file_get_contents("http://www.lfsworld.net/pubstat/{$file}?version={$this->version}&idk={$this->idk}&ps={$this->ps}{$qryStr}");
}
function get_hl($racer) {
if (is_array($racer)) {
foreach($racer as $uname) {
$result[$uname] = $this->get_hl($uname);
}
} else {
foreach (explode("\n", $this->make_query("&action=hl&racer={$racer}")) as $line => $data) {
list($result[$line]['id_hl'], $result[$line]['track'], $result[$line]['car'], $result[$line]['split1'], $result[$line]['split2'], $result[$line]['split3'], $result[$line]['time'], $result[$line]['flags_hlaps']) = split(' ', $data, 8);
}
unset($result[$line]);
}
return $result;
}
function get_pb($racer) {
if (is_array($racer)) {
foreach($racer as $uname) {
$result[$uname] = $this->get_pb($uname);
}
} else {
foreach (explode("\n", $this->make_query("&action=pb&racer={$racer}")) as $line => $data) {
list($result[$line]['track'], $result[$line]['car'], $result[$line]['time'], $result[$line]['lapcount']) = split(' ', $data, 4);
}
unset($result[$line]);
}
return $result;
}
function get_ch($track, $car, $control = null) {
if (is_array($track) || is_array($car)) {
if (is_array($track) && is_array($car)) {
foreach($track as $tname) {
foreach ($car as $cname) {
$result[$tname][$cname] = $this->get_ch($tname, $cname, $control);
}
}
} else if (is_array($track)) {
foreach($track as $tname) {
$result[$tname] = $this->get_ch($tname, $cname, $control);
}
} else if (is_array($car)) {
foreach ($car as $cname) {
$result[$cname] = $this->get_ch($tname, $cname, $control);
}
}
} else {
foreach (explode("\n", $this->make_query("&action=ch&track={$track}&car={$car}&control={$control}")) as $line => $data) {
list($result[$line]['split1'], $result[$line]['split2'], $result[$line]['split3'], $result[$line]['time'], $result[$line]['flags_hlaps'], $result[$line]['racername']) = split(' ', $data, 6);
}
unset($result[$line]);
}
return $result;
}
function get_wr() {
foreach (explode("\n", $this->make_query("&action=wr")) as $line => $data) {
list($result[$line]['id_wr'], $result[$line]['track'], $result[$line]['car'], $result[$line]['split1'], $result[$line]['split2'], $result[$line]['split3'], $result[$line]['time'], $result[$line]['flags_hlaps'], $result[$line]['racername']) = split(' ', $data, 9);
}
unset($result[$line]);
return $result;
}
function get_pst($racer) {
if (is_array($racer)) {
foreach($racer as $uname) {
$result[$uname] = $this->get_pst($uname);
}
} else {
list($result['distance'], $result['fuel'], $result['laps'], $result['hosts'], $result['wins'], $result['second'], $result['third'], $result['finished'], $result['quals'], $result['pole'], $result['credits'], $result['drags'], $result['drag'], $result['status'], $result['hostname'], $result['time'], $result['track'], $result['car']) = explode("\n", $this->make_query("&action=pst&racer={$racer}"));
}
return $result;
}
function get_hosts() {
$string = $this->make_query("&action=hosts");
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$NumberOfRacers = @unpack("c", substr($string, $pointer + 52, 1));
$NumberOfRacers = $NumberOfRacers[1];
$NumberOfRacersLen = $NumberOfRacers * 24;
$PointerPast = $NumberOfRacersLen + 53;
$result[$i] = array();
if (($result[$i] = @unpack("a32hostname/A4tmlt/a4tcrm/icars/irules/claps/cqual/cspare1/cspare2/cnrofracers/a{$NumberOfRacersLen}racernames", substr($string, $pointer, $PointerPast)))) {
$result[$i]['racernames'] = preg_split("/\\0/", $result[$i]['racernames'], -1, PREG_SPLIT_NO_EMPTY);
$result[$i]['tmlt'] = unpack("ctype/cmain/a1letter/ctestId", $result[$i]['tmlt']);
$result[$i]['tcrm'] = unpack("ctrack/cconfig/creversed/cmax", $result[$i]['tcrm']);
}
else
unset($result[$i]);
$pointer += $PointerPast;
}
return $result;
}
function get_progress($host) {
$string = $this->make_query("&host={$host}", 'hostprogress.php');
list($null, $string) = explode("\n", $string);
return json_decode($string, true);
}
function get_teams() {
$string = $this->make_query("&action=teams");
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$infoLen = @unpack("S", substr($string, $pointer + 298, 2));
$infoLen = $infoLen[1];
$nrMembers = @unpack("S", substr($string, $pointer + 300 + $infoLen, 2));
$nrMembers = $nrMembers[1] * 24;
$PointerPast = 302 + $infoLen + $nrMembers;
$result[$i] = array();
if (($result[$i] = @unpack("a128team/a6tag/a32country/a128url/Ibits/Sinfo_len/a{$infoLen}info/Snr_members/a{$nrMembers}members", substr($string, $pointer, $PointerPast)))) {
$result[$i]['members'] = preg_split("/\\0/", $result[$i]['members'], -1, PREG_SPLIT_NO_EMPTY);
$result[$i]['info'] = urldecode($result[$i]['info']);
}
else
unset($result[$i]);
$pointer += $PointerPast;
}
return $result;
}
function get_hl_log($log_filter = 4, $lines = 150, $control = null, $starttime = 0) {
$string = $this->make_query("&action=hl_log&log_filter={$log_filter}&lines={$lines}&control={$control}&starttime={$starttime}&format=3");
for ($pointer = 0, $i = 0; $pointer <= strlen($string); $i++) {
$result[$i] = array();
if (($result[$i] = @unpack("itime/a24racer/a32country/A4tcrc/i4split/Spos/Sflags/iid_hl", substr($string, $pointer, 88))))
$result[$i]['tcrc'] = unpack("ctrack/cconfig/creversed/ccar", $result[$i]['tcrc']);
else
unset($result[$i]);
$pointer += 88;
}
return $result;
}
}
$LFS_Tracks = array(
'BL1' => array('Blackwood', 'GP Track', 2.1, 'Standard', '000'),
'BL1R' => array('Blackwood', 'GP Track', 2.1, 'Reversed', '001'),
'BL2' => array('Blackwood', 'Rally Cross', 1.2, 'Standard', '010'),
'BL2R' => array('Blackwood', 'Rally Cross', 1.2, 'Reversed', '011'),
'BL3' => array('Blackwood', 'Car Park', 0.2, 'Arena', '020'),
'SO1' => array('South City', 'Classic', 1.3, 'Standard', '100'),
'SO1R' => array('South City', 'Classic', 1.3, 'Reversed', '101'),
'SO2' => array('South City', 'Sprint Track 1', 1.3, 'Standard', '110'),
'SO2R' => array('South City', 'Sprint Track 1', 1.3, 'Reversed', '111'),
'SO3' => array('South City', 'Sprint Track 2', 0.8, 'Standard', '120'),
'SO3R' => array('South City', 'Sprint Track 2', 0.8, 'Reversed', '121'),
'SO4' => array('South City', 'Long', 2.5, 'Standard', '130'),
'SO4R' => array('South City', 'Long', 2.5, 'Reversed', '131'),
'SO5' => array('South City', 'Town Course ', 2.0, 'Standard', '140'),
'SO5R' => array('South City', 'Town Course', 2.0, 'Reversed', '141'),
'FE1' => array('Fern Bay', 'Club', 1.0, 'Standard', '200'),
'FE1R' => array('Fern Bay', 'Club', 1.0, 'Reversed', '201'),
'FE2' => array('Fern Bay', 'Green Track', 1.9, 'Standard', '210'),
'FE2R' => array('Fern Bay', 'Green Track', 1.9, 'Reversed', '211'),
'FE3' => array('Fern Bay', 'Gold Track', 2.2, 'Standard', '220'),
'FE3R' => array('Fern Bay', 'Gold Track', 2.2, 'Reversed', '221'),
'FE4' => array('Fern Bay', 'Black Track', 4.1, 'Standard', '230'),
'FE4R' => array('Fern Bay', 'Black Track', 4.1, 'Reversed', '231'),
'FE5' => array('Fern Bay', 'Rally Cross', 1.3, 'Standard', '240'),
'FE5R' => array('Fern Bay', 'Rally Cross', 1.3, 'Reversed', '241'),
'FE6' => array('Fern Bay', 'RallyX Green', 0.5, 'Standard', '250'),
'FE6R' => array('Fern Bay', 'RallyX Green', 0.5, 'Reversed', '251'),
'AU1' => array('Autocross', 'Autocross', 0.3, 'Arena', '300'),
'AU2' => array('Autocross', 'Slod Pad', 0.1, 'Arena', '310'),
'AU3' => array('Autocross', 'Drag Strip', 0.7, 'Single Stage', '320'),
'AU4' => array('Autocross', '8 Lane Drag', 0.7, 'Single Stage', '330'),
'KY1' => array('Kyoto Ring', 'Oval', 1.9, 'Standard', '400'),
'KY1R' => array('Kyoto Ring', 'Oval', 1.9, 'Reversed', '401'),
'KY2' => array('Kyoto Ring', 'National', 3.2, 'Standard', '410'),
'KY2R' => array('Kyoto Ring', 'National', 3.2, 'Reversed', '411'),
'KY3' => array('Kyoto Ring', 'GP Long', 4.6, 'Standard', '420'),
'KY3R' => array('Kyoto Ring', 'GP Long', 4.6, 'Reversed', '421'),
'WE1' => array('Westhill', 'International', 3.2, 'Standard', '500'),
'WE1R' => array('Westhill', 'International', 3.2, 'Reversed', '501'),
'AS1' => array('Aston', 'Cadet', 1.2, 'Standard', '600'),
'AS1R' => array('Aston', 'Cadet', 1.2, 'Reversed', '601'),
'AS2' => array('Aston', 'Club', 1.9, 'Standard', '610'),
'AS2R' => array('Aston', 'Club', 1.9, 'Reversed', '611'),
'AS3' => array('Aston', 'National', 3.5, 'Standard', '620'),
'AS3R' => array('Aston', 'National', 3.5, 'Reversed', '621'),
'AS4' => array('Aston', 'Historic', 5.0, 'Standard', '630'),
'AS4R' => array('Aston', 'Historic', 5.0, 'Reversed', '631'),
'AS5' => array('Aston', 'Grand Prix', 5.5, 'Standard', '640'),
'AS5R' => array('Aston', 'Grand Prix', 5.5, 'Reversed', '641'),
'AS6' => array('Aston', 'Grand Touring', 5.0, 'Standard', '650'),
'AS6R' => array('Aston', 'Grand Touring', 5.0, 'Reversed', '651'),
'AS7' => array('Aston', 'North', 3.2, 'Standard', '660'),
'AS7R' => array('Aston', 'North', 3.2, 'Reversed', '661'),
'000' => 'BL1',
'001' => 'BL1R',
'010' => 'BL2',
'011' => 'BL2R',
'020' => 'BL3',
'100' => 'SO1',
'101' => 'SO1R',
'110' => 'SO2',
'111' => 'SO2R',
'120' => 'SO3',
'121' => 'SO3R',
'130' => 'SO4',
'131' => 'SO4R',
'140' => 'SO5',
'141' => 'SO5R',
'200' => 'FE1',
'201' => 'FE1R',
'210' => 'FE2',
'211' => 'FE2R',
'220' => 'FE3',
'221' => 'FE3R',
'230' => 'FE4',
'231' => 'FE4R',
'240' => 'FE5',
'241' => 'FE5R',
'250' => 'FE6',
'251' => 'FE6R',
'300' => 'AU1',
'310' => 'AU2',
'320' => 'AU3',
'330' => 'AU4',
'400' => 'KY1',
'401' => 'KY1R',
'410' => 'KY2',
'411' => 'KY2R',
'420' => 'KY3',
'421' => 'KY3R',
'500' => 'WE1',
'501' => 'WE1R',
'600' => 'AS1',
'601' => 'AS1R',
'610' => 'AS2',
'611' => 'AS2R',
'620' => 'AS3',
'621' => 'AS3R',
'630' => 'AS4',
'631' => 'AS4R',
'640' => 'AS5',
'641' => 'AS5R',
'650' => 'AS6',
'651' => 'AS6R',
'660' => 'AS7',
'661' => 'AS7R'
);
$LFS_Cars = array(
'UF1' => 'UF 1000',
'XFG' => 'XF GTI',
'XRG' => 'XR GT',
'LX4' => 'LX4',
'RB4' => 'RB4 GT',
'FXO' => 'FXO TURBO',
'XRT' => 'XR GT TURBO',
'LX6' => 'LX6',
'RAC' => 'RA',
'FZ5' => 'FZ50',
'UFR' => 'UF GTR',
'XFR' => 'XF GTR',
'MRT' => 'MTR5',
'FOX' => 'FORMULA XR',
'FO8' => 'FORMULA V8',
'BF1' => 'BMW SAUBER',
'FXR' => 'FXO GTR',
'XRR' => 'XR GTR',
'FZR' => 'FZ50 GTR',
// Classes
'ALL' => 'All Cars Allowed',
'STD' => 'UF1,XFG,XRG',
'TBO' => 'UF1,XFG,XRG,LX4,RB4,FXO,XRT',
'LRF' => 'UF1,XFG,XRG,LX4,RB4,FXO,XRT,LX6,RAC,FZ5',
'FWD' => 'UF1,XFG,FXO,UFR,XFR',
'GTR' => 'FXR,XRR,FXR',
'S-S' => 'MRT,FOX,FO8,BF1'
);
?>
Dygear
4th November 2007, 02:16
Has anyone had the chance to use this yet? Any issues you would like to report, anything you would like added, anything you would like improved? I would like to say that I will at some point implement the compression that LFSWorld offers, me thinks that will happen in the next build. You can expect the next build in around a weeks time, I'm going to take some time off the project.
OldBloke
4th November 2007, 10:07
FYI re 1.6
Your sig point to the first post which (for me) points to the download of 1.5 :shrug:
Dygear
7th November 2007, 03:41
Fair point, that is now fixed.
Victor
8th November 2007, 05:22
dygear - i mailed you a SDK version with compression earlier this week. Did you receive that mail?
Dygear
9th November 2007, 20:37
Dude, that's awesome, I'm stoked! Thanks for the help. I see the changes, and I'll commit all of the changes later today. (Along with the changes I made in the last version to keep up with continuity.
Dygear
12th November 2007, 08:09
As I don't want to keep this update away from anyone for any longer, and I need to get in contact with the guys at SourceForge to upload the new versions. I'll just update the new version here.
Changes:
New: Compression used when available. (Thanks Victor)
Cng: $LFS_Tracks changed, made $LFSW_Tracks.
Cng: $LFS_Cars changed, made $LFS_Car_Classes.
<?php
$SDK = new LFSWorldSDK('idk', true);
/*
** Live For Speed World SDK, easily find what you need from the World of Live For Speed.
**
** @package LFSWorldSDK
** @since 2007-10-27 06:30
** @author Mark 'Dygear' Tomlin
** @coauthor Mikael 'filur' Forsberg
** @coauthor Victor van Vlaardingen.
** @license MIT License (http://opensource.org/licenses/mit-license.php)
** @copyright Copyright (C) 2006, Mark 'Dygear' Tomlin, Mikael 'filur' Forsberg & Victor van Vlaardingen.
** @version 1.7
*/
class LFSWorldSDK {
function LFSWorldSDK($idk, $ps = false) {
$this->ps = $ps;
$this->idk = $idk;
$this->version = 1.3;
$this->compression = (function_exists ('gzinflate')) ? 3 : 0;
}
function make_query($qryStr, $file = 'get_stat2.php') {
return $this->res_preproc (file_get_contents("http://www.lfsworld.net/pubstat/{$file}?version={$this->version}&idk={$this->idk}&ps={$this->ps}{$qryStr}&c={$this->compression}"));
}
function res_preproc ($data) {
return ($