SHOW:
|
|
- or go back to the newest paste.
| 1 | - | local computer = require("computer") |
| 1 | + | local computer = require("computer")
|
| 2 | - | computer.beep(440, .1) |
| 2 | + | local component = require("component")
|
| 3 | - | local component = require("component") |
| 3 | + | local event = require("event")
|
| 4 | - | local reactors = {} |
| 4 | + | local term = require("term")
|
| 5 | - | do |
| 5 | + | |
| 6 | - | local t = component.list("nc_fission_reactor") |
| 6 | + | -- control just one reactor per computer. Simpler that way. |
| 7 | - | for address in pairs(t) do table.insert(reactors, component.proxy(address)) end |
| 7 | + | local reactor |
| 8 | - | end |
| 8 | + | do |
| 9 | - | local event = require("event") |
| 9 | + | local t = component.list("nc_fission_reactor")
|
| 10 | - | local term = require("term") |
| 10 | + | if not next(t) then -- none! |
| 11 | - | if term then term.clear() end |
| 11 | + | print("Error: no reactors found!")
|
| 12 | - | local controls, formatstring, header = {}, "", "" |
| 12 | + | os.exit() |
| 13 | - | do |
| 13 | + | end |
| 14 | - | for i = 1, #reactors do |
| 14 | + | if next(t, (next(t))) then -- more than one! |
| 15 | - | controls[i] = {fuzzyenergyshutdown = false, fuzzyheatshutdown = false, shutdown = true} |
| 15 | + | print("Error: this program can only control one reactor!")
|
| 16 | - | end |
| 16 | + | os.exit() |
| 17 | - | header = string.format(string.format("%%-%ds Fuel Heat Energy Status", tostring(#reactors):len()), "#") |
| 17 | + | end |
| 18 | - | formatstring = string.format("%%-0%dd %%-7s %%5.1f%%%% %%5.1f%%%% %%s", tostring(#reactors):len()) |
| 18 | + | reactor = component.nc_fission_reactor |
| 19 | - | end |
| 19 | + | end |
| 20 | - | local low, high = 0.25, 0.5 |
| 20 | + | local isproblem = function() |
| 21 | - | if term then |
| 21 | + | local problem = reactor.getProblem() |
| 22 | - | term.clear() |
| 22 | + | if (problem == "No Problem") and (reactor.getFissionFuelName() == "No Fuel") then problem = "No Fuel" end |
| 23 | - | print(header) |
| 23 | + | return problem |
| 24 | - | end |
| 24 | + | end |
| 25 | - | repeat |
| 25 | + | reactor.deactivate() -- just so we know. |
| 26 | - | local keypress = event.pull(0, "key_down") |
| 26 | + | |
| 27 | - | if keypress then |
| 27 | + | -- scale a number in the 0 to 1 range to an integer in the 1 to n range in such a way that all integers are equally represented. |
| 28 | - | print("Keypress detected! Shutting down all reactors.") |
| 28 | + | local scalenumber = function(x, n) |
| 29 | - | for _, reactor in pairs(reactors) do |
| 29 | + | return math.floor(math.max(math.min(x * n + 1, n), 1)) |
| 30 | - | reactor.deactivate() |
| 30 | + | end |
| 31 | - | end |
| 31 | + | |
| 32 | - | os.exit() |
| 32 | + | -- stubs for term not being available. |
| 33 | - | end |
| 33 | + | local t = {
|
| 34 | - | if term then term.setCursor(1, 2) end |
| 34 | + | drawdisplay = function(t) |
| 35 | - | for i = 1, #reactors do |
| 35 | + | if isproblem() ~= "No Problem" then computer.beep(440, .1) end |
| 36 | - | local reactor = reactors[i] |
| 36 | + | end, |
| 37 | - | local energylevel = reactor.getEnergyStored() / reactor.getMaxEnergyStored() |
| 37 | + | err = function(s) |
| 38 | - | local heatlevel = reactor.getHeatLevel() / reactor.getMaxHeatLevel() |
| 38 | + | print(s) |
| 39 | - | local newfuzzyenergyshutdown = controls[i].fuzzyenergyshutdown and (energylevel > low) or (energylevel > high) |
| 39 | + | os.exit() |
| 40 | - | local newfuzzyheatshutdown = controls[i].fuzzyheatshutdown and (heatlevel > low) or (heatlevel > high) |
| 40 | + | end, |
| 41 | - | local newshutdown = newfuzzyenergyshutdown or newfuzzyheatshutdown |
| 41 | + | } |
| 42 | - | if newshutdown then reactor.deactivate() else reactor.activate() end |
| 42 | + | -- set up display stuff. |
| 43 | - | if term then |
| 43 | + | if term.isAvailable() then |
| 44 | - | print(string.format(formatstring, i, reactor.getFissionFuelName(), heatlevel * 100, energylevel * 100, outoffuel and "Out of fuel!" or (newshutdown and "Off " or "On "))) |
| 44 | + | local gpu = component.gpu |
| 45 | - | end |
| 45 | + | local sf, sb = gpu.setForeground, gpu.setBackground |
| 46 | - | controls[i].fuzzyenergyshutdown, controls[i].fuzzyheatshutdown, controls[i].shutdown = newfuzzyenergyshutdown, newfuzzyheatshutdown, newshutdown |
| 46 | + | t.err = function(s) |
| 47 | - | end |
| 47 | + | sf(0xffffff) |
| 48 | - | until false |
| 48 | + | sb(0x000000) |
| 49 | term.clear() | |
| 50 | term.write(s, true) | |
| 51 | os.exit() | |
| 52 | end | |
| 53 | sf(0xffffff) | |
| 54 | sb(0x000000) | |
| 55 | term.clear() | |
| 56 | local colorscreen = gpu.getDepth() ~= 1 | |
| 57 | local width, height = gpu.maxResolution() | |
| 58 | local aspectratio = 1 | |
| 59 | width = math.min(width, height * aspectratio * 2) -- * 2 because of character size | |
| 60 | -- we want the height to be a multiple of 4 plus 3. | |
| 61 | height = math.floor((width / 2 / aspectratio - 3) / 4) * 4 + 3 | |
| 62 | -- resize the width accordingly. | |
| 63 | width = math.floor(height * 2 * aspectratio) | |
| 64 | -- and set bar tops and height. | |
| 65 | local barheight = math.floor((height - 3) / 4) | |
| 66 | local bartops = {
| |
| 67 | energy = 1, | |
| 68 | heat = 2 + barheight, | |
| 69 | fueltime = 3 + barheight * 2, | |
| 70 | runtime = 4 + barheight * 3 | |
| 71 | } | |
| 72 | gpu.setResolution(width, height) | |
| 73 | local sevenths = {
| |
| 74 | energy = {0xff0000, 0xff8000, 0xffff00, 0x00ff00, 0xffff00, 0xff8000, 0xff0000},
| |
| 75 | heat = {0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0xffff00, 0xff8000, 0xff0000},
| |
| 76 | fueltime = {0xff0000, 0xff8000, 0xffff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00},
| |
| 77 | runtime = {0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00, 0xffff00}
| |
| 78 | } | |
| 79 | if not colorscreen then | |
| 80 | for i = 1, 7 do | |
| 81 | sevenths.energy[i] = 0xffffff | |
| 82 | end | |
| 83 | sevenths.heat, sevenths.fueltime, sevenths.runtime = sevenths.energy, sevenths.energy, sevenths.energy | |
| 84 | end | |
| 85 | -- draw a line of the display. | |
| 86 | local line = function(bartype, x, y, isblack) | |
| 87 | sb(isblack and 0 or sevenths[bartype][scalenumber((x - 1) / (width - 1), 7)]) | |
| 88 | gpu.fill(x, bartops[bartype], 1, y, " ") | |
| 89 | end | |
| 90 | -- initialize the display. | |
| 91 | for bartype, wedges in pairs(sevenths) do | |
| 92 | for x = 1, width do | |
| 93 | line(bartype, x, barheight) | |
| 94 | end | |
| 95 | end | |
| 96 | ||
| 97 | local lastreadings = {energy = -1, heat = -1, fueltime = -1, runtime = -1}
| |
| 98 | local lastnoproblem = true | |
| 99 | local operatingtrack = {}
| |
| 100 | for i = 1, width do table.insert(operatingtrack, false) end | |
| 101 | local tickson = 0 | |
| 102 | local currenttick = 0 | |
| 103 | ||
| 104 | -- draw the display. | |
| 105 | t.drawdisplay = function(t) | |
| 106 | sf(0xffffff) | |
| 107 | currenttick = (currenttick % width) + 1 | |
| 108 | if t.reactoron ~= operatingtrack[currenttick] then | |
| 109 | tickson = tickson + (t.reactoron and 1 or -1) | |
| 110 | operatingtrack[currenttick] = t.reactoron | |
| 111 | end | |
| 112 | t.runtime, t.reactoron = tickson / width, nil | |
| 113 | for bartype, fraction in pairs(t) do | |
| 114 | local reading = scalenumber(fraction, width) | |
| 115 | if lastreadings[bartype] ~= reading then | |
| 116 | line(bartype, lastreadings[bartype], math.floor(barheight / 2)) | |
| 117 | line(bartype, reading, math.floor(barheight / 2), true) | |
| 118 | lastreadings[bartype] = reading | |
| 119 | end | |
| 120 | end | |
| 121 | local problem = isproblem() | |
| 122 | local noproblem = (problem == "No Problem") | |
| 123 | if lastnoproblem ~= noproblem then | |
| 124 | problem = string.format("Error: %s!", problem)
| |
| 125 | problem = string.format("%s%s", string.rep(" ", math.floor((width - problem:len()) / 2)), problem)
| |
| 126 | sf(0xff0000) | |
| 127 | for _, bartype in pairs({"heat", "fueltime", "runtime"}) do
| |
| 128 | local y = bartops[bartype] - 1 | |
| 129 | gpu.fill(1, y, width - 1, 1, " ") | |
| 130 | if not noproblem then | |
| 131 | term.setCursor(1, y) | |
| 132 | term.write(problem) | |
| 133 | end | |
| 134 | end | |
| 135 | sf(0x000000) | |
| 136 | lastnoproblem = noproblem | |
| 137 | end | |
| 138 | if not noproblem then computer.beep(440, .1) end | |
| 139 | end | |
| 140 | end | |
| 141 | local drawdisplay, err = t.drawdisplay, t.err | |
| 142 | ||
| 143 | local scrub = function(reason) | |
| 144 | reactor.deactivate() | |
| 145 | err(string.format("%s! Shutting down reactor.", reason))
| |
| 146 | end | |
| 147 | ||
| 148 | local MaxEnergyStoredConstant, MaxHeatLevelConstant = reactor.getMaxEnergyStored(), reactor.getMaxHeatLevel() | |
| 149 | ||
| 150 | -- and here we go. | |
| 151 | computer.beep(440, .1) | |
| 152 | repeat | |
| 153 | local keypress = event.pull(0, "key_down") | |
| 154 | if keypress then scrub("Keypress detected") end
| |
| 155 | local status = {
| |
| 156 | energy = reactor.getEnergyStored() / MaxEnergyStoredConstant, | |
| 157 | heat = reactor.getHeatLevel() / MaxHeatLevelConstant, | |
| 158 | fueltime = reactor.getFissionFuelTime(), | |
| 159 | } | |
| 160 | if status.fueltime ~= 0 then status.fueltime = 1 - reactor.getCurrentProcessTime() / status.fueltime end -- avoiding divide by zero for no fuel | |
| 161 | status.reactoron = (status.energy <= 0.5) and (status.heat <= 0.5) | |
| 162 | reactor[status.reactoron and "activate" or "deactivate"]() | |
| 163 | drawdisplay(status) | |
| 164 | until false | |
| 165 |