2022-05-10 21:06:27 +00:00
|
|
|
--
|
|
|
|
-- Utility Functions
|
|
|
|
--
|
|
|
|
|
|
|
|
---@class util
|
2022-05-04 17:37:01 +00:00
|
|
|
local util = {}
|
2022-04-25 14:36:47 +00:00
|
|
|
|
2022-05-04 17:37:01 +00:00
|
|
|
-- PRINT --
|
2022-04-05 21:28:19 +00:00
|
|
|
|
|
|
|
-- print
|
2022-05-04 17:37:01 +00:00
|
|
|
util.print = function (message)
|
2022-04-05 21:28:19 +00:00
|
|
|
term.write(message)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- print line
|
2022-05-04 17:37:01 +00:00
|
|
|
util.println = function (message)
|
|
|
|
print(message)
|
2022-04-05 21:28:19 +00:00
|
|
|
end
|
|
|
|
|
2022-01-13 15:11:42 +00:00
|
|
|
-- timestamped print
|
2022-05-04 17:37:01 +00:00
|
|
|
util.print_ts = function (message)
|
2022-01-13 15:11:42 +00:00
|
|
|
term.write(os.date("[%H:%M:%S] ") .. message)
|
|
|
|
end
|
|
|
|
|
2022-04-05 21:28:19 +00:00
|
|
|
-- timestamped print line
|
2022-05-04 17:37:01 +00:00
|
|
|
util.println_ts = function (message)
|
|
|
|
print(os.date("[%H:%M:%S] ") .. message)
|
2022-04-05 21:28:19 +00:00
|
|
|
end
|
|
|
|
|
2022-04-25 14:36:47 +00:00
|
|
|
-- TIME --
|
|
|
|
|
2022-05-10 21:06:27 +00:00
|
|
|
-- current time
|
|
|
|
---@return integer milliseconds
|
2022-05-04 17:37:01 +00:00
|
|
|
util.time_ms = function ()
|
2022-05-10 15:41:49 +00:00
|
|
|
---@diagnostic disable-next-line: undefined-field
|
2022-04-25 14:36:47 +00:00
|
|
|
return os.epoch('local')
|
|
|
|
end
|
|
|
|
|
2022-05-10 21:06:27 +00:00
|
|
|
-- current time
|
|
|
|
---@return integer seconds
|
2022-05-04 17:37:01 +00:00
|
|
|
util.time_s = function ()
|
2022-05-10 15:41:49 +00:00
|
|
|
---@diagnostic disable-next-line: undefined-field
|
2022-04-25 14:36:47 +00:00
|
|
|
return os.epoch('local') / 1000
|
|
|
|
end
|
|
|
|
|
2022-05-10 21:06:27 +00:00
|
|
|
-- current time
|
|
|
|
---@return integer milliseconds
|
2022-05-04 17:37:01 +00:00
|
|
|
util.time = function ()
|
|
|
|
return util.time_ms()
|
2022-04-25 14:36:47 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- PARALLELIZATION --
|
|
|
|
|
2022-04-27 20:06:30 +00:00
|
|
|
-- protected sleep call so we still are in charge of catching termination
|
2022-05-10 21:06:27 +00:00
|
|
|
---@param t integer seconds
|
|
|
|
--- EVENT_CONSUMER: this function consumes events
|
2022-05-04 17:37:01 +00:00
|
|
|
util.psleep = function (t)
|
2022-05-10 15:41:49 +00:00
|
|
|
---@diagnostic disable-next-line: undefined-field
|
2022-04-27 20:06:30 +00:00
|
|
|
pcall(os.sleep, t)
|
|
|
|
end
|
|
|
|
|
2022-05-10 21:06:27 +00:00
|
|
|
-- no-op to provide a brief pause (1 tick) to yield
|
|
|
|
---
|
|
|
|
--- EVENT_CONSUMER: this function consumes events
|
2022-05-04 17:37:01 +00:00
|
|
|
util.nop = function ()
|
|
|
|
util.psleep(0.05)
|
2022-04-25 14:36:47 +00:00
|
|
|
end
|
|
|
|
|
2022-04-27 23:06:01 +00:00
|
|
|
-- attempt to maintain a minimum loop timing (duration of execution)
|
2022-05-10 21:06:27 +00:00
|
|
|
---@param target_timing integer minimum amount of milliseconds to wait for
|
|
|
|
---@param last_update integer millisecond time of last update
|
|
|
|
---@return integer time_now
|
2022-05-10 15:35:52 +00:00
|
|
|
-- EVENT_CONSUMER: this function consumes events
|
2022-05-04 17:37:01 +00:00
|
|
|
util.adaptive_delay = function (target_timing, last_update)
|
|
|
|
local sleep_for = target_timing - (util.time() - last_update)
|
2022-04-27 23:06:01 +00:00
|
|
|
-- only if >50ms since worker loops already yield 0.05s
|
|
|
|
if sleep_for >= 50 then
|
2022-05-04 17:37:01 +00:00
|
|
|
util.psleep(sleep_for / 1000.0)
|
2022-04-27 23:06:01 +00:00
|
|
|
end
|
2022-05-04 17:37:01 +00:00
|
|
|
return util.time()
|
2022-04-27 23:06:01 +00:00
|
|
|
end
|
|
|
|
|
2022-05-16 21:11:46 +00:00
|
|
|
-- TABLE UTILITIES --
|
|
|
|
|
|
|
|
-- delete elements from a table if the passed function returns false when passed a table element
|
|
|
|
--
|
|
|
|
-- put briefly: deletes elements that return false, keeps elements that return true
|
|
|
|
---@param t table table to remove elements from
|
|
|
|
---@param f function should return false to delete an element when passed the element: f(elem) = true|false
|
|
|
|
---@param on_delete? function optional function to execute on deletion, passed the table element to be deleted as the parameter
|
|
|
|
util.filter_table = function (t, f, on_delete)
|
|
|
|
local move_to = 1
|
|
|
|
for i = 1, #t do
|
|
|
|
local element = t[i]
|
|
|
|
if element ~= nil then
|
|
|
|
if f(element) then
|
|
|
|
if t[move_to] == nil then
|
|
|
|
t[move_to] = element
|
|
|
|
t[i] = nil
|
|
|
|
end
|
|
|
|
move_to = move_to + 1
|
|
|
|
else
|
|
|
|
if on_delete then on_delete(element) end
|
|
|
|
t[i] = nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-05-18 18:30:48 +00:00
|
|
|
-- check if a table contains the provided element
|
|
|
|
---@param t table table to check
|
|
|
|
---@param element any element to check for
|
|
|
|
util.table_contains = function (t, element)
|
|
|
|
for i = 1, #t do
|
|
|
|
if t[i] == element then return true end
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2022-05-10 21:06:27 +00:00
|
|
|
-- MEKANISM POWER --
|
|
|
|
|
|
|
|
-- function kFE(fe) return fe / 1000 end
|
|
|
|
-- function MFE(fe) return fe / 1000000 end
|
|
|
|
-- function GFE(fe) return fe / 1000000000 end
|
|
|
|
-- function TFE(fe) return fe / 1000000000000 end
|
|
|
|
|
|
|
|
-- -- FLOATING POINT PRINTS --
|
|
|
|
|
|
|
|
-- local function fractional_1s(number)
|
|
|
|
-- return number == math.round(number)
|
|
|
|
-- end
|
|
|
|
|
|
|
|
-- local function fractional_10ths(number)
|
|
|
|
-- number = number * 10
|
|
|
|
-- return number == math.round(number)
|
|
|
|
-- end
|
|
|
|
|
|
|
|
-- local function fractional_100ths(number)
|
|
|
|
-- number = number * 100
|
|
|
|
-- return number == math.round(number)
|
|
|
|
-- end
|
|
|
|
|
|
|
|
-- function power_format(fe)
|
|
|
|
-- if fe < 1000 then
|
|
|
|
-- return string.format("%.2f FE", fe)
|
|
|
|
-- elseif fe < 1000000 then
|
|
|
|
-- return string.format("%.3f kFE", kFE(fe))
|
|
|
|
-- end
|
|
|
|
-- end
|
|
|
|
|
2022-04-25 14:36:47 +00:00
|
|
|
-- WATCHDOG --
|
2022-04-05 21:28:19 +00:00
|
|
|
|
2022-01-13 15:11:42 +00:00
|
|
|
-- ComputerCraft OS Timer based Watchdog
|
2022-05-10 17:06:13 +00:00
|
|
|
---@param timeout number timeout duration
|
|
|
|
---
|
|
|
|
--- triggers a timer event if not fed within 'timeout' seconds
|
2022-05-04 17:37:01 +00:00
|
|
|
util.new_watchdog = function (timeout)
|
2022-05-10 17:06:13 +00:00
|
|
|
---@diagnostic disable-next-line: undefined-field
|
2022-05-10 15:41:49 +00:00
|
|
|
local start_timer = os.startTimer
|
2022-05-10 17:06:13 +00:00
|
|
|
---@diagnostic disable-next-line: undefined-field
|
2022-05-10 15:41:49 +00:00
|
|
|
local cancel_timer = os.cancelTimer
|
|
|
|
|
2022-05-10 15:35:52 +00:00
|
|
|
local self = {
|
2022-05-10 17:06:13 +00:00
|
|
|
timeout = timeout,
|
|
|
|
wd_timer = start_timer(timeout)
|
2022-01-13 15:11:42 +00:00
|
|
|
}
|
|
|
|
|
2022-05-10 17:06:13 +00:00
|
|
|
---@class watchdog
|
|
|
|
local public = {}
|
|
|
|
|
|
|
|
---@param timer number timer event timer ID
|
|
|
|
public.is_timer = function (timer)
|
|
|
|
return self.wd_timer == timer
|
2022-01-13 15:11:42 +00:00
|
|
|
end
|
2022-05-10 15:35:52 +00:00
|
|
|
|
2022-05-10 17:06:13 +00:00
|
|
|
-- satiate the beast
|
|
|
|
public.feed = function ()
|
|
|
|
if self.wd_timer ~= nil then
|
|
|
|
cancel_timer(self.wd_timer)
|
2022-01-13 15:11:42 +00:00
|
|
|
end
|
2022-05-10 17:06:13 +00:00
|
|
|
self.wd_timer = start_timer(self.timeout)
|
2022-01-13 15:11:42 +00:00
|
|
|
end
|
|
|
|
|
2022-05-10 17:06:13 +00:00
|
|
|
-- cancel the watchdog
|
|
|
|
public.cancel = function ()
|
|
|
|
if self.wd_timer ~= nil then
|
|
|
|
cancel_timer(self.wd_timer)
|
2022-05-02 15:44:10 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-05-10 17:06:13 +00:00
|
|
|
return public
|
|
|
|
end
|
|
|
|
|
|
|
|
-- LOOP CLOCK --
|
|
|
|
|
|
|
|
-- ComputerCraft OS Timer based Loop Clock
|
|
|
|
---@param period number clock period
|
|
|
|
---
|
|
|
|
--- fires a timer event at the specified period, does not start at construct time
|
|
|
|
util.new_clock = function (period)
|
|
|
|
---@diagnostic disable-next-line: undefined-field
|
|
|
|
local start_timer = os.startTimer
|
|
|
|
|
|
|
|
local self = {
|
|
|
|
period = period,
|
|
|
|
timer = nil
|
2022-01-13 15:11:42 +00:00
|
|
|
}
|
2022-05-10 17:06:13 +00:00
|
|
|
|
|
|
|
---@class clock
|
|
|
|
local public = {}
|
|
|
|
|
|
|
|
---@param timer number timer event timer ID
|
|
|
|
public.is_clock = function (timer)
|
|
|
|
return self.timer == timer
|
|
|
|
end
|
|
|
|
|
|
|
|
-- start the clock
|
|
|
|
public.start = function ()
|
|
|
|
self.timer = start_timer(self.period)
|
|
|
|
end
|
|
|
|
|
|
|
|
return public
|
2022-01-13 15:11:42 +00:00
|
|
|
end
|
2022-05-04 17:37:01 +00:00
|
|
|
|
|
|
|
return util
|