Asioron

Nanit

Mar 25th, 2016
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.60 KB | None | 0 0
  1. -- Copyright 2016-2017 Fingercomp
  2.  
  3. -- Licensed under the Apache License, Version 2.0 (the "License");
  4. -- you may not use this file except in compliance with the License.
  5. -- You may obtain a copy of the License at
  6.  
  7. --     http://www.apache.org/licenses/LICENSE-2.0
  8.  
  9. -- Unless required by applicable law or agreed to in writing, software
  10. -- distributed under the License is distributed on an "AS IS" BASIS,
  11. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. -- See the License for the specific language governing permissions and
  13. -- limitations under the License.
  14.  
  15. local CONF = "/etc/nn.conf"
  16.  
  17. local m = require("component").modem
  18. local event = require("event")
  19. local ser = require("serialization")
  20. local fs = require("filesystem")
  21. local unicode = require("unicode")
  22. _G.port = _G.port or 27091
  23. _G.max = _G.max or 15
  24. _G.effects = _G.effects or {}
  25. _G.effectscomb = _G.effectscomb or {}
  26. _G.groups = _G.groups or {}
  27. _G.init = _G.init or false
  28. _G.nnaddress = _G.nnaddress or false
  29.  
  30. codes = {
  31.   success    = 0x000,
  32.   fail       = 0x001,
  33.   initfail   = 0x100,
  34.   uninit     = 0x101,
  35.   noresponse = 0x102
  36. }
  37.  
  38. local function s(...)
  39.   if _G.nnaddress then
  40.     m.send(_G.nnaddress, _G.port, "nanomachines", ...)
  41.   else
  42.     m.broadcast(_G.port, "nanomachines", ...)
  43.   end
  44. end
  45.  
  46. local function g(...)
  47.   s(...)
  48.   if _G.nnaddress then
  49.     return {event.pull(6, "modem_message", _G.nnaddress)}
  50.   else
  51.     return {event.pull(6, "modem_message")}
  52.   end
  53. end
  54.  
  55. local function init(rqpt, prpt)
  56.   prpt = prpt or _G.port
  57.   _G.port = rqpt or _G.port
  58.   m.broadcast(prpt, "nanomachines", "setResponsePort", _G.port)
  59.   event.pull(6, "modem_message")
  60.   m.close(prpt)
  61.   m.open(_G.port)
  62.   resp = g("getTotalInputCount") or {}
  63.   _G.max = resp[8]
  64.   if not _G.max then
  65.     io.stderr:write("Failed to init.\n")
  66.     io.write("Are you sure you're near enough to modem and have nanomachines?\n")
  67.     _G.max = 15
  68.     return codes.initfail
  69.   end
  70.   _G.nnaddress = resp[2]
  71.   if fs.exists(CONF) then
  72.     dofile(CONF)
  73.   else
  74.     group = {}
  75.   end
  76.   _G.groups = group
  77.   _G.init = true
  78.   io.write("Configured: PORT " .. _G.port .. ", MAX " .. _G.max .. "\n")
  79.   return codes.success
  80. end
  81.  
  82. local function isIn(tbl, value)
  83.   for i = 1, #tbl, 1 do
  84.     if tbl[i] == value then
  85.       return true, i
  86.     end
  87.   end
  88.   return false
  89. end
  90.  
  91. local function test(...)
  92.   if not _G.init then
  93.     io.stderr:write("Run nn init first!\n")
  94.     return -codes.uninit
  95.   end
  96.   local exclude = {...}
  97.   io.write("Starting basic testing\n")
  98.   io.write("Total runs: " .. _G.max .. "\n")
  99.   io.write("Testing starts in 3s...\n")
  100.   os.sleep(3)
  101.   io.write("Beginning test\n")
  102.   _G.effects = {}
  103.   for i = 1, _G.max, 1 do
  104.     if not isIn(exclude, i) then
  105.       io.write("Run #" .. i .. "\n")
  106.       g("setInput", i, true)
  107.       _G.effects[i] = g("getActiveEffects")[8]
  108.       g("setInput", i, false)
  109.       io.write("Effects found:\n")
  110.       io.write(_G.effects[i] .. "\n")
  111.     else
  112.       io.write("Run #" .. i .. " skipped per user's request\n")
  113.     end
  114.   end
  115.   return codes.success
  116. end
  117.  
  118. local function recurSum(num)
  119.   if num > 0 then
  120.     return num + recurSum(num - 1)
  121.   end
  122.   return 0
  123. end
  124.  
  125. local function splitComma(str)
  126.   str = str:sub(2, -2)
  127.   local l = {}
  128.   for i in str:gmatch("(.-),.-") do
  129.     table.insert(l, i)
  130.   end
  131.   table.insert(l, str:match(".+,(.+)"))
  132.   if #l == 0 then
  133.     if str ~= "" then
  134.       table.insert(l, str)
  135.     end
  136.   end
  137.   return l
  138. end
  139.  
  140. local function combotest(...)
  141.   if not _G.init then
  142.     io.stderr:write("Run nn init first!\n")
  143.     return -codes.uninit
  144.   end
  145.   io.write("Combinatoric test\n")
  146.   io.write("Total runs: " .. recurSum(_G.max - 1) .. "\n")
  147.   io.write("It may take very long time!\n")
  148.   io.write("Testing begins is 3s...\n")
  149.   os.sleep(3)
  150.   if #_G.effects == 0 then
  151.     io.write("No input info, starting basic testing\n")
  152.     test(...)
  153.   end
  154.   io.write("Started combinatoric test\n")
  155.   _G.effectscomb = {}
  156.   local exclude = {...}
  157.   for i = 1, _G.max, 1 do
  158.     if not isIn(exclude, i) then
  159.       _G.effectscomb[i] = {}
  160.       io.write("Run #" .. i .. "\n")
  161.       g("setInput", i, true)
  162.       for j = i, _G.max, 1 do
  163.         if i ~= j then
  164.           if not isIn(exclude, j) and not isIn(exclude, i .. "-" .. j) then
  165.             io.write("Run #" .. i .. "." .. j .. "...\n")
  166.             g("setInput", j, true)
  167.             local effComb = g("getActiveEffects")[8] or "{}"
  168.             local effI, effJ = splitComma(_G.effects[i]), splitComma(_G.effects[j])
  169.             local effCombUS = splitComma(effComb)
  170.             local toRemove = {}
  171.             for num, i in ipairs(effI) do
  172.               if isIn(effCombUS, i) then
  173.                 table.insert(toRemove, i)
  174.               end
  175.             end
  176.             for num, i in ipairs(toRemove) do
  177.               local _, pos = isIn(effCombUS, i)
  178.               table.remove(effCombUS, pos)
  179.             end
  180.             toRemove = {}
  181.             for num, j in ipairs(effJ) do
  182.               if isIn(effCombUS, j) then
  183.                 table.insert(toRemove, j)
  184.               end
  185.             end
  186.             for num, i in ipairs(toRemove) do
  187.               local _, pos = isIn(effCombUS, i)
  188.               table.remove(effCombUS, pos)
  189.             end
  190.             effComb = ser.serialize(effCombUS)
  191.             _G.effectscomb[i][j] = effComb
  192.             io.write("Effects found:\n")
  193.             io.write(_G.effectscomb[i][j] .. "\n")
  194.             g("setInput", j, false)
  195.           else
  196.             io.write("Run #" .. i .. "." .. j .. " skipped per user's request\n")
  197.           end
  198.         end
  199.       end
  200.       g("setInput", i, false)
  201.     else
  202.       io.write("Run #" .. i .. " skipped per user's request\n")
  203.     end
  204.   end
  205.   return codes.success
  206. end
  207.  
  208. local function reset()
  209.   for i = 1, _G.max, 1 do
  210.     io.write("Turning off #" .. i .. "\n")
  211.     g("setInput", i, false)
  212.   end
  213.   return codes.success
  214. end
  215.  
  216. local function ge()
  217.   if not _G.init then
  218.     io.stderr:write("Run nn init first!\n")
  219.     return -codes.uninit
  220.   end
  221.   for i = 1, _G.max, 1 do
  222.     if _G.effects[i] then
  223.       io.write("Input #" .. i .. ":\t" .. _G.effects[i] .. "\n")
  224.     end
  225.   end
  226.   return codes.success, _G.effects
  227. end
  228.  
  229. local function getCombo()
  230.   if not _G.init then
  231.     io.stderr:write("Run nn init first!\n")
  232.     return -codes.uninit
  233.   end
  234.   for numi, i in pairs(_G.effectscomb) do
  235.     for numj, j in pairs(_G.effectscomb[numi]) do
  236.       if j ~= "{}" then
  237.         io.write("Input #" .. numi .. "+" .. numj .. ":\t" .. j .. "\n")
  238.       end
  239.     end
  240.   end
  241.   return codes.success, _G.effectscomb
  242. end
  243.  
  244. local function clear()
  245.   _G.max, _G.port, _G.effects = 15, 27091, {}
  246.   _G.init, _G.nnaddress = false, false
  247.   return codes.success
  248. end
  249.  
  250. local function info()
  251.   io.write("PORT: " .. ((_G.port) or "none") .. "\n")
  252.   io.write("MAX: " .. ((_G.max) or "none") .. "\n")
  253.   io.write("EFFECTS: \n")
  254.   return ge()
  255. end
  256.  
  257. local function gc(...)
  258.   local data = g(...)
  259.   io.write("FROM " .. data[4] .. " in " .. data[5] .. " msg: \n")
  260.   for i = 7, #data, 1 do
  261.     io.write(data[i] .. " ")
  262.   end
  263.   print()
  264.   return codes.success, data
  265. end
  266.  
  267. local function on(i)
  268.   g("setInput", i, true)
  269.   return codes.success
  270. end
  271.  
  272. local function off(i)
  273.   g("setInput", i, false)
  274.   return codes.success
  275. end
  276.  
  277. local function getHP()
  278.   local data = g("getHealth")
  279.   if data then
  280.     io.write("HP: " .. string.rep("♥", data[8]) .. string.rep("♡", data[9] - data[8]) .. " (" .. data[8] .. "/" .. data[9] .. ")\n")
  281.   else
  282.     io.write("Oops, no response\n")
  283.     return codes.noresponse
  284.   end
  285.   return codes.success, data[8], data[9]
  286. end
  287.  
  288. local function getHung()
  289.   local data = g("getHunger")
  290.   if data then
  291.     io.write("Hunger: " .. data[8] .. " | Saturation: " .. data[9])
  292.   else
  293.     io.write("Oops, no response\n")
  294.     return codes.noresponse
  295.   end
  296.   return codes.success, data[8], data[9]
  297. end
  298.  
  299. local function getEnergy()
  300.   local data = g("getPowerState")
  301.   if data then
  302.     io.write("↯: " .. data[8] .. "/" .. data[9] .. " (" .. math.floor(data[8] / data[9] * 100) .. "%)\n")
  303.   else
  304.     io.write("Opps, no response\n")
  305.     return codes.noresponse
  306.   end
  307.   return codes.success, data[8], data[9]
  308. end
  309.  
  310. local function formatNum(num)
  311.   return num > 0 and "+" .. tostring(num) or tostring(num)
  312. end
  313.  
  314. local function usage()
  315.   io.write("Requesting data...\n")
  316.   local data = {}
  317.   for run = 1, 2, 1 do
  318.     data[run] = g("getPowerState")
  319.     if not data[run] then
  320.       io.write("Oops, no response\n")
  321.       return codes.noresponse
  322.     end
  323.     os.sleep(1)
  324.   end
  325.   io.write("Usage: " .. formatNum(data[2][8] - data[1][8]) .. " per second\n")
  326.   return codes.success, data[2][8] - data[1][8]
  327. end
  328.  
  329. local function getAge()
  330.   local data = g("getAge")
  331.   if data then
  332.     io.write("Age: " .. data[8] .. "s\n")
  333.   else
  334.     io.write("Oops, no response\n")
  335.     return codes.noresponse
  336.   end
  337.   return codes.success, data[8]
  338. end
  339.  
  340. local function getName()
  341.   local data = g("getName")
  342.   if data then
  343.     io.write("Player's name is " .. data[8] .. "\n")
  344.   else
  345.     io.write("Oops, no response\n")
  346.     return codes.noresponse
  347.   end
  348.   return codes.success, data[8]
  349. end
  350.  
  351. local function getInputsInfo()
  352.   local safe = g("getSafeActiveInputs")
  353.   local max = g("getMaxActiveInputs")
  354.   io.write("Safe: " .. (safe[8] or "none") .. ", max: " .. (max[8] or "none") .. "\n")
  355.   return codes.success, safe[8], max[8]
  356. end
  357.  
  358. local function getActiveEffects()
  359.   local data = g("getActiveEffects")
  360.   if data then
  361.     io.write(data[8] .. "\n")
  362.   else
  363.     io.write("Oops, no response\n")
  364.     return codes.noresponse
  365.   end
  366.   return codes.success, data[8]
  367. end
  368.  
  369. local function copy()
  370.   local data = g("saveConfiguration")
  371.   if data then
  372.     if data[8] == false then
  373.       io.stderr("There was a problem: " .. (data[9] or "unknown") .. " \n")
  374.       return codes.fail
  375.     else
  376.       io.write("Copied!\n")
  377.     end
  378.   else
  379.     io.write("Oops, no response\n")
  380.     return codes.noresponse
  381.   end
  382.   return codes.success
  383. end
  384.  
  385. local function group(...)
  386.   if not _G.init then
  387.     io.stderr:write("Run nn init first!\n")
  388.     return -codes.uninit
  389.   end
  390.   local args = {...}
  391.   local command = args[1]
  392.   table.remove(args, 1)
  393.   if command == "set" then
  394.     local name = args[1]
  395.     table.remove(args, 1)
  396.     local inputs = args
  397.     for num, i in pairs(inputs) do
  398.       if not tonumber(i) then
  399.         table.remove(inputs, num)
  400.       end
  401.     end
  402.     _G.groups[name] = inputs
  403.     io.write("Added group \"" .. name .. "\" with inputs:\t" .. unicode.sub(ser.serialize(inputs), 2, -2) .. "\n")
  404.   elseif command == "del" then
  405.     local name = args[1]
  406.     _G.groups[name] = nil
  407.     io.write("Removed group \"" .. name .. "\"\n")
  408.   elseif command == "save" then
  409.     local f = io.open(CONF, "w")
  410.     f:write("group={")
  411.     local grstr = ""
  412.     for name, value in pairs(groups) do
  413.       grstr = grstr .. "[\"" .. name .. "\"]={"
  414.       for _, i in ipairs(value) do
  415.         grstr = grstr .. i .. ","
  416.       end
  417.       grstr = unicode.sub(grstr, 1, -2) .. "},"
  418.     end
  419.     grstr = unicode.sub(grstr, 1, -2)
  420.     f:write(grstr.."}")
  421.     f:close()
  422.     io.write("Saved to file\n")
  423.   elseif command == "on" or command == "off" then
  424.     local name = args[1]
  425.     table.remove(args, 1)
  426.     if _G.groups[name] then
  427.       for _, i in pairs(_G.groups[name]) do
  428.         if command == "on" then
  429.           on(i)
  430.         else
  431.           off(i)
  432.         end
  433.       end
  434.       io.write("Group \"" .. name .. "\" " .. (command == "on" and "activated" or "disabled") .. "\n")
  435.     end
  436.   elseif command == "list" then
  437.     for name, value in pairs(_G.groups) do
  438.       io.write("Group \"" .. name .. "\":\t" .. unicode.sub(ser.serialize(value), 2, -2) .. "\n")
  439.     end
  440.   end
  441.   return codes.success
  442. end
  443.  
  444. local function help()
  445.   io.write("Run `man nn` or open /usr/share/doc/nn/README.md for help!\n")
  446.   return codes.success
  447. end
  448.  
  449. local actions = {
  450.   get = ge,
  451.   clear = clear,
  452.   test = test,
  453.   init = init,
  454.   g = gc,
  455.   s = s,
  456.   reset = reset,
  457.   info = info,
  458.   on = on,
  459.   off = off,
  460.   hp = getHP,
  461.   hunger = getHung,
  462.   energy = getEnergy,
  463.   usage = usage,
  464.   age = getAge,
  465.   name = getName,
  466.   input = getInputsInfo,
  467.   copy = copy,
  468.   efon = getActiveEffects,
  469.   combo = combotest,
  470.   getcombo = getCombo,
  471.   group = group,
  472.   help = help
  473. }
  474.  
  475. local args = {...}
  476. local command = args[1]
  477. table.remove(args, 1)
  478.  
  479. for num, i in ipairs(args) do
  480.   if tonumber(i) then
  481.     args[num] = tonumber(i)
  482.   end
  483. end
  484.  
  485. if not command then
  486.   return actions["init"]()
  487. end
  488. if actions[command] then
  489.   return actions[command](table.unpack(args))
  490. end
  491.  
  492. -- vim: autoindent expandtab tabstop=2 shiftwidth=2 :
Advertisement
Add Comment
Please, Sign In to add comment