Advertisement
fingercomp

[OC] Автокрафт: comp/CRAFT.LUA

Aug 15th, 2015
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ------------------------------------------------------
  2. -- Внимание! Код не смотреть                      | --
  3. -- Во избежания повреждения чего бы то ни было    . --
  4. ------------------------------------------------------
  5.  
  6. local FILE = "/usr/share/db"
  7. local PORT = 666
  8. local ROBOT = "62907d63-2067-4973-9742-2554daa93c88"
  9. local DIR = "north"
  10. local TECH_SLOTS = 3
  11. local DEBUG = false
  12. ---===---
  13. local com = require("component")
  14. local modem = com.modem
  15. local event = require("event")
  16. local me = com.me_interface
  17. local term = require("term")
  18. local gpu = com.gpu
  19. local unicode = require("unicode")
  20. local comp = require("computer")
  21.  
  22. local w, h = gpu.getResolution()
  23. modem.open(PORT)
  24. local all = me.getAvailableItems()
  25. local stacks = {}
  26. local function updateList()
  27.   stacks = {}
  28.   for i = 1, #all, 1 do
  29.     local fingerprint = all[i].fingerprint
  30.     if fingerprint.dmg ~= 0 then
  31.       stacks[fingerprint.id .. "@" .. fingerprint.dmg] = all[i]
  32.     else
  33.       stacks[fingerprint.id] = all[i]
  34.     end
  35.   end
  36. end
  37. loadfile(FILE, _ENV, _ENV)()
  38. updateList()
  39.  
  40. local checkAvail -- Forward declaration
  41.  
  42. local function centerY(text, line)
  43.   local textDiv = math.floor(unicode.len(text) / 2)
  44.   local widthDiv = math.floor(w / 2)
  45.   gpu.set(widthDiv - textDiv - 1, line, text)
  46. end
  47.  
  48. local function pushItem(item, slot)
  49.   local itemPrint = item.fingerprint
  50.   print("[INFO] [Pusher] Exporting " .. itemPrint.id .. "@" .. itemPrint.dmg .. " into robot (Slot: " .. slot .. ")")
  51.   rSlot = slot + TECH_SLOTS
  52.   rSlot = rSlot + math.floor((slot - 1) / 3)
  53.   me.exportItem(itemPrint, DIR, 1, rSlot)
  54. end
  55.  
  56. local function getItem(itemName)
  57.   return recipes[itemName]
  58. end
  59.  
  60. checkAvail = function(itemName, item)
  61.   if DEBUG then print(itemName, item) end
  62.   local itemStack
  63.   if item == nil then
  64.     itemStack = getItem(itemName)
  65.   else
  66.     itemStack = item
  67.   end
  68.   updateList()
  69.   local itemFP = itemStack.fingerprint
  70.   local data = false
  71.   for i = 1, #all, 1 do
  72.     if all[i].fingerprint.id == itemFP.id and all[i].fingerprint.dmg == itemFP.dmg then
  73.       data = {true, all[i], i}
  74.       break
  75.     end
  76.   end
  77.   if data == false then
  78.     return false
  79.   end
  80.   return table.unpack(data)
  81. end
  82.  
  83. local tree = {}
  84.  
  85. local function smartInsert(item, order, qty, noCraft, combine)
  86.   if DEBUG then print("SI", item, order, qty, noCraft, combine) end
  87.   local new = true
  88.   if combine then
  89.     for i = 1, #tree, 1 do
  90.       if tree[i].item.fingerprint.id == item.fingerprint.id and tree[i].item.fingerprint.dmg == item.fingerprint.dmg then
  91.         tree[i].order = math.max(order, tree[i].order)
  92.         tree[i].qty = tree[i].qty + qty
  93.         new = false
  94.         break
  95.       end
  96.     end
  97.   end
  98.   if new then
  99.     if noCraft then
  100.       table.insert(tree, {["item"] = item, ["order"] = order, ["qty"] = qty, ["noCraft"] = true})
  101.     else
  102.       table.insert(tree, {["item"] = item, ["order"] = order, ["qty"] = qty, ["noCraft"] = false})
  103.     end
  104.   end
  105. end
  106.  
  107. local function buildTree(itemName, order, qty, itemStack, toCraft, combine)
  108.   if DEBUG then print(itemName, order, qty, itemStack, toCraft, combine) end
  109.   local item = {}
  110.   if itemName ~= nil then
  111.     item = getItem(itemName)
  112.   elseif itemStack ~= nil then
  113.     item = itemStack
  114.   end
  115.   if type(item.recipe) == "table" then
  116.     for i = 1, 9, 1 do
  117.       if item.recipe[i] ~= "" then
  118.         if not checkAvail(item.recipe[i]) then
  119.           buildTree(item.recipe[i], order + 1, math.ceil(qty / item.qty), nil, false, true)
  120.         else
  121.           smartInsert(getItem(item.recipe[i]), order + 1, math.ceil(qty / item.qty), true, true)
  122.         end
  123.       end
  124.     end
  125.   else
  126.     if not checkAvail(itemName) then
  127.       io.stderr:write("Отсутствует компонент крафта: " .. item.fingerprint.id .. "@" .. item.fingerprint.dmg .. "!")
  128.       os.exit()
  129.     end
  130.   end
  131.   if toCraft == nil then toCraft = false end
  132.   if combine == nil then combine = true end
  133.   if DEBUG then print("TC", toCraft, combine) end
  134.   smartInsert(item, order, qty, toCraft, combine)
  135. end
  136.  
  137. local stack = {}
  138.  
  139. local function checkTree()
  140.   for i = 1, #tree, 1 do
  141.     local stack = tree[i]
  142.     if DEBUG then print("ID", stack.item.fingerprint.id, stack.item.fingerprint.dmg) end
  143.     local avail, info, _ = checkAvail(nil, stack.item)
  144.     if DEBUG then print("AQ", avail, stack.qty, type(stack.qty)) end
  145.     if stack.noCraft then
  146.       if avail then
  147.         if DEBUG then print("CS", info.size) end
  148.         if stack.qty > info.size then
  149.           if stack.item.recipe then
  150.             buildTree(nil, stack.order + 1, stack.qty - info.size, stack.item, false, false)
  151.           else
  152.             io.stderr:write("[ERR] Недостаточно ресурсов: " .. stack.item.fingerprint.id .. "@" .. stack.item.fingerprint.dmg .. " (" .. info.size .. "/" .. stack.qty .. ")!")
  153.             os.exit()
  154.           end
  155.         end
  156.       else
  157.         if stack.item.recipe then
  158.           print("M", stack.qty)
  159.           buildTree(nil, stack.order + 1, stack.qty, stack.item, false, false)
  160.         else
  161.           io.stderr:write("[ERR] Отсутствие ресурсов: " .. stack.item.fingerprint.id .. "@" .. stack.item.fingerprint.dmg .. " (" .. stack.qty .. ")!")
  162.           os.exit()
  163.         end
  164.       end
  165.     end
  166.   end
  167. end
  168.  
  169. local function craft()
  170.   local stats = {}
  171.   stats.crafted = 0
  172.   stats.timeStart = comp.uptime()
  173.   stats.timeStop = 0
  174.   stats.treeLen = #tree
  175.   local orderTree = {}
  176.   for i = 1, #tree, 1 do
  177.     local order = tree[i].order + 1
  178.     if not orderTree[order] then
  179.       orderTree[order] = {}
  180.     end
  181.     table.insert(orderTree[order], {["item"] = tree[i].item, ["qty"] = tree[i].qty, ["noCraft"] = tree[i].noCraft})
  182.   end
  183.   stats.maxOrder = #orderTree
  184.   for i = #orderTree, 1, -1 do
  185.     print("[INFO] [Craft] Обработка очереди " .. i)
  186.     for j = 1, #orderTree[i], 1 do
  187.       print("[INFO] [Craft] Обработка задачи " .. j)
  188.       if orderTree[i][j].item.recipe then
  189.         if not orderTree[i][j].noCraft then
  190.           print("[INFO] [Craft] ID предмета в задаче: " .. orderTree[i][j].item.fingerprint.id .. "@" .. orderTree[i][j].item.fingerprint.dmg)
  191.           for l = 1, math.ceil(orderTree[i][j].qty / orderTree[i][j].item.qty), 1 do
  192.             print("[INFO] [Craft] Крафт #" .. l)
  193.             for k = 1, 9, 1 do
  194.               if orderTree[i][j].item.recipe[k] ~= "" then
  195.                 pushItem(getItem(orderTree[i][j].item.recipe[k]), k)
  196.               end
  197.             end
  198.             modem.send(ROBOT, PORT, "craft")
  199.             stats.crafted = stats.crafted + 1
  200.             os.sleep(0.5)
  201.           end
  202.         end
  203.       end
  204.     end
  205.   end
  206.   stats.timeStop = comp.uptime()
  207.   return stats
  208. end
  209.  
  210.  
  211. modem.send(ROBOT, PORT, "clear")
  212.  
  213. local listH = h - 1
  214.  
  215. local function getNumber(min, max)
  216.   repeat
  217.     gpu.fill(1, h, w, 1, " ")
  218.     term.setCursor(1, h)
  219.     io.write("Предмет для крафта (0 для выхода): ")
  220.     input = term.read(nil, false)
  221.     if tonumber(input) == 0 then
  222.       term.clear()
  223.       term.setCursor(1, 1)
  224.       os.exit()
  225.     end
  226.   until tonumber(input) ~= nil and tonumber(input) <= max and tonumber(input) >= min
  227.   return tonumber(input)
  228. end
  229.  
  230. local names = {}
  231.  
  232. for name, _ in pairs(recipes) do
  233.   table.insert(names, name)
  234. end
  235.  
  236. local pages = {}
  237. local onPage = listH * 2
  238. if #names > onPage then
  239.   onPage = onPage - 1
  240. end
  241. local j = 1
  242. local page = {}
  243. while true do
  244.   page = {}
  245.   for i = 1, onPage, 1 do
  246.     if names[j + i] then
  247.       table.insert(page, {j + i - 1, names[j + i - 1]})
  248.     else
  249.       break
  250.     end
  251.   end
  252.   table.insert(pages, page)
  253.   if not names[j + onPage + 1] then break end
  254.   j = j + onPage
  255. end
  256.  
  257. local lines = {}
  258.  
  259. local function list(page)
  260.   term.clear()
  261.   for i = 1, #pages[page], 1 do
  262.     local item = pages[page][i]
  263.     local nonCraftable = (recipes[item[2]].recipe and "[*] " or "")
  264.     if i > listH then
  265.       gpu.set(w / 2, i - listH, "[" .. item[1] .. "] " .. nonCraftable .. item[2])
  266.     else
  267.       gpu.set(1, i, "[" .. item[1] .. "] " .. nonCraftable .. item[2])
  268.     end
  269.   end
  270. end
  271.  
  272. local function drawNext(id)
  273.   gpu.set(w / 2, listH, "[" .. id .. "] Next ->")
  274. end
  275.  
  276. local page = 0
  277. local input = ""
  278. local nextId = 0
  279. local returnToBack = false
  280.  
  281. repeat
  282.   page = page + 1
  283.   if page > #pages then
  284.     page = 1
  285.   end
  286.   list(page)
  287.   if onPage ~= listH * 2 then
  288.     nextId = pages[page][#pages[page]][1] + 1
  289.     drawNext(nextId)
  290.     input = getNumber(pages[page][1][1], pages[page][#pages[page]][1] + 1)
  291.   else
  292.     input = getNumber(pages[1][1][1], pages[1][#pages[1]][1])
  293.   end
  294. until input ~= nextId
  295.  
  296. gpu.setBackground(0xFFFFFF)
  297. gpu.setForeground(0x000000)
  298.  
  299. local request, id, lineH, offset = "", 0, 0, 1
  300. for i = 1, #pages[page], 1 do
  301.   if pages[page][i][1] == tonumber(input) then
  302.     request = pages[page][i][2]
  303.     id = i
  304.   end
  305. end
  306. if id > listH then
  307.   lineH = id - listH
  308.   offset = w / 2
  309. else
  310.   lineH = id
  311. end
  312.  
  313. gpu.fill(offset, lineH, w / 2 - 2, 1, " ")
  314. gpu.set(offset, lineH, "[" .. input .. "] " .. request)
  315.  
  316. gpu.setForeground(0xFFFFFF)
  317. gpu.setBackground(0x000000)
  318.  
  319. local qty = 0
  320. repeat
  321.   term.clearLine(h)
  322.   term.setCursor(1, h)
  323.   io.write("Выберите количество (0 для выхода): ")
  324.   qty = term.read()
  325. until tonumber(qty) ~= nil
  326.  
  327. if tonumber(qty) < 1 then
  328.   term.clear()
  329.   term.setCursor(1, 1)
  330.   os.exit()
  331. end
  332.  
  333. qty = tonumber(qty)
  334. term.clear()
  335. term.setCursor(1, 2)
  336. gpu.set(1, 1, string.rep("-", w))
  337. centerY("ПЛАН КРАФТА", 1)
  338. buildTree(request, 0, qty)
  339. for i =1, #tree, 1 do
  340.   if tree[i].noCraft then
  341.     noCraft = "[X]"
  342.   else
  343.     noCraft = ""
  344.   end
  345.   print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
  346. end
  347. gpu.set(1, h, "Нажмите [Enter] для проверки дерева и старта крафта...")
  348. local keyData = {event.pull("key_down")}
  349. if keyData[1] == nil or keyData[3] ~= 13 then
  350.   term.clear()
  351.   term.setCursor(1, 1)
  352.   os.exit()
  353. end
  354. term.clear()
  355. term.setCursor(1, 2)
  356. gpu.set(1, 1, string.rep("-", w))
  357. centerY("ПЛАН КРАФТА (ПЕРЕПРОВЕРКА)", 1)
  358. checkTree()
  359. for i = 1, #tree, 1 do
  360.   if tree[i].noCraft then
  361.     noCraft = "[X]"
  362.   else
  363.     noCraft = ""
  364.   end
  365.   print("[" .. i .. "] " .. tree[i].item.fingerprint.id .. "@" .. tree[i].item.fingerprint.dmg .. " x " .. tree[i].qty .. " " .. noCraft .. " (порядок: " .. tree[i].order .. ")")
  366. end
  367. gpu.set(1, h, "Нажмите [Enter] для продолжения...")
  368. keyData = {event.pull("key_down")}
  369. if keyData[1] == nil or keyData[3] ~= 13 then
  370.   term.clear()
  371.   term.setCursor(1, 1)
  372.   os.exit()
  373. end
  374. term.clear()
  375. term.setCursor(1, 2)
  376. gpu.set(1, 1, string.rep("-", w))
  377. centerY("ЛОГ КРАФТА", 1)
  378. print("[ATTN] Пожалуйста, не изменяйте содержимое МЭ-сети до завершения процесса крафта!")
  379. local stats = craft()
  380. print("")
  381. print("[INFO] [Stats] Статистика:")
  382. print("[INFO] [Stats] Всего крафтов: " .. stats.crafted)
  383. print("[INFO] [Stats] Время крафта: " .. stats.timeStop - stats.timeStart .. "s")
  384. print("[INFO] [Stats] Очередей всего: " .. stats.maxOrder)
  385. print("[INFO] [Stats] Длина дерева: " .. stats.treeLen .. "\n")
  386. gpu.set(1, h - 1, string.rep("-", w))
  387. centerY("КРАФТ ЗАВЕРШЁН", h - 1)
  388. term.setCursor(1, h)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement