This is just some notes I'm making about how to develop the CharityFrag parser (SKP - Streamed Kill Parser).
Currently, SKP is written in (procedural) Java. It works as follows: it boots up, reads in a bunch of data from the prefs.ini file using a java.util.Properties object. It connects to a db using JDBC. We load up the log file and start reading it using a BufferedReader. We sit and loop waiting for the next line, and then when it comes in, we parse it as follows:
- if it contains the string "<non-client>", we ignore it.
- if it contains the string "Kill:", we parse it using a regex.
- otherwise, we ignore it.
Once it finds a kill, we construct an INSERT to load it into the database. The data that needs to go into the database is killer_id, the killed_id, the weapon and the timestamp. The code needs to look up the killer_id and the killed_id from the database.
Stuff that still needs testing:
- UTF-8 character names, symbols in names, junk etc.
- How many players can we have going at once?
Stuff that could be added:
- Tracking in-game character renaming and handing those back to the server
Issues:
- SKP currently looks up player IDs every time a kill is parsed.
- Caching that data is a sensible starting point. Perhaps use a LinkedHashMap to store the data. When to flush that data is important: if one had a UrT server on the Internet that's being used 24x7, we'd need to flush the cache frequently or it'd just eat memory forever. Simple way: when you get the data back, just tag it with a timestamp of an hour. While each DB call is running, prune the map in the background.
- Alternatively, don't bother. Just have it so that you construct a query that works by doing an INSERT that contains two SELECT queries for the IDs.
- Concurrency
- Currently, each database call blocks filesystem IO - this isn't efficient. Imagine a game of UrT where lots of stuff happens but without many kills (maybe a CTF round) - the code gets stuck into looking up data for the last kill, constructing a query and sending it off to the database. But then once it's done, there might be hundreds or thousands of lines to read before it finds the next kill.
- Use queuing for that?
- Use INSERT DELAYED in MySQL - we're not then waiting for the database to insert.
- Scala?
- Security - anyone can camp names.
- Possibly, do a client-server model. Have a central server, where people sign up, set up payment (and taxation stuff, charity affiliation etc.). Then each game can download a CharityFrag local server, which would keep track of kills and money transfers, then whoever is running the local game could transfer it to the central server at some point. That way, we can implement on LAN parties and where there's shaky Internet access.
- Implementing security: use OAuth (when there is a connection) or use SSL certificate authentication. There's still a trust issue involved: when the local servers sync up with the central server, you need to check with people to say "you really mean this?"