Today was another social coding day with friends, the first one where I wasn’t teaching the entire day. I spent the whole morning experimenting with cutting up Möbius strips, did a little pair programming, worked on my mob coding app a bit, and played Dungeons and Dragons for the first time!
Saturday morning Möbius strip art project
After learning this mathematical magic trick yesterday at our math study group, I couldn’t stop myself from cutting up a bunch of Möbius strips this morning and confirming the pattern based on the initial number of twists. Fun times!
Saturday morning art project: cutting Möbius strips with varying twists to create various knots, because why not? https://t.co/rEMSuUfnMp pic.twitter.com/wWjVSUXmgT
— Liz Krane (@LearningNerd) July 1, 2017
Refactoring events for mob coding app
I was definitely overthinking things when I was wondering whether it’s better to send more events with less data or less events with more data (see GitHub issue #6). Short answer: since each event probably has some overhead in addition to its payload, less events with more data would be better! But here’s the more important question that I should have asked much sooner: what’s the bare essential data that needs to be sent, and when does each piece need to be sent? Here’s what I came up with today:
-
userLogin
- Client sends to server: an object containing the player’s SocketIO ID, GitHub username, and avatar URL -
playerListChange
or just reuseuserLogin
- Server sends to all other clients: an object containing the new player’s SocketIO ID, GitHub username, and avatar URL -
startGame
orinitializeUser
or just reuseuserLogin
- Server sends to only the new client: entire game state??? -
Maybe get rid of
createNewGist
and instead include that action as a result of the newstartGame
event? -
turnChange
- Server sends to all clients: time remaining in the current turn? (Or maybe don’t even send any data at all?) -
disconnect
- Server sends to all other clients: ID of the disconnected player -
newGistLink
- Sent from clients and server: an object containing Gist ID, URL, and owner -
editorTextChange
,editorCursorChange
,editorScrollChange
- Ace Editor content, cursor/selection, and scroll data
The main change: mirror the entire game state on the clients and the server, and only send the bare minimum data needed to update either side!
Questions to think about next here:
-
When does the client need to find out how much time is left on the timer? (I think it’s just when the client first logs into the game!)
-
Does any data actually need to be sent with the
turnChange
event? (I don’t think so! As long as the clients know how long the turns are, like if it’s hard-coded or if the server sends that information at some earlier time, then it shouldn’t matter, right?) -
If I had just one event for initializing a client that just logged in, what would that data structure look like and how would I iterate through all of it to update every piece of the user interface and local game state? Would that be too messy?
-
Should I recycle unidirectional event names, like having
userLogin
do one action when received on the server and another action when received on the clients? Or is it better to use different event names? (The latter is probably better to avoid confusion, and there’s no real cost associated with using more event name strings anyhow!)
Notes on refactoring how the server starts the game
Since the game starts when a new user logs in, there are two sets of actions that need to happen – one set for handling the userLogin
event, which happens multiple times throughout the game, and another set for starting the game only when the first user joins. I wasn’t sure which set of actions should happen first, so I scribbled them down on paper, two scenarios side-by-side:
Scenario 1: Start the game first
- User logs in, sends
userLogin
event to server - Game start condition: if player list is null, if player list length is 0, or if turn index is null or -1?
- Start the timer
- Initialize turn index (or reusable
changeTurn
function that increments the turn index) - Emit “startGame” event to the newly-connected client (or
createNewGist
or whatever I settle on)
- Then handle user login (regardless of whether we’re starting a new game):
- Update player list
- Update all other clients with new player data
Scenario 2: Handle user login first
- User logs in, sends
userLogin
event to server - First handle user login (regardless of whether we’re starting a new game):
- Update player list
- Update all other clients with new player data
- Game start condition: if length of player list is 1 (not 0 this time!), or if turn index is -1 or null?
- Start the timer
- Initialize turn index (or reusable
changeTurn
function that increments the turn index) - Emit
startGame
event to the newly-connected client (orcreateNewGist
or whatever I settle on)
Oh, maybe I just realized that the order doesn’t matter if I completely separate the data sent for updating the player list and for starting the turn timer! Oh wait, maybe it does still matter – the part that matters is the condition for checking whether the game should start or not.
Next question: which condition should I use for starting the game?
Gathering string
-
More on the Möbius strip tangent: Wolfram MathWorld has a table that looks similar to the one I sketched out, but I’m not sure if I made “paradromic rings” or something entirely different! One day I want to understand the math behind this better.
-
What is the technical definition of a knot? And how do you count knots?
-
Check out the Style-Scanner Ruby gem again, a command line tool that checks text not just for spelling errors but also for passive tense, 600 different clichés, ugly words, and more! I love the idea for this project and hope to use it sometime.
-
Hunspell is the spell checker used by LibreOffice, Mozilla Firefox 3, and other open-source software projects. Very cool!
-
Can unit testing frameworks (like Mocha, etc) be used to automatically grade and provide helpful feedback for solutions to math problems? This morning while talking to my friend who develops math curriculum and getting a walkthrough of Moodle, we stumbled onto the issue of automatic grading and now I’m super curious about what else you can use unit testing frameworks for! (That Style-Scanner project soudns like a unit testing framework for writers!)
-
When we played Dungeons and Dragons, we used this character set (PDF) – something to look at for the next time I try playing DnD!