Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,4 @@ luac.out

/wiki
/logs
*.json
38 changes: 17 additions & 21 deletions cc-apps/branch_mine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ package.path = '../?.lua;../?/init.lua;' .. package.path
local logging = require 'cc-libs.util.logging'
logging.basic_config {
level = logging.Level.INFO,
file_level = logging.Level.DEBUG,
file_level = logging.Level.TRACE,
filepath = 'logs/branch_mine.log',
}
logging.get_logger('map').level = logging.Level.WARNING
logging.get_logger('nav').file_level = logging.Level.TRACE
local log = logging.get_logger('main')

local FORWARD_MAX_TRIES = 10
local map_file = 'branch.map'
local map_file = 'branch_map.json'

local cc_motion = require 'cc-libs.turtle.motion'
local Motion = cc_motion.Motion
Expand All @@ -25,30 +23,28 @@ local Compass = rgps.Compass
local cc_nav = require('cc-libs.turtle.nav')
local Nav = cc_nav.Nav

local args = { ... }
if #args < 2 then
print('Usage: branch_mine <shafts> <length> [torch|8] [skip|0]')
print()
print('Options:')
print(' shafts: number of shafts to mine')
print(' length: length of each shaft')
print(' torch: interval to place torches')
print(' skip: number of shafts to skip')
return
end
local argparse = require 'cc-libs.util.argparse'
local parser = argparse.ArgParse:new('branch_mine', 'branch mine')
parser:add_arg('shafts', { help = 'number of shafts to mine' })
parser:add_arg('length', { help = 'length of each shaft' })
parser:add_arg('torch', { help = 'interval to place torches', required = false, default = 8 })
parser:add_arg('skip', { help = 'number of shafts to skip', required = false, default = 0 })
local args = parser:parse_args({ ... })

-- TODO don't crash if torch chest is empty

local shafts = tonumber(args[1])
local length = tonumber(args[2])
local torch = tonumber(args[3] or 8)
local skip = tonumber(args[4] or 0)
local shafts = tonumber(args.shafts)
local length = tonumber(args.length)
local torch = tonumber(args.torch)
local skip = tonumber(args.skip)

log:info('Starting with parameters shafts=', shafts, 'length=', length, 'torc=', torch, 'skip=', skip)

-- TODO fix link error when using loaded map
local map = Map:new()
if fs.exists(map_file) then
map:load(map_file)
log:warning('LOAD MAP IS DISABLED')
-- map:load(map_file)
end
local gps = RGPS:new(map)
local tmc = Motion:new(gps)
Expand Down Expand Up @@ -362,4 +358,4 @@ local function run()
log:info('Done!')
end

run()
log:log_errors(run)
2 changes: 1 addition & 1 deletion cc-libs/astar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ local function astar(start, goal, get_neighbors, cost_fn, heuristic_fn, start_to

-- Iterate over all neighbors of current
local neighbors = get_neighbors(current)
for _, neighbor in ipairs(neighbors) do
for neighbor, weight in pairs(neighbors) do
-- Calculate f score for neighbor
local dist = f_score[current] + cost_fn(current, neighbor)

Expand Down
36 changes: 31 additions & 5 deletions cc-libs/map.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ local log = logging.get_logger('map')
---@param z number
---@return PointId
local function point_id(x, y, z)
log:trace('Point id from pos', x, y, z)
return x .. ',' .. y .. ',' .. z
end

Expand Down Expand Up @@ -50,6 +49,29 @@ function Point:link(other, weight)
self.links[other.id] = weight
end

local function table_size(t)
local count = 0
for _ in pairs(t) do
count = count + 1
end
return count
end

---String conversion overload
function Point:__tostring()
return 'Point(id="'
.. self.id
.. '",x='
.. self.x
.. ',y='
.. self.y
.. ',z='
.. self.z
.. ',#inks='
.. table_size(self.links)
.. ')'
end

---@class Map
---@field graph { [PointId]: Point }
local Map = {}
Expand Down Expand Up @@ -105,7 +127,6 @@ end
---@param pid PointId
---@return Point
function Map:get(pid)
log:trace('Get point for id', pid)
return self.graph[pid]
end

Expand All @@ -115,12 +136,14 @@ end
---@param z number
---@return Point
function Map:point(x, y, z)
log:trace('Get point for pos', x, y, z)
local pid = point_id(x, y, z)
local point = self:get(pid)
if point == nil then
log:trace('Creating point for id', pid)
point = Point:new(x, y, z)
self.graph[point.id] = point
else
log:trace('Got point', point, 'for id', pid)
end
return point
end
Expand All @@ -130,13 +153,16 @@ end
---@param p2 vec3|Point the second point
---@param weight? number weight of the link
function Map:add(p1, p2, weight)
log:info('Add point', p1.x, p1.y, p1.y, 'and', p2.x, p2.y, p2.z)
log:debug('Add point', p1, 'and', p2)
assert(is_inline(p1, p2), 'p1 is not inline with p2')

local g_p1 = self:point(p1.x, p1.y, p1.z)
local g_p2 = self:point(p2.x, p2.y, p2.z)

g_p1:link(g_p2, weight)
g_p1:link(g_p1, weight)
g_p2:link(g_p1, weight)

log:trace('p1 becomes', g_p1, 'p2 becomes', g_p2)
end

local M = {
Expand Down
20 changes: 13 additions & 7 deletions cc-libs/turtle/nav.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ end
---@param pos2 vec3
---@return boolean
local function is_inline(pos1, pos2)
log:trace('is inline', pos1, pos2)
if pos1.x ~= pos2.x then
return pos1.y == pos2.y and pos1.z == pos2.z
elseif pos1.y ~= pos2.y then
Expand Down Expand Up @@ -159,30 +160,35 @@ function Nav:back_follow()
end
end

local function table_size(t)
local count = 0
for _ in pairs(t) do
count = count + 1
end
return count
end

function Nav:find_path(start, goal)
log:debug('Searching for path between', start.x, start.y, start.z, 'and', goal.x, goal.y, goal.z)
log:debug('Searching for path between', start, 'and', goal)

log:debug('Start pos is', start.x, start.y, start.z)
local p_start = self.map:point(start.x, start.y, start.z)

log:debug('Goal pos is', goal.x, goal.y, goal.z)
local p_goal = self.map:point(goal.x, goal.y, goal.z)

local function neighbors(pid)
log:trace('neighbors', pid)
local point = self.map:get(pid)
log:trace('neighbors', pid, table_size(point.links))
return point.links
end

local function f(n1, n2)
log:trace('f', n1, n2)
log:trace('f n1=', n1, 'n2=', n2)
local dx = math.abs(self.map:get(n1).x - self.map:get(n2).x)
local dy = math.abs(self.map:get(n1).y - self.map:get(n2).y)
return dx + dy
end

local function h(n1, n2)
log:trace('h', n1, n2)
log:trace('h n1=', n1, 'n2=', n2)
local dx = math.abs(self.map:get(n1).x - self.map:get(n2).x)
local dy = math.abs(self.map:get(n1).y - self.map:get(n2).y)
return math.sqrt(dx * dx + dy * dy)
Expand Down
4 changes: 3 additions & 1 deletion cc-libs/util/argparse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,9 @@ function ArgParse:parse_args(args)
if arg.default ~= nil then
break
end
missing = missing .. ' ' .. arg.name
if arg.required then
missing = missing .. ' ' .. arg.name
end
end
end
self:print_help()
Expand Down
24 changes: 23 additions & 1 deletion cc-libs/util/logging/logger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ local Handler = log_handler.Handler
---@return debuginfo info name and debug
local function traceback()
local info = debug.getinfo(3, 'Slfn')
for _, check in ipairs({ 'trace', 'debug', 'info', 'warn', 'warning', 'error', 'fatal' }) do
for _, check in ipairs({ 'traceback', 'trace', 'debug', 'info', 'warn', 'warning', 'error', 'fatal' }) do
if info.name == check then
info = debug.getinfo(4, 'Slf')
break
Expand Down Expand Up @@ -97,6 +97,14 @@ function Logger:log(level, ...)
end
end

-- TODO test traceback
---Write a log message with TRACE level including a traceback
---@param ... any message
function Logger:traceback(...)
self:log(Level.TRACE, ...)
self:log(Level.TRACE, debug.traceback('', 2))
end

---Write a log message with TRACE level
---@param ... any message
function Logger:trace(...)
Expand Down Expand Up @@ -140,6 +148,20 @@ function Logger:fatal(...)
error(table.concat({ ... }, ''))
end

---Call a function and log any errors that occur.
---@param fn fun() function to run catching and logging errors
---@return boolean status true if an error was caught
---@return any result of `fn`
function Logger:log_errors(fn)
local status, res = xpcall(fn, debug.traceback)

if not status then
self:error(res)
end

return status, res
end

return {
Logger = Logger,
}
15 changes: 15 additions & 0 deletions cc-libs/util/uuid.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-- https://gist.github.com/jrus/3197011

math.randomseed(os.time())

local function uuid()
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
-- gsub returns 2 values, string and count
local res = string.gsub(template, '[xy]', function(c)
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
return string.format('%x', v)
end)
return res
end

return uuid
1 change: 1 addition & 0 deletions tests/test_argparse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ end
function test.parse_args_missing()
local ap = ArgParse:new('name')
ap:add_arg('arg1')
ap:add_arg('arg2', { required = false })

local success, err = pcall(ap.parse_args, ap, {})
expect_false(success)
Expand Down
6 changes: 3 additions & 3 deletions tests/test_astar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ local nodes = {
a = {
x = 0,
y = 0,
neighbors = { 'b' },
neighbors = { ['b'] = 1 },
},
b = {
x = 0,
y = 3,
neighbors = { 'a', 'c' },
neighbors = { ['a'] = 1, ['c'] = 1 },
},
c = {
x = 2,
y = 3,
neighbors = { 'b' },
neighbors = { ['b'] = 1 },
},
}

Expand Down
24 changes: 24 additions & 0 deletions tests/test_logging_logger.lua
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,28 @@ function test.level_methods()
expect_eq('g', l.log.args[3])
end

function test.log_errors()
local l = Logger:new('ss')
l.log = MagicMock()

local function good()
return 'res'
end

local status, res = l:log_errors(good)
assert_true(status)
assert_eq('res', res)
l.log.reset()

local function bad()
error('fn error')
end

local status2, err = l:log_errors(bad)
assert_false(status2)
assert_eq(1, l.log.call_count)
expect_eq(Level.ERROR, l.log.args[2])
expect_true(string.find(l.log.args[3], 'fn error'))
end

return test
Loading