The JSON deserializer works really well actually. I've written a little LFSWorld object that can handle doing the queries for you and returns a decoded JSON object.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;
namespace LfsWorldExample
{
public class LfsWorld
{
private string _identKey;
public LfsWorld(string identKey)
{
_identKey = identKey;
}
public Uri CreatePubStatUrl(object args)
{
var url = new StringBuilder();
url.AppendFormat(
"http://www.lfsworld.net/pubstat/get_stat2.php?version=1.4&idk={0}&s=1",
_identKey);
foreach (var property in args.GetType().GetProperties())
{
url.AppendFormat(
"&{0}={1}",
property.Name,
property.GetValue(args, null));
}
return new Uri(url.ToString());
}
public Stream GetResponse(Uri url)
{
var request = WebRequest.Create(url);
var response = request.GetResponse();
return response.GetResponseStream();
}
public T GetJsonResponse<T>(Uri url)
{
using (var stream = GetResponse(url))
{
var json = new DataContractJsonSerializer(typeof(T));
return (T)json.ReadObject(stream);
}
}
public IQueryable<T> Query<T>(object args)
{
var url = CreatePubStatUrl(args);
return GetJsonResponse<List<T>>(url).AsQueryable();
}
}
}
To use it you first of all need to create a data-contract for the JSON results you want to deserialize, which at its simplest is basically just an object with each property named after the corresponding JSON field in the pubstat response.
Here is a very simple data-contract for the host list.
[DataContract]
public class Host
{
[DataMember]
public string hostname;
[DataMember]
public string tmlt;
[DataMember]
public string tcrm;
[DataMember]
public int cars;
[DataMember]
public int rules;
[DataMember]
public int laps;
[DataMember]
public int qualmins;
[DataMember]
public string country;
[DataMember]
public int nrracers;
[DataMember]
public List<string> racers; // It supports lists
}
Then you can create simple queries to request the list of hosts like this.
var lfs = new LfsWorld("<your ident key>");
var hosts = lfs.Query<Host>(new
{
action = "hosts",
});
The query is returned as a type of IQueryable, so you can perform LINQ operations on it. For instance if you wanted to get a list of only the populated hosts (hosts with one or more drivers) you could do a simple query like this.
var lfs = new LfsWorld("<your ident key>");
var hosts = lfs.Query<Host>(new
{
action = "hosts",
});
var populatedHosts = from h in hosts
where h.nrracers > 0
orderby h.nrracers descending
select h;
foreach (var host in populatedHosts)
{
Console.WriteLine(host.hostname);
}
You can pass multiple arguments into the query method, so to request a list of a players personal bests you could do this:
var lfs = new LfsWorld("<your ident key">);
var pbs = lfs.Query<PersonalBest>(new
{
action = "pb",
racer = "DarkTimes",
});
foreach (var pb in pbs)
{
// etc..
}
Or to request the hotlaps for a specific car and track.
var lfs = new LfsWorld("<your ident key>");
var hotlaps = lfs.Query<HotLap>(new
{
action = "ch",
track = "BL1",
car = "FBM",
});