Advertisement
Lordeah18

stocker.lua

Nov 23rd, 2024
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.45 KB | None | 0 0
  1. if not fs.exists("json") then
  2.     shell.run("pastebin get 4nRg9CHU json")
  3. end
  4.  
  5. os.loadAPI("json")
  6.  
  7. local configFolder = "stock_config"
  8. local defaultSourcePeripheral = "left"
  9. local monitorPeripheral = "top"
  10.  
  11. -- Reads configuration files
  12. local function readConfigFiles(folder)
  13.     local configs = {}
  14.     if fs.exists(folder) and fs.isDir(folder) then
  15.         for _, file in ipairs(fs.list(folder)) do
  16.             local filePath = fs.combine(folder, file)
  17.             if not fs.isDir(filePath) then
  18.                 local fileHandle = fs.open(filePath, "r")
  19.                 if fileHandle then
  20.                     local content = fileHandle.readAll()
  21.                     fileHandle.close()
  22.                     local parsed = json.decode(content)
  23.                     if parsed then
  24.                         table.insert(configs, parsed)
  25.                     end
  26.                 end
  27.             end
  28.         end
  29.     end
  30.     return configs
  31. end
  32.  
  33. -- Checks the stock level of a product
  34. local function checkStockLevel(itemName, destinationPeripheral)
  35.     local stockPeripheral = peripheral.wrap(destinationPeripheral)
  36.     if not stockPeripheral then
  37.         print("Error: Could not find destination peripheral.")
  38.         return 0
  39.     end
  40.  
  41.     local currentStock = 0
  42.     for _, item in pairs(stockPeripheral.list()) do
  43.         if item.name == itemName then
  44.             currentStock = currentStock + item.count
  45.         end
  46.     end
  47.     return currentStock
  48. end
  49.  
  50. -- Checks for missing items and calculates the largest possible batch
  51. local function checkMissingItems(config)
  52.     local missingItems = {}
  53.     local maxBatchCount = math.huge  -- Start with an unlimited batch count and reduce as needed
  54.  
  55.     for _, ingredient in ipairs(config.ingredients) do
  56.         local itemName = ingredient.name
  57.         local requiredQuantity = ingredient.quantity or 1
  58.         local availableQuantity = 0
  59.  
  60.         -- Determine the source for this specific ingredient
  61.         local sourcePeripheral = peripheral.wrap(ingredient.source or config.destination or defaultSourcePeripheral)
  62.         if not sourcePeripheral then
  63.             print("Error: Could not find source peripheral for " .. itemName)
  64.             table.insert(missingItems, { name = itemName, missing = requiredQuantity })
  65.             maxBatchCount = 0  -- If a source is missing, no batches can be created
  66.         else
  67.             -- Accumulate the count of the item in the source inventory
  68.             for slot, itemDetail in pairs(sourcePeripheral.list()) do
  69.                 if itemDetail.name == itemName then
  70.                     availableQuantity = availableQuantity + itemDetail.count
  71.                 end
  72.             end
  73.  
  74.             -- Calculate max possible batches for this ingredient
  75.             local maxIngredientBatches = math.floor(availableQuantity / requiredQuantity)
  76.             if maxIngredientBatches < maxBatchCount then
  77.                 maxBatchCount = maxIngredientBatches
  78.             end
  79.  
  80.             -- Add to missing items if quantity is insufficient for at least one batch
  81.             if availableQuantity < requiredQuantity then
  82.                 table.insert(missingItems, {
  83.                     name = itemName,
  84.                     missing = requiredQuantity - availableQuantity
  85.                 })
  86.             end
  87.         end
  88.     end
  89.  
  90.     -- Return the missing items and the largest possible batch count
  91.     return missingItems, maxBatchCount
  92. end
  93.  
  94. -- Transfers ingredients to the processing input peripheral
  95. local function transferIngredients(ingredients, processingInput, batchCount)
  96.     local inputPeripheral = peripheral.wrap(processingInput)
  97.     if not inputPeripheral then
  98.         print("Error: Could not find processing input peripheral.")
  99.         return false
  100.     end
  101.  
  102.     for _, ingredient in ipairs(ingredients) do
  103.         local ingredientName = ingredient.name
  104.         local quantity = (ingredient.quantity or 1) * batchCount
  105.         local sourcePeripheral = peripheral.wrap(ingredient.source or defaultSourcePeripheral)
  106.  
  107.         if not sourcePeripheral then
  108.             print("Error: Could not find source peripheral for " .. ingredientName)
  109.             return false
  110.         end
  111.  
  112.         local transferred = 0
  113.         for slot, item in pairs(sourcePeripheral.list()) do
  114.             if item.name == ingredientName then
  115.                 local toTransfer = math.min(quantity - transferred, item.count)
  116.                 inputPeripheral.pullItems(peripheral.getName(sourcePeripheral), slot, toTransfer)
  117.                 transferred = transferred + toTransfer
  118.                 if transferred >= quantity then break end
  119.             end
  120.         end
  121.  
  122.         if transferred < quantity then
  123.             print("Error: Not enough " .. ingredientName .. " available.")
  124.             return false
  125.         end
  126.     end
  127.     return true
  128. end
  129.  
  130. local function waitForProduct(processingInput)
  131.     local inputPeripheral = peripheral.wrap(processingInput)
  132.     while #inputPeripheral.list() > 0 do
  133.         os.sleep(1)
  134.     end
  135. end
  136.  
  137. -- Transfers finished products to the stock destination peripheral
  138. local function transferProduct(productName, processingOutput, destination)
  139.     local outputPeripheral = peripheral.wrap(processingOutput)
  140.     local destinationPeripheral = peripheral.wrap(destination)
  141.  
  142.     if not outputPeripheral or not destinationPeripheral then
  143.         print("Error: Could not find processing output or destination peripheral.")
  144.         return
  145.     end
  146.  
  147.     for slot, item in pairs(outputPeripheral.list()) do
  148.         if item.name == productName then
  149.             outputPeripheral.pushItems(peripheral.getName(destinationPeripheral), slot)
  150.         end
  151.     end
  152. end
  153.  
  154. -- Displays missing items on the monitor
  155. local function displayMissingResources(missingItems)
  156.     local monitor = peripheral.wrap(monitorPeripheral)
  157.     if not monitor then
  158.         print("Error: Monitor not found. Missing resources will not be displayed.")
  159.         return
  160.     end
  161.  
  162.     monitor.clear()
  163.     monitor.setCursorPos(1, 1)
  164.     monitor.write("Missing Resources:")
  165.  
  166.     local width, height = monitor.getSize()
  167.     local line = 2
  168.  
  169.     for _, item in ipairs(missingItems) do
  170.         local text = "- " .. item.name .. ": " .. item.missing
  171.         while #text > 0 do
  172.             local chunk = text:sub(1, width) -- Split into chunks that fit the monitor width
  173.             monitor.setCursorPos(1, line)
  174.             monitor.write(chunk)
  175.             text = text:sub(width + 1)
  176.             line = line + 1
  177.  
  178.             if line > height then
  179.                 -- Pause and clear monitor when space is exhausted
  180.                 os.sleep(2)
  181.                 monitor.clear()
  182.                 monitor.setCursorPos(1, 1)
  183.                 monitor.write("Missing Resources (cont'd):")
  184.                 line = 2
  185.             end
  186.         end
  187.  
  188.         -- Add a blank line between items for readability
  189.         if line < height then
  190.             line = line + 1
  191.         else
  192.             os.sleep(2)
  193.             monitor.clear()
  194.             monitor.setCursorPos(1, 1)
  195.             monitor.write("Missing Resources (cont'd):")
  196.             line = 2
  197.         end
  198.     end
  199. end
  200.  
  201.  
  202. -- Displays status on the monitor
  203. local function displayStatus(config, currentStock, ingredientsReady, batchesAvailable)
  204.     local monitor = peripheral.wrap(monitorPeripheral)
  205.     if not monitor then
  206.         print("Error: Monitor not found.")
  207.         return
  208.     end
  209.  
  210.     monitor.clear()
  211.     monitor.setCursorPos(1, 1)
  212.     monitor.write("Stock Management:")
  213.     monitor.setCursorPos(1, 2)
  214.     monitor.write("- Product: " .. config.product)
  215.     monitor.setCursorPos(1, 3)
  216.     monitor.write("- Required Stock: " .. config.stock)
  217.     monitor.setCursorPos(1, 4)
  218.     monitor.write("- Current Stock: " .. currentStock)
  219.     monitor.setCursorPos(1, 5)
  220.     monitor.write("- Ingredients Ready: " .. (ingredientsReady and "Yes" or "No"))
  221.     monitor.setCursorPos(1, 6)
  222.     monitor.write("- Batches Available: " .. batchesAvailable)
  223. end
  224.  
  225. -- Main logic
  226. local function main()
  227.     local configFiles = readConfigFiles(configFolder)
  228.     for _, config in ipairs(configFiles) do
  229.         local productName = config.product
  230.         local requiredStock = config.stock
  231.         local destination = config.destination
  232.         local processingInput = config.processing_input
  233.         local processingOutput = config.processing_output or config.processing_input
  234.         local ingredients = config.ingredients
  235.         local batchSize = config.batch_size or 1
  236.  
  237.         local currentStock = checkStockLevel(productName, destination)
  238.  
  239.         if currentStock < requiredStock then
  240.             local missingItems, maxBatchCount = checkMissingItems(config)
  241.            
  242.             if maxBatchCount > 0 then
  243.                 -- Transfer ingredients for the maximum number of batches possible
  244.                 local ingredientsReady = transferIngredients(ingredients, processingInput, maxBatchCount)
  245.                 displayStatus(config, currentStock, ingredientsReady, maxBatchCount)
  246.  
  247.                 if ingredientsReady then
  248.                     waitForProduct(processingInput)
  249.                     transferProduct(productName, processingOutput, destination)
  250.                 else
  251.                     print("Could not transfer ingredients for " .. productName .. ".")
  252.                 end
  253.             else
  254.                 displayMissingResources(missingItems)
  255.             end
  256.         end
  257.     end
  258.     print("Stock management cycle complete.")
  259. end
  260.  
  261. while true do
  262.     main()
  263.     os.sleep(10)
  264. end
  265.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement