Finding the Perfect Meeting Spot: Building a 'Meet in the Middle' App with TFL Data and GeminiCLI

Rich HanesRich Hanes
5 min read

I’ve created an app to find fair and fast meeting points in London for groups of people. I started working on it a decade ago, and finally released it in July ‘05 with the help of GeminiCLI. Why did it take 10 years I hear your inner voice asking, well let me explain. But first:

Halfway ← If you have ever asked the question, where shall we meet (in London) that works for everyone, this could help.

Problem:

Imagine the situation, you are meeting friends after work for a drink, but you all work in different places, and want to meet somewhere that is easy for everyone to get home from. What I have found is that the first person to pick a place usually wins with some resentment that follows from the others.

Solution:

Enter all the starting (and home) destinations into Halfway and it will provide a list of stations that will work for everyone, for example:

Improvements

Awesome, thanks Rich, this app looks perfect and does not need any new features to be really useful, said no one ever. Please let me know what you think in the comments by answering this question:
“This app would be more useful if it …”

Technical Details

In order to be fast, I needed to pre-calculate the distance between each of the 266 tfl stations, in both directions, which is 71,022 (266×267) journeys. The tfl api is generous with its free tier, but this is way too much, even if each request took 1s, this would take 19hr 43mins, and who has that long? Not me, I have 2 kids. So what can we do?

Graphs Galore

How about this: Lets reconstruct the whole tfl network in graph structure on our laptop. Sounds pretty intense, why would that help? Great question, it turns out, if we have the graph locally, we can run an algorithm called Dijkstra from each station that will give us what we need. OK, but how about the tfl api limit. Aha, you are paying attention, good. To build the graph, we need the list of 266 stations (1 request) plus the distance from each station to it neighbouring stations (~600 requests). Now if each request takes 1s this will still take 10 minutes, however we can reduce this further by doing multiple requests at the same time, and tfl lets us do 8, which reduces the time down to ~ 90 seconds. Not too shabby. The code is hand written python, you can find it here.

Database

Now there are some details of how tfl represents data that needed a little more care and some modelling, but the gist is there, we now now the time it takes to get from every station to every other station in London. The final stage of this pre work is to store this somewhere where we can quickly query it, as we have 71,022 entries and we want it to be blazing. This is the bread and butter use case of a db, and the simplest one I could find that worked for this app is sqlite3. No, sockets or connections, just a single file that can be shipped with the app. Great.

Algorithm

This all sounds delightful, but how does this solve the problem? Well, in our DB we have rows that look like this:

From StationTo StationTime
VictoriaBrixton13mins
London BridgeEdgware Underground Station23mins

And from the highly intelligent and very good looking user of the app, we get a list of ‘From Stations’. Using this information, we run a query that matches all the users from stations (266 results per input station) and we group the times based on the ‘To Station’. An example may help here:

From the screenshot above, the input was:

  • Crystal Palace

  • Edgware Underground Station

  • Shepard’s Bush

After the the query and grouping, we have a list of all 266 stations, and three times attached to each one, each time representing the time taken to get there from each one of the inputs:

From: Crystal PalaceFrom Edgware Underground StationFrom: Shepherd’s Bush
To: Old Street41 mins36 mins25 mins
To: London Bridge32 mins40 mins23 mins
To: … (264 more rows)

Is this all making sense? I do hope so. One more step in this algorithm discussion, finding the best station. Well that is quite easy now, if we take the average of the times across the row, sprinkle in a small factor that penalises the numbers if they are too far apart (variance) and then sort, lower is better. Take the top 5 and Tada, we have it.

The Front End

Hold on, you said you used GeminiCLI to make this, and that it took you 10 years, where is that part of the story. Yes yes, hold your horses. It turns out, that last bit, talking to tfl and making the DB I did in very small chunks, and tried a react native app, and a budget website which all did not go very well. A few weeks ago I fed everything I had done into GeminiCLI and asked it to make a front end. It suggested using Next.js and hosting on vercel. I am not hugely interested in web dev and so I did some vibe coding. It is not as easy as ‘make this a site’ and off it goes, I had to refine the prompt 5 or 6 times, and it struggles with launching servers are checking logs etc. But, I think it looks pretty good, and the code is quite clean.

Thanks for reading.

0
Subscribe to my newsletter

Read articles from Rich Hanes directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rich Hanes
Rich Hanes