SHOW:
|
|
- or go back to the newest paste.
1 | -- keeps reactor working efficiently at all times; increases power load when necessary, goes idle at 90% power until below 10% | |
2 | ||
3 | -- updated to Bigger Reactors; see earlier versions for the big reactors versions (they exist) | |
4 | - | local reactor,terminal --also searches for a terminal glasses terminal |
4 | + | |
5 | - | for k,v in pairs(rs.getSides()) do |
5 | + | timer=nil |
6 | - | if (peripheral.getType(v) == "BigReactors-Reactor") then |
6 | + | |
7 | local timeOperationTable={ | |
8 | __sub=function(a,b) | |
9 | - | break |
9 | + | if not a or not b then return false end |
10 | if b[2]>a[2] then | |
11 | return setmetatable({(a[1]-1)-b[1],(a[2]-b[2])%24},timeOperationTable) | |
12 | - | print('terminal found!') |
12 | + | else |
13 | return setmetatable({a[1]-b[1],a[2]-b[2]},timeOperationTable) | |
14 | end | |
15 | - | return reactor, terminal |
15 | + | end, |
16 | __tostring=function(t) | |
17 | return t[1]..' in-game days, ' .. math.floor(t[2]) ..' hours' | |
18 | end | |
19 | - | local reactor,terminal=findPeripherals() |
19 | + | } |
20 | ||
21 | - | local curPower,oldPower,controlRodLevel,powerMode,secondsWorked=0,0,100,0,0 |
21 | + | |
22 | local reactor,terminal,monitor | |
23 | for k,v in pairs(peripheral.getNames()) do | |
24 | local t = peripheral.getType(v) | |
25 | - | powerMode = reactor.getEnergyStored()<9000000 |
25 | + | if (t == "BiggerReactors_Reactor") then |
26 | reactor = peripheral.wrap(v) | |
27 | print('reactor found!') | |
28 | elseif (peripheral.getType(v) == "openperipheral_glassesbridge") and (not terminal) then | |
29 | - | secondsWorked=secondsWorked+1 |
29 | + | |
30 | - | print('Yes, I am working. Total time: ' .. secondsWorked .. ' steps.') |
30 | + | print('terminal glasses terminal found!') |
31 | - | oldPower=curPower |
31 | + | elseif (peripheral.getType(v) == 'monitor') then |
32 | - | curPower=reactor.getEnergyStored() |
32 | + | monitor=peripheral.wrap(v) |
33 | - | if oldPower==0 then |
33 | + | local x,y=monitor.getSize() |
34 | - | oldPower=curPower+(target*interval) |
34 | + | monitor.setTextScale(math.min(5,math.max(x/60,0.5))) |
35 | print('monitor found!') | |
36 | - | if curPower>9000000 then |
36 | + | |
37 | end | |
38 | - | elseif curPower<1000000 then |
38 | + | return reactor, terminal, monitor |
39 | end | |
40 | ||
41 | ||
42 | - | oldDeltaPower=deltaPower or 0 |
42 | + | local reactor,terminal,monitor=findPeripherals() |
43 | - | deltaPower = curPower-oldPower |
43 | + | |
44 | - | local curError = deltaPower-(target*interval) |
44 | + | local controlRodLevel,powerMode,tickCount,showAdvancedSettings=0,50,0,0,false |
45 | - | integral=integral+curError |
45 | + | |
46 | - | print('Error: ' .. curError) |
46 | + | local upTicks=0 |
47 | - | print('Integral: ' .. integral) |
47 | + | |
48 | - | local deltaControlRodLevel=(Kp*curError)+(Ki*integral) |
48 | + | |
49 | - | if deltaControlRodLevel>50 or deltaControlRodLevel<-50 then |
49 | + | |
50 | - | if curError<target*10 and curError>-target*10 then |
50 | + | local function powerPerc() |
51 | - | Kp=Kp/2 |
51 | + | return reactor.battery().stored()/reactor.battery().capacity() |
52 | - | end |
52 | + | |
53 | - | if integral>100000 or integral<100000 then |
53 | + | |
54 | - | integral=0 |
54 | + | local function reactivity() |
55 | - | end |
55 | + | return reactor.fuelTank().fuelReactivity() |
56 | - | end |
56 | + | |
57 | - | if deltaControlRodLevel>-1 and deltaControlRodLevel<1 then |
57 | + | |
58 | - | if curError>target*10 then |
58 | + | tempGuess = 1000 |
59 | - | Kp=Kp*1.5 |
59 | + | |
60 | - | end |
60 | + | tempGuessChange = 2 |
61 | - | end |
61 | + | |
62 | - | deltaControlRodLevel=deltaControlRodLevel<0 and math.ceil(deltaControlRodLevel) or deltaControlRodLevel>0 and math.floor(deltaControlRodLevel) or 0 |
62 | + | reactivities = {} |
63 | - | print('Control rod level change: ' .. deltaControlRodLevel) |
63 | + | |
64 | lastReactivity = 1 | |
65 | - | if controlRodLevel>100 or controlRodLevel<0 then |
65 | + | |
66 | bestFound = false | |
67 | ||
68 | powerMode = powerPerc() < 0.1 | |
69 | - | if curPower<10000 then |
69 | + | |
70 | - | controlRodLevel=0 |
70 | + | |
71 | term.clear() | |
72 | tickCount=tickCount+1 | |
73 | - | print('Current control rod level: ' .. controlRodLevel) |
73 | + | if powerMode and powerPerc()>0.99 then |
74 | powerMode=false | |
75 | timeStarted={os.day(),os.time()} --I keep repeating this because not doing it (using a function) makes setmetatable apparently completely and utterly fail to work and gives me a bunch of other stupid crap | |
76 | - | reactor.setAllControlRodLevels(100) |
76 | + | setmetatable(timeStarted,timeOperationTable) |
77 | - | print("Reactor's nearly full.") |
77 | + | elseif not powerMode and powerPerc()<0.1 then |
78 | - | print("Current status: off.") |
78 | + | |
79 | timeStarted={os.day(),os.time()} | |
80 | setmetatable(timeStarted,timeOperationTable) | |
81 | elseif powerPerc() < 0.001 then | |
82 | reactor.setActive(true) | |
83 | reactor.setAllControlRodLevels(0) | |
84 | - | local wastePercent=reactor.getWasteAmount()/reactor.getFuelAmountMax() |
84 | + | |
85 | - | local fuelPercent=(reactor.getWasteAmount()+reactor.getFuelAmount())/reactor.getFuelAmountMax() |
85 | + | |
86 | upTicks=upTicks+1 | |
87 | - | terminal.addBox(5,5,math.floor(curPower/100000),10,0x00cc00,0.8) |
87 | + | reactor.setActive(true) |
88 | local temperature = reactor.fuelTemperature() | |
89 | oldError=curError or 0 | |
90 | curError = temperature - tempGuess or 0 | |
91 | integral=integral+curError or 0 | |
92 | derivative = tickCount>1 and curError - oldError or 0 | |
93 | term.setCursorPos(1,1) | |
94 | term.write('Error: ' .. curError) | |
95 | term.setCursorPos(1,2) | |
96 | - | args = {...} |
96 | + | term.write('Integral: ' .. integral) |
97 | term.setCursorPos(1,3) | |
98 | - | interval = args[1] or 2 |
98 | + | term.write('Derivative: ' .. derivative) |
99 | - | target = args[2] or 100 |
99 | + | term.setCursorPos(1,4) |
100 | - | Kp=0.001 |
100 | + | Kp=Kp or 0.1*interval |
101 | - | Ki=0.0001 |
101 | + | Ki=Ki or 0.001*interval |
102 | Kd=Kd or 0.001*interval | |
103 | local deltaControlRodLevel=(Kp*curError)+(Ki*integral)+(Kd*derivative) | |
104 | - | target=tonumber(target) |
104 | + | term.write('Control rod level change: ' .. deltaControlRodLevel) |
105 | controlRodLevel = controlRodLevel+deltaControlRodLevel | |
106 | if controlRodLevel>100 or controlRodLevel<0 then | |
107 | integral=0 | |
108 | end | |
109 | controlRodLevel = controlRodLevel>100 and 100 or controlRodLevel<0 and 0 or controlRodLevel | |
110 | - | while reactor.getConnected() do |
110 | + | term.setCursorPos(1,5) |
111 | - | if interval then os.startTimer(interval) end |
111 | + | term.write('Current control rod level: ' .. controlRodLevel) |
112 | term.setCursorPos(1,6) | |
113 | - | if event[1]=='timer' then |
113 | + | term.write('Uptime: ' .. timeOperationTable.__tostring(setmetatable({os.day(),os.time()},timeOperationTable)-timeStarted)) --wow the normal tostring should really work here |
114 | - | reactorActivities() |
114 | + | term.setCursorPos(1,7) |
115 | term.write('Uptime percentage: ' ..(upTicks*100)/tickCount..'%') | |
116 | - | terminalActivities() |
116 | + | if term.isColor() then |
117 | term.setCursorPos(1,8) | |
118 | term.write('Error weight: ' .. Kp) | |
119 | term.setCursorPos(1,9) | |
120 | term.write('Integral weight: ' .. Ki) | |
121 | term.setCursorPos(1,10) | |
122 | term.write('Derivative weight: ' .. Kd) | |
123 | term.setCursorPos(1,11) | |
124 | term.write('Target temp: ' .. tempGuess) | |
125 | for i=8,11,1 do | |
126 | term.setCursorPos(30,i) | |
127 | term.write('+-') | |
128 | end | |
129 | end | |
130 | reactor.setAllControlRodLevels(controlRodLevel) | |
131 | else | |
132 | term.setCursorPos(1,1) | |
133 | term.write("Reactor's nearly full.") | |
134 | term.setCursorPos(1,2) | |
135 | term.write("Current status: off.") | |
136 | reactor.setActive(false) | |
137 | end | |
138 | end | |
139 | ||
140 | local function terminalActivities() | |
141 | terminal.clear() | |
142 | local fuel = reactor.fuelTank() | |
143 | local wastePercent=fuel.waste()/fuel.capacity() | |
144 | local fuelPercent=(fuel.waste()+fuel.fuel())/fuel.capacity() | |
145 | terminal.addBox(5,5,100,10,0xcc0000,0.8) | |
146 | terminal.addBox(5,5,math.floor(powerPerc()),10,0x00cc00,0.8) | |
147 | terminal.addBox(105,5,10,100,0xcccccc,0.8) | |
148 | terminal.addBox(105,5,10,controlRodLevel,0x303030,0.8) | |
149 | terminal.addBox(5,20,100,10,0x303030,0.8) | |
150 | terminal.addBox(5,20,math.min(math.floor(100*fuelPercent),100),10,0xcccc00,0.8) | |
151 | terminal.addBox(5,20,math.min(math.floor(100*wastePercent),100),10,0x00cccc,0.8) | |
152 | end | |
153 | ||
154 | local function monitorActivities() | |
155 | monitor.clear() | |
156 | monitor.setTextColor(colors.white) | |
157 | monitor.setCursorPos(1,1) | |
158 | monitor.write('Power mode: ') | |
159 | if powerMode then | |
160 | monitor.setTextColor(colors.green) | |
161 | monitor.write('On') | |
162 | monitor.setTextColor(colors.white) | |
163 | monitor.setCursorPos(1,4) | |
164 | monitor.write('Reactor working at ' .. 100-controlRodLevel .. '% capacity.') | |
165 | monitor.setCursorPos(1,5) | |
166 | monitor.write('Uptime: ' .. timeOperationTable.__tostring(setmetatable({os.day(),os.time()},timeOperationTable)-timeStarted)) | |
167 | else | |
168 | monitor.setTextColor(colors.red) | |
169 | monitor.write('Off') | |
170 | monitor.setTextColor(colors.white) | |
171 | monitor.setCursorPos(1,4) | |
172 | monitor.write("Reactor's off.") | |
173 | monitor.setCursorPos(1,5) | |
174 | monitor.write('Downtime: ' .. timeOperationTable.__tostring(setmetatable({os.day(),os.time()},timeOperationTable)-timeStarted)) | |
175 | end | |
176 | monitor.setCursorPos(1,2) | |
177 | monitor.write('Current temperature: ') | |
178 | monitor.setTextColor(curError>100 and colors.red or curError>10 and colors.orange or curError>-10 and colors.green or curError>-100 and colors.lightBlue or colors.cyan) | |
179 | monitor.write(reactor.fuelTemperature()) | |
180 | monitor.setCursorPos(1,3) | |
181 | monitor.setTextColor(colors.white) | |
182 | monitor.write('Current energy storage: ' .. reactor.battery().stored()) | |
183 | monitor.setCursorPos(1,6) | |
184 | monitor.write('Uptime percentage: ' ..(upTicks*100)/tickCount..'%') | |
185 | if monitor.isColor() then | |
186 | if showAdvancedSettings then | |
187 | monitor.setCursorPos(1,7) | |
188 | derweight='Derivative weight: ' .. Kd | |
189 | monitor.write('Error weight: ' .. Kp) | |
190 | monitor.setCursorPos(1,8) | |
191 | monitor.write('Integral weight: ' .. Ki) | |
192 | monitor.setCursorPos(1,9) | |
193 | monitor.write(derweight) | |
194 | monitor.setCursorPos(1,10) | |
195 | monitor.write("Target temp:" .. tempGuess) | |
196 | for i=7,10,1 do | |
197 | monitor.setCursorPos(string.len(derweight)+2,i) | |
198 | monitor.write('+-') | |
199 | end | |
200 | monitor.setCursorPos(1,11)--hate hardcoding hate hardcoding | |
201 | monitor.setTextColor(colors.yellow) | |
202 | monitor.write('Hide advanced settings') | |
203 | else | |
204 | monitor.setCursorPos(1,7) | |
205 | monitor.setTextColor(colors.yellow) | |
206 | monitor.write('Show advanced settings') | |
207 | end | |
208 | end | |
209 | end | |
210 | ||
211 | function monitorTouch(x,y) | |
212 | if showAdvancedSettings then -- all these global variables are going to make me sick | |
213 | if x==(string.len(derweight)>23 and string.len(derweight)+3 or string.len(derweight)+2) then | |
214 | if y==5 then | |
215 | Kp=Kp+0.05 | |
216 | elseif y==6 then | |
217 | Ki=Ki+(0.005*interval) | |
218 | elseif y==7 then | |
219 | Kd=Kd+0.01 | |
220 | elseif y==8 then | |
221 | tempGuess = tempGuess + 10 | |
222 | end | |
223 | elseif x==((string.len(derweight)>22) and string.len(derweight)+4 or string.len(derweight)+3) then --in case you're wondering, I have no idea either, but it's necessary | |
224 | if y==5 then | |
225 | Kp=Kp-0.05 | |
226 | elseif y==6 then | |
227 | Ki=Ki-(0.005*interval) | |
228 | elseif y==7 then | |
229 | Kd=Kd-0.01 | |
230 | elseif y==8 then | |
231 | tempGuess = tempGuess - 10 | |
232 | elseif y==9 then | |
233 | showAdvancedSettings=false | |
234 | end | |
235 | end | |
236 | else | |
237 | if y==5 then | |
238 | showAdvancedSettings=true | |
239 | end | |
240 | end | |
241 | end | |
242 | ||
243 | local args = {...} | |
244 | ||
245 | interval = args[1] or 0.5 | |
246 | ||
247 | interval=tonumber(interval) | |
248 | ||
249 | if interval<0.5 then | |
250 | interval=0.5 | |
251 | end | |
252 | ||
253 | local timeStarted={os.day(),os.time()} | |
254 | ||
255 | setmetatable(timeStarted,timeOperationTable) | |
256 | ||
257 | while reactor.connected() do | |
258 | if not timer then timer=os.startTimer(interval) end | |
259 | local event = {os.pullEvent()} | |
260 | if event[1]=='timer' and event[2]==timer then | |
261 | timer=nil | |
262 | pcall(reactorActivities) | |
263 | if terminal then | |
264 | pcall(terminalActivities) | |
265 | end | |
266 | if monitor then | |
267 | pcall(monitorActivities) | |
268 | end | |
269 | elseif event[1]=='mouse_click' then | |
270 | if event[2]=='1' then | |
271 | if event[3]==49 then | |
272 | if event[4]==5 then | |
273 | Kp=Kp+0.05 | |
274 | elseif event[4]==6 then | |
275 | Ki=Ki+(0.005*interval) | |
276 | elseif event[4]==7 then | |
277 | Kd=Kd+0.01 | |
278 | elseif event[4]==8 then | |
279 | tempGuess=tempGuess+10 | |
280 | end | |
281 | elseif event[3]==50 then | |
282 | if event[4]==5 then | |
283 | Kp=Kp-0.05 | |
284 | elseif event[4]==6 then | |
285 | Ki=Ki-(0.005*interval) | |
286 | elseif event[4]==7 then | |
287 | Kd=Kd-0.01 | |
288 | elseif event[4]==8 then | |
289 | tempGuess=tempGuess-10 | |
290 | end | |
291 | end | |
292 | end | |
293 | elseif event[1]=='monitor_touch' then | |
294 | pcall(monitorTouch,event[3],event[4]) | |
295 | pcall(monitorActivities) | |
296 | end | |
297 | end |