Advertisement
Lordeah18

stocker.lua

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