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

Parallel Api

Started by Alerith, 22 April 2013 - 12:20 AM
Alerith #1
Posted 22 April 2013 - 02:20 AM
Hello there! I've been reading in the wiki but I still don't get it, I mean, I understand both apis (ForAny and ForAll) but I don't know how to use it and when.

I'm making a new program, is a countdown and I want when the countdown is close to 0 min, like 2 min, I can write something but the countdown must don't stop. So —> countdown —> 2min—> write something while the countdown is still on —-> if the words are correct, like a password then something happens, if not, otherwise. I think I can use the Parallel Api for this, but I don't know how..

I don't want the entire code, I just want a little jog :P/>

Thank you very much in advance :3
Espen #2
Posted 22 April 2013 - 04:32 AM
I wouldn't recommend to do it with the parallel API.
When you start a counter in one part of your code, you'll have to yield and wait until there is an event that tells you that the amount of time has passed.
But in order for some other part of your code to know how how much time has passed UNTIL that event occurs, you'd have to set up another timer in parallel.
The problem with that is that you'd have to make sure to start up these timers at the same time and even then they might not be fully in synch.
IMO a better solution would be to not use parallel at all and instead use a one-second timer, which you'd restart in a loop and count the passed time with a counter variable.
Example:
local printTime  = 3  -- Time at which to print a message
local endTime	= 6  -- Time after which to stop the countdown
local timePassed = 0  -- Counts the seconds that have passed
local countdown  = os.startTimer(1)  -- Starts a one second timer

write("Progress: ")
while timePassed < endTime do
  -- Wait until our second has passed, i.e. when we are told about it via an event.
  local _, timer = os.pullEvent("timer")

  write(".")
  if timer == countdown then
	timePassed = timePassed + 1

	-- If printTime seconds have passed, we will write 'FOO'
	if timePassed == printTime then
	  write("FOO")
	end

	-- Restart the timer
	countdown = os.startTimer(1)
  end
end

print()
theoriginalbit #3
Posted 22 April 2013 - 04:43 AM
In addition to what Espen just said…

Since you want to also allow user input you will need to slightly modify how his code works, like so

This line

local _, timer = os.pullEvent("timer")
would need to become

local event, param1 = os.pullEvent()

and then you would need to check the events and go from there, essentially you are making your own read function

if event == 'timer' then
  -- Espens code here
elseif event == 'char' then
  -- add the char to the input string
elseif event == 'key' then
  -- check for backspace and enter here
end

you would then need a string at the top of your code like this

local input = ""
and this is what you append to

if event == 'char' then
  input = input..param1
elseif event == 'key' then
  if param1 == keys.backspace then
    input = string.sub( input, 1, string.len(input) - 1 )
  elseif param1 == keys.enter then
    -- ok check the password here and do whatever you want the program to do when it is correct, when false just input = "" again
  end
end
Espen #4
Posted 22 April 2013 - 05:49 AM
Oh, I thought he just wanted to print something after x amount of time.
Totally overlooked him wanting to do input as well. :wacko:/>

In that case I take back what I said about the use of the parallel API.
Because in order not having to write your own complete read() function, it's much more comfortable to use the parallel API.
In this particular case I'd suggest a combination of the one-second timer with manual counting and parallel, like so:
function login()
  local pwd = "secret"
  local input
  term.clear()
  term.setCursorPos( 1, 2 )

  while input ~= pwd do
    write("Password: ")
    input = read("*")
    if input == pwd then
      print("Correct!")
    end
  end
end

function countdown()
  local printTime  = 4  -- Time at which to print a message
  local endTime    = 8  -- Time after which to stop the countdown
  local timePassed = 0  -- Counts the seconds that have passed
  local countdown  = os.startTimer(1)

  while timePassed < endTime do
    local _, timer = os.pullEvent("timer")

    if timer == countdown then
      timePassed = timePassed + 1

      if timePassed == printTime then
        local currX, currY = term.getCursorPos()    -- Note current cursor position.
        term.setCursorPos( 1, 1 )
        term.clearLine()

        write( printTime .. " seconds left..." )
        term.setCursorPos( currX, currY )   -- Reset cursor position to where it was before.
      end

      countdown = os.startTimer(1)
    end
  end
  print()
end

parallel.waitForAny( login, countdown )

Edit: Added some comments.
Edited on 22 April 2013 - 03:52 AM
Alerith #5
Posted 22 April 2013 - 07:29 AM
Whoa, thanks for the response guys! I will analize that :3 If I have any questions, I will post them here :D/>
I'm not in my PC right now, so later :P/>
Alerith #6
Posted 23 April 2013 - 10:22 AM
Just a little question, what is the "_" variable?
remiX #7
Posted 23 April 2013 - 10:26 AM
When you pull an event, even if you put a 'filter' within the function call, the event still gets returned with the first variable.
People use any short character like _ to just 'ignore' that returned variable by putting it it's place because you won't be using it.

Not sure If i explained it properly xD
Alerith #8
Posted 23 April 2013 - 10:30 AM
When you pull an event, even if you put a 'filter' within the function call, the event still gets returned with the first variable.
People use any short character like _ to just 'ignore' that returned variable by putting it it's place because you won't be using it.

Not sure If i explained it properly xD

I get it.. something, is like drop that value right?
remiX #9
Posted 23 April 2013 - 10:32 AM
Yeah just to ignore it because you won't be using it
Espen #10
Posted 23 April 2013 - 10:43 AM
I get it.. something, is like drop that value right?
Yep, exactly as remiX has explained it already.
But to put any misunderstanding out of the way, I would explicitly add that Lua doesn't do anything special for _
It's a valid variable name like any other and it's just a convention of many programmers to show their intentions with that variable, i.e. that they don't use its content at all. But it stores the content nontheless and can be used like any other variable.
Alerith #11
Posted 23 April 2013 - 10:44 AM
Perfect. Thank you both :3