Advertisement
pneisen

energy.lua

Feb 21st, 2018
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.24 KB | None | 0 0
  1. local os = require("os")
  2. local event = require("event")
  3. local sides = require("sides")
  4. local component = require("component")
  5. local math = require("math")
  6. local bit32 = require("bit32")
  7. local string = require("string")
  8. local gpu = component.gpu
  9. local width, height = gpu.getResolution()
  10.  
  11. function clear()
  12.   gpu.setBackground(0x000000)
  13.   local width, height = gpu.getResolution()
  14.   gpu.fill(1, 1, width, height, " ")
  15. end
  16.  
  17. function singleBorderBox(x, y, w, h)
  18.   gpu.fill(x, y, w, 1, "█")
  19.   gpu.fill(x, y + h - 1, w, 1, "█")
  20.   gpu.fill(x, y + 1, 1, h - 1, "█")
  21.   gpu.fill(x + w - 1, y + 1, 1, h - 1, "█")
  22. end
  23.  
  24. function doubleBorderBox(x, y, w, h)
  25.   singleBorderBox(x, y, w, h)
  26.   singleBorderBox(x + 2, y + 2, w - 4, h - 4)
  27. end
  28.  
  29.  
  30. function horizontalProgressBar(x, y, w, h, progress, color, showPercent)
  31.   -- 0 >= progress <= 1
  32.   singleBorderBox(x,y,w,h)
  33.  
  34.   local oldFG = gpu.getForeground()
  35.   gpu.setForeground(color)
  36.  
  37.   gpu.fill(x + 2, y + 2, math.floor(((w - 4) *  progress) + 0.5), h - 4, "█")
  38.  
  39.   if showPercent then
  40.     -- Figure out placement of the percent label
  41.     local percent = string.format("%.2f", progress * 100) .. "%"
  42.     local len = string.len(percent)
  43.     local labelX = math.floor((((w - 2) / 2) - (len / 2)) + 0.5) + x + 1
  44.     local labelY = math.floor(((h - 2) / 2) + 0.5) + y
  45.  
  46.     -- Display the label with appropriate coloring.      
  47.     for i = 1, len do
  48.       local c, fg, bg, _, _ = gpu.get(labelX + i - 1, labelY)
  49.       if c == "█" then
  50.         gpu.setForeground(bg)
  51.         gpu.setBackground(fg)
  52.         gpu.set(labelX + i - 1, labelY, string.sub(percent, i, i))
  53.         gpu.setBackground(bg)
  54.         gpu.setForeground(fg)
  55.       else
  56.         gpu.set(labelX + i - 1, labelY, string.sub(percent, i, i))    
  57.       end
  58.     end
  59.   end
  60.   gpu.setForeground(oldFG)
  61. end
  62.  
  63. function adjustShade(color, factor)
  64.   local red = bit32.band(16711680, color)
  65.   local green = bit32.band(65280, color)
  66.   local blue = bit32.band(255, color)
  67.  
  68.   red = red * factor
  69.   green = green * factor
  70.   blue = blue * factor
  71.  
  72.   local result = bit32.bor(blue, 0)
  73.   result = bit32.bor(green, result)
  74.   result = bit32.bor(red, result)
  75.   return result
  76. end
  77.  
  78. function maxAndMinFromArray(data)
  79.   local max = data[1]
  80.   local min = data[1]
  81.   if #data > 1 then
  82.     for i=2, #data do
  83.       if data[i] > max then
  84.         max = data[i]
  85.       end
  86.       if data[i] < min then
  87.         min = data[i]
  88.       end
  89.     end
  90.   end
  91.   return max, min
  92. end
  93.  
  94. function verticalBarChart(x, y, w, h, data, color)
  95.   -- Draw the axies
  96.   gpu.fill(x, y, 1, h, "█")
  97.   gpu.fill(x + 1, y + h - 1, w - 1, 1, "█")
  98.  
  99.   local max, min = maxAndMinFromArray(data)
  100.  
  101.   local oldFG = gpu.getForeground()
  102.   gpu.setForeground(color)
  103.  
  104.   -- Draw the bars
  105.   local numberOfBars = math.min(#data, math.floor((w - 2) / 2))
  106.  
  107.   for i=1, numberOfBars do
  108.     if i >= 2 then
  109.       gpu.setForeground(adjustShade(color, .75))
  110.     end
  111.     local heightOfBar = math.floor(((((h - 2)  * .95) / max) * data[i]) +0.5)
  112.     gpu.fill(x + w - (2 * i), (h - 2) - heightOfBar + y, 2, heightOfBar, "█")
  113.   end
  114.  
  115.   gpu.setForeground(oldFG)
  116. end
  117.  
  118. function format_int(number)
  119.   -- stolen from here: https://stackoverflow.com/questions/10989788/lua-format-integer
  120.   local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)')
  121.  
  122.   -- reverse the int-string and append a comma to all blocks of 3 digits
  123.   int = int:reverse():gsub("(%d%d%d)", "%1,")
  124.  
  125.   -- reverse the int-string back remove an optional comma and put the
  126.   -- optional minus and fractional part back
  127.   return minus .. int:reverse():gsub("^,", "") .. fraction
  128. end
  129.  
  130. function condenseInt(number)
  131.   if number >= 1000000000 then
  132.     return string.format("%.2f", number / 1000000000) .. "B"
  133.   elseif number >=1000000 then
  134.     return string.format("%.2f", number / 1000000) .. "M"
  135.   elseif number >= 1000 then
  136.     return string.format("%.2f", number / 1000) .. "K"
  137.   else
  138.     return number
  139.   end
  140. end
  141.  
  142. function updateScreen(currentRF, RFStorage, supplyData, demandData)
  143.   clear()
  144.   gpu.setBackground(0x000000)
  145.   gpu.setForeground(0x696969)
  146.   doubleBorderBox(1, 1, width, height)
  147.  
  148.   gpu.setForeground(0xD2D2D2)
  149.   horizontalProgressBar(6, 6, width - 10, 9, currentRF/RFStorage, 0xCC0000, true)
  150.   verticalBarChart(23, 19, 46, 23, supplyData, 0x00DB00)
  151.   verticalBarChart(91, 19, 46, 23, demandData, 0xCC0000)
  152.  
  153.   gpu.setForeground(0xFFFFFF)
  154.  
  155.   local rf = "Redstone Flux: " .. format_int(currentRF) .. " / " .. format_int(RFStorage)
  156.   gpu.set(math.floor(((width - #rf) / 2) + 0.5), 5, rf)
  157.  
  158.   local supplyTitle = "RF Supply"
  159.   gpu.set(math.floor(((46 - #supplyTitle) / 2) + 0.5 + 23), 18, supplyTitle)
  160.  
  161.   local demandTitle = "RF Demand"
  162.   gpu.set(math.floor(((46 - #demandTitle) / 2) + 0.5 + 91), 18, demandTitle)
  163.  
  164.   local currentSupply = supplyData[1]
  165.   local maxSupply, minSupply = maxAndMinFromArray(supplyData)
  166.   gpu.set(27, 43, "Current Supply: " .. condenseInt(currentSupply) .. " RF/t")
  167.   gpu.set(27, 44, "Max Supply (last 10 min): " .. condenseInt(maxSupply) .. " RF/t")
  168.   gpu.set(27, 45, "Min Supply (last 10 min): " .. condenseInt(minSupply) .. " RF/t")
  169.  
  170.   local currentDemand = demandData[1]
  171.   local maxDemand, minDemand = maxAndMinFromArray(demandData)
  172.   gpu.set(96, 43, "Current Demand: " .. condenseInt(currentDemand) .. " RF/t")
  173.   gpu.set(96, 44, "Max Demand (last 10 min): " .. condenseInt(maxDemand) .. " RF/t")
  174.   gpu.set(96, 45, "Min Demand (last 10 min): " .. condenseInt(minDemand) .. " RF/t")
  175. end
  176.  
  177. function interruptHandler()
  178.   print("Interrupted. Setting gates back to manual")
  179.   for addr, type in component.list("flux_gate", true) do
  180.     local gate = component.proxy(addr)
  181.     gate.setOverrideEnabled(false)
  182.   end
  183.   print("Exiting")
  184. end
  185.  
  186. -- Main
  187. local pylon = component.draconic_rf_storage
  188. local redstone = component.redstone
  189.  
  190. local gates = {}
  191. local i = 0
  192.  
  193. for addr, type in component.list("flux_gate", true) do
  194.   gates[i] = addr
  195.   i = i + 1
  196. end
  197.  
  198. print("Found " .. i .. " flux gate(s)")
  199.  
  200. if i == 2 then
  201.   print("Figuring out which is which")
  202.  
  203.   local gate1 = component.proxy(gates[0])
  204.   local gate2 = component.proxy(gates[1])
  205.  
  206.   -- Computer control and set the flow high.
  207.   gate1.setOverrideEnabled(true)
  208.   gate1.setFlowOverride(100000000)
  209.   gate2.setOverrideEnabled(true)
  210.   gate2.setFlowOverride(100000000)
  211.  
  212.  
  213.   -- Close one gate and see if we get a negative transfer in the storage.
  214.   -- This only works if there is a draw on the system. We assume there is something...
  215.   gate1.setFlowOverride(0)
  216.   os.sleep(2)
  217.   if pylon.getTransferPerTick() < 0 then
  218.     inGate = gate1
  219.     outGate = gate2    
  220.   else
  221.     inGate = gate2
  222.     outGate = gate1
  223.   end
  224.   gate1.setFlowOverride(100000000)
  225.   print("Figured it out")
  226.  
  227.   print("Running tests...")
  228.  
  229.   local supplyData = {}
  230.   local demandData = {}
  231.   local runFlag = true
  232.  
  233.   while(runFlag) do
  234.     local currentRF = pylon.getEnergyStored()
  235.     local storageRF = pylon.getMaxEnergyStored()
  236.  
  237.     -- Test: Determine total in/out.
  238.     inGate.setFlowOverride(0)
  239.     os.sleep(2)
  240.  
  241.     local newDemandData = { math.abs(pylon.getTransferPerTick()) }
  242.     for i = 1, math.min(#demandData, 22) do
  243.       newDemandData[i + 1] = demandData[i]
  244.     end
  245.     demandData = newDemandData
  246.  
  247.     if (pylon.getMaxEnergyStored() - pylon.getEnergyStored()) < 20000000 then
  248.       -- Storage is almost full. Trash enough that we can get a read on incoming RF
  249.       redstone.setOutput(sides.south, 15)
  250.       os.sleep(2)
  251.       redstone.setOutput(sides.south, 0)
  252.     end
  253.  
  254.     outGate.setFlowOverride(0)
  255.     inGate.setFlowOverride(100000000)
  256.     os.sleep(2)
  257.     local RFIn = pylon.getTransferPerTick()
  258.     outGate.setFlowOverride(100000000)
  259.  
  260.     -- Maybe nothing is coming in.
  261.     if RFIn < 1 then
  262.       RFIn = 0
  263.     end    
  264.  
  265.     local newSupplyData = { math.abs(RFIn) }
  266.     for i = 1, math.min(#supplyData, 22) do
  267.       newSupplyData[i + 1] = supplyData[i]
  268.     end
  269.     supplyData = newSupplyData
  270.  
  271.  
  272.     -- Update the screen
  273.     updateScreen(currentRF, storageRF, supplyData, demandData)
  274.  
  275.     local name, _ = event.pull(30, "interrupted")
  276.     if name == "interrupted" then
  277.       interruptHandler()
  278.       runFlag = false
  279.     end
  280.   end
  281.  
  282. else
  283.   print("Found more or less than 2 flux gates. Exiting...")
  284. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement