PHP5 - Simple MPR parser
Hi all!

It's simple, this script allow to you to read the MPR files and extract the headers and the results of the race (if someone finish the race)

This is a frustrating try to read all the race. All I obtain was the documented info at www.lfs.net/?page=MPR .... and all the car/head skins used by the participants... but It isn't implemented. As I've said... I finished frustrated

You can use my script with something like this:


<?php 

require_once('phpmpr.php');

// parse the file
$o = new PHPMPR('some-mpr-file.mpr');

// see the content
var_dump($o);

?>

The $o object has two principal properties: $o->headers with all the header info, and $o->players with an array with all the results.

See the code and the dump for more info Demo: http://mch.lfsteam.es/forum/mpr.php

P.D.: Sorry for my english... I know PHP, not english



Edit1: updated file to avoid a file requirement
Attached files
phpmpr.rar - 1.6 KB - 439 views
works great. Thanks. Gracias.
I parsed an mpr with the script and most values are right just the output for best laptime and racetime is always strange. I know all the times are in milliseconds, but sometimes i recieve negative numbers. And it's not just a single replay which doesnt work well. Here's an example (not formatted just the default output):


<?php 
["Dominic123"]=>
  
object(PHPMPR_Player)#10 (15) {
    
["pname"]=>
    
string(13"07 - D. Klein"
    
["numplate"]=>
    
string(6"Bla <3"
    
["scarname"]=>
    
string(3"FZR"
    
["lfsuname"]=>
    
string(10"Dominic123"
    
["laps"]=>
    
int(6144)
    [
"pflags"]=>
    
int(290)
    [
"cflags"]=>
    
int(2)
    [
"pits"]=>
    
int(1)
    [
"penalsecs"]=>
    
int(0)
    [
"racetime"]=>
    
int(1780820480)
    [
"bestlaptime"]=>
    
int(-1766653696)
    [
"zero"]=>
    
int(0)
    [
"startpos"]=>
    
int(16)
    [
"handicapmass"]=>
    
int(10)
    [
"intakeres"]=>
    
int(15)
  }
?>

Does someone know a solution or an idea what's the source of this problem?
I'll have to check my replay parsing code, but I think those negative numbers come from an incorrect parameter while unpacking.

Yup, I use "i" instead of "I" to unpack the int.
So it has to be like this?
i1racetime/i1bestlaptime

Edit: Doesn't work aswell :/
That looks right.
Same result unfortunately
It took a re-read of the MPR format, but I think your issue is because the size of the int is 4 bytes not 1.

try:
i4racetime/i4bestlaptime

actually i (or I) don't require a size-value (nor are they supported, if I'm not wrong).

My guess is: Your machine does not(!) interpret i as an 32bit integer (4byte), as the parameter i (or I) is machine-depentent in it's size.

I'd recommend the use of "L" instead, as this one is always 32bit ... or "l" for a signed integer which is useless here of course


edit:
btw: "i" is for signed integers, so use of "I" was - out of those two - the right choice
In that case how do you account for the different sizes of integers in the MPR format?

Quote :
TYPES :
=======

char : 1-byte ascii character
byte : 1-byte integer
word : 2-byte integer
int : 4-byte integer, lowest byte first


Here "integer" standy for exactly that: an integer value, in difference to a floating number. There is no direct correspondence with what "character-type" the pack (or unpack) function assumes.

Actually, you would like to use:
char: a
byte: C (c for signed ones)
word: S (s for signed ones)
int: L (l for signed ones)
Quote from bdshan :It took a re-read of the MPR format, but I think your issue is because the size of the int is 4 bytes not 1.

try:
i4racetime/i4bestlaptime


But if i paste this code there's an error message becuase the sum of all bytes isn't 80 bytes, what it should be.
Quote from Dominic123 :But if i paste this code there's an error message becuase the sum of all bytes isn't 80 bytes, what it should be.

That's because i4 = 4 integers = 16 bytes, you only need one int per value.
A byte is unsigned (as opposed to char, which is signed), as is a word (as opposed to short, which is signed) and while an int is usually signed, I really don't think it's meant to be in this case since you can't really achieve a negative laptime, so let's assume that was meant to be unsigned.

Use C for the byte, that's an unsigned 8bit integer.
Use v for the word, that's an unsigned 16bit integer guaranteed to be little-endian.
Use V for the int, that's an unsigned 32bit integer guaranteed to be little-endian.
put it back to 1, then post the mpr and describe which values are incorrect.
Ok, so here's my problem. I uploaded any replay, and parsed it, thats the array dump for a driver (Me in that case :P):

<?php 
array(7) {
  [
"Dominic123"]=>
  
object(PHPMPR_Player)#3 (15) {
    
["pname"]=>
    
string(10"per.Domi K"
    
["numplate"]=>
    
string(0""
    
["scarname"]=>
    
string(3"FZR"
    
["lfsuname"]=>
    
string(10"Dominic123"
    
["laps"]=>
    
int(1536)
    [
"pflags"]=>
    
int(290)
    [
"cflags"]=>
    
int(2)
    [
"pits"]=>
    
int(1)
    [
"penalsecs"]=>
    
int(0)
    [
"racetime"]=>
    
int(-1932654336// Negative Number
    
["bestlaptime"]=>
    
int(1854931200// Way too high
    
["zero"]=>
    
int(0)
    [
"startpos"]=>
    
int(4)
    [
"handicapmass"]=>
    
int(0)
    [
"intakeres"]=>
    
int(0)
  }
?>

As you can see these two values i mentioned before are incorrect.
Attached files
as3_public_top4.mpr - 1.7 MB - 344 views
I ran your replay thru the parser, and the output is correct, at least on my machine.


<?php 
array(7) { 
[
"Dominic123"]=> object(PHPMPR_Player)#3 (15) {
["pname"]=> string(10"per.Domi K" 
["numplate"]=> string(0"" 
["scarname"]=> string(3"FZR" 
["lfsuname"]=> string(10"Dominic123" 
["laps"]=> int(6
[
"pflags"]=> int(8705
[
"cflags"]=> int(2
[
"pits"]=> int(1
[
"penalsecs"]=> int(0
[
"racetime"]=> int(642700
[
"bestlaptime"]=> int(102510
[
"zero"]=> int(0
[
"startpos"]=> int(4
[
"handicapmass"]=> int(0
[
"intakeres"]=> int(0) }
?>

I also ran it thru my parser and got the same results. Must be something on your side.
Follow my suggestion, enforce little-endian :rolleyes:
I'm afraid not only those are wrong, but laps too (and i assume even pflags ...)

Here's my own readout of the replay:
[1] => Array
(
[nick] => per.Domi K
[numberplate] =>
[car] => FZR
[lfsw] => Dominic123
[lapsdone] => 6
[flags] => 8705
[confirm] => 2
[numstops] => 1
[penalty] => 0
[totaltime] => 642700
[bestlap] => 102510
[null] => 0
[startpos] => 4
[handicap] => 0
[restrictor] => 0
)

flags is your pflags ... my values result in: CustomView, AutoClutch, LeftHand and Wheel ...

done with this unpack:

<?php 
unpack
("@0/a24nick/a8numberplate/a4car/a24lfsw/Slapsdone/Sflags/Cconfirm/Cnumstops/Spenalty/Ltotaltime/Lbestlap/Cnull/Cstartpos/Chandicap/Crestrictor",$string);
?>

Edit:
1: too slow
2: just doublechecked: little-endian enforcment is the key ... so do what morpha said ... you seem to have a "big-endian-machine"
Byte order for the lose.
Just tested it on an other server - and it works perfect so thanks for the advice and for trying it on your machines

@avetere: laps and flags may be wrong, too but i didn't notice it, cause i didn't care about them :P

@morpha: how can i enforce it?
Quote from Dominic123 :
@avetere: laps and flags may be wrong, too but i didn't notice it, cause i didn't care about them :P

@morpha: how can i enforce it?

The error there is the same: byte order ...

to enforce it, use "V" (upper case) instead of "i" or "I" ... and for those 2-byte things (words: laps, pflags, penalties) use "v" (lower case)
Quote from avetere :The error there is the same: byte order ...

to enforce it, use "V" (upper case) instead of "i" or "I" ... and for those 2-byte things (words: laps, pflags, penalties) use "v" (lower case)

Nicely done sir!
Am I getting completely ignored here? I wrote that a couple of posts up
Or is it a forum bug and my post simply doesn't show? Cause that's what it feels like
Quote from morpha :I wrote that a couple of posts up

Yeah, he didn't seem to realize that ...
Quote from avetere :Yeah, he didn't seem to realize that ...

Well it's not that I care much, but with the forum bugs increasing rapidly lately (incorrect UIDs, polls getting mixed up, thread ratings breaking, ...) I just wondered if there might be a more serious issue
1

FGED GREDG RDFGDR GSFDG