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

Out of (could be infinite) get shortest range

Started by lifewcody, 02 November 2014 - 06:49 PM
lifewcody #1
Posted 02 November 2014 - 07:49 PM
So I have cell towers put up over a city I have and I am trying to get the distance of them and put that into a 'signal strength' bar.
Here is the code:

dir = shell.dir().."/"

os.loadAPI(dir.."settings")

main = peripheral.wrap(settings.mainSide)

dis = 0

pkt = {"cellDis", os.getComputerID()}

main.open(101)

function mainLoop()
while true do
term.clear()
if dis>=1 and dis<=146 then
      term.setBackgroundColor(colors.green)
      --paintutils.drawLine(1,1,3,1,colors.green)
      term.setCursorPos(1,1)
      write(">>>")
      term.setBackgroundColor(colors.black)
      --print(dis)
      elseif dis>=147 and dis<=181 then
      term.setBackgroundColor(colors.orange)
      --paintutils.drawLine(1,1,2,1,colors.orange)
      term.setCursorPos(1,1)
      write(">>")
      term.setBackgroundColor(colors.black)
      --print(dis)
      elseif dis>=182 and dis<=220 then
      term.setBackgroundColor(colors.red)
      --paintutils.drawLine(1,1,1,1,colors.red)
      term.setCursorPos(1,1)
      write(">")
      term.setBackgroundColor(colors.black)
      --print(dis)
      elseif dis == 0 then
      term.setBackgroundColor(colors.red)
      --paintutils.drawLine(1,1,3,1,colors.red)
      term.setCursorPos(1,1)
      write("N/A")
      term.setBackgroundColor(colors.black)
      --print(dis)
      end
      dis = 0
      sleep(1)
      main.transmit(101,101,pkt)
end
end

function listen()
while true do
  event = {os.pullEvent()}
    if event[1] == "modem_message" then
      local side = event[2]
      local freq = event[3]
      local rfreq = event[4]
      local msg = event[5]
      dis = event[6]
      --dist = tonumber(dis)
    end
     --elseif event[1] == "timer" and event[2] == timeout then
     --print("unable to get location")
     --break
end
end

main.transmit(101,101,pkt)
parallel.waitForAll(listen,mainLoop)


The problem is say is celltower A is 200 blocks away and cell tower B is 100 then it takes celltower A's measurement and it says you have 1 bar, instead of say 3. When you are out of celltower A's range then it connects to cell tower B and then you get 3 bars.
Lyqyd #2
Posted 02 November 2014 - 08:06 PM
You'd likely want to capture all of the responses in a table and then iterate through it to find the shortest.
lifewcody #3
Posted 02 November 2014 - 08:12 PM
You'd likely want to capture all of the responses in a table and then iterate through it to find the shortest.

How would I iterate through it?
Lyqyd #4
Posted 02 November 2014 - 08:23 PM
Depends on how you implement the table, of course. You might use a pairs() loop, or an ipairs() loop, or a simple for loop.
lifewcody #5
Posted 02 November 2014 - 08:34 PM
Depends on how you implement the table, of course. You might use a pairs() loop, or an ipairs() loop, or a simple for loop.
It will just have numbers in it
Lyqyd #6
Posted 02 November 2014 - 08:59 PM
You'd just need to create a minimum variable, then iterate through the table with a for loop and set minimum to the minimum of the current minimum and the current value from the table. You should also be able to sort the table and then look at the first (or last, can't remember which) entry. I'm not sure which of the two ways would be faster.
Bomb Bloke #7
Posted 02 November 2014 - 09:40 PM
It sounds like you're not interested in knowing which tower has the best "reception", you only want to know what the best "reception" is. In that case, math.min() should do the job.

local myTable = {234,435,34,2,4,345}
print(math.min(unpack(myTable)))  --> 2

local function listen()
	local distances, distanceTimers = {}, {}  -- Create a pair of empty tables.

	while true do
		local event = {os.pullEvent()}
		
		if event[1] == "modem_message" then
			distances[#distances+1] = event[6]  -- Store the distance.
			distanceTimers[#distanceTimers+1] = os.startTimer(10)  -- Rig up a timer related to that distance.
			if dis > event[6] or dis == 0 then dis = event[6] end
		elseif event[1] == "timer" and distanceTimers[1] == event[2] then  -- If the timer for our oldest distance expired,
			if dis == table.remove(distances, 1) then dis = #distances > 0 and math.min(unpack(distances)) or 0 end  -- ... recheck the minimum distance as we wipe it from our "distances" table,
			table.remove(distanceTimers, 1)  -- ... and clear it from the timer table too.
		end
	end
end
Edited on 02 November 2014 - 10:14 PM
lifewcody #8
Posted 02 November 2014 - 11:35 PM
It sounds like you're not interested in knowing which tower has the best "reception", you only want to know what the best "reception" is. In that case, math.min() should do the job.

local myTable = {234,435,34,2,4,345}
print(math.min(unpack(myTable)))  --> 2

local function listen()
	local distances, distanceTimers = {}, {}  -- Create a pair of empty tables.

	while true do
		local event = {os.pullEvent()}
		
		if event[1] == "modem_message" then
			distances[#distances+1] = event[6]  -- Store the distance.
			distanceTimers[#distanceTimers+1] = os.startTimer(10)  -- Rig up a timer related to that distance.
			if dis > event[6] or dis == 0 then dis = event[6] end
		elseif event[1] == "timer" and distanceTimers[1] == event[2] then  -- If the timer for our oldest distance expired,
			if dis == table.remove(distances, 1) then dis = #distances > 0 and math.min(unpack(distances)) or 0 end  -- ... recheck the minimum distance as we wipe it from our "distances" table,
			table.remove(distanceTimers, 1)  -- ... and clear it from the timer table too.
		end
	end
end

What I was planning to do was to see what the best reception was and then get which tower has that reception. Also how would I get the distance from the listen function?
Bomb Bloke #9
Posted 02 November 2014 - 11:44 PM
Getting the tower with the best reception could be done in much the same way as I got the timer related to each tower; rig up another table, add tower IDs to it as messages come in, remove them once their timers expire. Whenever "dis" is updated, update another variable ("bestTower" or somesuch) too.

"dis" isn't declared as local to the listen() function, meaning it can be accessed from elsewhere. Really it should be declared as local to the script up the top of your script, though functionally it makes little difference here. See this tutorial for more details on how local/global variables work.
lifewcody #10
Posted 03 November 2014 - 12:04 AM
Getting the tower with the best reception could be done in much the same way as I got the timer related to each tower; rig up another table, add tower IDs to it as messages come in, remove them once their timers expire. Whenever "dis" is updated, update another variable ("bestTower" or somesuch) too.

"dis" isn't declared as local to the listen() function, meaning it can be accessed from elsewhere. Really it should be declared as local to the script up the top of your script, though functionally it makes little difference here. See this tutorial for more details on how local/global variables work.

Ah ok, I didn't see this part:

if dis > event[6] or dis == 0 then dis = event[6] end
Also, why would you need timer's on the distances? I don't see any need for them.
Bomb Bloke #11
Posted 03 November 2014 - 12:53 AM
It depends whether or not you're using a mobile system (such as a turtle or pocket computer). What if a tower that was closest, no longer is? What if you go out of range of all towers? Or even hop from one side of the city to the other via a teleport?
lifewcody #12
Posted 03 November 2014 - 01:02 AM
It depends whether or not you're using a mobile system (such as a turtle or pocket computer). What if a tower that was closest, no longer is? What if you go out of range of all towers? Or even hop from one side of the city to the other via a teleport?
The way I had it was setting dis to 0 after 5 seconds, but that also works :)/>