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

CCSensors Help (Ic2 Reactor Inventory)

Started by Curtis33210, 02 December 2012 - 04:39 PM
Curtis33210 #1
Posted 02 December 2012 - 05:39 PM
Ok so i have been looking for some good Tutorials on how to use the inventory aspect of ccSensors but cannot find one, so i decided to copy code off the forums without understanding it and trying to break it down and make it work for me. But i have had no luck. here is the code

local data = ""
local ctrl = sensors.getController()
os.unloadAPI("sensors")
os.loadAPI("/rom/apis/sensors")
function printDict(data)
for i,v in pairs(data) do
  print(tostring(i).." - "..tostring(v))
end
end
function sum(data)
local sum = 0
for k,v in pairs(data) do
  sum = sum + v
end
return sum
end
data = sensors.getSensors(ctrl)
Reactor = data[1]
data = sensors.getProbes(ctrl, Reactor)
ReactorInv = data[5]
data = sensors.getAvailableTargetsforProbe(ctrl, Reactor, ReactorInv)
ReactorContent = data[1]
data = sensors.getSensorReadingAsDict(ctrl, Reactor, ReactorContent, ReactorInv)
for i = 1, #data do
local amount, item, slot = string.match( data[i], pattern )
if item == "item.ice" then
  table.insert(tableIce, amount)
end
end
write(" Ice:		  ")
data = tableIce
print(sum(data))

local pattern = "^(%d+)%*(%a+%.?%a+)@(%d+)"
local g = 0
local h = 1
while g ~= h do
local tableUranium = {}
local tableIce = {}
local tableBucket = {}
data = sensors.getSensorReadingAsDict(ctrl, Reactor, ReactorContent, ReactorInv)
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.itemCellUran" then
   table.insert(tableUranium,amount)
  end
  if item == "tile.ice" then
   table.insert(tableIce,amount)
  end
  if item == "item.bucketWater" then
   table.insert(tableBucket,amount)
  end
	print(tostring( item ).." "..tostring(amount))
end
print("Amount")
write(" Uranium:		  ")
data = tableUranium
print(sum(data))
write(" Ice:	")
data = tableIce
print(sum(data))
write(" Buckets:  ")
data = tableBucket
print(sum(data))
end

(im new to forums)
So what im attempting to do is find out how many uranium cells there are in the reactor and how much ice, and if it is incorrect do something. To start with im trying to get it to display how many there are, i have Ice in the first slot, Uranium in the second and water bucket in the third. There are many parts i dont understand about how this code should be working such as the patter string and the two functions, sum and printDict.

when i run the program i get this:
Ice: reactor:15 bad argument: table expected, got nil

I know that if i print the amount and item i get nil for both no matter how i run it, any ideas pro's? xD
zekesonxx #2
Posted 02 December 2012 - 07:07 PM
That means the error is on line 15 and it is expecting a table to be there, but instead the data is nil. (Empty or undefined)

And please post on Pastebin.
Curtis33210 #3
Posted 02 December 2012 - 07:53 PM
That means the error is on line 15 and it is expecting a table to be there, but instead the data is nil. (Empty or undefined)

And please post on Pastebin.

Thanks for the Reply, but that does not help, i am aware of that but i do not know how to fix it and make it get real values. Is there another way to do it?
And i said i was new to forums because i know i would do something wrong, what is PasteBin for?
zekesonxx #4
Posted 02 December 2012 - 09:10 PM
Formatting and line numbers.

I can't see the problem, but I also rarely use Lua tables.
Curtis33210 #5
Posted 02 December 2012 - 09:18 PM
Formatting and line numbers.

I can't see the problem, but I also rarely use Lua tables.


http://pastebin.com/KQ8SG4mE
Is this how it is used?

Do you have any other suggestions on how to do it without tables? like i said i don't understand it at all so i would like an alternative
zekesonxx #6
Posted 02 December 2012 - 09:49 PM
Yes, quite so.

And no, sorry. Me != CCSensors
ChunLing #7
Posted 03 December 2012 - 03:49 AM
You've got what looks to me like a stray chunk of code at line 30-something:

write(" Ice:              ")
data = tableIce
print(sum(data))

This attempts to use tableIce to set data, which is then used in sum, but tableIce is only defined later. This appears to be the origin of the error that you saw.

You should set your program scope local declarations up top. A local declaration is usually best placed at the top of the scope it will occupy.
Curtis33210 #8
Posted 03 December 2012 - 10:16 AM
You've got what looks to me like a stray chunk of code at line 30-something:

write(" Ice:			  ")
data = tableIce
print(sum(data))

This attempts to use tableIce to set data, which is then used in sum, but tableIce is only defined later. This appears to be the origin of the error that you saw.

You should set your program scope local declarations up top. A local declaration is usually best placed at the top of the scope it will occupy.

Thank you, that fixed that problem, but as usual with code, i encountered another, which would have been the other reason it isn't working. #data == 0 even though i can print them with printDict over and over again, print(#data) is always 0. Also i even tried print(data[1]) which also did not work because it is == nil. Any ideas? ( i can get the stuff to display perfectly but because the for loop runs the same amount of times as there is 'things' in data and #data == nil it doesnt run so it just shows 0 to the right of all of the words on the display.)
ChunLing #9
Posted 03 December 2012 - 10:35 AM
Used on a table, # returns the number of sequential entries, that is, it does something like:
local index = 0
repeat index = index+1 until not data[index]
index = index-1
It doesn't usually actually do this, it usually remembers the answer somewhere at the top of the table, but in the case of your tables they probably aren't sequentially indexed. Traverse them with pairs and print out the keys to find out exactly what they look like, so:
for k,v in pairs(data) do print("Key: ",k," of type ",type(k)," = ",v) end

If that doesn't print "Key: 1 of type number = " at any point, then data[1] doesn't exist so the table is marked as being size 0 to prevent you from trying to access it sequentially. However, your other entries should give you some idea of how big the table actually is. You can make your own table size function if you just need to know the number of entries the table contains, just do a for in pairs loop and count the loops.
Curtis33210 #10
Posted 03 December 2012 - 03:46 PM
Used on a table, # returns the number of sequential entries, that is, it does something like:
local index = 0
repeat index = index+1 until not data[index]
index = index-1
It doesn't usually actually do this, it usually remembers the answer somewhere at the top of the table, but in the case of your tables they probably aren't sequentially indexed. Traverse them with pairs and print out the keys to find out exactly what they look like, so:
for k,v in pairs(data) do print("Key: ",k," of type ",type(k)," = ",v) end

If that doesn't print "Key: 1 of type number = " at any point, then data[1] doesn't exist so the table is marked as being size 0 to prevent you from trying to access it sequentially. However, your other entries should give you some idea of how big the table actually is. You can make your own table size function if you just need to know the number of entries the table contains, just do a for in pairs loop and count the loops.

Sigh i had just replyed to this and i clicked backspace and it took me back two pages and reset it all -_-/>

Ok so i dont understand the in pairs stuff or how those two first functions work, i just guess they do. Why is it preventing me from accessing it sequentially? I do know how many slots are in the reactor so i can just hard code that into the for loop but the problem is local amount, item, slot = string.match(data[i], pattern) , because there is apparently nothing in data it gives me a error saying it wants something other then nil. Would you be able to tell me the code to make it so i could call it like that?

But if you know a simpler way of doing this without all these tables and stuff i would much apreciate it. I also need to find what slot it is in and check each slot to make sure that each slot has the right item in it, continuing on the way i am going with this code will that be possible?
ChunLing #11
Posted 04 December 2012 - 09:10 AM
The problem is that accessing it sequentially, the first entry would be data[1] and there is no such entry. There is data in the table, but it is not keyed by a sequence of integers starting with one. So you cannot use a method of accessing it that depends on starting with data[1] and proceeding from there.

The for k,v in pairs(data) do … end loop reads the table to find out what value and key pairs are stored in the table, and returns them in the order in which they were added to the table (rather than anything based on the keys or values themselves). So it is a bit like for i = 1,#data do … end, really (only a bit slower because the iterator has to follow a bunch of pointers to find out what the next key-value pair is rather than just looking up the next value by a sequential key). Because the sequential table is faster, I prefer to use them, but non-sequential tables definitely have more flexibility and power, so I use them too and don't find anything wrong with that.

Anyway, these tables are non-sequential, so we have to crawl them using in pairs like you did in your sum function. But I'm not familiar with the structure of the tables (I don't have CCSensors or Build/IndustrialCraft). So you need to find out how those tables are structured. How about this, just use print(textutils.serialize(data)) and post what you get from that? You can save the string from textutils.serialize(data) in a file if it is large, but post that and then we'll know everything.
Curtis33210 #12
Posted 04 December 2012 - 11:18 AM
The problem is that accessing it sequentially, the first entry would be data[1] and there is no such entry. There is data in the table, but it is not keyed by a sequence of integers starting with one. So you cannot use a method of accessing it that depends on starting with data[1] and proceeding from there.

The for k,v in pairs(data) do … end loop reads the table to find out what value and key pairs are stored in the table, and returns them in the order in which they were added to the table (rather than anything based on the keys or values themselves). So it is a bit like for i = 1,#data do … end, really (only a bit slower because the iterator has to follow a bunch of pointers to find out what the next key-value pair is rather than just looking up the next value by a sequential key). Because the sequential table is faster, I prefer to use them, but non-sequential tables definitely have more flexibility and power, so I use them too and don't find anything wrong with that.

Anyway, these tables are non-sequential, so we have to crawl them using in pairs like you did in your sum function. But I'm not familiar with the structure of the tables (I don't have CCSensors or Build/IndustrialCraft). So you need to find out how those tables are structured. How about this, just use print(textutils.serialize(data)) and post what you get from that? You can save the string from textutils.serialize(data) in a file if it is large, but post that and then we'll know everything.

ok it says:
{["2,0"]="1*item.bucketWater@0",["1,0"]="1*item,itemCellUran@0",["0,0"]="1*tile.ice@0",}
So im guessing this means that instead of it being data[1] i have to use the pairs in some way to check the two numbers so its more like data[2,0]? (i wouldnt have a clue how to do that so i still need help if im right :P/> But thank you very much in advance, once i have this completed i can make a reactor 100% completely automatic and have it display everything. (I know it's been done, but i want to do it myself… with some help of course :)/>)
ChunLing #13
Posted 04 December 2012 - 03:26 PM
Okay, what you have there would be a valid table constructor in lua. Conventionally we might see it like so:
data = {
  ["2,0"]="1*item.bucketWater@0",
  ["1,0"]="1*item,itemCellUran@0",
  ["0,0"]="1*tile.ice@0",}
Now, what the CCSensors author has done here is made the reactor inventory table reflect three different inventories…and has decided to use coordinate strings as keys rather than integers. So "2,0" is presumably the key representing slot zero of the number two inventory area, which contains "1*item.bucketWater@0" in our example. And the same thing for slot zero in inventory one and inventory zero, except that these contain Uranium and Ice, respectively.

Does this seem to correspond to what you had in the reactor?
Curtis33210 #14
Posted 04 December 2012 - 08:12 PM
Okay, what you have there would be a valid table constructor in lua.  Conventionally we might see it like so:
data = {
  ["2,0"]="1*item.bucketWater@0",
  ["1,0"]="1*item,itemCellUran@0",
  ["0,0"]="1*tile.ice@0",}
Now, what the CCSensors author has done here is made the reactor inventory table reflect three different inventories…and has decided to use coordinate strings as keys rather than integers.  So "2,0" is presumably the key representing slot zero of the number two inventory area, which contains "1*item.bucketWater@0" in our example.  And the same thing for slot zero in inventory one and inventory zero, except that these contain Uranium and Ice, respectively.

Does this seem to correspond to what you had in the reactor?

Yes that is exactly what I have in the reactor, how am I able to access the second set of data using the first set to do what I want to? Am I able to store the "0,1" or any other coords into the variable I and access the item in that slot? I'm not sure if i told you what my plan is, but i want to check each inventory slot when the output isn't 100% to see what's missing and to make sure the ice is in the right slots. Then anyones that are missing or incorrect will be replaced. For that i need the slot coords, the item and the amount (for the ice). Would you be able to tell me the code for how to extract that info so i can continue?
ChunLing #15
Posted 04 December 2012 - 08:52 PM
I'm not sure about the ins and outs of reactors, since I don't use those mods. I assume that it is important that there are three different inventory sections.

You'll still need to use for k,v in pairs(data) do … end, so that you can traverse all the values. And I don't know what you want to do about it if you find ice blocks in section 1 and water in section 0 and stuff. But the for loop might look like this now:
for k,v in pairs(data) do
    local amount,item,slot = string.match(v,pattern)
    if item == "item.itemCellUran" then
        table.insert(tableUranium,amount)
    end
    if item == "tile.ice" then
        table.insert(tableIce,amount)
    end
    if item == "item.bucketWater" then
        table.insert(tableBucket,amount)
    end
    print(k..": "..tostring( item ).." "..tostring(amount))
end
This is basically almost what you had before, only "for k,v in pairs(data)" replaces "for i = 1,#data" and "string.match(v,pattern)" replaces "string.match(data,pattern)". I also added printing the key, since that seems to indicate which inventory something's in.

If you need to check whether things are in their right inventory sections, you could add a "if k:sub(1,1) ~= '1' then … end". That should do something if an item's key indicates that it's in the wrong inventory section.
Lyqyd #16
Posted 05 December 2012 - 03:40 AM
Reactors only have a single inventory.
ChunLing #17
Posted 05 December 2012 - 10:42 AM
Ah…what do those keys mean, then? Are they just xy coordinate pairs specifying the slot or what?
Lyqyd #18
Posted 05 December 2012 - 11:10 AM
That would be a reasonable guess. Reactors have an adjustable size, dependent on the presence of certain adjacent blocks. In that context, coordinate pairs give you information about the location of object inside it that you cannot know with a simple numerical index system (such as adjacencies) without also knowing the inventory size (which should be available anyway). This makes it significantly easier to perform advanced operations such as predicting the behavior of the reactor based on the interactions of the various components. Obviously, if the size is also available, the coordinates are reproducible information.
ChunLing #19
Posted 05 December 2012 - 07:05 PM
So the relative position of things matters for a reactor. I guess that makes sense, given how reactors work (or fail) in the real world. Though really, you should just use those graphite covered balls like sensible peoples would :P/>
Lyqyd #20
Posted 05 December 2012 - 07:42 PM
Yeah, unfortunately, IC2 won't let you make a pebble-bed reactor. It'd be easy-win mode anyway, basically.