feat: add menu to toggle solved state

This commit is contained in:
2025-11-28 18:29:58 +01:00
parent c75a882e2c
commit 080f2b51c7
5 changed files with 154 additions and 17 deletions

View File

@@ -128,6 +128,7 @@ local function main()
dayStats.puzzle2
)
day:show()
stats = loadStats("aoc/res/stats.json")
end
end
end

View File

@@ -1,3 +1,4 @@
local json = require("json")
local utils = require("utils")
local days = {}
@@ -7,6 +8,7 @@ local CHOICES = {
create = "Create files",
example = "Run examples",
real = "Run with real input",
star = "Mark solved",
main = "Back to main menu"
}
@@ -150,6 +152,49 @@ function Day:choosePuzzle()
return c
end
function Day:menuStars()
local solvedTxt = function (b)
if b then
return "solved"
end
return "unsolved"
end
local c0 = 1
while true do
self:printTitle()
local choices = {
puzzle1 = "Mark puzzle 1 as " .. solvedTxt(not self.puzzle1),
puzzle2 = "Mark puzzle 2 as " .. solvedTxt(not self.puzzle2),
back = "Back"
}
local c = utils.promptChoices({choices.puzzle1, choices.puzzle2, choices.back}, c0)
if c == choices.back then
return
end
if c == choices.puzzle1 then
self.puzzle1 = not self.puzzle1
self:saveStats()
c0 = 1
elseif c == choices.puzzle2 then
self.puzzle2 = not self.puzzle2
self:saveStats()
c0 = 2
end
end
end
function Day:saveStats()
local path = RES_PATH .. "/stats.json"
local content = utils.readFile(path) or "{}"
local data = json.loads(content) or {}
data[("day%02d"):format(self.day)] = {
puzzle1=self.puzzle1,
puzzle2=self.puzzle2,
}
content = json.dumps(data, 4, true)
utils.writeFile(path, content, true)
end
function Day:printTitle()
term.clear()
term.setCursorPos(1, 1)
@@ -163,22 +208,25 @@ function Day:show()
while true do
self:printTitle()
if fs.exists(self:srcDir()) then
local c = utils.promptChoices({CHOICES.example, CHOICES.real, CHOICES.main})
local c = utils.promptChoices({CHOICES.example, CHOICES.real, CHOICES.star, CHOICES.main})
if c == CHOICES.main then
return
end
local puzzle = self:choosePuzzle()
if puzzle ~= "Back" then
local puzzleI = ({
["Puzzle 1"] = 1,
["Puzzle 2"] = 2
})[puzzle]
if c == CHOICES.example then
self:execExample(puzzleI)
elseif c == CHOICES.real then
self:execReal(puzzleI)
elseif c == CHOICES.star then
self:menuStars()
else
local puzzle = self:choosePuzzle()
if puzzle ~= "Back" then
local puzzleI = ({
["Puzzle 1"] = 1,
["Puzzle 2"] = 2
})[puzzle]
if c == CHOICES.example then
self:execExample(puzzleI)
elseif c == CHOICES.real then
self:execReal(puzzleI)
end
utils.waitForKey(keys.enter)
end
utils.waitForKey(keys.enter)
end
else
local c = utils.promptChoices({CHOICES.create, CHOICES.main})

View File

@@ -20,6 +20,13 @@ local function errFactory(prefix)
end
end
local function ifNil(test, ifNil, ifNotNil)
if test == nil then
return ifNil
end
return ifNotNil
end
local function parseObj(data)
local printErr = errFactory("Error while parsing object")
local obj = {}
@@ -199,4 +206,86 @@ function json.loads(data)
return res
end
local function kind(obj)
if type(obj) ~= "table" then
return type(obj)
end
local i = 1
for _ in pairs(obj) do
if obj[i] ~= nil then
i = i + 1
else
return "table"
end
end
if i == 1 then
return "table"
end
return "array"
end
local function escapeStr(str)
local in_char = {'\\', '"', '/', '\b', '\f', '\n', '\r', '\t'}
local out_char = {'\\', '"', '/', 'b', 'f', 'n', 'r', 't'}
for i, c in ipairs(in_char) do
str = str:gsub(c, '\\' .. out_char[i])
end
return str
end
function json.dumps(data, indent, sortKeys, depth)
if data == json.null then
return "null"
end
local t = kind(data)
if t == "string" then
return '"' .. escapeStr(data) .. '"'
elseif t == "number" or t == "boolean" then
return tostring(data)
end
depth = depth or 0
local spaces = ""
if indent ~= nil then
spaces = string.rep(" ", indent * depth)
end
local res = ""
if t == "array" then
res = res .. "[" .. ifNil(indent, "", "\n")
for i, val in ipairs(data) do
if i > 1 then
res = res .. "," .. ifNil(indent, " ", "\n")
end
res = res .. spaces .. string.rep(" ", indent or 0)
res = res .. json.dumps(val, indent, sortKeys, depth + 1)
end
res = res .. ifNil(indent, "", "\n") .. spaces .. "]"
elseif t == "table" then
res = res .. "{" .. ifNil(indent, "", "\n")
local first = true
local keys = {}
for k, _ in pairs(data) do
table.insert(keys, k)
end
if sortKeys then
table.sort(keys)
end
for _, k in ipairs(keys) do
local v = data[k]
if not first then
res = res .. "," .. ifNil(indent, " ", "\n")
end
first = false
res = res .. spaces .. string.rep(" ", indent or 0)
res = res .. '"' .. escapeStr(k) .. '": '
res = res .. json.dumps(v, indent, sortKeys, depth + 1)
end
res = res .. ifNil(indent, "", "\n") .. spaces .. "}"
end
return res
end
return json

View File

@@ -1,7 +1,7 @@
local utils = {}
function utils.promptChoices(choices)
local c = 1
function utils.promptChoices(choices, default)
local c = default or 1
local ox, oy = term.getCursorPos()
while true do
term.setCursorPos(ox, oy)