CCCPaste

EnanReactorAutoConfig

local event = require("event")
local component = require("component")
local term = require("term")

local TARGET_INSTABILITY = 2
local STABILIZER_ENERGY  = 10000
local OUTPUT_RATE    = 60000

local SLEEP_TIME = 3.0

local CORE_TYPE = "warpdriveEnanReactorCore"
local PROCESSED_EVENTS = {
  "interrupted",
  "component_added",
  "component_removed"
}

local function pairsByKeys(t, f)
  -- Возвращает элементы массива в отсортированном порядке
  local a = {}
  for n in pairs(t) do table.insert(a, n) end
  table.sort(a, f)
  local i = 0
  local iter = function ()
    i = i + 1
    if a[i] == nil then return nil
      else return a[i], t[a[i]]
    end
  end
  return iter
end

local function configureRelease(core)
  local energy, capacity = core.energy()
  local pct = energy / capacity
  if pct > 0.9 then
    core.releaseRate(OUTPUT_RATE)
  else
    core.release(false)
  end
end

local function initialConfig(core)
  core.stabilizerEnergy(STABILIZER_ENERGY)
  core.instabilityTarget(100 - TARGET_INSTABILITY)
  configureRelease(core)
  core.enable(true)
end

local function drawState(cores)
  term.clear()
  print("Состояние ядер:")

  for addr, core in pairsByKeys(cores) do
    pcall(function()
      local instabil = {core.instability()}
      instabil = 100.0 - (instabil[1] + instabil[2] + instabil[3] + instabil[4]) / 4.0
      local rmode = core.releaseRate()
      if rmode == "at_rate" then rmode = "rate" else rmode = "hold" end
      local strToPrint = addr ..
              "\tEnergy: " .. tostring(core.energy()) ..
              "\tStability: " .. tostring(instabil) ..
              "\tRelease mode: " .. rmode
      print(strToPrint)
    end)
  end
end

local function main()
  local cores = {}
  local rawList = component.list(CORE_TYPE)
  for addr, _ in pairs(rawList) do
    cores[addr] = component.proxy(addr)
    initialConfig(cores[addr])
  end
  rawList = nil

  drawState(cores)

  while true do
    local e = {event.pullFiltered(SLEEP_TIME, function(...)
      local passedName = select(1, ...)
      for _, ename in ipairs(PROCESSED_EVENTS) do
        if ename == passedName then
          return true
        end
      end
      return false
    end)}
    if e[1] == "interrupted" then
      return
    elseif e[1] == "component_added" then
      local addr, ctype = e[2], e[3]
      if ctype == CORE_TYPE then
        cores[addr] = component.proxy(addr)
        initialConfig(cores[addr])
      end
    elseif e[1] == "component_removed" then
      local addr, ctype = e[2], e[3]
      if ctype == CORE_TYPE then
        cores[addr] = nil
      end
    end

    for _, core in pairs(cores) do
      pcall(configureRelease, core)
    end
    drawState(cores)
  end
end

local s, e = xpcall(main(), function(err) return err .. "\n" .. debug.traceback(); end)
if not s then error(e) end