Added item-reports endpoint, schematic-exporter2.lua

This commit is contained in:
Andrew Lalis 2023-07-24 09:04:40 -04:00
parent 78a8aec3e8
commit 4762e216d9
2 changed files with 311 additions and 1 deletions

299
schematic-exporter2.lua Normal file
View File

@ -0,0 +1,299 @@
local g = require("simple-graphics")
local mon = peripheral.wrap("monitor_24")
local W, H = mon.getSize()
local RUNNING = true -- Flag to indicate global program state.
-- Export flags
local EXPORTING = false -- Flag to indicate if we're exporting.
local EXPORT_SKIP = false -- Flag to indicate we should skip the current item.
local EXPORT_REPORT = false -- Flag to indicate we should report the current item as invalid.
local function startsWith(str, start)
return str:sub(1, #start) == start
end
local function getTotalItemCount(itemList)
local total = 0
for name, value in pairs(itemList) do
if not startsWith(name, "__") then
total = total + value
end
end
local count = 1
if itemList.__COUNT__ then count = itemList.__COUNT__ end
return count * total
end
local function findItem(items, name)
for _, item in pairs(items) do
if item.name == name then return item end
end
return nil
end
local function attemptItemExport(name, count)
local P_NAME = "meBridge_4"
local p = peripheral.wrap(P_NAME)
if p == nil then
return nil, "Missing peripheral "..P_NAME
end
local func = function()
return p.exportItem({name=name, count=count}, "south")
end
local success, result = pcall(func)
if success then
return result
else
return nil, result
end
end
local function drawProgress(p)
local discreteWidth = W - 2
local filled = p * discreteWidth
g.drawXLine(mon, 2, W-1, 5, colors.lightGray)
g.drawXLine(mon, 2, 2+filled-1, 5, colors.green)
local s = string.format("%.0f%%", p*100)
for i = 1, #s do
local x = 2+i
local c = s:sub(i,i)
local bg = colors.lightGray
if x < filled then bg = colors.green end
g.drawText(mon, x, 5, c, colors.white, bg)
end
end
local function setProgressText(text)
g.drawXLine(mon, 2, W-1, 6, colors.gray)
if text ~= nil and #text > 0 then
g.drawText(mon, 2, 6, text, colors.white, colors.gray)
end
end
local function clearMainPanel()
g.fillRect(mon, 1, 7, W, H-6, colors.black)
end
local function clearExportPanel()
g.fillRect(mon, 1, 7, W, H-9, colors.black)
end
local function promptForUrlInput()
clearMainPanel()
drawProgress(0)
setProgressText(nil)
g.drawText(mon, 1, 8, "Please enter a schematic URL that", colors.white, colors.black)
g.drawText(mon, 1, 9, "you've obtained from", colors.white, colors.black)
g.drawText(mon, 1, 10, "schematics.andrewlalis.com in the", colors.white, colors.black)
g.drawText(mon, 1, 11, "computer to your right to continue.", colors.white, colors.black)
g.clear(term, colors.black)
g.drawText(term, 1, 1, "Paste your schematic URL here (CTRL+V): ", colors.white)
g.drawText(term, 2, 2, "*Press enter without pasting to quit*", colors.gray)
term.setCursorPos(1, 3)
term.setTextColor(colors.lightGray)
local link = io.read()
if link == nil or #link == 0 then
g.drawText(term, 1, 8, "No URL entered. Quitting.", colors.white)
return nil
else
g.drawText(term, 1, 8, "URL was pasted. Please continue on the monitor.", colors.white)
return link
end
end
local function fetchItemLists(url)
local response = http.get(url)
if response == nil then
return nil, "HTTP request failed."
end
if response.getResponseCode() ~= 200 then
return nil, "HTTP code " .. response.getResponseCode()
end
local rawText = response.readAll()
response.close()
local itemLists, jsonErr = textutils.unserializeJSON(rawText)
if not itemLists then
return nil, "Failed to parse JSON: "..jsonErr
end
return itemLists
end
local function exportItem(name, count)
clearExportPanel()
g.drawText(mon, 1, 7, "Exporting "..count.." of", colors.white, colors.black)
g.drawText(mon, 1, 8, name, colors.lime, colors.black)
-- Check for flags and do different stuff if so.
if EXPORT_REPORT then
-- Report the item issue to the schematic site.
g.drawText(mon, 1, 10, "Reporting item. Skipping to next one.", colors.orange, colors.black)
os.sleep(2)
return count
elseif EXPORT_SKIP then
-- Skip this item.
g.drawText(mon, 1, 10, "Skipping this item.", colors.orange, colors.black)
os.sleep(2)
return count
end
local me = peripheral.find("meBridge")
if me == nil then
g.drawText(mon, 1, 10, "Error: No \"meBridge\" peripheral.", colors.red, colors.black)
g.drawText(mon, 1, 11, "Attach one please.", colors.red, colors.black)
os.sleep(1)
return 0
end
local allItems, err = me.listItems()
if allItems == nil or #allItems < 5 then
g.drawText(mon, 1, 10, "Error: Couldn't list AE items.", colors.red, colors.black)
g.drawText(mon, 1, 11, "Msg: " .. err, colors.red, colors.black)
os.sleep(1)
return 0
end
local item = findItem(allItems, name)
if item ~= nil and item.amount > 0 then
local exported, err = attemptItemExport(name, count)
if exported ~= nil then
if exported == 0 then
g.drawText(mon, 1, 10, "Exported 0 items. Make sure there is", colors.yellow, colors.black)
g.drawText(mon, 1, 11, "space in the output container.", colors.yellow, colors.black)
os.sleep(0.5)
end
return exported
end
g.drawText(mon, 1, 10, "Transfer failed: " .. err, colors.red, colors.black)
os.sleep(1)
return 0
else
g.drawText(mon, 1, 10, "Item isn't present in the AE system.", colors.yellow, colors.black)
g.drawText(mon, 1, 11, "Please add some, craft, or skip.", colors.yellow, colors.black)
os.sleep(1)
return 0
end
end
local function exportSchematics(itemLists)
-- First build a list of instances of schematics, each with a task list.
local totalItemCount = 0
local listInstances = {}
for _, list in pairs(itemLists) do
totalItemCount = totalItemCount + getTotalItemCount(list)
for i = 1, list.__COUNT__ do
local instance = {
name = list.__NAME__,
instanceNumber = i,
countOfThisType = list.__COUNT__,
tasks = {}
}
for name, amount in pairs(list) do
if not startsWith(name, "__") then
table.insert(instance.tasks, {name=name, amount=amount})
end
end
table.insert(listInstances, instance)
end
end
-- Now execute on that task list, quitting if the EXPORTING flag goes false.
local totalItemsExported = 0
local instanceIndex = 1
while instanceIndex <= #listInstances and EXPORTING do
local listInstance = listInstances[instanceIndex]
setProgressText(listInstance.instanceNumber.."/"..listInstance.countOfThisType.." "..listInstance.name)
local taskIndex = 1
while taskIndex <= #listInstance.tasks and EXPORTING do
local task = listInstance.tasks[taskIndex]
local itemsExported = 0
-- Reset item-specific control flags.
EXPORT_REPORT = false
EXPORT_SKIP = false
while itemsExported < task.amount and EXPORTING do
local exportedCount = exportItem(task.name, task.amount - itemsExported)
itemsExported = itemsExported + exportedCount
totalItemsExported = totalItemsExported + exportedCount
drawProgress(totalItemsExported / totalItemCount)
end
taskIndex = taskIndex + 1
end
instanceIndex = instanceIndex + 1
end
-- Done! Show a small message, then set the EXPORTING flag to false.
EXPORTING = false
for i = 1, 3 do -- Queue up some no-op touch events make sure the event handler quits.
os.queueEvent("monitor_touch", "monitor_24", 1, 1)
end
g.drawText(mon, 1, H-4, "Export complete!", colors.lime, colors.black)
end
local function handleExportEvents()
while EXPORTING do
local event, monName, x, y = os.pullEvent("monitor_touch")
if monName == "monitor_24" and y >= H-2 then
if x >= 27 then
EXPORTING = false
elseif x >= 14 then
EXPORT_REPORT = true
else
EXPORT_SKIP = true
end
end
end
end
local function handleSchematicUrl(url)
clearMainPanel()
if url == nil then
g.drawText(mon, 1, 8, "No URL was entered. Quitting.", colors.white, colors.black)
RUNNING = false
os.sleep(2)
return
end
g.drawText(mon, 1, 8, "Fetching item lists from URL...", colors.lightGray, colors.black)
local itemLists, err = fetchItemLists(url)
if not itemLists then
g.drawText(mon, 1, 9, "Failed to fetch item lists.", colors.red, colors.black)
g.drawText(mon, 1, 10, err, colors.red, colors.black)
os.sleep(3)
return
end
g.drawText(mon, 1, 9, "Got lists for "..(#itemLists).." schematics.", colors.white, colors.black)
local y = 10
for i, itemList in pairs(itemLists) do
local count = itemList.__COUNT__
local name = itemList.__NAME__
g.drawText(mon, 2, y, count.."x "..name, colors.white, colors.black)
y = y+1
if y == H and i < #itemLists then
local numRemaining = #itemLists - i
g.drawText(mon, 2, y, "... and "..numRemaining.." more.")
end
end
os.sleep(3)
-- Draw control buttons.
g.fillRect(mon, 1, H-2, 13, 3, colors.blue)
g.drawText(mon, 5, H-1, "Skip", colors.white)
g.fillRect(mon, 14, H-2, 13, 3, colors.yellow)
g.drawText(mon, 14, H-1, "Report Error", colors.lightBlue)
g.fillRect(mon, 27, H-2, 13, 3, colors.red)
g.drawText(mon, 31, H-1, "Quit", colors.white)
EXPORTING = true
local fExport = function() exportSchematics(itemLists) end
local fHandleEvents = function() handleExportEvents() end
parallel.waitForAll(fExport, fHandleEvents)
end
-- MAIN SCRIPT
g.clear(mon, colors.black)
g.fillRect(mon, 1, 1, W, 3, colors.yellow)
g.drawTextCenter(mon, W/2, 2, "Schematic Exporter", colors.black)
g.fillRect(mon, 1, 4, W, 3, colors.gray)
g.drawText(mon, 2, 4, "Progress", colors.white)
g.drawXLine(mon, 2, W-1, 5, colors.lightGray)
while RUNNING do
local url = promptForUrlInput()
handleSchematicUrl(url)
end

View File

@ -17,6 +17,7 @@ void startServer() {
PathDelegatingHandler handler = new PathDelegatingHandler();
handler.addMapping("POST", "/extracts", &handleExtract);
handler.addMapping("GET", "/extracts/{extractId}", &getExtract);
handler.addMapping("POST", "/item-reports", &handleItemReport);
handler.addMapping("GET", "/status", (ref HttpRequestContext ctx) {
ctx.response.setStatus(HttpStatus.OK);
ctx.response.writeBodyString("online");
@ -43,3 +44,13 @@ private void getExtract(ref HttpRequestContext ctx) {
const extractFile = buildPath(EXTRACTS_DIR, extractId ~ ".json");
fileResponse(ctx.response, extractFile, "application/json");
}
private void handleItemReport(ref HttpRequestContext ctx) {
import std.string : strip;
import std.stdio;
string itemName = ctx.request.readBodyAsString().strip();
File f = File("item-reports.txt", "a");
f.writeln(itemName);
f.close();
}