· 6 years ago · Oct 18, 2019, 06:02 PM
1-- RF Control Center (RFCC) v0.3
2-- by dlord
3
4
5-- Main configuration
6local tArgs = {...}
7local CONFIG_FILE = "power_conf"
8
9local CONFIG_TEMPLATE = [[-- adjust these configuration options as necessary.
10-- delay for checking all capacitors
11TICK_DELAY = ${tickDelay}
12
13-- threshold in percentages
14GREEN_ZONE = ${greenZone}
15YELLOW_ZONE = ${yellowZone}
16
17NORMAL_POWER_THRESHOLD = ${nomalPowerThreshold}
18LOW_POWER_THRESHOLD = ${lowPowerThreshold}
19
20-- configures what side to emit when low power
21-- a valid side is required.
22SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER = "${sideForRedstone}"
23
24-- Active monitors on startup
25MONITORS_ACTIVE = ${monitorsActive}
26]]
27
28local MONITORS_ACTIVE = {}
29
30do
31 if #tArgs > 0 and tArgs[1] == "update" then
32 print("Updating RFCC...")
33 local updateFile = "/rfcc_update"
34 local pastebinKey = "TfeHE7Wy"
35 shell.run("pastebin", "get", pastebinKey, updateFile)
36
37 if fs.exists(updateFile) then
38 local programPath = shell.getRunningProgram()
39 fs.delete(programPath)
40 fs.move(updateFile, programPath)
41 print("Success!")
42 return
43 else
44 print("Unable to retrieve update from pastebin.")
45 print("Check your connection, and try again.")
46 error()
47 end
48 end
49end
50
51local function interpolate(s, params)
52 return s:gsub('($%b{})', function(w) return params[w:sub(3, -2)] or w end)
53end
54
55local function saveSettings()
56 local h = fs.open("/"..CONFIG_FILE, "w")
57
58 local settings = {
59 tickDelay = TICK_DELAY or 10,
60 greenZone = GREEN_ZONE or 70,
61 yellowZone = YELLOW_ZONE or 30,
62 nomalPowerThreshold = NORMAL_POWER_THRESHOLD or 90,
63 lowPowerThreshold = LOW_POWER_THRESHOLD or 10,
64 sideForRedstone = SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER or "bottom",
65 monitorsActive = textutils.serialize(MONITORS_ACTIVE)
66 }
67
68 h.write(interpolate(CONFIG_TEMPLATE, settings))
69 h.close()
70end
71
72
73if fs.exists(CONFIG_FILE) == false then
74 print("Config introuvable.")
75 print("Génération...")
76
77 saveSettings()
78
79 print("")
80 print("Config > /"..CONFIG_FILE)
81 print("Reboot par la suite.")
82 return
83else
84 os.unloadAPI(CONFIG_FILE)
85
86 if os.loadAPI("/"..CONFIG_FILE) == false then
87 error("Fichier config > Erreur !")
88 end
89
90 CONFIG = nil
91 for k, v in pairs(_G) do
92 if k == CONFIG_FILE then
93 CONFIG = v
94 break
95 end
96 end
97
98 if CONFIG == nil then
99 print("Config introuvable.")
100 print("Quleque chose ne va pas.")
101 error()
102 end
103end
104
105term.setCursorPos(1, 1)
106term.clear()
107print("Démarrage...")
108sleep(2)
109
110-- Constants
111local GET_ENERGY_STORED_FUNCTION="getEnergyStored"
112local GET_MAX_ENERGY_STORED_FUNCTION="getMaxEnergyStored"
113
114local TICK_DELAY = CONFIG.TICK_DELAY
115local PAUSE_TIME_IN_SECONDS = TICK_DELAY / 20
116
117-- threshold in percentages
118local GREEN_ZONE = CONFIG.GREEN_ZONE
119local YELLOW_ZONE = CONFIG.YELLOW_ZONE
120
121local NORMAL_POWER_THRESHOLD = CONFIG.NORMAL_POWER_THRESHOLD
122local LOW_POWER_THRESHOLD = CONFIG.LOW_POWER_THRESHOLD
123
124-- configures what side to emit when low power
125local SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER = CONFIG.SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER
126
127MONITORS_ACTIVE = CONFIG.MONITORS_ACTIVE
128
129-- state variables
130local clickableLines = {}
131local clickableOutputMonitors = {}
132local monitors = {}
133local capacitors = {}
134local dashboardButtons = {}
135local totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0
136
137-- Capacitor basic functions
138do
139 capacitors.add = function(params)
140 table.insert(capacitors, params)
141 end
142
143 capacitors.get = function(name)
144 for i, v in ipairs(capacitors) do
145 if name == v.name then
146 return v
147 end
148 end
149
150 return nil
151 end
152
153 capacitors.remove = function(name)
154 local found = nil
155 for i, v in ipairs(capacitors) do
156 if name == v.name then
157 found = i
158 break
159 end
160 end
161
162 if found then
163 table.remove(capacitors, found)
164 end
165 end
166
167 capacitors.clear = function()
168 for i, v in ipairs(capacitors) do
169 capacitors[i] = nil
170 end
171 end
172end
173
174
175-- Special Windows
176local nativeDisplayTabs = {}
177local nativeMonitorTabWindow
178local consoleWindow
179local monitorSelectionWindow
180
181do
182 local nativeTerm = term.native()
183 local width, height = term.getSize()
184 local x, y = 1, 2
185 local newWidth, newHeight = width, height - 1
186
187 nativeTerm.setCursorPos(x, y)
188
189 nativeMonitorTabWindow = window.create(nativeTerm, 1, 1, width, 1, false)
190
191 consoleWindow = window.create(nativeTerm, x, y, newWidth, newHeight, false)
192 consoleWindow.active = true
193
194 monitorSelectionWindow = window.create(nativeTerm, x, y, newWidth, newHeight, false)
195 monitorSelectionWindow.active = true
196end
197
198-- TODO: break up this humongous script into smaller chunks that can be loaded
199-- via os.loadAPI().
200
201
202-- basic functions
203local function tableSize(targetTable)
204 local i = 0
205 for k, v in pairs(targetTable) do
206 i = i + 1
207 end
208
209 return i
210end
211
212local function padRight(text, width, padCharacter)
213 if width == nil then
214 width = term.getSize()
215 end
216
217 padCount = width - string.len(text)
218
219 if padCharacter == nil then
220 padCharacter = " "
221 end
222
223 if padCount > 0 then
224 return text..string.rep(padCharacter, padCount)
225 else
226 return text
227 end
228end
229
230local function padLeft(text, width, padCharacter)
231 if width == nil then
232 width = term.getSize()
233 end
234
235 padCount = width - string.len(text)
236
237 if padCharacter == nil then
238 padCharacter = " "
239 end
240
241 if padCount > 0 then
242 return string.rep(padCharacter, padCount)..text
243 else
244 return text
245 end
246end
247
248local function printZoneText(percent, callback)
249 if percent >= GREEN_ZONE then
250 term.setTextColor(colors.green)
251 elseif percent >= YELLOW_ZONE and percent < GREEN_ZONE then
252 term.setTextColor(colors.yellow)
253 else
254 term.setTextColor(colors.red)
255 end
256
257 callback()
258
259 term.setTextColor(colors.white)
260end
261
262local function resetRedstoneState()
263 for k,v in pairs(rs.getSides()) do
264 rs.setOutput(v, false)
265 end
266end
267-- basic functions
268
269
270-- line drawing API
271local function drawVerticalLine(targetWindow, x, y, height)
272 targetWindow.setCursorPos(x, y)
273
274 targetWindow.setBackgroundColor(colors.blue)
275 for i = 1, height do
276 targetWindow.write(" ")
277 targetWindow.setCursorPos(x, i)
278 end
279 targetWindow.setBackgroundColor(colors.black)
280end
281
282local function drawHorizontalLine(targetWindow, x, y, width)
283 targetWindow.setCursorPos(x, y)
284 targetWindow.setBackgroundColor(colors.blue)
285 targetWindow.write(string.rep(" ", width))
286 targetWindow.setBackgroundColor(colors.black)
287end
288-- line drawing API
289
290
291-- window management
292local console = {
293 log = function(message)
294 local currentTerm = term.current()
295 term.redirect(consoleWindow)
296
297 print(message)
298
299 term.redirect(currentTerm)
300 end
301}
302
303local function showWindows(...)
304 for i, v in ipairs(arg) do
305 if v.active == true then
306 v.setVisible(true)
307 else
308 v.setVisible(false)
309 end
310 end
311end
312
313local function hideWindows(...)
314 for i, v in ipairs(arg) do
315 v.setVisible(false)
316 end
317end
318
319local function getCursorPositionRelativeToParent(currentWindow)
320 -- determine offset of current window from parent
321 local x, y = currentWindow.getPosition()
322 local xOffset, yOffset = x - 1, y - 1
323
324 local cursorX, cursorY = currentWindow.getCursorPos()
325 return cursorX + xOffset, cursorY + yOffset
326end
327
328local function createInformationWindow(parentWindow)
329 local width, height = parentWindow.getSize()
330
331 local widthOffset = 2
332 local heightOffset = 2
333
334 local windowWidth = width - (widthOffset * 2)
335 local windowHeight = height - (heightOffset * 2)
336
337 local informationWindow = window.create(parentWindow, 1 + widthOffset, 1 + heightOffset, windowWidth, windowHeight, false)
338 informationWindow.active = false
339
340 drawHorizontalLine(informationWindow, 1, 1, windowWidth)
341 drawHorizontalLine(informationWindow, 1, windowHeight, windowWidth)
342
343 drawVerticalLine(informationWindow, 1, 1, windowHeight)
344 drawVerticalLine(informationWindow, windowWidth, 1, windowHeight)
345
346 return informationWindow
347end
348
349local function createSummaryWindow(parentWindow, x, y)
350 local width, height = parentWindow.getSize()
351
352 -- we make use of the parent window's cursor position to make it more convenient.
353 local x, y = parentWindow.getCursorPos()
354 local newHeight = height - (y - 1)
355
356 local summaryWindow = window.create(parentWindow, x, y, width, newHeight, false)
357 summaryWindow.active = false
358
359 return summaryWindow
360end
361
362local function printToWindow(targetWindow, widthOffset, text)
363 local x, y = targetWindow.getCursorPos()
364 local width, height = targetWindow.getSize()
365 local maxTextSize = width - (widthOffset * 2)
366
367 targetWindow.write(text:sub(1, maxTextSize))
368 targetWindow.setCursorPos(x, y+1)
369end
370
371local function createDashboardWindows(parentWindow)
372 -- order is important here!
373 local summaryWindow = createSummaryWindow(parentWindow)
374 summaryWindow.active = true
375 local informationWindow = createInformationWindow(parentWindow)
376 informationWindow.active = false
377
378 local windows = {
379 [1] = summaryWindow,
380 [2] = informationWindow,
381
382 getSummaryWindow = function()
383 return summaryWindow
384 end,
385
386 getInformationWindow = function()
387 return informationWindow
388 end
389 }
390
391 return windows
392end
393
394local function initializeNativeDisplayTabs()
395 local nativeTerm = term.native()
396 nativeTerm.setCursorPos(1, 2)
397
398 local dashboardWindows = createDashboardWindows(nativeTerm)
399
400 table.insert(nativeDisplayTabs, {
401 tab = {
402 label = "Panel",
403 event = "dashboard_clicked",
404 active = true,
405 startX = 0,
406 startY = 0
407 },
408
409 windows = dashboardWindows
410 })
411 table.insert(nativeDisplayTabs, {
412 tab = {
413 label = "Ecran",
414 event = "monitors_clicked",
415 startX = 0,
416 startY = 0
417 },
418
419 windows = { monitorSelectionWindow }
420 })
421 table.insert(nativeDisplayTabs, {
422 tab = {
423 label = "Console",
424 event = "console_clicked",
425 startX = 0,
426 startY = 0
427 },
428
429 windows = { consoleWindow }
430 })
431
432 nativeDisplayTabs.getSelectedTab = function(x, y)
433 if x == nil or y == nil then
434 return nil
435 end
436
437 for i, v in ipairs(nativeDisplayTabs) do
438 local tab = v.tab
439 local withinX = x >= tab.startX and x <= tab.endX
440 local withinY = y >= tab.startY and y <= tab.endY
441
442 if withinX and withinY then
443 return i
444 end
445 end
446
447 return nil
448 end
449
450 nativeDisplayTabs.setSelectedTab = function(selected)
451 for i, v in ipairs(nativeDisplayTabs) do
452 if i == selected then
453 v.tab.active = true
454 else
455 v.tab.active = false
456 end
457 end
458 end
459
460 nativeDisplayTabs.getActiveTab = function()
461 for i, v in ipairs(nativeDisplayTabs) do
462 if v.tab.active == true then
463 return i
464 end
465 end
466 end
467
468 nativeDisplayTabs.getDashboardWindows = function()
469 return dashboardWindows
470 end
471end
472
473-- window management
474
475
476-- capacitor management
477local function addCapacitors(...)
478 local peripheralList = arg
479
480 if #peripheralList == 0 then
481 peripheralList = peripheral.getNames()
482 capacitors.clear()
483 end
484
485 for i, p in ipairs(peripheralList) do
486 local currentPeripheral = peripheral.wrap(p)
487
488 if currentPeripheral[GET_ENERGY_STORED_FUNCTION] ~= nil and currentPeripheral[GET_MAX_ENERGY_STORED_FUNCTION] ~= nil and currentPeripheral[GET_ENERGY_STORED_FUNCTION]("north") ~= nil then
489 console.log("Nouveau Stockage: "..p)
490 capacitors.add({
491 name = p,
492 peripheral = currentPeripheral,
493 lastReading = 0,
494 flowRate = 0,
495 percent = 0
496 })
497 end
498 end
499end
500
501local function removeCapacitors(...)
502 for i, k in ipairs(arg) do
503 capacitors.remove(k)
504 end
505end
506
507local function getReading()
508 local totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0
509
510 for i, v in ipairs(capacitors) do
511 local currentReading = v.peripheral[GET_ENERGY_STORED_FUNCTION]("north") or 0
512 local capacity = v.peripheral[GET_MAX_ENERGY_STORED_FUNCTION]("north") or 0
513
514 if currentReading ~= nil then
515 v.flowRate = (currentReading - v.lastReading) / TICK_DELAY
516 v.lastReading = currentReading
517
518 if capacity == 0 then
519 v.percent = 0
520 else
521 v.percent = math.floor((currentReading / capacity) * 100)
522 end
523
524 totalEnergyAvailable = totalEnergyAvailable + v.lastReading
525 totalFlowRate = totalFlowRate + v.flowRate
526 end
527
528 totalCapacity = totalCapacity + capacity
529 end
530
531 local sortByLastReading = function(a, b)
532 return a.percent > b.percent
533 end
534
535 table.sort(capacitors, sortByLastReading)
536
537 return totalEnergyAvailable, totalCapacity, totalFlowRate
538end
539
540local function emitRedstoneSignalOnLowPower(percent)
541 if percent < LOW_POWER_THRESHOLD and rs.getOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER) == false then
542 console.log("Low power threshold reached.")
543 rs.setOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER, true)
544 elseif percent >= NORMAL_POWER_THRESHOLD and rs.getOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER) == true then
545 console.log("Back to normal power levels.")
546 rs.setOutput(SIDE_TO_EMIT_REDSTONE_ON_LOW_POWER, false)
547 end
548end
549-- capacitor management
550
551
552-- monitor management
553local function addMonitors(...)
554 local monitorList = arg
555
556 if #monitorList == 0 then
557 monitorList = peripheral.getNames()
558 monitors = {}
559 end
560
561 for i, m in ipairs(monitorList) do
562 local currentPeripheral = peripheral.wrap(m)
563
564 if "monitor" == peripheral.getType(m) and currentPeripheral.isColour() == true then
565 console.log("Ajout nouveaux écran: "..m)
566 currentPeripheral.setCursorPos(1, 1)
567 monitors[m] = {
568 peripheral = currentPeripheral,
569 windows = createDashboardWindows(currentPeripheral),
570 active = false
571 }
572 end
573 end
574end
575
576local function removeMonitors(...)
577 local activeMonitorsCount = tableSize(MONITORS_ACTIVE)
578
579 for i, k in ipairs(arg) do
580 monitors[k] = nil
581 dashboardButtons[k] = nil
582 MONITORS_ACTIVE[k] = nil
583 end
584
585 if activeMonitorsCount ~= tableSize(MONITORS_ACTIVE) then
586 saveSettings()
587 end
588end
589-- monitor management
590
591
592-- hotplug system
593local function doWhileMonitorSuspended(callback)
594 os.queueEvent("pause_monitor")
595 callback()
596 os.queueEvent("resume_monitor")
597end
598
599local function hotplugPeripherals()
600 while true do
601 local event, name = os.pullEvent()
602 local callback = nil
603
604 if event == "peripheral" then
605 console.log("Detected new peripheral: "..name)
606
607 callback = function()
608 addMonitors(name)
609 addCapacitors(name)
610 end
611 elseif event == "peripheral_detach" then
612 console.log("Peripheral removed: "..name)
613
614 callback = function()
615 removeMonitors(name)
616 removeCapacitors(name)
617 end
618 elseif event == "monitor_resize" then
619 console.log("Monitor resized: "..name)
620
621 callback = function()
622 monitors[name].peripheral.setCursorPos(1, 1)
623 monitors[name].windows = createDashboardWindows(monitors[name].peripheral)
624 dashboardButtons[name] = nil
625
626 if monitors[name].active == true then
627 showWindows(unpack(monitors[name].windows))
628 end
629 end
630 end
631
632 if callback ~= nil then
633 doWhileMonitorSuspended(callback)
634 end
635 end
636end
637-- hotplug system
638
639
640-- information window for the capacitors
641local function addClickableLine(monitorName, key, currentY)
642 clickableLines[monitorName][key] = {
643 line = currentY
644 }
645end
646
647local function toggleInformationWindow(summaryWindow, informationWindow, capacitorName)
648 if capacitorName == nil then
649 summaryWindow.active = true
650 informationWindow.active = false
651 else
652 summaryWindow.active = not summaryWindow.active
653 informationWindow.active = not informationWindow.active
654 end
655
656 local capacitor = capacitors.get(capacitorName)
657
658 if informationWindow.active == true then
659 widthOffset = 3
660 heightOffset = 3
661
662 informationWindow.setCursorPos(widthOffset, heightOffset)
663 local width, height = informationWindow.getSize()
664 local labelWidth = width - (widthOffset * 2)
665 local capacity = capacitor.peripheral[GET_MAX_ENERGY_STORED_FUNCTION]("north")
666
667 printToWindow(informationWindow, widthOffset, "Nom:")
668 printToWindow(informationWindow, widthOffset, padRight(" "..capacitorName, labelWidth))
669 printToWindow(informationWindow, widthOffset, "Type:")
670 printToWindow(informationWindow, widthOffset, padRight(" "..peripheral.getType(capacitorName), labelWidth))
671 printToWindow(informationWindow, widthOffset, "Capacité:")
672 printToWindow(informationWindow, widthOffset, padRight(" "..capacity.." RF", labelWidth))
673 printToWindow(informationWindow, widthOffset, "Actuel:")
674 printToWindow(informationWindow, widthOffset, padRight(" "..capacitor.lastReading.." RF", labelWidth))
675
676 local closeLabel = " Clique pour fermer "
677
678 local x = math.floor(((width - string.len(closeLabel)) / 2 ) + 0.5)
679
680 informationWindow.setCursorPos(x, height-2)
681
682 informationWindow.setBackgroundColor(colors.red)
683 informationWindow.write(closeLabel)
684 informationWindow.setBackgroundColor(colors.black)
685 end
686
687 showWindows(summaryWindow, informationWindow)
688end
689
690local function checkForSelectableLine(monitorName, x, y)
691 if clickableLines[monitorName] == nil then
692 return nil
693 end
694
695 for k,v in pairs(clickableLines[monitorName]) do
696 if y == v.line then
697 return k
698 end
699 end
700
701 return nil
702end
703
704local function getSelectedDashboardButton(monitorName, x, y)
705 if x == nil or y == nil then
706 return nil
707 end
708
709 local v = dashboardButtons[monitorName]
710
711 local nextButtonSelected = (x >= v.next.startX and x <= v.next.endX) and (y >= v.next.startY and y <= v.next.endY)
712 local prevButtonSelected = (x >= v.prev.startX and x <= v.prev.endX) and (y >= v.prev.startY and y <= v.prev.endY)
713
714 if nextButtonSelected then
715 return "next"
716 elseif prevButtonSelected then
717 return "prev"
718 end
719
720 return nil
721end
722
723-- information window for the capacitors
724
725
726-- main display
727local function renderPaginationButtons(monitorName, max)
728 local width, height = term.getSize()
729 local nextButton = " Suivant "
730 local previousButton = " Retour "
731 local spacer = " "
732
733 local dashboardButtonsToRender = previousButton..spacer..nextButton
734 local buttonOffset = (width - (string.len(dashboardButtonsToRender))) / 2
735
736 term.setCursorPos(buttonOffset, height)
737 local x, y = getCursorPositionRelativeToParent(term.current())
738
739 if dashboardButtons[monitorName] == nil then
740 dashboardButtons[monitorName] = {
741 prev = {
742 startX = x,
743 startY = y,
744 endX = x,
745 endY = y
746 },
747
748 next = {
749 startX = x,
750 startY = y,
751 endX = x,
752 endY = y
753 },
754
755 offset = 1,
756 max = max
757 }
758 end
759
760 if dashboardButtons[monitorName].offset == 1 then
761 dashboardButtons[monitorName].max = max
762 end
763
764 term.setBackgroundColor(colors.red)
765 term.write(previousButton)
766 dashboardButtons[monitorName].prev.endX, dashboardButtons[monitorName].prev.endY = getCursorPositionRelativeToParent(term.current())
767
768 term.setBackgroundColor(colors.black)
769 term.write(spacer)
770
771 dashboardButtons[monitorName].next.startX, dashboardButtons[monitorName].next.startY = getCursorPositionRelativeToParent(term.current())
772 term.setBackgroundColor(colors.red)
773 term.write(nextButton)
774 dashboardButtons[monitorName].next.endX, dashboardButtons[monitorName].next.endY = getCursorPositionRelativeToParent(term.current())
775
776 term.setBackgroundColor(colors.black)
777end
778
779local function writeSummary(monitorName, totalEnergyAvailable, totalCapacity, totalFlowRate)
780 local width, height = term.getSize()
781 local gridLabel = os.getComputerLabel() or "Stockage Energie Team DraconiC"
782 local gridLabelOffset = (width - (string.len(gridLabel))) / 2
783
784 term.setCursorPos(gridLabelOffset, 1)
785 term.write(gridLabel)
786 term.setCursorPos(1, 3)
787
788 print(padRight("Core: "..tostring(#capacitors)))
789 print(padRight("Maximum: "..totalCapacity.." RF"))
790
791 local totalPercentRemaining = math.floor((totalEnergyAvailable / totalCapacity) * 100)
792 emitRedstoneSignalOnLowPower(totalPercentRemaining)
793
794 printZoneText(totalPercentRemaining, function() print(padRight("Energie Disponible : "..totalEnergyAvailable.." RF")) end)
795
796 if totalFlowRate < 0 then
797 term.setTextColor(colors.red)
798 elseif totalFlowRate > 0 then
799 term.setTextColor(colors.green)
800 else
801 term.setTextColor(colors.white)
802 end
803
804 print(padRight("Flux Actuel : "..totalFlowRate.." RF/t"))
805 term.setTextColor(colors.white)
806
807 local currentX, currentY = term.getCursorPos()
808 term.setCursorPos(1, currentY+1)
809
810 clickableLines[monitorName] = {}
811 local pagination = dashboardButtons[monitorName] or {}
812 local offset = pagination.offset or 1
813
814 local count = 0
815 for i = offset, #capacitors do
816 local v = capacitors[i]
817 local name = string.format(" %03d", i)..": "
818 local percent = v.percent
819
820 printZoneText(percent, function() term.write(name) end)
821
822 local labelLength = string.len(name)
823 local powerBarLength = width - labelLength - 1
824 local powerBarReading = math.floor((width - labelLength - 1) * (percent/100))
825
826 local zoneColor = colors.red
827 local textColor = colors.white
828 if percent >= GREEN_ZONE then
829 zoneColor = colors.green
830 elseif percent >= YELLOW_ZONE and percent < GREEN_ZONE then
831 zoneColor = colors.yellow
832 textColor = colors.blue
833 end
834
835 local stats = padRight(string.format(" %d", percent).."%, "..v.flowRate.." RF/t", powerBarLength)
836
837 term.setTextColor(textColor)
838 term.setBackgroundColor(zoneColor)
839 j = 1
840 for c in stats:gmatch(".") do
841 if(j>powerBarReading) then
842 term.setBackgroundColor(colors.black)
843 end
844
845 term.write(c)
846
847 j = j + 1
848 end
849 term.setTextColor(colors.white)
850 term.setBackgroundColor(colors.black)
851
852 local currentX, currentY = getCursorPositionRelativeToParent(term.current())
853 addClickableLine(monitorName, v.name, currentY)
854
855 local termX, termY = term.getCursorPos()
856 term.setCursorPos(1, termY+2)
857 count = count + 1
858
859 if termY > (height - 4) then
860 max = count
861 break
862 end
863 end
864
865 local currentX, currentY = term.getCursorPos()
866 for k = currentY, height-1 do
867 term.setCursorPos(1, k)
868 term.clearLine()
869 end
870
871 renderPaginationButtons(monitorName, count)
872end
873
874local function displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate, targetMonitor)
875 local listOfSummaryWindows = {
876 native = nativeDisplayTabs.getDashboardWindows().getSummaryWindow()
877 }
878
879 for k, v in pairs(monitors) do
880 listOfSummaryWindows[k] = v.windows.getSummaryWindow()
881 end
882
883 for k, v in pairs(listOfSummaryWindows) do
884 if targetMonitor == nil or (k == targetMonitor) then
885 local currentTerm = term.current()
886
887 term.redirect(v)
888
889 writeSummary(k, totalEnergyAvailable, totalCapacity, totalFlowRate)
890
891 term.redirect(currentTerm)
892
893 if k == targetMonitor then
894 return
895 end
896 end
897 end
898end
899
900local function monitorCapacitors()
901 totalEnergyAvailable, totalCapacity, totalFlowRate = 0, 0, 0
902
903 while true do
904 -- show reading
905 displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate)
906
907 -- need to call this first to get most current sample
908 getReading()
909
910 local samplingTimer = os.startTimer(PAUSE_TIME_IN_SECONDS)
911 while true do
912 local event, p1 = os.pullEvent()
913 if event == "timer" and p1 == samplingTimer then
914 totalEnergyAvailable, totalCapacity, totalFlowRate = getReading()
915 break
916 elseif event == "pause_monitor" then
917 os.pullEvent("resume_monitor")
918 break
919 end
920 end
921 end
922end
923
924local function changePages(monitor, x, y, isInformationWindowActive)
925 local selectedButton = getSelectedDashboardButton(monitor, x, y)
926 local showSummary = false
927
928 if selectedButton == "next" and not isInformationWindowActive then
929 local newOffset = dashboardButtons[monitor].offset + (dashboardButtons[monitor].max or 0)
930 if newOffset <= #capacitors then
931 dashboardButtons[monitor].offset = newOffset
932
933 showSummary = true
934 end
935 elseif selectedButton == "prev" and not isInformationWindowActive then
936 local newOffset = dashboardButtons[monitor].offset - (dashboardButtons[monitor].max or 0)
937 if newOffset > 0 then
938 dashboardButtons[monitor].offset = newOffset
939 else
940 dashboardButtons[monitor].offset = 1
941 end
942
943 showSummary = true
944 end
945
946 if showSummary then
947 displaySummary(totalEnergyAvailable, totalCapacity, totalFlowRate, p1)
948 return true
949 end
950
951 return false
952end
953
954local function nativeDashboardHandler()
955 while true do
956 local event, x, y = os.pullEvent("dashboard_clicked")
957 local isInformationWindowActive = nativeDisplayTabs.getDashboardWindows().getInformationWindow().active
958
959 if not changePages("native", x, y, isInformationWindowActive) then
960 local selectedCapacitor = checkForSelectableLine("native", x, y)
961
962 local summaryWindow = nativeDisplayTabs.getDashboardWindows().getSummaryWindow()
963 local informationWindow = nativeDisplayTabs.getDashboardWindows().getInformationWindow()
964
965 toggleInformationWindow(summaryWindow, informationWindow, selectedCapacitor)
966 end
967 end
968end
969
970local function monitorDashboardHandler()
971 while true do
972 local event, monitor, x, y = os.pullEvent("monitor_touch")
973
974 if monitors[monitor].active == true then
975 local summaryWindow = monitors[monitor].windows.getSummaryWindow()
976 local informationWindow = monitors[monitor].windows.getInformationWindow()
977
978 if not changePages(monitor, x, y, informationWindow.active) then
979 local selectedCapacitor = checkForSelectableLine(monitor, x, y)
980 toggleInformationWindow(summaryWindow, informationWindow, selectedCapacitor)
981 end
982 end
983 end
984end
985-- main display
986
987
988-- monitor selection screen (if monitor is attached)
989local function addClickableOutputMonitor(k, currentY)
990 clickableOutputMonitors[k] = {
991 line = currentY
992 }
993end
994
995local function toggleMonitor(monitorName)
996 monitors[monitorName].active = not monitors[monitorName].active
997
998 if monitors[monitorName].active then
999 console.log("Enabling "..monitorName)
1000 MONITORS_ACTIVE[monitorName] = true
1001 else
1002 console.log("Disabling "..monitorName)
1003 MONITORS_ACTIVE[monitorName] = nil
1004
1005 hideWindows(unpack(monitors[monitorName].windows))
1006 monitors[monitorName].peripheral.setBackgroundColor(colors.black)
1007 monitors[monitorName].peripheral.clear()
1008 end
1009
1010 saveSettings()
1011end
1012
1013local function showMonitorSelection(targetWindow)
1014 local currentTerm = term.current()
1015
1016 term.redirect(targetWindow)
1017 term.setCursorPos(1, 1)
1018 term.clear()
1019
1020 local width, height = term.getSize()
1021
1022 if tableSize(monitors) > 0 then
1023 printToWindow(term, 0, "Ecran: ")
1024 else
1025 printToWindow(term, 0, "Aucun dispo.")
1026 end
1027
1028 printToWindow(term, 0, "")
1029
1030 local currentX, currentY = term.getCursorPos()
1031 term.setCursorPos(currentX + 2, currentY)
1032
1033 clickableOutputMonitors = {}
1034 for k, v in pairs(monitors) do
1035 currentX, currentY = getCursorPositionRelativeToParent(targetWindow)
1036 term.setBackgroundColor(colors.black)
1037
1038 if v.active == true then
1039 term.setBackgroundColor(colors.blue)
1040 showWindows(unpack(v.windows))
1041 end
1042
1043 label = padRight(" "..k, width-4)
1044 printToWindow(term, 0, label)
1045
1046 addClickableOutputMonitor(k, currentY)
1047 end
1048 term.setBackgroundColor(colors.black)
1049
1050 term.redirect(currentTerm)
1051
1052 while true do
1053 local event, x, y = os.pullEvent()
1054
1055 if "monitors_clicked" == event then
1056 for k, v in pairs(clickableOutputMonitors) do
1057 if v.line == y then
1058 toggleMonitor(k)
1059 return
1060 end
1061 end
1062 elseif event == "peripheral" or event == "peripheral_detach" then
1063 coroutine.yield()
1064 return
1065 end
1066 end
1067end
1068
1069local function monitorSelection()
1070 for k, v in pairs(MONITORS_ACTIVE) do
1071 if monitors[k] then
1072 monitors[k].active = true
1073 end
1074 end
1075
1076 while true do
1077 showMonitorSelection(monitorSelectionWindow)
1078 end
1079end
1080
1081local function nativeDisplay()
1082 while true do
1083 local currentTerm = term.current()
1084
1085 term.redirect(nativeMonitorTabWindow)
1086 nativeMonitorTabWindow.setVisible(true)
1087
1088 term.setCursorPos(1, 1)
1089 term.setBackgroundColor(colors.gray)
1090 term.clearLine()
1091 term.setTextColor(colors.yellow)
1092
1093 for i, v in ipairs(nativeDisplayTabs) do
1094 hideWindows(unpack(v.windows))
1095 end
1096
1097 for i, v in ipairs(nativeDisplayTabs) do
1098 local tab = v.tab
1099 tab.startX, tab.startY = getCursorPositionRelativeToParent(term.current())
1100
1101 if tab.active then
1102 term.setBackgroundColor(colors.black)
1103 showWindows(unpack(v.windows))
1104 else
1105 term.setBackgroundColor(colors.gray)
1106 end
1107
1108 term.write(" "..tab.label.." ")
1109 tab.endX, tab.endY = getCursorPositionRelativeToParent(term.current())
1110 end
1111 term.setTextColor(colors.white)
1112 term.redirect(currentTerm)
1113
1114 while true do
1115 local event, selectedTab = os.pullEvent("selected_tab")
1116
1117 if selectedTab then
1118 nativeDisplayTabs.setSelectedTab(selectedTab)
1119 break
1120 end
1121 end
1122 end
1123end
1124
1125local function mouseClickEventMonitor()
1126 while true do
1127 local event, type, x, y = os.pullEvent("mouse_click")
1128 local selectedTab = nativeDisplayTabs.getSelectedTab(x, y)
1129
1130 if selectedTab and nativeDisplayTabs.getDashboardWindows().getInformationWindow().active == false then
1131 os.queueEvent("selected_tab", selectedTab)
1132 elseif selectedTab == nil then
1133 local activeTab = nativeDisplayTabs[nativeDisplayTabs.getActiveTab()]
1134
1135 os.queueEvent(activeTab.tab.event, x, y)
1136 end
1137 end
1138end
1139
1140-- Initialization
1141initializeNativeDisplayTabs()
1142resetRedstoneState()
1143addCapacitors()
1144addMonitors()
1145
1146while true do
1147 parallel.waitForAll(mouseClickEventMonitor, nativeDisplay, monitorSelection, hotplugPeripherals, monitorCapacitors, nativeDashboardHandler, monitorDashboardHandler)
1148end