require("common.class") local Util = require("common.util") local ServiceField = require("api.page.servicefield") ---@class SelfTestStatus SelfTestStatus = { IDLE = 1, INPROGRESS = 2, OK = 3, PASS = 4, ERROR = 5 } local function statusToString(status) local statusName = {"IDLE", "INPROGRESS", "OK", "PASS", "ERROR"} return statusName[status] end ---@class SelfTestField: ServiceField ---@field checkTask nil|fun(): SelfTestStatus # a function that will run asynchronously on activating the Field ---@field status SelfTestStatus ---@field _thread thread ---@field _timer number local SelfTestField = { __name = "SelfTestField", COLOR_INPROGRESS = {255, 255, 255, 255}, COLOR_OK = {0, 255, 0, 255}, COLOR_PASS = {255, 255, 0, 255}, COLOR_ERROR = {255, 0, 0, 255}, INPROGRESS_FREQ = 1 / 20, --20Hz } ---Create a new SelfTestField instance ---@param params? SelfTestField ---@return SelfTestField function SelfTestField.new(params) params = params or {} params.status = params.status or SelfTestStatus.IDLE local self = CreateInstance(SelfTestField, params, ServiceField) self._timer = 0.0 self._thread = nil return self end function SelfTestField:init() self._thread = coroutine.create(self.checkTask) end function SelfTestField.checkTask() return SelfTestStatus.PASS end function SelfTestField:_closeThread() if self._thread and coroutine.status(self._thread) ~= "dead" then --coroutine.close(self._thread) --only god knows why this crashes lmao end end function SelfTestField:_resumeThread() if self._thread and coroutine.status(self._thread) == "suspended" then local success, status = coroutine.resume(self._thread) game.Log(self.label .. ": success: " .. tostring(success) .. ", status: " .. status .. " (" .. statusToString(status) .. ")", game.LOGGER_DEBUG ) if success and status ~= self.status then self.status = status if self.onStatusChange then game.Log("SKIN CONFIG: onStatusChange(" .. status .. ") (" .. statusToString(status) .. ")", game.LOGGER_DEBUG ) self:onStatusChange(status) end end end end function SelfTestField:activate(obj) self:_closeThread() self:_resumeThread() end function SelfTestField:deactivate(obj) self:_closeThread() end function SelfTestField:tick(deltaTime) self:_resumeThread() self._timer = self._timer + deltaTime end ---@param status SelfTestStatus function SelfTestField:onStatusChange(status) end function SelfTestField:drawValue(deltaTime) gfx.Translate(self.VALUE_OFFSETX, 0) gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT | gfx.TEXT_ALIGN_TOP) gfx.FillColor(table.unpack(self.FONT_COLOR)) gfx.Text(": ", 0, 0) local color, text if self.status == SelfTestStatus.IDLE then color = self.FONT_COLOR text = "" elseif self.status == SelfTestStatus.INPROGRESS then local progress = math.ceil(Util.lerp(self._timer % self.INPROGRESS_FREQ, 0, 0, self.INPROGRESS_FREQ, 4 )) color = self.COLOR_INPROGRESS text = string.rep(".", progress) elseif self.status == SelfTestStatus.OK then color = self.COLOR_OK text = "OK" elseif self.status == SelfTestStatus.PASS then color = self.COLOR_PASS text = "PASS" elseif self.status == SelfTestStatus.ERROR then color = self.COLOR_ERROR text = "ERROR" end gfx.TextAlign(gfx.TEXT_ALIGN_LEFT | gfx.TEXT_ALIGN_TOP) gfx.FillColor(table.unpack(color)) gfx.Text(text, 0, 0) end function SelfTestField:render(deltaTime) self:tick(deltaTime) ServiceField.render(self, deltaTime) end return SelfTestField