SHOW:
|
|
- or go back to the newest paste.
| 1 | -------------------------------------------------- | |
| 2 | -- Сервер для оравы шахтерских лазеров из кросоварпа. | |
| 3 | -- Ставится в кабине шахтерской платформы | |
| 4 | -- и подключается сетевыми кабелями к компьютерам, | |
| 5 | -- стоящим у лазеров. На те компьютеры | |
| 6 | -- нужно поставить клиентскую программу. | |
| 7 | -- И то, и то нужно поставить в autostart. | |
| 8 | -- | |
| 9 | -- (c) Efrim | |
| 10 | -- skype: gods_pee | |
| 11 | -- 05.10.2013 | |
| 12 | -------------------------------------------------- | |
| 13 | -- Changelog: | |
| 14 | -- 1.0: release | |
| 15 | -- 1.1: saving only IDs of miners instead of full statuses | |
| 16 | -------------------------------------------------- | |
| 17 | ||
| 18 | NETWORK_SIDE = "bottom" -- Сторона, к которой подключен модем | |
| 19 | DATA_FILE = "miners.dat" -- Файл для сохранения данных | |
| 20 | TEMP_FILE = "miners.temp" -- Временное хранилище | |
| 21 | TIMEOUTS_MAX = 3 -- Максимальное количество таймаутов в сетевом общении | |
| 22 | TIMEOUT = 1 -- Время таймаута | |
| 23 | REFRESH_PERIOD = 1 -- Период обновления экрана | |
| 24 | ||
| 25 | -------------------------------------------------- | |
| 26 | ||
| 27 | nTotal = -1 | |
| 28 | nOnline = -1 | |
| 29 | nLowEnergy = -1 | |
| 30 | nMining = -1 | |
| 31 | nQuarry = -1 | |
| 32 | nStopped = -1 | |
| 33 | maxLayer = -1 | |
| 34 | minLayer = -1 | |
| 35 | ||
| 36 | ||
| 37 | -------------------------------------------------- | |
| 38 | ||
| 39 | -- Массив данных о майнерах: | |
| 40 | -- 1 - ID | |
| 41 | -- 2 - 'state' | |
| 42 | -- 3 - 'energy' | |
| 43 | -- 4 - 'currentLayer' | |
| 44 | -- 5 - 'mined' | |
| 45 | -- 6 - 'total' | |
| 46 | -- 7 - online | |
| 47 | ||
| 48 | miners = {}
| |
| 49 | for i = 1, 81 do | |
| 50 | miners[i] = {}
| |
| 51 | ||
| 52 | for j = 1, 7 do | |
| 53 | miners[i][j] = 0 -- Fill the values here | |
| 54 | end | |
| 55 | end | |
| 56 | ||
| 57 | minersCompact = {}
| |
| 58 | ||
| 59 | -------------------------------------------------- | |
| 60 | -- Графическая часть | |
| 61 | -------------------------------------------------- | |
| 62 | ||
| 63 | function DisplayStats() | |
| 64 | term.clear() | |
| 65 | term.setCursorPos(1, 1) | |
| 66 | print("__ Lasers __")
| |
| 67 | print("Online / Total: " .. nOnline .. " / " .. nTotal)
| |
| 68 | print("Stopped / Mining / Quarry: " .. nStopped .. " / " .. nMining .. " / " .. nQuarry)
| |
| 69 | print("Max / Min layer: " .. maxLayer .. " / " .. minLayer)
| |
| 70 | print("With low energy: " .. nLowEnergy)
| |
| 71 | print("")
| |
| 72 | print("Press C to type a command")
| |
| 73 | return 0 | |
| 74 | end | |
| 75 | ||
| 76 | function SubmitCommand() | |
| 77 | print("")
| |
| 78 | print("Enter command")
| |
| 79 | sleep(1/10) | |
| 80 | print("> ")
| |
| 81 | local input = read() | |
| 82 | return input | |
| 83 | end | |
| 84 | ||
| 85 | function ExecuteCommand(command) | |
| 86 | if command == "help" then | |
| 87 | PrintHelp() | |
| 88 | SubmitCommand() | |
| 89 | elseif command == "reinit" then | |
| 90 | rednet.broadcast(command) | |
| 91 | sleep(1/3) | |
| 92 | rednet.broadcast(command) | |
| 93 | sleep(1/3) | |
| 94 | rednet.broadcast(command) | |
| 95 | sleep(1/3) | |
| 96 | InitializeNetwork() | |
| 97 | DisplayStats() | |
| 98 | else | |
| 99 | rednet.broadcast(command) | |
| 100 | DisplayStats() | |
| 101 | end | |
| 102 | return 0 | |
| 103 | end | |
| 104 | ||
| 105 | function PrintHelp() | |
| 106 | print("help")
| |
| 107 | print("start")
| |
| 108 | print("quarry")
| |
| 109 | print("stop")
| |
| 110 | print("restart")
| |
| 111 | print("reinit")
| |
| 112 | print("offset --layers")
| |
| 113 | print("update --pastebin")
| |
| 114 | print("")
| |
| 115 | return 0 | |
| 116 | end | |
| 117 | ||
| 118 | - | if not rednet.isOpen(NETWORK_SIDE) then |
| 118 | + | |
| 119 | - | rednet.open(NETWORK_SIDE) |
| 119 | + | |
| 120 | -------------------------------------------------- | |
| 121 | ||
| 122 | function InitializeNetwork() | |
| 123 | rednet.open(NETWORK_SIDE) | |
| 124 | ||
| 125 | nTotal = 0 | |
| 126 | local nTimeouts = 0 | |
| 127 | ||
| 128 | term.clear() | |
| 129 | term.setCursorPos(1,1) | |
| 130 | print("Initializing...")
| |
| 131 | ||
| 132 | while nTimeouts <= TIMEOUTS_MAX do | |
| 133 | sleep(1/4) | |
| 134 | rednet.broadcast("Server is here")
| |
| 135 | ||
| 136 | local receivedID, receivedMessage, _ = rednet.receive(TIMEOUT) | |
| 137 | ||
| 138 | print(receivedID) | |
| 139 | ||
| 140 | if receivedID == nil then | |
| 141 | nTimeouts = nTimeouts + 1 | |
| 142 | print("Timeout.")
| |
| 143 | else | |
| 144 | print("Received message.")
| |
| 145 | local _, _, minerIDstr = string.find(receivedMessage, "Miner (%d+) is here") | |
| 146 | minerID = tonumber(minerIDstr) | |
| 147 | if receivedID == minerID then | |
| 148 | AddMiner(minerID) | |
| 149 | nTimeouts = 0 | |
| 150 | rednet.send(minerID, "Gotcha") | |
| 151 | print("Miner " .. nTotal .. " initialized.")
| |
| 152 | end | |
| 153 | end | |
| 154 | end | |
| 155 | ||
| 156 | print("Initialized total " .. nTotal .. " miners.")
| |
| 157 | ||
| 158 | SaveMinersTableToFile() | |
| 159 | ||
| 160 | return 0 | |
| 161 | end | |
| 162 | ||
| 163 | function AddMiner(minerID) | |
| 164 | nTotal = nTotal + 1 | |
| 165 | miners[nTotal][1] = minerID | |
| 166 | miners[nTotal][7] = 1 | |
| 167 | ||
| 168 | minersCompact[nTotal] = minerID | |
| 169 | ||
| 170 | return 0 | |
| 171 | end | |
| 172 | ||
| 173 | -------------------------------------------------- | |
| 174 | -- Общение с имеющимися майнерами | |
| 175 | -------------------------------------------------- | |
| 176 | ||
| 177 | function UpdateMiner(minerN) -- Обновление статуса майнера | |
| 178 | local timeouts = 0 | |
| 179 | local minerID = miners[minerN][1] | |
| 180 | ||
| 181 | while timeouts <= TIMEOUTS_MAX do | |
| 182 | CommandMiner(minerN, "statusrequest") | |
| 183 | local receivedID, receivedMessage, _ = rednet.receive(TIMEOUT) | |
| 184 | ||
| 185 | if receivedID == minerID then | |
| 186 | local state = textutils.unserialize(receivedMessage) | |
| 187 | ||
| 188 | miners[minerN][2] = state[1] | |
| 189 | miners[minerN][3] = state[2] | |
| 190 | miners[minerN][4] = state[3] | |
| 191 | miners[minerN][5] = state[4] | |
| 192 | miners[minerN][6] = state[5] | |
| 193 | miners[minerN][7] = 1 | |
| 194 | ||
| 195 | return 0 | |
| 196 | end | |
| 197 | ||
| 198 | timeouts = timeouts + 1 -- Если дошли до этого места, то таймаут | |
| 199 | end | |
| 200 | miners[minerN][7] = 0 -- Если дошли до этого места, то майнер в оффлайне | |
| 201 | return 1 | |
| 202 | end | |
| 203 | ||
| 204 | function UpdateAllMiners() -- Обновление статусов всех майнеров | |
| 205 | for i = 1, nTotal do | |
| 206 | UpdateMiner(i) | |
| 207 | end | |
| 208 | ||
| 209 | return 0 | |
| 210 | end | |
| 211 | ||
| 212 | function CommandMiner(minerN, action) | |
| 213 | local minerID = miners[minerN][1] | |
| 214 | ||
| 215 | rednet.send(minerID, action) | |
| 216 | ||
| 217 | return 0 | |
| 218 | end | |
| 219 | ||
| 220 | function CommandAllMiners(action) | |
| 221 | ||
| 222 | rednet.broadcast(action) | |
| 223 | ||
| 224 | return 0 | |
| 225 | end | |
| 226 | ||
| 227 | -------------------------------------------------- | |
| 228 | -- Пересчет статистики | |
| 229 | -------------------------------------------------- | |
| 230 | ||
| 231 | function RecalculateStatistics () | |
| 232 | nOnline = 0 | |
| 233 | nLowEnergy = 0 | |
| 234 | nMining = 0 | |
| 235 | nQuarry = 0 | |
| 236 | nStopped = 0 | |
| 237 | maxLayer = 0 | |
| 238 | minLayer = 256 | |
| 239 | ||
| 240 | for i = 1, nTotal do | |
| 241 | -- nOnline | |
| 242 | nOnline = nOnline + miners[i][7] | |
| 243 | -- nLowEnergyTemp | |
| 244 | if miners[i][3] <= 50000 then | |
| 245 | nLowEnergy = nLowEnergy + 1 | |
| 246 | end | |
| 247 | -- nMiningTemp, nQuarryTemp, nStoppedTemp | |
| 248 | if miners[i][2] == "not mining" then | |
| 249 | nStopped = nStopped + 1 | |
| 250 | elseif miners[i][2] == "mining" then | |
| 251 | nMining = nMining + 1 | |
| 252 | elseif miners[i][2] == "mining %(quarry mode%)" then | |
| 253 | nQuarry = nQuarry + 1 | |
| 254 | end | |
| 255 | -- maxLayerTemp | |
| 256 | maxLayer = math.max(maxLayer, miners[i][4]) | |
| 257 | minLayer = math.min(minLayer, miners[i][4]) | |
| 258 | end | |
| 259 | ||
| 260 | return 0 | |
| 261 | end | |
| 262 | - | file.writeLine(textutils.serialize(miners)) |
| 262 | + | |
| 263 | -------------------------------------------------- | |
| 264 | -- Сохранение и загрузка | |
| 265 | -------------------------------------------------- | |
| 266 | ||
| 267 | function SaveMinersTableToFile() | |
| 268 | local file = fs.open(TEMP_FILE, "w") | |
| 269 | file.writeLine(textutils.serialize(minersCompact)) | |
| 270 | file.writeLine(nTotal) | |
| 271 | file.close() | |
| 272 | ||
| 273 | fs.delete(DATA_FILE) | |
| 274 | - | miners = textutils.unserialize(file.readLine()) |
| 274 | + | |
| 275 | ||
| 276 | return 0 | |
| 277 | end | |
| 278 | ||
| 279 | function LoadMinersTableFromFile() | |
| 280 | local file = fs.open(DATA_FILE, "r") | |
| 281 | minersCompact = textutils.unserialize(file.readLine()) | |
| 282 | nTotal = tonumber(file.readLine()) | |
| 283 | ||
| 284 | for i = 1, nTotal do | |
| 285 | miners[i][1] = minersCompact[i] | |
| 286 | - | if not rednet.isOpen(NETWORK_SIDE) then |
| 286 | + | |
| 287 | - | print("Opening networking...")
|
| 287 | + | |
| 288 | - | rednet.open(NETWORK_SIDE) |
| 288 | + | |
| 289 | ||
| 290 | return 0 | |
| 291 | end | |
| 292 | ||
| 293 | -------------------------------------------------- | |
| 294 | -- Главный луп | |
| 295 | -------------------------------------------------- | |
| 296 | ||
| 297 | function main() | |
| 298 | rednet.open(NETWORK_SIDE) | |
| 299 | ||
| 300 | if fs.exists(DATA_FILE) then | |
| 301 | print("Loading previous data...")
| |
| 302 | LoadMinersTableFromFile() | |
| 303 | - | SaveMinersTableToFile() |
| 303 | + | |
| 304 | print("Initializing...")
| |
| 305 | InitializeNetwork() | |
| 306 | end | |
| 307 | ||
| 308 | while true do | |
| 309 | UpdateAllMiners() | |
| 310 | RecalculateStatistics() | |
| 311 | DisplayStats() | |
| 312 | ||
| 313 | local timeout = os.startTimer(REFRESH_PERIOD) | |
| 314 | while true do | |
| 315 | event = {os.pullEvent()}
| |
| 316 | if event[1] == "key" and event[2] == 46 then | |
| 317 | local command = SubmitCommand() | |
| 318 | ExecuteCommand(command) | |
| 319 | timeout = os.startTimer(REFRESH_PERIOD) | |
| 320 | elseif event[1] == "timer" and event[2] == timeout then | |
| 321 | break | |
| 322 | end | |
| 323 | end | |
| 324 | end | |
| 325 | end | |
| 326 | ||
| 327 | main() |