P—05 · Case study
Fencing results reader
For the French Fencing Federation, a web tool that reads a competition’s raw export and turns it into pools, bouts, rankings and stats, ready to share with coaches.
Code on GitHub ↗ Requirements spec (French, PDF) ↗After every competition: Excel.
At the end of a competition, the refereeing software produces an XML file with everything in it: pools, every bout, the direct-elimination brackets, the final ranking, the referees.
The catch is that nobody reads XML. Staff opened the file by hand to work out who beat whom, copied the scores into Excel and rebuilt the rankings before sending them to coaches. Every competition meant starting from scratch, and it depended on whoever happened to be free that weekend.
Fast, reliable, usable by non-developers.
Before writing any code, I wrote a requirements spec describing every page, the data it shows and how navigation works. In practice, I was the product manager before I was the developer.
| Page | Content |
|---|---|
index.php | Competition name, venue, date, format (pools → direct elimination). |
inscrits.php | Registered fencers: name, club, category, weapon, with search. |
arbitre.php | Referees assigned to the event, with club and level. |
poules.php | Every pool and every bout: touches scored and received, wins, referee. |
classement_f.php | Final ranking, medals, and the round each fencer reached. |
match.php | Detailed view of a single bout for review with the coach. |
One file in, pages out.
The key decision: no database. Everything is computed in memory from the XML on each load. For a new competition, you swap the file and the site is up to date, with nothing to reprogram or migrate.
Refereeing software (e.g. lille.xml)
Extraction, stats computation
One URL per view, easy to share
Reading a pool.
A simplified excerpt from poules.php: load the export, loop over each pool, then over each bout and its score. The same pattern drives the rankings, referees and registrations pages.
// Load the competition data $xml = simplexml_load_file("lille.xml"); $pools = []; foreach ($xml->Poule as $poule) { $num = (string) $poule['Num']; $pools[$num] = ["referee" => (string) $poule['Arbitre'], "matches" => []]; foreach ($poule->Match as $m) { $pools[$num]["matches"][] = [ "a" => (string) $m->TireurA['Nom'], "b" => (string) $m->TireurB['Nom'], "sa" => (int) $m['ScoreA'], "sb" => (int) $m['ScoreB'], ]; } } // … then render each pool as an HTML table
Demo, feedback, version two.
I demoed the tool live to the federation lead. Most of the feedback was about which metrics actually matter to a coach, so I reworked the stats and the layout accordingly.
The spec also laid out future work: tracking cards per fencer, referee stats, and flagging upsets (a low seed beating a favorite).
Minutes instead of hours.
Above all, I learned to turn “we want stats” into metrics you can actually compute, and to present information the way people need it in the field.