This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
FortuneSyn's profile picture

[lua] formatting the inventoryinfo from chests from ccSensors

Started by FortuneSyn, 08 November 2012 - 06:28 AM
FortuneSyn #1
Posted 08 November 2012 - 07:28 AM
Hi!

I am trying to code a program that will show the item count of specific items (such as diamonds, iron, gold, etc) in an easy to read format, that is constantly being updated and shown on a 2 high 4 wide monitor. This is how long I've gotten so far :P/>/> :


------------- Load API for sensors ------------
os.unloadAPI("sensors")
os.loadAPI("/rom/apis/sensors")
------------- Dictionary Printer --------------
function printDict(data)
for i,v in pairs(data) do
  print(tostring(i).." - "..tostring(v))
end
end
------------- TheCode -------------------------
--what side is controller on?
ctrl = sensors.getController()
--list all the sensors and name them
data = sensors.getSensors(ctrl)
invSensorA = data[1]
--list all the probes of specific sensors and name them
data = sensors.getProbes(ctrl,invSensorA)
inventoryContent = data[3]
--list all targets of specific sensor+probe and name them
data = sensors.getAvailableTargetsforProbe(ctrl,invSensorA,inventoryContent)
chestLeftUp = data[6]
data = sensors.getSensorReadingAsDict(ctrl,invSensorA,chestLeftUp,inventoryContent)
printDict(data)

this is what the data looks like:


My question(s):
- How do I extract these item names and numbers reliably?
- How can I add, for example, all the iron ingots listed reliably?

Thanks in advance.
Lyqyd #2
Posted 08 November 2012 - 08:50 AM
You'll want to use string.match. I can't pull up the image of the data (which ideally should have been posted as text), so I will not be able to provide a matching pattern until I'm home tonight.
Espen #3
Posted 08 November 2012 - 09:18 AM
Here's a small example with string.match:
local testStrings = {}
testStrings[1] = "53*null@6"
testStrings[2] = "7*item.itemHarz@0"
testStrings[3] = "64*item.itemIngotTin@0"
local pattern = "^(%d+)%*(%a+%.?%a+)@(%d+)$"

for i = 1, #testStrings do
    local amount, item, slot = string.match( testStrings[i], pattern )
    print( testStrings[i] )
    print( "tAmount:\t"..tostring( amount ))
    print( "tItem:\t\t\t"..tostring( item ))
    print( "tSlot:\t\t\t"..tostring( slot ))
    print()
end

And here one with string.gsub, which calls 'printCaptures()' for every match passing the captures as arguments:
local testStrings = {}
testStrings[1] = "53*null@6"
testStrings[2] = "7*item.itemHarz@0"
testStrings[3] = "64*item.itemIngotTin@0"
local pattern = "^(%d+)%*(%a+%.?%a+)@(%d+)$"

local function printCaptures( ... )
    local tArg = { ... }
    if not (#tArg == 3) then error("Error: Expected 3 captures, but got "..#tArg..".") end

    print( "tAmount:\t"..tostring( tArg[1] ))
    print( "tItem:\t\t\t"..tostring( tArg[2] ))
    print( "tSlot:\t\t\t"..tostring( tArg[3] ))
end

for i = 1, #testStrings do
    print( testStrings[i] )
    string.gsub( testStrings[i], pattern, printCaptures )
    print()
end

Output (the same for both examples):
Spoiler
53*null@6
	Amount:	53
	Item:	null
	Slot:	6

7*item.itemHarz@0
	Amount:	7
	Item:	item.itemHarz
	Slot:	0

64*item.itemIngotTin@0
	Amount:	64
	Item:	item.itemIngotTin
	Slot:	0

The regular expression within the 'pattern' variable is used to match the strings.
The brackets () within the regular expression mark the places where I want to capture parts of the matched strings.
As you can see in the pattern, there are 3 bracket-pairs, meaning 3 captures will be returned by the string.match() function.

For more info on all the available regex-options, take a look at this:
Roblox - String patterns

Hope this helps,
Cheers

EDIT #1: Added output & beautified link.
EDIT #2: Did some search'n'replace errors before posting. Code now fixed.^^
EDIT #3: Added another example to showcase string.gsub()
EDIT #4: Added the $-anchor, since in the example I match the whole string anyway. Redundant, but just for completeness' sake.
EDIT #5: Due to forum changes some escape characters got removed from the code. Fixed it.
Edited on 16 February 2013 - 12:13 AM
FortuneSyn #4
Posted 08 November 2012 - 10:43 AM
Awesome, thankyou so much. I'm gonna have to play around with what you've told me for a bit to absorb it all.
FortuneSyn #5
Posted 08 November 2012 - 12:06 PM
OK so I'm trying to add how much iron is there in total. I'm trying to do this by collecting all the iron counts into a table, and then I want to sum up all the numbers in the table to give my final total iron count. How do I sum up the numbers in the table? Sometimes there might be 2 numbers, sometimes 12.

Is this a decent way to do it? If not, feel free to suggest alternative to using a table.


local pattern = "^(%d+)%*(%a+%.?%a+)@(%d+)"
local tableIron = {}
for i = 1, #data do
	local amount, item, slot = string.match( data[i], pattern )
if item == "item.ingotIron" then
  table.insert(tableIron,amount)
end
end

Woohoo, nevermind, I found it by googling :P/>/> although i still don't really understand how it works:


function sum(data)
    local sum = 0
    for k,v in pairs(data) do
	    sum = sum + v
    end

    return sum
end
FortuneSyn #6
Posted 08 November 2012 - 01:24 PM
Success!!!!!!!!!! =) =) Image if you want to see result.

Spoiler

Code is below, feel free to criticize so I can learn. Currently one bug is that if the items are spread out in the chest (for example items in slots 1-40, but then some items in slot 44, 50, 52, etc), I won't get any values and it will return zero for all items.

Also, the sensorcontroller acts very strange in multiplayer. It saves old sensors that i have placed and removed from the world, it keeps renaming one of my sensors to sensor, and it can only communicate with one sensor for some reason.

Also, I assume there's a better way to create that infinite loop than how i did it?



------------- Load API for sensors ------------
os.unloadAPI("sensors")
os.loadAPI("/rom/apis/sensors")
------------- Dictionary Printer --------------
function printDict(data)
for i,v in pairs(data) do
  print(tostring(i).." - "..tostring(v))
end
end
----------------Table Sum Function-------------------------------
function sum(data)
	local sum = 0
	for k,v in pairs(data) do
		sum = sum + v
	end

	return sum
end
------------- TheCode -------------------------
--what side is controller on?
ctrl = sensors.getController()
--list all the sensors and name them
data = sensors.getSensors(ctrl)
invSensorA = data[1]
--list all the probes of specific sensors and name them
data = sensors.getProbes(ctrl,invSensorA)
inventoryContent = data[3]
--list all targets of specific sensor+probe and name them
data = sensors.getAvailableTargetsforProbe(ctrl,invSensorA,inventoryContent)
chestLeftUp = data[6]

local pattern = "^(%d+)%*(%a+%.?%a+)@(%d+)"
local g = 0
local h = 1
while g ~= h do
local tableDiamond = {}
local tableIron = {}
local tableRedstone = {}
data = sensors.getSensorReadingAsDict(ctrl,invSensorA,chestLeftUp,inventoryContent)
--printDict(data)
term.clear()
term.setCursorPos(2,2)
for i = 1, #data do
  local amount, item, slot = string.match( data[i], pattern )
  if item == "item.ingotIron" then
   table.insert(tableIron,amount)
  end
  if item == "item.emerald" then
   table.insert(tableDiamond,amount)
  end
  if item == "item.redstone" then
   table.insert(tableRedstone,amount)
  end
	--print(tostring( item ).." "..tostring(amount))
end
print("Amount")
write("	Diamonds:	   ")
data = tableDiamond
print(sum(data))
write("	Iron Ingots:	")
data = tableIron
print(sum(data))
write("	Redstone dust:  ")
data = tableRedstone
print(sum(data))

sleep(1)
end
Doyle3694 #7
Posted 08 November 2012 - 01:28 PM
the most common infinite loop syntax is

while true do
end

But yours work aswell. Sometimes I use while 1==1 do just for the laugh people get when reading my programs
Curtis33210 #8
Posted 03 December 2012 - 10:30 AM
Success!!!!!!!!!! =) =) Image if you want to see result.

Spoiler

Code is below, feel free to criticize so I can learn. Currently one bug is that if the items are spread out in the chest (for example items in slots 1-40, but then some items in slot 44, 50, 52, etc), I won't get any values and it will return zero for all items.

Also, the sensorcontroller acts very strange in multiplayer. It saves old sensors that i have placed and removed from the world, it keeps renaming one of my sensors to sensor, and it can only communicate with one sensor for some reason.

Also, I assume there's a better way to create that infinite loop than how i did it?



------------- Load API for sensors ------------
os.unloadAPI("sensors")
os.loadAPI("/rom/apis/sensors")
------------- Dictionary Printer --------------
function printDict(data)
for i,v in pairs(data) do
  print(tostring(i).." - "..tostring(v))
end
end
----------------Table Sum Function-------------------------------
function sum(data)
	local sum = 0
	for k,v in pairs(data) do
		sum = sum + v
	end

	return sum
end
------------- TheCode -------------------------
--what side is controller on?
ctrl = sensors.getController()
--list all the sensors and name them
data = sensors.getSensors(ctrl)
invSensorA = data[1]
--list all the probes of specific sensors and name them
data = sensors.getProbes(ctrl,invSensorA)
inventoryContent = data[3]
--list all targets of specific sensor+probe and name them
data = sensors.getAvailableTargetsforProbe(ctrl,invSensorA,inventoryContent)
chestLeftUp = data[6]

local pattern = "^(%d+)%*(%a+%.?%a+)@(%d+)"
local g = 0
local h = 1
while g ~= h do
local tableDiamond = {}
local tableIron = {}
local tableRedstone = {}
data = sensors.getSensorReadingAsDict(ctrl,invSensorA,chestLeftUp,inventoryContent)
--printDict(data)
term.clear()
term.setCursorPos(2,2)
for i = 1, #data do
  local amount, item, slot = string.match( data[i], pattern )
  if item == "item.ingotIron" then
   table.insert(tableIron,amount)
  end
  if item == "item.emerald" then
   table.insert(tableDiamond,amount)
  end
  if item == "item.redstone" then
   table.insert(tableRedstone,amount)
  end
	--print(tostring( item ).." "..tostring(amount))
end
print("Amount")
write("	Diamonds:	   ")
data = tableDiamond
print(sum(data))
write("	Iron Ingots:	")
data = tableIron
print(sum(data))
write("	Redstone dust:  ")
data = tableRedstone
print(sum(data))

sleep(1)
end

Ok so i tried this and modified it to work for my reactor but i am having problems. i know this is dead but if you could help i would much appreciate it. (Im using the Ic2 sensor module to look at the inventory of the reactor) The problem i am having is that i can display data using printDict, but when i try to print #data with a normal bring command, it comes up with nil, which 1 stops the for loop running, and if i manually make it run, then local amount, item, slot = string.match( data, pattern ) wont work because there is no data[1] or any number because there is nil :/ I do have items in the chest, they display like i said with printDict, so i have no idea whats happening. Is the Ic2 sensor different to the inventory sensor maybe?
here is my code: http://pastebin.com/74wRmLQX
(It is virtually a copy and paste of yours to try to get it to work.)
Mordokk #9
Posted 27 February 2013 - 07:13 PM
anyone able to help modify this code so that is uses inventory sensor and to where it takes info from multiple sensors, where I must specify each chest to take data from to prevent overlap of sensors and displays the information to a monitor on the right…. =D

Just a small example from someone of how to do each part would be amazingly helpful for a noob like myself.



Spoiler————- Load API for sensors ————
os.unloadAPI("sensors")
os.loadAPI("/rom/apis/sensors")
————- Dictionary Printer ————–
function printDict(data)
for i,v in pairs(data) do
print(tostring(i).." - "..tostring(v))
end
end
—————-Table Sum Function——————————-
function sum(data)
local sum = 0
for k,v in pairs(data) do
sum = sum + v
end
return sum
end
————- TheCode ————————-
–what side is controller on?
ctrl = sensors.getController()
–list all the sensors and name them
data = sensors.getSensors(ctrl)
testInv = data[1]
–list all the probes of specific sensors and name them
data = sensors.getProbes(ctrl,testInv)
inventoryContent = data[3]
–list all targets of specific sensor+probe and name them
data = sensors.getAvailableTargetsforProbe(ctrl,invSensorA,inventoryContent)
chestLeftUp = data[6]
local pattern = "^(%d+)%*(%a+%.?%a+)@(%d+)"
local g = 0
local h = 1
while g ~= h do
local tableWood = {}
local tableStone = {}
local tableStonebrick = {}
local tableRpstone = {}
local tableDiamond = {}
local tableIron = {}
local tableRedstone = {}
data = sensors.getSensorReadingAsDict(ctrl,invSensorA,chestLeftUp,inventoryContent)
–printDict(data)
term.clear()
term.setCursorPos(2,2)
for i = 1, #data do
local amount, item, slot = string.match( data, pattern )
if item == "item.ingotIron" then
table.insert(tableIron,amount)
end
if item == "item.emerald" then
table.insert(tableDiamond,amount)
end
if item == "item.redstone" then
table.insert(tableRedstone,amount)
end
if item == "tile.stonebrick@0" then
table.insert(tableStonebrick,amount)
end
if item == "tile.rpstone@0" then
table.insert(tableRpstone,amount)
end
–print(tostring( item ).." "..tostring(amount))
end
print("Amount")
write(" Diamonds: ")
data = tableDiamond
print(sum(data))
write(" Iron Ingots: ")
data = tableIron
print(sum(data))
write(" Redstone dust: ")
data = tableRedstone
print(sum(data))
write(" Stone: ")
data = tableStone
print(sum(data))
write(" Rpstone: ")
data = tableRpstone
print(sum(data))

sleep(1)
end