Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions src/kilogram.salt
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Kilogram — weightlifting plate calculator (IWF standard)
// Usage: kilogram <weight> [m|w]

Plate { weight float, color int, width int, height int }

// IWF competition plates: heaviest to lightest, ANSI 256-color codes
PLATES = [
Plate { weight: 25.0, color: 9, width: 3, height: 7 },
Plate { weight: 20.0, color: 12, width: 2, height: 7 },
Plate { weight: 15.0, color: 11, width: 1, height: 7 },
Plate { weight: 10.0, color: 10, width: 1, height: 7 },
Plate { weight: 5.0, color: 15, width: 1, height: 5 },
Plate { weight: 2.5, color: 9, width: 1, height: 5 },
Plate { weight: 2.0, color: 12, width: 1, height: 3 },
Plate { weight: 1.5, color: 11, width: 1, height: 3 },
Plate { weight: 1.0, color: 10, width: 1, height: 1 },
Plate { weight: 0.5, color: 15, width: 1, height: 1 }
]

ART = ["|", "||", "|¦|"]
BLANK = [" ", " ", " "]

// Whether a plate is visible at row (0-6, centered at row 3)
visible(p Plate, row int) bool {
half = p.height / 2
return row >= 3 - half and row <= 3 + half
}

// Render one plate cell: colored art or blank
cell(p Plate, row int) string {
return cond {
visible(p, row): "{ansi_fg(p.color)}{ART[p.width - 1]}{ansi_reset()}"
else: BLANK[p.width - 1]
}
}

// Greedy plate allocation (one side of the bar)
allocate(side float) Array(Plate) {
rem mut = side
result mut Array(Plate) = []
for spec in PLATES {
qty = to_int(floor(rem / spec.weight))
rem -= to_float(qty) * spec.weight
for _ in range(0, qty) {
result = push(result, spec)
}
}
return result
}

// Render the full barbell with loaded plates
render(plates Array(Plate)) {
n = len(plates)
for row in range(0, 7) {
sb = string_builder()
ch = cond { row == 3: "="; else: " " }
collar = cond { row == 3: "O"; else: " " }
bar = cond { row == 3: "=----------------="; else: " " }

sb_write(sb, "{ch}{ch}{collar}")
for i in range(0, n) { sb_write(sb, cell(plates[n - 1 - i], row)) }
sb_write(sb, bar)
for p in plates { sb_write(sb, cell(p, row)) }
sb_write(sb, "{collar}{ch}{ch}")

print(sb_build(sb))
}
}

// --- CLI ---
weight_str = arg(1) else {
print("Usage: kilogram <weight> [m|w]")
print(" m = men's 20kg bar (default)")
print(" w = women's 15kg bar")
exit(0)
}

total float = parse_float(weight_str) else {
print("Weight must be a valid number")
exit(1)
}

bar_weight = cond (arg(2) else "m") {
"w": 15.0
else: 20.0
}

cond total < bar_weight + 5.0 {
print("Minimum weight: {bar_weight + 5.0}kg (bar + collars)")
exit(1)
}

side = (total - bar_weight) / 2.0 - 2.5
allocate(side) | render