absurdor

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 6f38e6d417536b97296b51572d1aa7170d43de44
parent 80e53b31df8cfd4788a927b3f726ccac82205b31
Author: Juan F. Meleiro <juan@juanmeleiro.mat.br>
Date:   Wed, 18 Dec 2024 16:18:24 -0300

Split script into files

Diffstat:
Mabsurdor | 137++-----------------------------------------------------------------------------
Alib/log.lua | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/util.lua | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 141 insertions(+), 134 deletions(-)

diff --git a/absurdor b/absurdor @@ -1,144 +1,13 @@ #!/usr/bin/env lua5.4 + local argparse = require "argparse" local json = require "json" local path = require "path" local fs = require "path.fs" -local date = require "date" local pprint = require("pprint").pprint -function die(err, msg, ...) - msg = tostring(msg or err) - if err then - io.stderr:write(string.format(msg .. "\n", ...)) - os.exit(1) - end -end - -function maildate(s) - local d = date(s) - local sec = date.diff(d, date.epoch()):spanseconds() - return sec -end - -function yn(prompt) - meaning = {Y = true, y = true, n = false, N = false} - while meaning[ans] == nil do - io.write(prompt) - io.flush() - ans = io.read(1) - end - return meaning[ans] -end - -function decodewith(decoder, fn) - die(not path.exists(fn), fn.." does not exist.") - die(not path.isfile(fn), fn.." is not a file.") - local f, err = io.open(fn, "r") - die(err) - status, res = xpcall(decoder, die, f:read("a")) - f:close() - die(not status, res) - return res -end - -function encodewith(encoder, fn, data) - local f, err = io.open(fn, "w") - die(not status, err) - status, err = f:write(encoder(data)) - die(not status, err) -end - -function format(fmt, dict, sett) - -- A identifier is - -- > any string of Latin letters, Arabic-Indic digits, and - -- > underscores, not beginning with a digit and not being a reserved - -- > word - - -- local reserved = { - -- "and", "break", "do", "else", "elseif", "end", "false", "for", - -- "function", "goto", "if", "in", "local", "nil", "not", "or", "repeat", - -- "return", "then", "true", "until", "while" - -- } - res = fmt - for s in string.gmatch(fmt, "%{([_a-zA-Z][._a-zA-Z0-9]*)%}") do - local value = dict - local pref = sett - for k in string.gmatch(s, "([_a-zA-Z][_a-zA-Z0-9]*)") do - if type(value) == "table" then value = value[k] end - if type(pref) == "table" then pref = pref[k] end - end - if pref and value then string.format(pref, value) end - res = fmt.gsub(res, "{"..s.."}", value or "nil") - end - return res -end - -function is_valid_entry(e) - return ( - (e.what ~= nil) and - (e.when ~= nil) and - (e.what ~= "push" or e.who ~= nil) and - (e.what ~= "report" or e.height ~= nil) - ) -end - -function parse_jsonl(f) - local log = {} - for l in f:lines() do - local e = json.decode(l) - die(not is_valid_entry(e), string.format("Invalid log entry:\n %s", l)) - table.insert(log, e) - end - return log -end - -function write_jsonl(l) - local res = "" - for _,v in ipairs(l) do - res = res .. json.encode(v) .. "\n" - end - return res -end - -function fmt_event(e) - date = os.date("!%Y-%m-%d %H:%M:%S %z", e.when) - args = {ts = date} - if e.what == "report" then - fmt = "[{ts}] Reported boulder at height {height}" - args.height = e.height - elseif e.what == "push" then - fmt = "[{ts}] {who} pushed the boulder" - args.who = e.who - elseif e.what == "transfer" then - fmt = "[{ts}] {who} transfered the Veblen for {payed}" - args.who = e.who - args.payed= e.payed - elseif e.what == "devalue" then - fmt = "[{ts}] {who} devalued the Veblen to {value}" - args.who = e.who - args.value = e.value - else - die(true, "Unknown event type '%s'", e.what) - end - return format(fmt, args) -end - -function sec2week(s) - return math.floor(s/(24 * 60 * 60 * 7)) -end - -function week2sec(w) - return w*24*60*60*7 -end - -function is_duplicate(ts, log) - for _,e in ipairs(log) do - if e.when == ts then - return true - end - end - return false -end +require "lib.util" +require "lib.log" local parser = argparse("absurdor", "Manage Absurdor duties") :command_target("command") diff --git a/lib/log.lua b/lib/log.lua @@ -0,0 +1,61 @@ +require "lib.util" + +function is_valid_entry(e) + return ( + (e.what ~= nil) and + (e.when ~= nil) and + (e.what ~= "push" or e.who ~= nil) and + (e.what ~= "report" or e.height ~= nil) + ) +end + +function parse_jsonl(f) + local log = {} + for l in f:lines() do + local e = json.decode(l) + die(not is_valid_entry(e), string.format("Invalid log entry:\n %s", l)) + table.insert(log, e) + end + return log +end + +function write_jsonl(l) + local res = "" + for _,v in ipairs(l) do + res = res .. json.encode(v) .. "\n" + end + return res +end + +function fmt_event(e) + date = os.date("!%Y-%m-%d %H:%M:%S %z", e.when) + args = {ts = date} + if e.what == "report" then + fmt = "[{ts}] Reported boulder at height {height}" + args.height = e.height + elseif e.what == "push" then + fmt = "[{ts}] {who} pushed the boulder" + args.who = e.who + elseif e.what == "transfer" then + fmt = "[{ts}] {who} transfered the Veblen for {payed}" + args.who = e.who + args.payed= e.payed + elseif e.what == "devalue" then + fmt = "[{ts}] {who} devalued the Veblen to {value}" + args.who = e.who + args.value = e.value + else + die(true, "Unknown event type '%s'", e.what) + end + return format(fmt, args) +end + +function is_duplicate(ts, log) + for _,e in ipairs(log) do + if e.when == ts then + return true + end + end + return false +end + diff --git a/lib/util.lua b/lib/util.lua @@ -0,0 +1,77 @@ +local date = require "date" +local path = require "path" + +function die(err, msg, ...) + msg = tostring(msg or err) + if err then + io.stderr:write(string.format(msg .. "\n", ...)) + os.exit(1) + end +end + +function maildate(s) + local d = date(s) + local sec = date.diff(d, date.epoch()):spanseconds() + return sec +end + +function yn(prompt) + meaning = {Y = true, y = true, n = false, N = false} + while meaning[ans] == nil do + io.write(prompt) + io.flush() + ans = io.read(1) + end + return meaning[ans] +end + +function decodewith(decoder, fn) + die(not path.exists(fn), fn.." does not exist.") + die(not path.isfile(fn), fn.." is not a file.") + local f, err = io.open(fn, "r") + die(err) + status, res = xpcall(decoder, die, f:read("a")) + f:close() + die(not status, res) + return res +end + +function encodewith(encoder, fn, data) + local f, err = io.open(fn, "w") + die(not status, err) + status, err = f:write(encoder(data)) + die(not status, err) +end + +function format(fmt, dict, sett) + -- A identifier is + -- > any string of Latin letters, Arabic-Indic digits, and + -- > underscores, not beginning with a digit and not being a reserved + -- > word + + -- local reserved = { + -- "and", "break", "do", "else", "elseif", "end", "false", "for", + -- "function", "goto", "if", "in", "local", "nil", "not", "or", "repeat", + -- "return", "then", "true", "until", "while" + -- } + res = fmt + for s in string.gmatch(fmt, "%{([_a-zA-Z][._a-zA-Z0-9]*)%}") do + local value = dict + local pref = sett + for k in string.gmatch(s, "([_a-zA-Z][_a-zA-Z0-9]*)") do + if type(value) == "table" then value = value[k] end + if type(pref) == "table" then pref = pref[k] end + end + if pref and value then string.format(pref, value) end + res = fmt.gsub(res, "{"..s.."}", value or "nil") + end + return res +end + +function sec2week(s) + return math.floor(s/(24 * 60 * 60 * 7)) +end + +function week2sec(w) + return w*24*60*60*7 +end