[READ-ONLY] Mirror of https://github.com/thoda-dev/DU-Mining-Units-Monitoring. A mining units monitoring script jericho.dev
dual-universe dualuniverse lua mining mining-pool mining-units
0

Configure Feed

Select the types of activity you want to include in your feed.

version 1

Thomas (Apr 27, 2022, 9:47 PM +0200) 5a40738e fb1ccc17

+320
+1
.gitignore
··· 1 + .idea
+5
.idea/.gitignore
··· 1 + # Default ignored files 2 + /shelf/ 3 + /workspace.xml 4 + # Editor-based HTTP Client requests 5 + /httpRequests/
+12
.idea/DU-Mining-Units-Monitoring.iml
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <module type="WEB_MODULE" version="4"> 3 + <component name="NewModuleRootManager"> 4 + <content url="file://$MODULE_DIR$"> 5 + <excludeFolder url="file://$MODULE_DIR$/temp" /> 6 + <excludeFolder url="file://$MODULE_DIR$/.tmp" /> 7 + <excludeFolder url="file://$MODULE_DIR$/tmp" /> 8 + </content> 9 + <orderEntry type="inheritedJdk" /> 10 + <orderEntry type="sourceFolder" forTests="false" /> 11 + </component> 12 + </module>
+8
.idea/modules.xml
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <project version="4"> 3 + <component name="ProjectModuleManager"> 4 + <modules> 5 + <module fileurl="file://$PROJECT_DIR$/.idea/DU-Mining-Units-Monitoring.iml" filepath="$PROJECT_DIR$/.idea/DU-Mining-Units-Monitoring.iml" /> 6 + </modules> 7 + </component> 8 + </project>
+6
.idea/vcs.xml
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <project version="4"> 3 + <component name="VcsDirectoryMappings"> 4 + <mapping directory="$PROJECT_DIR$" vcs="Git" /> 5 + </component> 6 + </project>
+24
README.md
··· 1 1 # DU Mining Units Monitoring 2 2 A mining units monitoring script 3 + 4 + ![Img001](https://github.com/Jericho1060/du-mining-units-monitoring/blob/main/du-mining-units-monitoring.png?raw=true) 5 + 6 + # Guilded Server (better than Discord) 7 + 8 + You can join me on Guilded for help or suggestions or requests by following that link : https://guilded.jericho.dev 9 + 10 + # Installation 11 + 12 + ### required elements 13 + 14 + - screen : 1 (you can add several il you want to display it in several places) 15 + - programming bard : 1 16 + 17 + ### Links 18 + 19 + Connect at least one screen to the programming board 20 + Connect mining units to the board 21 + 22 + You don't have to touch slots name or anything, the script will detect all elements automatically. 23 + 24 + ### informations 25 + 26 + Mining units will be displayed in the order they are linked to the board
+1
config.json
··· 1 + {"events":[],"handlers":[{"code":"if coroutine.status(MainCoroutine) == \"dead\" then\n MainCoroutine = coroutine.create(runCoroutines)\nend\nif coroutine.status(MainCoroutine) == \"suspended\" then\n assert(coroutine.resume(MainCoroutine))\nend","filter":{"args":[],"signature":"update()","slotKey":"-2"},"key":"1"},{"code":"system.print(\"-----------------------------------\")\nsystem.print(\"DU-Mining-Units-Monitoring version 1.0.0\")\nsystem.print(\"-----------------------------------\")\n\nlocal renderScript = [[\nlocal json = require('dkjson')\nlogMessage(getInput())\nlocal data = json.decode(getInput()) or {}\nimages = {}\nfor index,mu in ipairs(data) do\n images[index] = loadImage(mu[3][2])\nend\n\nlocal rx,ry = getResolution()\n\nlocal back=createLayer()\nlocal front=createLayer()\n\nfont_size = 25\n\nlocal mini=loadFont('Play',12)\nlocal small=loadFont('Play',14)\nlocal smallBold=loadFont('Play-Bold',18)\nlocal itemName=loadFont('Play-Bold',font_size)\nlocal medV=loadFont('Play-Bold', 25)\nlocal bigV=loadFont('Play-Bold', 30)\nlocal big=loadFont('Play',38)\n\nsetBackgroundColor( 15/255,24/255,29/255)\n\nsetDefaultStrokeColor( back,Shape_Line,0,0,0,0.5)\nsetDefaultShadow( back,Shape_Line,6,0,0,0,0.5)\n\nsetDefaultFillColor( front,Shape_BoxRounded,249/255,212/255,123/255,1)\nsetDefaultFillColor( front,Shape_Text,0,0,0,1)\nsetDefaultFillColor( front,Shape_Box,0.075,0.125,0.156,1)\nsetDefaultFillColor( front,Shape_Text,0.710,0.878,0.941,1)\n\nfunction format_number(value)\n local formatted = value\n while true do\n formatted, k = string.gsub(formatted, \"^(-?%d+)(%d%d%d)\", '%1 %2')\n if (k==0) then\n break\n end\n end\n return formatted\nend\n\nfunction SecondsToClockString(seconds)\n local seconds = tonumber(seconds)\n\n if seconds == nil or seconds <= 0 then\n return \"-\";\n else\n days = string.format(\"%2.f\", math.floor(seconds/(3600*24)));\n hours = string.format(\"%2.f\", math.floor(seconds/3600 - (days*24)));\n mins = string.format(\"%2.f\", math.floor(seconds/60 - (hours*60) - (days*24*60)));\n secs = string.format(\"%2.f\", math.floor(seconds - hours*3600 - (days*24*60*60) - mins *60));\n str = \"\"\n if tonumber(days) > 0 then str = str .. days..\"d \" end\n if tonumber(hours) > 0 then str = str .. hours..\"h \" end\n if tonumber(mins) > 0 then str = str .. mins..\"m \" end\n if tonumber(secs) > 0 then str = str .. secs ..\"s\" end\n return str\n end\nend\n\nfunction round(value, precision)\n if precision then return utils.round(value / precision) * precision end\n return value >= 0 and math.floor(value+0.5) or math.ceil(value-0.5)\nend\n\nfunction renderHeader(title)\n local h_factor = 12\n local h = 35\n if subtitle ~= nil and subtitle ~= \"\" then \n h = 50\n end\n addLine( back,0,h+12,rx,h+12)\n addBox(front,0,12,rx,h)\n addText(front,smallBold,title,44,35)\nend\n\nlocal storageBar = createLayer()\nsetDefaultFillColor(storageBar,Shape_Text,110/255,166/255,181/255,1)\nsetDefaultFillColor(storageBar,Shape_Box,0.075,0.125,0.156,1)\nsetDefaultFillColor(storageBar,Shape_Line,1,1,1,1)\n\nlocal storageYellow = createLayer()\nsetDefaultFillColor(storageYellow,Shape_Text,249/255,212/255,123/255,1)\nsetDefaultFillColor(storageYellow,Shape_Box,249/255,212/255,123/255,1)\n\nlocal storageDark = createLayer()\nsetDefaultFillColor(storageDark,Shape_Text,63/255,92/255,102/255,1)\nsetDefaultFillColor(storageDark,Shape_Box,13/255,24/255,28/255,1)\n\nlocal storageRed = createLayer()\nsetDefaultFillColor(storageRed,Shape_Text,177/255,42/255,42/255,1)\nsetDefaultFillColor(storageRed,Shape_Box,177/255,42/255,42/255,1)\n\nlocal storageGreen = createLayer()\nsetDefaultFillColor(storageGreen,Shape_Text,34/255,177/255,76/255,1)\nsetDefaultFillColor(storageGreen,Shape_Box,34/255,177/255,76/255,1)\n\nlocal imagesLayer = createLayer()\n\nfunction renderResistanceBar(title, index, status, time, prod_rate, calibration, efficiency, x, y, w, h, withTitle)\n local quantity_x_pos = font_size * 6.7\n local percent_x_pos = font_size * 2\n\n local colorLayer = storageGreen\n if status == \"STALLED\" then colorLayer = storageYellow end\n if status == \"STOPPED\" then colorLayer = storageRed end\n \n addBox(storageBar,x,y,w,h)\n \n \n if withTitle then\n addText(storageBar, small, \"ORE\", x, y-5)\n addText(storageBar, small, \"STATUS\", x+w-60, y-5)\n setNextTextAlign(storageBar, AlignH_Center, AlignV_Bottom)\n addText(storageBar, small, \"TIME\", x+w-200-quantity_x_pos-(font_size*3)-(font_size*8.2), y-3)\n setNextTextAlign(storageBar, AlignH_Center, AlignV_Bottom)\n addText(storageBar, small, \"RATE\", x+w-50-quantity_x_pos-(font_size*3)-(font_size*8.2), y-3)\n setNextTextAlign(storageBar, AlignH_Center, AlignV_Bottom)\n addText(storageBar, small, \"CALIBRATION\", x+w+100-quantity_x_pos-(font_size*3)-(font_size*8.2), y-3)\n setNextTextAlign(storageBar, AlignH_Center, AlignV_Bottom)\n addText(storageBar, small, \"EFFICIENCY\", x+w+250-quantity_x_pos-(font_size*3)-(font_size*8.2), y-3)\n end\n \n addText(storageBar, itemName, title, x+15+font_size, y+h-font_size/2)\n addBox(colorLayer,x,y+h-3,w,3)\n \n if isImageLoaded(images[index]) then\n addImage(imagesLayer, images[index], x+10, y+5, font_size, font_size)\n end\n setNextTextAlign(storageBar, AlignH_Center, AlignV_Middle)\n addText(storageBar, smallBold, SecondsToClockString(time), x+w-200-quantity_x_pos-(font_size*3)-(font_size*8.2), y+(h/2)-3)\n setNextTextAlign(storageBar, AlignH_Center, AlignV_Middle)\n addText(storageBar, smallBold, format_number(prod_rate) .. 'L', x+w-50-quantity_x_pos-(font_size*3)-(font_size*8.2), y+(h/2)-3)\n setNextTextAlign(storageBar, AlignH_Center, AlignV_Middle)\n addText(storageBar, smallBold, format_number(calibration) .. '%', x+w+100-quantity_x_pos-(font_size*3)-(font_size*8.2), y+(h/2)-3)\n setNextTextAlign(storageBar, AlignH_Center, AlignV_Middle)\n addText(storageBar, smallBold, format_number(efficiency) .. '%', x+w+250-quantity_x_pos-(font_size*3)-(font_size*8.2), y+(h/2)-3)\n \n setNextTextAlign(colorLayer, AlignH_Right, AlignV_Middle)\n addText(colorLayer, itemName, status, x+w-10, y+(h/2)-3)\n \n --addBox(storageDark,x+w-400,y+5,390,20)\nend\n\nrenderHeader('MINING UNITS MONITORING')\n\nstart_h = 75\n\nlocal h = font_size + font_size / 2\nfor i,mu in ipairs(data) do\n renderResistanceBar(mu[3][1], i, mu[1], mu[2], mu[4], mu[5], mu[6], 44, start_h, rx-88, h, i==1)\n start_h = start_h+h+10\nend\nrequestAnimationFrame(10)\n]]\n\nscreens = {}\nmining_units = {}\nfor slot_name, slot in pairs(unit) do\n if type(slot) == \"table\"\n and type(slot.export) == \"table\"\n and slot.getElementClass\n then\n slot.slotname = slot_name\n if slot.getElementClass():lower() == 'screenunit' then\n table.insert(screens,slot)\n slot.setRenderScript(renderScript)\n elseif slot.getElementClass():lower() == 'miningunit' then\n table.insert(mining_units,slot)\n end\n end\nend\nif #screens == 0 then\n system.print(\"No screen detected\")\nelse\n table.sort(screens, function(a,b) return a.slotname < b.slotname end)\n local plural = \"\"\n if #screens > 1 then plural = \"s\" end\n system.print(#screens .. \" screen\" .. plural .. \" connected\")\nend\nif #mining_units == 0 then\n system.print(\"No mining unit detected\")\nelse\n table.sort(mining_units, function(a,b) return a.slotname < b.slotname end)\n local plural = \"\"\n if #mining_units > 1 then plural = \"s\" end\n system.print(#mining_units .. \" mining unit\" .. plural .. \" connected\")\nend\n\nfunction round(value, precision)\n if precision then return utils.round(value / precision) * precision end\n return value >= 0 and math.floor(value+0.5) or math.ceil(value-0.5)\nend\n\nores = {}\n\n--Nested Coroutines by Jericho\ncoroutinesTable = {}\n--all functions here will become a coroutine\nMyCoroutines = {\n function()\n screen_data = {}\n for index, mu in pairs(mining_units) do\n local ore_id = mu.getActiveOre()\n if ores[ore_id] == nil then\n local item_data = system.getItem(ore_id)\n ores[ore_id] = {\n item_data.displayName,\n item_data.iconPath\n }\n end\n local mu_data = {\n mu.getStatus(),\n round(mu.getRemainingTime()),\n ores[ore_id],\n mu.getProductionRate(),\n round(mu.getCalibrationRate()*100),\n round(mu.getEfficiency()*100),\n }\n table.insert(screen_data, mu_data)\n coroutine.yield(coroutinesTable[1])\n end\n for index, screen in pairs(screens) do\n screen.setScriptInput(json.encode(screen_data))\n end\n end\n}\n\nfunction initCoroutines()\n for _,f in pairs(MyCoroutines) do\n local co = coroutine.create(f)\n table.insert(coroutinesTable, co)\n end\nend\n\ninitCoroutines()\n\nrunCoroutines = function()\n for i,co in ipairs(coroutinesTable) do\n if coroutine.status(co) == \"dead\" then\n coroutinesTable[i] = coroutine.create(MyCoroutines[i])\n end\n if coroutine.status(co) == \"suspended\" then\n assert(coroutine.resume(co))\n end\n end\nend\n\nMainCoroutine = coroutine.create(runCoroutines)","filter":{"args":[],"signature":"start()","slotKey":"-1"},"key":"0"}],"methods":[],"slots":{"0":{"name":"slot1","type":{"events":[],"methods":[]}},"1":{"name":"slot2","type":{"events":[],"methods":[]}},"2":{"name":"slot3","type":{"events":[],"methods":[]}},"3":{"name":"slot4","type":{"events":[],"methods":[]}},"4":{"name":"slot5","type":{"events":[],"methods":[]}},"5":{"name":"slot6","type":{"events":[],"methods":[]}},"6":{"name":"slot7","type":{"events":[],"methods":[]}},"7":{"name":"slot8","type":{"events":[],"methods":[]}},"8":{"name":"slot9","type":{"events":[],"methods":[]}},"9":{"name":"slot10","type":{"events":[],"methods":[]}},"-3":{"name":"library","type":{"events":[],"methods":[]}},"-2":{"name":"system","type":{"events":[],"methods":[]}},"-1":{"name":"unit","type":{"events":[],"methods":[]}}}}
du-mining-units-monitoring.png

This is a binary file and will not be displayed.

+6
source/system/update.lua
··· 1 + if coroutine.status(MainCoroutine) == "dead" then 2 + MainCoroutine = coroutine.create(runCoroutines) 3 + end 4 + if coroutine.status(MainCoroutine) == "suspended" then 5 + assert(coroutine.resume(MainCoroutine)) 6 + end
+257
source/unit/start.lua
··· 1 + system.print("-----------------------------------") 2 + system.print("DU-Mining-Units-Monitoring version 1.0.0") 3 + system.print("-----------------------------------") 4 + 5 + local renderScript = [[ 6 + local json = require('dkjson') 7 + logMessage(getInput()) 8 + local data = json.decode(getInput()) or {} 9 + images = {} 10 + for index,mu in ipairs(data) do 11 + images[index] = loadImage(mu[3][2]) 12 + end 13 + 14 + local rx,ry = getResolution() 15 + 16 + local back=createLayer() 17 + local front=createLayer() 18 + 19 + font_size = 25 20 + 21 + local mini=loadFont('Play',12) 22 + local small=loadFont('Play',14) 23 + local smallBold=loadFont('Play-Bold',18) 24 + local itemName=loadFont('Play-Bold',font_size) 25 + local medV=loadFont('Play-Bold', 25) 26 + local bigV=loadFont('Play-Bold', 30) 27 + local big=loadFont('Play',38) 28 + 29 + setBackgroundColor( 15/255,24/255,29/255) 30 + 31 + setDefaultStrokeColor( back,Shape_Line,0,0,0,0.5) 32 + setDefaultShadow( back,Shape_Line,6,0,0,0,0.5) 33 + 34 + setDefaultFillColor( front,Shape_BoxRounded,249/255,212/255,123/255,1) 35 + setDefaultFillColor( front,Shape_Text,0,0,0,1) 36 + setDefaultFillColor( front,Shape_Box,0.075,0.125,0.156,1) 37 + setDefaultFillColor( front,Shape_Text,0.710,0.878,0.941,1) 38 + 39 + function format_number(value) 40 + local formatted = value 41 + while true do 42 + formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1 %2') 43 + if (k==0) then 44 + break 45 + end 46 + end 47 + return formatted 48 + end 49 + 50 + function SecondsToClockString(seconds) 51 + local seconds = tonumber(seconds) 52 + 53 + if seconds == nil or seconds <= 0 then 54 + return "-"; 55 + else 56 + days = string.format("%2.f", math.floor(seconds/(3600*24))); 57 + hours = string.format("%2.f", math.floor(seconds/3600 - (days*24))); 58 + mins = string.format("%2.f", math.floor(seconds/60 - (hours*60) - (days*24*60))); 59 + secs = string.format("%2.f", math.floor(seconds - hours*3600 - (days*24*60*60) - mins *60)); 60 + str = "" 61 + if tonumber(days) > 0 then str = str .. days.."d " end 62 + if tonumber(hours) > 0 then str = str .. hours.."h " end 63 + if tonumber(mins) > 0 then str = str .. mins.."m " end 64 + if tonumber(secs) > 0 then str = str .. secs .."s" end 65 + return str 66 + end 67 + end 68 + 69 + function round(value, precision) 70 + if precision then return utils.round(value / precision) * precision end 71 + return value >= 0 and math.floor(value+0.5) or math.ceil(value-0.5) 72 + end 73 + 74 + function renderHeader(title) 75 + local h_factor = 12 76 + local h = 35 77 + if subtitle ~= nil and subtitle ~= "" then 78 + h = 50 79 + end 80 + addLine( back,0,h+12,rx,h+12) 81 + addBox(front,0,12,rx,h) 82 + addText(front,smallBold,title,44,35) 83 + end 84 + 85 + local storageBar = createLayer() 86 + setDefaultFillColor(storageBar,Shape_Text,110/255,166/255,181/255,1) 87 + setDefaultFillColor(storageBar,Shape_Box,0.075,0.125,0.156,1) 88 + setDefaultFillColor(storageBar,Shape_Line,1,1,1,1) 89 + 90 + local storageYellow = createLayer() 91 + setDefaultFillColor(storageYellow,Shape_Text,249/255,212/255,123/255,1) 92 + setDefaultFillColor(storageYellow,Shape_Box,249/255,212/255,123/255,1) 93 + 94 + local storageDark = createLayer() 95 + setDefaultFillColor(storageDark,Shape_Text,63/255,92/255,102/255,1) 96 + setDefaultFillColor(storageDark,Shape_Box,13/255,24/255,28/255,1) 97 + 98 + local storageRed = createLayer() 99 + setDefaultFillColor(storageRed,Shape_Text,177/255,42/255,42/255,1) 100 + setDefaultFillColor(storageRed,Shape_Box,177/255,42/255,42/255,1) 101 + 102 + local storageGreen = createLayer() 103 + setDefaultFillColor(storageGreen,Shape_Text,34/255,177/255,76/255,1) 104 + setDefaultFillColor(storageGreen,Shape_Box,34/255,177/255,76/255,1) 105 + 106 + local imagesLayer = createLayer() 107 + 108 + function renderResistanceBar(title, index, status, time, prod_rate, calibration, efficiency, x, y, w, h, withTitle) 109 + local quantity_x_pos = font_size * 6.7 110 + local percent_x_pos = font_size * 2 111 + 112 + local colorLayer = storageGreen 113 + if status == "STALLED" then colorLayer = storageYellow end 114 + if status == "STOPPED" then colorLayer = storageRed end 115 + 116 + addBox(storageBar,x,y,w,h) 117 + 118 + 119 + if withTitle then 120 + addText(storageBar, small, "ORE", x, y-5) 121 + addText(storageBar, small, "STATUS", x+w-60, y-5) 122 + setNextTextAlign(storageBar, AlignH_Center, AlignV_Bottom) 123 + addText(storageBar, small, "TIME", x+w-200-quantity_x_pos-(font_size*3)-(font_size*8.2), y-3) 124 + setNextTextAlign(storageBar, AlignH_Center, AlignV_Bottom) 125 + addText(storageBar, small, "RATE", x+w-50-quantity_x_pos-(font_size*3)-(font_size*8.2), y-3) 126 + setNextTextAlign(storageBar, AlignH_Center, AlignV_Bottom) 127 + addText(storageBar, small, "CALIBRATION", x+w+100-quantity_x_pos-(font_size*3)-(font_size*8.2), y-3) 128 + setNextTextAlign(storageBar, AlignH_Center, AlignV_Bottom) 129 + addText(storageBar, small, "EFFICIENCY", x+w+250-quantity_x_pos-(font_size*3)-(font_size*8.2), y-3) 130 + end 131 + 132 + addText(storageBar, itemName, title, x+15+font_size, y+h-font_size/2) 133 + addBox(colorLayer,x,y+h-3,w,3) 134 + 135 + if isImageLoaded(images[index]) then 136 + addImage(imagesLayer, images[index], x+10, y+5, font_size, font_size) 137 + end 138 + setNextTextAlign(storageBar, AlignH_Center, AlignV_Middle) 139 + addText(storageBar, smallBold, SecondsToClockString(time), x+w-200-quantity_x_pos-(font_size*3)-(font_size*8.2), y+(h/2)-3) 140 + setNextTextAlign(storageBar, AlignH_Center, AlignV_Middle) 141 + addText(storageBar, smallBold, format_number(prod_rate) .. 'L', x+w-50-quantity_x_pos-(font_size*3)-(font_size*8.2), y+(h/2)-3) 142 + setNextTextAlign(storageBar, AlignH_Center, AlignV_Middle) 143 + addText(storageBar, smallBold, format_number(calibration) .. '%', x+w+100-quantity_x_pos-(font_size*3)-(font_size*8.2), y+(h/2)-3) 144 + setNextTextAlign(storageBar, AlignH_Center, AlignV_Middle) 145 + addText(storageBar, smallBold, format_number(efficiency) .. '%', x+w+250-quantity_x_pos-(font_size*3)-(font_size*8.2), y+(h/2)-3) 146 + 147 + setNextTextAlign(colorLayer, AlignH_Right, AlignV_Middle) 148 + addText(colorLayer, itemName, status, x+w-10, y+(h/2)-3) 149 + 150 + --addBox(storageDark,x+w-400,y+5,390,20) 151 + end 152 + 153 + renderHeader('MINING UNITS MONITORING') 154 + 155 + start_h = 75 156 + 157 + local h = font_size + font_size / 2 158 + for i,mu in ipairs(data) do 159 + renderResistanceBar(mu[3][1], i, mu[1], mu[2], mu[4], mu[5], mu[6], 44, start_h, rx-88, h, i==1) 160 + start_h = start_h+h+10 161 + end 162 + requestAnimationFrame(10) 163 + ]] 164 + 165 + screens = {} 166 + mining_units = {} 167 + for slot_name, slot in pairs(unit) do 168 + if type(slot) == "table" 169 + and type(slot.export) == "table" 170 + and slot.getElementClass 171 + then 172 + slot.slotname = slot_name 173 + if slot.getElementClass():lower() == 'screenunit' then 174 + table.insert(screens,slot) 175 + slot.setRenderScript(renderScript) 176 + elseif slot.getElementClass():lower() == 'miningunit' then 177 + table.insert(mining_units,slot) 178 + end 179 + end 180 + end 181 + if #screens == 0 then 182 + system.print("No screen detected") 183 + else 184 + table.sort(screens, function(a,b) return a.slotname < b.slotname end) 185 + local plural = "" 186 + if #screens > 1 then plural = "s" end 187 + system.print(#screens .. " screen" .. plural .. " connected") 188 + end 189 + if #mining_units == 0 then 190 + system.print("No mining unit detected") 191 + else 192 + table.sort(mining_units, function(a,b) return a.slotname < b.slotname end) 193 + local plural = "" 194 + if #mining_units > 1 then plural = "s" end 195 + system.print(#mining_units .. " mining unit" .. plural .. " connected") 196 + end 197 + 198 + function round(value, precision) 199 + if precision then return utils.round(value / precision) * precision end 200 + return value >= 0 and math.floor(value+0.5) or math.ceil(value-0.5) 201 + end 202 + 203 + ores = {} 204 + 205 + --Nested Coroutines by Jericho 206 + coroutinesTable = {} 207 + --all functions here will become a coroutine 208 + MyCoroutines = { 209 + function() 210 + screen_data = {} 211 + for index, mu in pairs(mining_units) do 212 + local ore_id = mu.getActiveOre() 213 + if ores[ore_id] == nil then 214 + local item_data = system.getItem(ore_id) 215 + ores[ore_id] = { 216 + item_data.displayName, 217 + item_data.iconPath 218 + } 219 + end 220 + local mu_data = { 221 + mu.getStatus(), 222 + round(mu.getRemainingTime()), 223 + ores[ore_id], 224 + mu.getProductionRate(), 225 + round(mu.getCalibrationRate()*100), 226 + round(mu.getEfficiency()*100), 227 + } 228 + table.insert(screen_data, mu_data) 229 + coroutine.yield(coroutinesTable[1]) 230 + end 231 + for index, screen in pairs(screens) do 232 + screen.setScriptInput(json.encode(screen_data)) 233 + end 234 + end 235 + } 236 + 237 + function initCoroutines() 238 + for _,f in pairs(MyCoroutines) do 239 + local co = coroutine.create(f) 240 + table.insert(coroutinesTable, co) 241 + end 242 + end 243 + 244 + initCoroutines() 245 + 246 + runCoroutines = function() 247 + for i,co in ipairs(coroutinesTable) do 248 + if coroutine.status(co) == "dead" then 249 + coroutinesTable[i] = coroutine.create(MyCoroutines[i]) 250 + end 251 + if coroutine.status(co) == "suspended" then 252 + assert(coroutine.resume(co)) 253 + end 254 + end 255 + end 256 + 257 + MainCoroutine = coroutine.create(runCoroutines)