Ticket to Graph: Revising Routes

What’s going on here?

If you’re lost about what I’m trying to do here, the beginning can be found here: Ticket to Graph: modeling a board game in Neo4j. The TL;DR is that Ticket to Ride is a popular board game that asks players to build the best rail network across North America by buying routes to connect cities. I’m building out a model that will eventually be able to track the state of the game and help suggest the best routes and most valuable cards to pick up. Below is a list that includes all the posts in this series in order.

The story so far:

Last time, we explained a very basic intro to graph data analysis and built out a few nodes representing two cities and the one route between them. The code looked something like this:

MERGE (p:City 
	{
		name:'Pittsburgh',
		code:'PIT'
	}
	)
;
MERGE (p:City 
	{
		name:'Toronto',
		code:'TOR'
	}
	)
;
MATCH 
	(p:City {code:'PIT'})	

MATCH
	(t:City {code:'TOR'})
MERGE
	(p)-[con1:CONNECTED_BY]->
	(x:Route {
		code:'PIT_TOR_2'
		length:2
		subroutes:[
		{
		color:null,
                Owner:null
		}
]

	})<-[con2:CONNECTED_BY]-(t)
return (p)
;

The problem with this setup with the subroutes is that we’re using arrays in an invalid way here, each item in a route can only be a discrete data type, no objects allowed. There are a few reasons why this was my first instinct to try, but the most important reason is that eventually, when we’re tracking the state of the game, double routes can interact with one another in different ways at times. In games of three or fewer players, only one of the two may be purchased, so we need to link the routes in some way. The reason we can’t just list off the available colors is we will eventually need to track who owns each route, as well as some other properties.

Route Revisions

So, we’re going to need to change the way we’re thinking about routes. Instead of treating the individual routes of a double-route like a property of the route and the node representing the combined two colors, what would have been called a subroute before is going to become the route node, so anything connected with a double route will now have two route nodes instead of one. In order to accomodate grouping the routes into doubles, I’ll create a new relationship called doubled_with to relate the two.

Really this should come as no surprise, as this result is a much more graphy (graphic?) design. Any object we need to represent probably makes the most sense as a node in our graph model. At this point, I’m going to add a few cities now that our model can (hopefully, I haven’t written the merges yet 😁) accommodate double routes and check back in once those are added.

MERGE (p:City 
	{
		name:'Pittsburgh',
		code:'PIT'
	}
	)
;
MERGE (p:City 
	{
		name:'Toronto',
		code:'TOR'
	}
	)
;
MATCH 
	(p:City {code:'PIT'})	

MATCH
	(t:City {code:'TOR'})
MERGE
	(p)-[con1:CONNECTED_BY]->
	(x:Route {
		code:'PIT_TOR_2',
		length:2
		//color: null (null values aren't explicitly defined in Cypher)

	})<-[con2:CONNECTED_BY]-(t)
return (p)
;

// Add Pittsburgh to New York Route
MERGE (n:City 
	{
		name:'New York',
		code:'NYC'
	}
	)
;

// Now we will add Pittsburgh to NY routes, and connect them as PARALLEL_TO

MATCH
	(t:City {code:'NYC'})
MATCH 
	(p:City {code:'PIT'})	
MERGE
	(p)-[con1:CONNECTED_BY]->
	(x:Route {
		code:'PIT_NYC_3_A',
		length:3,
		color: 'White'

	})<-[con2:CONNECTED_BY]-(t)
MERGE
	(p)-[con3:CONNECTED_BY]->
	(y:Route {
		code:'PIT_NYC_3_B',
		length:3,
		color: 'Green'

	})<-[con4:CONNECTED_BY]-(t)
MERGE
	(y)-[:PARALLEL_TO]->(x)
MERGE
	(x)-[:PARALLEL_TO]->(y)
return *
;
	

At this point, I’m now able to load the data into Neo4j. Here’s what the graph looks like for this subset of the board.

One thing that is working well enough for now, but that I’m not crazy about is the code for the routes. code: PIT_NYC_3_B for example. These aren’t named in any way by the game, so the best I could come up with is naming them by the cities they connect, their length, and just A or B. I can’t put the color in the name unless I want the code to have a different naming convention for uncolored routes. In all the versions I’m aware of, you will never have two blue routes be parallel, for example. And we need a specific way to refer to these nodes later. I’m putting a pin in that bit of functionality for now. I could just arbitrarily assign codes, but I do like them being somewhat descriptive.

Right now, I’m doing all of my building of the board manually, with individual merge statements. For the rest of this, I’m going to work on a better load process now that I have the very basics of the board bit of the model. That’s what I’ll continue working on with my next post.

Leave a Reply

Your email address will not be published. Required fields are marked *