There have been quite a few discussions this year about automatically collecting transcripts from testers/players, as some of the following links show. I’d like to make a more formal proposal now of a set of technologies which hopefully will meet everyone’s desires. I will make three largely independant proposals here, the protocol, a metadata extension, and a Glulx/Glk extension for tagged output.
- http://groups.google.com/group/parchment/browse_thread/thread/6fe4c5bb7ba4aa8f
- http://nitku.net/blog/2010/06/collecting-real-life-gameplay-data-with-parchment/
- http://github.com/sgranade/parchment
[size=150]The transcript protocol[/size]
I’ve wanted the protocol to be simple and extensible. It should be easily implemented in all languages, and useful for all IF systems. I think JSON sent over HTTP POST requests will fulfil these needs. In the following descriptions, almost everything is optional, though the more that is sent the more useful a transcript will be, of course. Remember that within an object {} the order of elements does not matter, and that each key can be used only once.
The handshake
Firstly, the interpreter sends a message to the server giving the details of the story file. Either an IFID or a URL must be sent, with an IFID being strongly preferred. The other items are all optional, though as much information should be given as is possible. The interpreter must have the user’s permission to send contact details.
{
"ifid": "ZCODE-2-080406-A377",
"url": "http://mirror.ifarchive.org/if-archive/games/zcode/LostPig.z8",
"release": 2,
"serial": "080406",
"contact": "Dannii <curiousdannii@gmail.com>",
"interpreter": "Gargoyle 2009-08-25 (Git 1.2.6)"
}
The server then replies with a session ID and a list of supported transcript types. If the server sends a HTTP code other than 200 or a non-JSON response, or it does not reply with both a session ID and at least the “input” type, then the client must not attempt to send any transcripts. Due to the protocol’s extensible nature the client can send more data than the server supports, but that just wastes bandwidth. An example response is as follows:
{
"session": 7253,
"input": 1,
"response": 1,
"tagged": 0,
"time": 1
}
If the client returns both a session ID and at least the “input” transcript type, then the client may proceed to send transcripts. Note that the “tagged” item could have been left out, with no difference to client behaviour.
Sending transcripts
Again, the client sends transcripts over HTTP POST requests, but after the handshake, it does not need to listen to the response. A fairly full example is as follows, with an explanation of the elements after that:
{
"session": 7253,
"log": [
{
"time": "2010-07-18T03:04:12",
"input": "x fsih",
"response": "You can't see any such thing.",
"response-type": "libmsg",
"response-code": 30
},
{
"time": "2010-07-18T03:04:48",
"input": "x fish",
"response": "Looks tasty."
}
]
}
A client first sends its session ID, followed by the logged commands. A client may send one command, or 100, and the server must be able to accept as many as it sends.
If the server indiciates that it supports time stamps, please send them with the following ISO 8601 format: YYYY-MM-DDTHH-MM-SS. If timestamps are not sent then the server should do its best to keep commands in order, and may use the time of the HTTP request instead. As JSON arrays are ordered structures, these timestamps must be strictly increasing.
The input command will always be sent, and if the server indicates that it supports response, the corresponding response may be sent too.
If the client has a way of detecting response types and codes it may send those too. Suggested types are “libmsg” for library messages, “parser” for parser errors and “runtime” for runtime errors. Again, check the server supports “tagged” logs first.
Here is an example of a minimal log, which may always be sent, even if the server supports more detailed logs:
{
"session": 7253,
"log": [
{"input": "x fsih"},
{"input": "x fish"}
]
}
Hanging questions
- What to do with key/mouse/hyperlink etc input?
- Have an explicit exit code?
[size=150]Metadata extension[/size]
An custom interpreter may be set up for sending transcripts, or the transcript server may be specified with a querystring parameter (for web interpreters). But in most cases it will be useful to keep the server info with the story file itself, so that it may be used with any terp which supports transcripts. I propose a simple extension to the iFiction XML record, which in most cases will be included in a blorbed story file. Both and are required. must use the HTTP protocol, and must be in the format of “3-letter-month-name day, four-digit-year” eg, “Aug 9, 2010”. The is required so that terps won’t attempt to send transcripts long after the author has stopped wanting them (or after the web server has been taken offline), it may be set to many years or even centuries into the future (but don’t do that unless you can guarantee your server’s uptime!)
<transcripts>
<url>URL</url>
<lastdate>DATE</lastdate>
</transcripts>
[size=150]Glulx/Glk extensions[/size]
This part of the proposal is actually where I really need help. Basically it would be good to be able to compile Glulx games which output tagged responses (with a type and code) so that the terps may then easily capture that information for the logs. Juhana’s proposal emitted stuff like “#ERROR:[parser error code]#” to the normal output streams, which is a simple option we could add, with a gestalt check so that other terps don’t see this nasty message. One advantage of this is that it could also be used with other VMs (in the Z-Machine for example, by first checking for a new previously unused interpreter number.) But it might be better to use new Glk streams. I don’t really know.
Suggestions?