I focused on modelling and draft creation logic and completed:
- registrations importing
- draft creation
Currently drafts are not exported but can still be viewed in the app
Due to time constraints, omitted:
- draft csv exports
- tasks from messages
We can discuss trade-offs and assumptions in the interview
bundle install
bin/rails db:prepare # creates the (empty) database
bin/rails server # then open http://localhost:3000Generally the app was design and built with my initial ideas then refined with the use of AI through discussion. The code generation was all by AI under my careful and considered instruction.
-
Five fixed, reusable teams are sufficient for this exercise.
-
The final duplicate Z001 row is treated as the latest record; the earlier row is ignored.
-
Known position aliases such as Def and Goalie are normalized using a fixed mapping.
-
Missing age and N/A rating values are stored as nil.
-
A missing rating is represented by the selected players’ average rating during balancing only.
-
Fairness means each team is within 75%–125% of the average team rating.
-
Seven of the 42 players remain undrafted because only 35 places exist.
-
Seeds increment sequentially, starting at 1.
-
Drafts and assignments are persisted, adding modelling complexity but preserving history.
-
The algorithm is greedy and retry-based rather than mathematically optimal.
-
Stronger players are assigned to weaker eligible teams, improving fairness but reducing pure randomness.
-
Seeded randomness controls player selection, equivalent choices, and tie- breaking.
-
Rigid-position players are considered before flexible players, reducing failed formations but influencing selection.
-
Registration imports use the supplied CSV only; file uploads and S3 integration were deliberately omitted.
-
Importing is treated as a one-time operation, so the button disappears after players are loaded.
-
Preference scoring and optimisation were omitted; the generator instead seeks candidates where drafted positions are preferred.
-
Export and the later Association messages remain separate follow-up work.
-
I challenged the assumption that seeds were explicitly required; they are an implementation choice for reproducibility.
-
I initially proposed ephemeral drafts, then accepted persisted assignments after clarifying the player–team relationship.
-
I rejected formal preference scoring as excessive for the take-home.
-
I pointed out that randomness limited to equal ratings would be too weak.
-
I suggested assigning stronger players to weaker teams rather than relying on fully random candidates.
-
I suggested validating the upper fairness boundary during allocation, not only afterward.
-
I caught that the flexible player, Finn, was being positioned too early; rigid players should be handled first.
-
I repeatedly kept the solution scoped as a basic, explainable first iteration rather than an optimisation system.
Thanks for taking this on, a quick word before the task itself.
This brief comes from an association that organises games for children. We have intentionally kept their request close to the wording they gave us, because we want this to feel like real client work rather than a purely academic exercise.
As you work, please keep some record of your decisions and why you made them. That record can be in git history, a short running note, or any other method you prefer.
On effort, please do not block out your calendar for this. Spending somewhere between one and two hours is more than enough. We care much more about how you think and what you prioritise than whether every part is fully polished. A smaller scope that is thoughtful and clearly explained is more useful to us than a larger scope that is rushed or fragile.
Use whatever tools you normally use, including AI tools if you want to. We would much rather hear an honest account of where it helped, where it did not, and where you chose to override it than have someone hide that part of their workflow.
The goal of this part of the test is to get a working version of the draft in place so we have something concrete to discuss in the live session. Please do not feel pressure to spend more time than you have available, and do not worry if you do not get to everything. We will talk through your decisions, priorities, and trade-offs together.
"We're finally ready — all the kids are registered, and I've attached the list, including the position each of them would most like to play. We need them drafted into 5 teams, seven-a-side: a goalkeeper, two defenders, two midfielders and two attackers each. The draft should be random but fair between the teams, and we need to be able to run it again and get the same result if a parent ever asks us to show our working. Where you can, give each kid a position they'd like to play. Then just give us a way to see the final teams."
Treat this as a small piece of real client work that may evolve as you go. The aim is to deliver a sensible first version, not a perfect finished system.
- Build enough to load and model the registration data, run a reproducible draft, present the outcome, and export the required CSV.
- Prioritise clarity over volume. We are evaluating your judgement, trade-offs, and technical decisions more than raw feature count.
- If you leave things out, that is fine. Call out what you chose not to do and why.
- AI use is allowed. Be prepared to explain what it produced, what you changed, and what decisions remained yours.
This is the shape of the work we expect to see. You do not need to follow this as a rigid checklist, but your submission should cover each area to a reasonable level.
-
Model and import data. Create the models you think are appropriate for teams and players, then import the registration list as the source data.
-
Run the draft. Allocate players across five teams so the formation is filled, results can be reproduced, and preferences are respected where possible.
-
Show the drafted teams. Provide a clear way to view outcomes so someone can understand who was drafted where.
-
Export results. Produce a CSV file with exactly these columns:
Team Name, Player Registration ID, Drafted PositionOne row per drafted player.
Player Registration IDis theidfrom the registration list;Drafted Positionis the position you drafted them into. It lets us read every submission the same way.
Spend your time in proportion. A sound model and a thoughtful draft are more important than a heavily polished interface.
This is the first requirement we look at, and it should be in place before draft logic begins. It creates the foundation for every later decision.
Your implementation choices are up to you, but by the end of Requirement 1 we should be able to:
- set up the database from scratch and load the registration CSV;
- inspect persisted records for players and teams;
- confirm each player still carries their source registration ID.
How you achieve this is your call, including schema design, import mechanism, validation strategy, and constraints. Choose an approach you can explain and defend in discussion.
This is a minimal Rails app. It boots and has a landing page; the registration
list is at db/registrations.csv. Everything else is up to you to build.
bundle install
bin/rails db:prepare # creates the (empty) database
bin/rails server # then open http://localhost:3000- Ruby — the version is pinned in
.ruby-version; any manager that reads it works (mise, rbenv, asdf). - SQLite — the database; nothing to install on macOS/most Linux.
- Platform — macOS or Linux; on Windows, please work inside WSL.
This is a web app, so we do care that it's easy to navigate and use. Think
about how someone would actually move around it and run the draft. To give you a
head start, Pico CSS is already vendored at
app/assets/stylesheets/pico.min.css and loaded before your own
application.css. Pico is classless: write plain, semantic HTML (<table>,
<article>, <nav>, headings…) inside <main class="container"> (the layout
already does that) and it looks presentable with no extra CSS. You're welcome to
beautify it however you like on top of that or even replace Pico with another
framework or a custom design.
Once the draft runs and the export works, look in the messages/
folder — requests from the Association that arrived while you were working.
They're part of this take-home: take them in number order, and treat each
the way you'd treat a follow-up on a real piece of client work — each one arrived
after the last.
- the code, and how to run it (a private repo you invite us to, or a zip);
- the exported CSVs — reflecting wherever your drafts ended up;
- a record of how the app grew — if you worked in git, the history is exactly this and you're done; otherwise a few lines of changelog in your note is fine;
- a short note (half a page is plenty): the decisions you made, anything in the brief you'd have pushed back on or questioned, what you deliberately left out, and, if you used AI, where it helped and where you had to overrule it.