Skip to content

Commit 6fa1887

Browse files
committed
feat: Replace tablewriter with toon-go for compact output
- Switch from olekukonko/tablewriter to toon-format/toon-go - TOON format is ~35% more compact than ASCII tables - Token-efficient format designed for LLM contexts - Maintains all data: queue, action, upgrade, timing, costs, food - Keeps emoji indicators (🏗️ 🔬 ⚔️ 🍺) for visual scanning - Only affects non-silent CLI output - Silent mode and all solver logic unchanged
1 parent ea78d9c commit 6fa1887

File tree

3 files changed

+71
-27
lines changed

3 files changed

+71
-27
lines changed

cmd/castle/main.go

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import (
77
"strings"
88

99
"github.com/fatih/color"
10-
"github.com/olekukonko/tablewriter"
1110
"github.com/spf13/cobra"
11+
"github.com/toon-format/toon-go"
1212

1313
"github.com/napolitain/solver-lnk/internal/loader"
1414
"github.com/napolitain/solver-lnk/internal/models"
@@ -309,49 +309,70 @@ func printBuildOrder(solution *models.Solution, finalFoodUsed, finalFoodCapacity
309309
return allActions[i].startTime < allActions[j].startTime
310310
})
311311

312-
// Create table with new API
313-
table := tablewriter.NewTable(os.Stdout,
314-
tablewriter.WithHeader([]string{"#", "Queue", "Action", "Upgrade", "Start", "End", "Duration", "Costs", "Food"}),
315-
)
312+
// Prepare data for TOON format
313+
type ToonAction struct {
314+
Num int `toon:"num"`
315+
Queue string `toon:"queue"`
316+
Action string `toon:"action"`
317+
Upgrade string `toon:"upgrade"`
318+
Start string `toon:"start"`
319+
End string `toon:"end"`
320+
Duration string `toon:"duration"`
321+
Costs string `toon:"costs"`
322+
Food string `toon:"food"`
323+
}
316324

317-
// Add rows
325+
var toonActions []ToonAction
318326
for i, a := range allActions {
319327
var queueType, upgradeStr string
320328
foodStr := fmt.Sprintf("%d/%d", a.foodUsed, a.foodCapacity)
321329

322330
switch a.actionType {
323331
case actionBuilding:
324-
queueType = "🏗️ Building"
325-
upgradeStr = fmt.Sprintf("%d%d", a.fromLevel, a.toLevel)
332+
queueType = "🏗️"
333+
upgradeStr = fmt.Sprintf("%d%d", a.fromLevel, a.toLevel)
326334
case actionResearch:
327-
queueType = "🔬 Research"
335+
queueType = "🔬"
328336
upgradeStr = ""
329337
case actionUnit:
330-
queueType = "⚔️ Train"
338+
queueType = "⚔️"
331339
upgradeStr = fmt.Sprintf("×%d", a.count)
332340
case actionMission:
333-
queueType = "🍺 Mission"
341+
queueType = "🍺"
334342
upgradeStr = ""
335343
}
336344

337345
duration := a.endTime - a.startTime
338346
name := formatBuildingName(a.name)
339347

340-
row := []string{
341-
fmt.Sprintf("%d", i+1),
342-
queueType,
343-
name,
344-
upgradeStr,
345-
formatTime(a.startTime),
346-
formatTime(a.endTime),
347-
formatTime(duration),
348-
formatCosts(a.costs),
349-
foodStr,
350-
}
351-
_ = table.Append(row)
348+
toonActions = append(toonActions, ToonAction{
349+
Num: i + 1,
350+
Queue: queueType,
351+
Action: name,
352+
Upgrade: upgradeStr,
353+
Start: formatTime(a.startTime),
354+
End: formatTime(a.endTime),
355+
Duration: formatTime(duration),
356+
Costs: formatCosts(a.costs),
357+
Food: foodStr,
358+
})
359+
}
360+
361+
// Create wrapper struct with array
362+
type BuildOrder struct {
363+
Actions []ToonAction `toon:"actions"`
364+
}
365+
366+
buildOrder := BuildOrder{Actions: toonActions}
367+
368+
// Marshal to TOON format
369+
encoded, err := toon.Marshal(buildOrder, toon.WithLengthMarkers(true))
370+
if err != nil {
371+
fmt.Fprintf(os.Stderr, "Error encoding TOON: %v\n", err)
372+
return 0
352373
}
353374

354-
_ = table.Render()
375+
fmt.Println(string(encoded))
355376

356377
// Calculate and return the total completion time (including units)
357378
var totalEndTime int

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ require (
66
github.com/fatih/color v1.18.0
77
github.com/olekukonko/tablewriter v1.1.2
88
github.com/spf13/cobra v1.10.2
9+
github.com/toon-format/toon-go v0.0.0-20251202084852-7ca0e27c4e8c
10+
google.golang.org/grpc v1.78.0
911
google.golang.org/protobuf v1.36.11
1012
)
1113

@@ -25,5 +27,4 @@ require (
2527
golang.org/x/sys v0.38.0 // indirect
2628
golang.org/x/text v0.31.0 // indirect
2729
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect
28-
google.golang.org/grpc v1.78.0 // indirect
2930
)

go.sum

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,16 @@ github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsV
77
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
88
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
99
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
10+
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
11+
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
12+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
13+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
14+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
15+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
1016
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
1117
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
18+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
19+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1220
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
1321
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
1422
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@@ -31,17 +39,31 @@ github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
3139
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
3240
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
3341
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
42+
github.com/toon-format/toon-go v0.0.0-20251202084852-7ca0e27c4e8c h1:D8lDFovBMZywze1eh9iwMLcYor5f11mHBocLhO7cBe8=
43+
github.com/toon-format/toon-go v0.0.0-20251202084852-7ca0e27c4e8c/go.mod h1:j/BOnpF2ihnz4lELs99h9mwGJBx/zdleOUCnLLRPCsc=
44+
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
45+
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
46+
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
47+
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
48+
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
49+
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
50+
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
51+
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
52+
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
53+
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
54+
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
55+
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
3456
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
3557
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
3658
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
3759
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3860
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
39-
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
40-
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
4161
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
4262
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
4363
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
4464
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
65+
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
66+
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
4567
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda h1:i/Q+bfisr7gq6feoJnS/DlpdwEL4ihp41fvRiM3Ork0=
4668
google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
4769
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=

0 commit comments

Comments
 (0)