feat: add menu to toggle solved state
This commit is contained in:
@@ -48,4 +48,3 @@
|
|||||||
"puzzle2": false
|
"puzzle2": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ local function main()
|
|||||||
dayStats.puzzle2
|
dayStats.puzzle2
|
||||||
)
|
)
|
||||||
day:show()
|
day:show()
|
||||||
|
stats = loadStats("aoc/res/stats.json")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
local json = require("json")
|
||||||
local utils = require("utils")
|
local utils = require("utils")
|
||||||
local days = {}
|
local days = {}
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ local CHOICES = {
|
|||||||
create = "Create files",
|
create = "Create files",
|
||||||
example = "Run examples",
|
example = "Run examples",
|
||||||
real = "Run with real input",
|
real = "Run with real input",
|
||||||
|
star = "Mark solved",
|
||||||
main = "Back to main menu"
|
main = "Back to main menu"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +152,49 @@ function Day:choosePuzzle()
|
|||||||
return c
|
return c
|
||||||
end
|
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()
|
function Day:printTitle()
|
||||||
term.clear()
|
term.clear()
|
||||||
term.setCursorPos(1, 1)
|
term.setCursorPos(1, 1)
|
||||||
@@ -163,22 +208,25 @@ function Day:show()
|
|||||||
while true do
|
while true do
|
||||||
self:printTitle()
|
self:printTitle()
|
||||||
if fs.exists(self:srcDir()) then
|
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
|
if c == CHOICES.main then
|
||||||
return
|
return
|
||||||
end
|
elseif c == CHOICES.star then
|
||||||
local puzzle = self:choosePuzzle()
|
self:menuStars()
|
||||||
if puzzle ~= "Back" then
|
else
|
||||||
local puzzleI = ({
|
local puzzle = self:choosePuzzle()
|
||||||
["Puzzle 1"] = 1,
|
if puzzle ~= "Back" then
|
||||||
["Puzzle 2"] = 2
|
local puzzleI = ({
|
||||||
})[puzzle]
|
["Puzzle 1"] = 1,
|
||||||
if c == CHOICES.example then
|
["Puzzle 2"] = 2
|
||||||
self:execExample(puzzleI)
|
})[puzzle]
|
||||||
elseif c == CHOICES.real then
|
if c == CHOICES.example then
|
||||||
self:execReal(puzzleI)
|
self:execExample(puzzleI)
|
||||||
|
elseif c == CHOICES.real then
|
||||||
|
self:execReal(puzzleI)
|
||||||
|
end
|
||||||
|
utils.waitForKey(keys.enter)
|
||||||
end
|
end
|
||||||
utils.waitForKey(keys.enter)
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local c = utils.promptChoices({CHOICES.create, CHOICES.main})
|
local c = utils.promptChoices({CHOICES.create, CHOICES.main})
|
||||||
|
|||||||
@@ -20,6 +20,13 @@ local function errFactory(prefix)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function ifNil(test, ifNil, ifNotNil)
|
||||||
|
if test == nil then
|
||||||
|
return ifNil
|
||||||
|
end
|
||||||
|
return ifNotNil
|
||||||
|
end
|
||||||
|
|
||||||
local function parseObj(data)
|
local function parseObj(data)
|
||||||
local printErr = errFactory("Error while parsing object")
|
local printErr = errFactory("Error while parsing object")
|
||||||
local obj = {}
|
local obj = {}
|
||||||
@@ -199,4 +206,86 @@ function json.loads(data)
|
|||||||
return res
|
return res
|
||||||
end
|
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
|
return json
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
local utils = {}
|
local utils = {}
|
||||||
|
|
||||||
function utils.promptChoices(choices)
|
function utils.promptChoices(choices, default)
|
||||||
local c = 1
|
local c = default or 1
|
||||||
local ox, oy = term.getCursorPos()
|
local ox, oy = term.getCursorPos()
|
||||||
while true do
|
while true do
|
||||||
term.setCursorPos(ox, oy)
|
term.setCursorPos(ox, oy)
|
||||||
|
|||||||
Reference in New Issue
Block a user