-- ATM10 AE2 pattern audit via Advanced Peripherals ME Bridge -- Read-only: does not craft, export, import, cancel or modify patterns. local OUTPUT_FILE = "me_pattern_debug.txt" local bridgeName local function hasType(name, wanted) if peripheral.hasType then return peripheral.hasType(name, wanted) end return peripheral.getType(name) == wanted end for _, name in ipairs(peripheral.getNames()) do if hasType(name, "me_bridge") then bridgeName = name break end end if not bridgeName then error("Keine ME Bridge am Computer gefunden", 0) end local function sortedKeys(value) local keys = {} for key in pairs(value or {}) do keys[#keys + 1] = key end table.sort(keys, function(a, b) return tostring(a) < tostring(b) end) return keys end local function serialize(value, depth, seen) depth, seen = depth or 0, seen or {} local kind = type(value) if kind == "string" then return string.format("%q", value) end if kind ~= "table" then return tostring(value) end if seen[value] then return "" end if depth >= 12 then return "" end seen[value] = true local parts = { "{" } for _, key in ipairs(sortedKeys(value)) do parts[#parts + 1] = string.rep(" ", depth + 1) .. "[" .. serialize(key, depth + 1, seen) .. "] = " .. serialize(value[key], depth + 1, seen) .. "," end parts[#parts + 1] = string.rep(" ", depth) .. "}" seen[value] = nil return table.concat(parts, "\n") end local function compact(value, seen) local kind = type(value) if kind == "string" then return string.format("%q", value) end if kind ~= "table" then return tostring(value) end seen = seen or {} if seen[value] then return "" end seen[value] = true local parts = {} for _, key in ipairs(sortedKeys(value)) do parts[#parts + 1] = "[" .. compact(key, seen) .. "]=" .. compact(value[key], seen) end seen[value] = nil return "{" .. table.concat(parts, ",") .. "}" end local function callRead(method, ...) local result = table.pack(pcall(peripheral.call, bridgeName, method, ...)) if not result[1] then return false, tostring(result[2]) end if result.n == 2 then return true, result[2] end local values = { n = result.n - 1 } for index = 2, result.n do values[index - 1] = result[index] end return true, values end local function listValues(value) local result = {} if type(value) ~= "table" then return result end for key, entry in pairs(value) do if key ~= "n" and type(entry) == "table" then result[#result + 1] = entry end end return result end local function recipeSide(pattern, names) for _, name in ipairs(names) do if pattern[name] ~= nil then return pattern[name] end end end local function fingerprint(pattern) local inputs = recipeSide(pattern, { "inputs", "input", "ingredients" }) local outputs = recipeSide(pattern, { "outputs", "output", "results", "result" }) if inputs ~= nil or outputs ~= nil then return "IN=" .. compact(inputs) .. "|OUT=" .. compact(outputs) end return compact(pattern) end local lines = {} local function emit(value) lines[#lines + 1] = tostring(value) end emit("ATM10 AE2 PATTERN DEBUG") emit("Computer ID: " .. tostring(os.getComputerID())) emit("Computer label: " .. tostring(os.getComputerLabel() or "")) emit("ME Bridge: " .. bridgeName) local okOnline, online = callRead("isConnected") emit("Connected: " .. (okOnline and tostring(online) or ("ERROR: " .. tostring(online)))) local okPatterns, rawPatterns = callRead("getPatterns") if not okPatterns then okPatterns, rawPatterns = callRead("getPatterns", {}) end if not okPatterns then error("getPatterns fehlgeschlagen: " .. tostring(rawPatterns), 0) end local patterns = listValues(rawPatterns) emit("Pattern records: " .. tostring(#patterns)) local groups = {} for index, pattern in ipairs(patterns) do local key = fingerprint(pattern) groups[key] = groups[key] or {} groups[key][#groups[key] + 1] = index end local duplicates = {} for key, indexes in pairs(groups) do if #indexes > 1 then duplicates[#duplicates + 1] = { key = key, indexes = indexes } end end table.sort(duplicates, function(a, b) if #a.indexes == #b.indexes then return a.key < b.key end return #a.indexes > #b.indexes end) emit("Duplicate candidate groups: " .. tostring(#duplicates)) emit("") emit("DUPLICATE CANDIDATES") emit(string.rep("=", 72)) if #duplicates == 0 then emit("No duplicates detected from the exposed pattern schema.") else for groupIndex, group in ipairs(duplicates) do emit("") emit("GROUP " .. groupIndex .. " | copies=" .. #group.indexes .. " | pattern indexes=" .. table.concat(group.indexes, ", ")) emit(group.key) end end emit("") emit("RAW GETPATTERNS RESULT") emit(string.rep("=", 72)) emit(serialize(rawPatterns)) local okCraftable, craftable = callRead("getCraftableItems") emit("") emit("RAW GETCRAFTABLEITEMS RESULT") emit(string.rep("=", 72)) emit(okCraftable and serialize(craftable) or ("ERROR: " .. tostring(craftable))) emit("") emit("CONNECTED PERIPHERALS") emit(string.rep("=", 72)) local peripheralNames = peripheral.getNames() table.sort(peripheralNames) for _, name in ipairs(peripheralNames) do local types = table.pack(peripheral.getType(name)) local typeNames = {} for index = 1, types.n do if types[index] ~= nil then typeNames[#typeNames + 1] = tostring(types[index]) end end emit(name .. " | " .. table.concat(typeNames, ", ")) end local file = assert(fs.open(OUTPUT_FILE, "w")) file.write(table.concat(lines, "\n")) file.write("\n") file.close() print("ME Pattern Audit abgeschlossen.") print("Pattern-Datensaetze: " .. tostring(#patterns)) print("Duplikat-Gruppen: " .. tostring(#duplicates)) print("Erstellt: " .. OUTPUT_FILE) print("Bitte danach Codex 'fertig' schreiben.")