Matt Compton
← All projects

DSGA Tools

A Windows desktop app that turns a handwritten yearly golf schedule into a typed schedule and a financial projection, both in Excel. It also compares language models on both jobs.

7models compared over 16 scored runs, as of October 7, 2026
4ways each run is scored: rules, answer key, judge, and human review
20minutes for both jobs, including the secretary’s review. The old way took 3 to 4 hours.
Built for
The secretary of the Dixie Seniors Golf Association (DSGA).
Status
In use by the league secretary since October 2026.
My role
Requirements, design rules, testing, and decisions. Claude Code wrote all the code.
Built with
Electron, TypeScript, and React. Every model call goes through OpenRouter.
Timeline
First commit September 11, 2026. First version delivered September 24, 2026.
Size
About 11,400 lines of code, 802 unit tests, and 42 pull requests.
The DSGA Tools Create Schedule screen. A sidebar lists Schedule, Projections, Run Log, and Settings. Two schedule pages and the DSGA Schedules workbook are added, beside a Create Schedule button.
The Create Schedule screen, with two pages of a handwritten schedule and the schedules workbook added.

The problem

Each fall, one DSGA officer spends 3 to 4 hours turning a handwritten schedule into two spreadsheets.

The league president handwrites next year’s tournament schedule, with each tournament falling on a Tuesday. The secretary types it up. He then builds a financial projection from it, estimating how many golfers will play in each tournament from past turnout at the same courses.

It is a small problem: a few hours a year for one person. I chose it for two reasons. It is real work for a user who is not me. More importantly, it let me build what I most wanted to show: a working set of evals.

What I built

DSGA Tools does two jobs for the secretary and one for me.

A handwritten page titled 2027 Schedule, Page 1, listing dates and short course names in two columns, with several entries scribbled out. The finished 2027 schedule in Excel, with a header and one row for each Tuesday from January 5 to May 25: course, tee time, fee, address, and phone.
Left:Top: page 1 of a test schedule I handwrote, with crossed-out lines. Right:Bottom: the start of the finished sheet. The app wrote out each short name, such as BC for Bull Creek, and added Point University on the second Tuesday of each month.

How it works

The model never writes an Excel file. It returns structured data, and code validates that data and builds the workbook. This keeps the output predictable, cheap, and easy to score.

Create Schedule

  1. UserThe user adds pictures of the handwritten schedule and picks the league’s schedule workbook.
  2. CodeCode resizes the pictures so every model gets the same input. It reads last year’s sheet for the header, the known courses, and their details.
  3. ModelA vision model reads the handwriting. It lists each tournament, skips crossed-out text, and flags anything it cannot read.
  4. CodeCode checks every tournament: a valid date, a Tuesday, no duplicates, a known course. Code also applies the league’s rules, such as tee times by season and open dates for skipped Tuesdays.
  5. UserModelCodeEvery problem becomes a question for the user. He answers, the model corrects its reply, and code checks it again.
  6. CodeCode writes the new sheet into the workbook.

Create Schedule

Add pictures
User

Photos or a PDF of the handwritten schedule, and the schedule workbook.

Prepare
Code

Resizes the pictures. Reads last year’s sheet.

Read the handwriting
Model

Lists each tournament. Flags anything it cannot read.

Check every tournament
Code

Dates, Tuesdays, duplicates, courses, and league rules.

Answer questions
UserModelCode

The user answers. The model corrects its reply. Code checks it again.

Write the sheet
Code

Adds next year’s sheet to the schedule workbook.

Create Projections

  1. CodeCode loads the schedule and reads past attendance from the league’s financial workbook. It removes canceled days and duplicates.
  2. UserThe user confirms each course’s fees.
  3. ModelA model gets the schedule, the fees, and the cleaned history. For each tournament, it returns a turnout estimate and a one-sentence reason explaining why it chose the number it did.
  4. CodeCode checks the estimates. One that falls more than 15 players outside a course’s past range becomes a question.
  5. CodeCode writes the projection sheet.

Create Projections

Load the history
Code

The schedule and past attendance. Removes canceled days and duplicates.

Confirm fees
User

The user confirms each course’s fees.

Estimate turnout
Model

For each tournament, an estimate and a one-sentence reason.

Check the estimates
Code

An estimate far outside a course’s past range becomes a question.

Write the sheet
Code

The sheet’s formulas calculate every dollar amount.

The model supplies only two columns on the projection sheet: the estimate and its reason. The secretary then reads each reason and changes any estimate he does not agree with.

My role and the AI’s

Claude Code wrote all the code. I set the requirements, tested the app, and made the decisions. Each build stage had a written spec and a build plan before any code was written.

Two design rules were mine:

Other important choices were Claude Code’s proposals, which I approved. They include having the model return data while code writes the files and hiding each model’s identity from the judge.

The user changed the requirements once. The schedule began as a Word document. On September 21 he asked for Excel instead, and the Word code was removed.

How I know it works

Tests. There are 802 unit tests and 23 smoke tests that drive the app. All of them use a fake model service, so no automated test calls a real model.

Evals. Each run can be scored four ways.

ScoreDone byWhat it measures
RulesCodeThings the model must always do, such as valid dates and exact course names. It runs after every reply, at no cost.
Answer keyCodeSchedule only. It compares the model’s raw reply with a hand-checked key, tournament by tournament, at no cost.
JudgeA second modelYes-or-no answers to a written rubric. The judge is not told which model did the work. Each judge call costs money.
Human reviewMeA form rating the final file, including whether it could be handed out with no edits.

The schedule’s total score ranks the models: 80% comes from the answer key and 20% comes from the rules. Each mistake on the answer key costs 1 point. A mistake is a missed tournament, an extra tournament, or a tournament with a wrong detail, such as the wrong course. A model can mark a tournament it is not sure about, and the app then asks the user about it. A wrong detail that the model did not mark costs 2 points instead of 1, because it can reach the file unnoticed. So the score rewards a model that asks instead of guessing.

The Evals screen. A results table for the 2027 handwritten full-year schedule lists five models, each with a total of 100, 39 of 39 rows right, and no silent errors, with columns for rules, judge, cost, judge cost, and time.
The Evals screen after a batch on the full-year test schedule. All five models got 39 of 39 tournaments right.

Projections have no answer key, because nobody knows the real turnout yet. The judge score ranks them.

The Evals screen. A results table for the full-year 2027 projections test lists five models with columns for judge, human, rules, range flags, questions, cost, judge cost, time, and failed. Gemini 3.8 Flash passed 252 of 254 judge checks. GLM 5.3 Flash failed with an empty answer.
The Evals screen after a batch on the full-year projections test. Gemini 3.8 Flash passed 252 of 254 judge checks, and GLM 5.3 Flash failed with an empty answer.

Results

Schedule. All seven models scored 100, with every tournament right and no silent errors. Five read a full-year schedule of 39 handwritten tournaments, and two read a sample of 11. (The full year also has 12 tournaments that the app adds itself, because one course is always played on the second Tuesday of the month.) A run cost between $0.002 and $0.025 and took 13 to 173 seconds. For this job, the choice comes down to cost and speed.

Projections, full year of about 50 tournaments. The judge was Claude Opus 5.5.

ModelJudge scoreCost per runTime
Gemini 3.8 Flash99.2%$0.06482 s
DeepSeek V4.1 Flash95.0%$0.02362 s
MiniMax M391.9%$0.035152 s
GPT-5.6 Luna91.3%$0.00726 s

A fifth model, GLM 5.3 Flash, failed on a provider error and got no score. In an earlier batch of 20 tournaments, GLM 5.3 Flash scored 95 to 96% and Claude Haiku 4.5 scored 56 to 59%. Haiku was about 12 times faster.

The app’s manual recommends Gemini 3.8 Flash for both jobs.

What went wrong

Most of the problems came from how the models and the provider behaved, and from my own evals.

Status

The app has done its real job once, and it took about 20 minutes.

The secretary ran both jobs on the president’s 2027 schedule. Using the app, it took about 5 minutes. He then spent about 15 minutes checking the schedule and the projection. The old way took 3 to 4 hours.

The schedule was 100% correct. He changed a turnout estimate for one tournament.