Migrate unlocking feature from old autograder.

This pull requests implements the unlocking functionality from the old autograder. The `Protocol` is not yet implemented (I'll do this in a separate pull request).

Some code for the grading protocol has also been rewritten to be more consistent (including the introduction of an `OkConsole` abstract class).

This resolves #53 .
I like the "concept" kind of questions, but I don't see why it's necessary to have it be it's own separate thing in the implementation. I was thinking that questions could have a format of the following:

We have a question be something that we ask them (this could be a "what would Python print?" or a conceptual question or a third kind of question that we haven't thought up of yet). Then, we could consider a student output to be the same as out answer through some equality test.

I seem to recall thinking of just using eval() a while ago, but I think either @albert12132 or @papajohn came up with a really good reason not to do that... We might be able to get away with doing eval() (or ==) as a default equality checker and then allow other staff members to come up with custom ones.

But yeah, I really dislike the organization of having conceptual questions be treated as separate objects entirely unless they absolutely need to be.