Inspiration
Every UMass student has stood in the Worcester Dining Commons line at 7 pm and watched the Grill run out. Worcester is one of the dining halls at UMass Amherst. About 3,000 students eat dinner there every night, and every afternoon the kitchen has to guess how much food to cook. Guess low and a station runs dry at the peak. Guess high and the food goes in the trash.
A kitchen can't experiment on real students. You can't test "smaller batches of chicken" or "one more server at the Grill" without risking a bad night. Pilots train in flight simulators, so we asked: why can't a dining hall test tonight's dinner before it happens?
What it does
Dineamics is a "what-if" simulator for Worcester Dining Commons. It replays dinner on the real menu for that date (from umassdining.com), with about 3,700 simulated students. Each student has their own diet, tastes and patience. They arrive in waves after class, pick a line, skip a line that's too long, and either get a plate or find an empty pan.
A kitchen manager can:
- Watch the hall: the night plays back on an illustrated floor plan. Click any student and an AI-written story of their night streams in.
- Try a change: smaller batches, an extra server, a busier night, removing a dish or adding a brand-new one. Dineamics runs 30 paired nights and gives an honest verdict for each metric: better, worse, same or can't tell, always with a range.
- Ask in plain English: type "one more server at Grill and 10% busier" and Gemini turns it into the simulator's own settings.
- Ask Sam: Sam the Minuteman is our planning agent. Give Sam a goal like "cut waste 20% without any vegetarian dish running out". Sam checks past nights in the database, proposes changes, simulates them, reads the results and tries again. Then Sam hands back a plan, or says honestly that the goal couldn't be fully met.
- Optimize: search 80 kitchen plans and see the trade-off between waste and stockouts.
- Get a cook sheet: the thing a kitchen actually uses. Portions to prepare, batch sizes, and when to start the last batch. Printable, or as a CSV.
How we built it
The simulation engine (Python, SimPy). A discrete-event model of the hall: students queue at 12 stations, pans empty, expire and get re-cooked, and cooks and ovens are limited resources. The real menus for 8 dates (Nov 13–20, including Thanksgiving dinner), the real hours and the real stations (Grill, Wok, Noodles, Sushi, Street Food, Latin…) are built in. A Worcester regular on our team checked the model against what they see every night: the 7–8 pm peak, 30–40 person lines, and Sushi made to order.
Honest comparisons. One simulated night proves nothing, so every decision runs on $N = 30$ nights. The baseline and the change share the same random seeds (common random numbers), so both runs get the same students on the same night. Any difference comes from the decision, not luck. For each metric $m$ (lower is better), we compare night by night:
$$ d_i = m_i^{\text{change}} - m_i^{\text{base}}, \qquad w = \frac{1}{N}\sum_{i=1}^{N} \mathbf{1}[d_i < 0], \qquad \ell = \frac{1}{N}\sum_{i=1}^{N} \mathbf{1}[d_i > 0] $$
A change is better only if $w \ge 0.6$ and $\operatorname{median}(d) < 0$. It is worse only if $\ell \ge 0.6$ and $\operatorname{median}(d) > 0$. It is same if $|\operatorname{median}(d)|$ is below a minimum meaningful difference, and otherwise it's can't tell. We'd rather say "can't tell" than claim a win that isn't there.
AI: Gemini API. Gemini never runs the simulation. It proposes, and the engine computes.
- Function calling for plain English (
gemini-3.5-flash-lite). We declared 13 functions, one per setting (set_servers,scale_batch,remove_dish, …). Station and dish arguments are enums of that night's real menu, so Gemini can't invent a dish. Invalid calls go back with the error for one retry, then a JSON-schema fallback, then keyword matching. Answers take about 1–1.3 s. - Sam's agent loop: goal → plan → simulate → observe → adjust, up to 5 tries. The pass/fail check is deterministic code, not the AI, and the final plan is re-checked on 30 nights Sam never saw.
- Student stories and "Why?" explanations, written only from the simulation's own event log and then checked against it.
- New-dish estimates (
gemini-4-hydrogen) and similar-dish search with embeddings (gemini-embedding-001).
Database: Tiger Data (TimescaleDB). Every simulated night and every "recorded" night is stored as time series, side by side:
- Hypertables with columnstore: they hold the nights, every plan search and a forecast ledger.
- Real-time continuous aggregates: they feed a live dashboard.
- A nightly job: it scores the forecasts.
- pgvector: it powers the similar-night search.
Sam reads the database through the Tiger MCP server, with read-only, guarded SQL.
Cloud: Vultr. The app and API run on a Vultr Ubuntu server, behind Caddy over HTTPS. For heavy runs, our dcsim fleet command rents one temporary 16-vCPU Vultr server per menu date and runs the optimizer on all dates in parallel. It saves every search to Tiger, then deletes every server: at the end, on an error, on Ctrl-C or after a time limit. A full week of plan searches took 3.3 minutes and about \$0.07.
Front end: React + TypeScript (Vite), designed first in Figma. It also works fully offline from a built-in bundle, so a Wi-Fi outage can't kill the demo.
Challenges we ran into
- Realism without real data. UMass doesn't publish waste or swipe data per dish. We used the real menus, hours, floor plan and diet survey, and generated the "recorded" waste history with our engine plus noise. Everything synthetic is labeled in the app. We also wrote down exactly which data we'd ask UMass Dining for (requests R01–R08).
- Keeping the AI honest. Language models are confident about numbers they can't know. We built the app so Gemini only turns intent into function calls. Every number comes from the engine, and every AI feature has a checked fallback.
- Stopping the agent from cheating. An early Sam could "meet" a waste goal by assuming fewer students. We hid the crowd, arrival and popularity settings while it plans, protected certain dishes, and re-check its final plan on unseen nights.
- Cloud plumbing. Restoring a 322 GB server snapshot took over 10 minutes, so workers now boot fresh Ubuntu 24.04 and install the engine instead. Snapshot images had no SSH key login, so we added our key through cloud-init. Vultr briefly locks new servers, so deletes now retry. A leftover server keeps billing, so cleanup had to be bulletproof.
- Speed. 30 nights per decision × 80 candidate plans × 8 dates is a lot of simulation. That's why we moved the heavy runs to Vultr.
Accomplishments that we're proud of
- 4,000 simulated nights across all 8 menu dates. On Thanksgiving dinner (Nov 18), the Southern Cornbread runs out on 97.6% of nights, and the 500-night query answers in about a tenth of a second.
- On Nov 13 the optimizer finds plans with about 28.6% less simulated waste for about 6 more stockout-minutes a night. It shows that trade-off instead of hiding it.
- A back-test of "smaller batches of favorites" over 39 past nights: about 8.8% less waste (range 5.6–10.4%).
- An agent that tells the truth: on a hard goal, Sam reports "closest plan, goal not fully met" and shows which check failed.
- 220 engine tests and 66 web tests, browser smoke tests at phone, tablet and desktop widths, and a golden-baseline test that fails if a number changes by accident.
- It's live on Vultr, and it's about our dining hall with tonight's menu.
What we learned
- Use AI where it's strong. An LLM can't count 3,700 students through 12 stations, but it's great at turning "one more Grill server" into settings. The best results came from letting Gemini handle language and letting code handle numbers.
- Function calling with enums is a simple, powerful way to keep a model grounded in real data.
- Paired experiments (common random numbers) cut the noise enough to give real answers from only 30 nights. And "can't tell" is a useful answer.
- Time-series databases fit simulations well. Hypertables and continuous aggregates made thousands of nights cheap to query.
- Elastic compute changes what's possible. Renting servers for 3 minutes instead of running overnight on a laptop let us sweep a whole week.
What's next for Dineamics
- Real data from UMass Dining: swipe counts, production logs and waste weights, to validate and calibrate the model for real. UMass already measures waste campus-wide (about 7.2 oz per swipe in FY2026), so the data exists.
- The other dining commons: Franklin, Hampshire and Berkshire. A new hall only needs new data files, not new code.
- A weekly planning view, so a manager can plan a whole week of menus at once.
- Beyond campus: any cafeteria, hospital or stadium kitchen has the same guess-and-throw-away problem.
Tracks
We're competing in:
- [HackUMass] Best UMass Hack: built on UMass, not just at UMass. It uses real Worcester menus and stations, the Thanksgiving dinner, and Sam the Minuteman.
- [MLH] Best Use of Gemini API: function calling grounded in real menu ids, an agent loop, checked narration, new-dish estimates and embeddings.
- [MLH] Best Use of Vultr: a production deploy, plus a temporary fleet of 16-vCPU servers that optimizes every menu date in parallel and deletes itself.
- [Sentient OS] Best Agentic Hack: Sam is a goal-driven agent with simulator and database tools (via MCP), deterministic grading, guardrails against cheating, and validation on unseen nights.
Built with sponsor technology from Google Gemini, Vultr and Tiger Data.