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

Pause clock and run again.

Started by Kristopher_Jones, 10 November 2015 - 04:59 PM
Kristopher_Jones #1
Posted 10 November 2015 - 05:59 PM
Hello.
I need again help.

Situation:
I have scoreclock who runs after pressing button from left side. I need stop this time and after some time continue countdown. I would like use this button on left side for starting countdown and pausing.
If somebody can help….

Code:


rs.setOutput("right",true)
print("Set countdown to game") --only need minutes
print("Minutes?") --only need minutes
write("-> ")
minute = tonumber(read()) --input directly as number(avoid string)
print("Seconds") --only need minutes
write("-> ")
sec = tonumber(read()) --input directly as number(avoid string)
print("TIme added, press button to start countdown")

local j = sec   --declare seconds variable
local i = minute   ---declare minutes variable
min = i
	    sleep(1)
	    --Returning Results
	    mon.setTextScale(5)
	  
	    mon.setCursorPos(7,5)
	    mon.write(min..":"..sec)
 
    os.pullEvent("redstone")
    if rs.getInput("left") then
    rs.setOutput("right",true)  
repeat
	    if i > 0 then
			    if j > 0 then
					    j = j - 1
			    else
					    j = 59
					    i = i - 1
			    end
	    else
			    if j > 0 then
					    j = j - 1
			    else
					    done = true
			    end
	    end
	    if j > 9 then
			    sec = j
	    else
			    sec = "0"..j
	    end
	    min = i
	    sleep(1)
 
	    --Returning Results
	    mon.setTextScale(5)
	 
		 mon.setCursorPos(7,5)
  
	    mon.write(min..":"..sec.." ")
	    until j == 0 and  i == 0
mon.setCursorPos(8,3)
mon.write("1")
rs.setOutput("right",true)			   -- trigger redstone output
sleep(1)
end

Bomb Bloke #2
Posted 11 November 2015 - 06:09 AM
When anything "happens" to a system, the result is an event popping into its event queue. For example, if a redstone pulse hits the side of the computer, then a "redstone" event goes into the queue. os.pullEvent() is used to pull information about the most recent event from the front of the queue. If there's nothing in there, then the system yields, waiting until an event arrives.

sleep() makes use of os.startTimer(), which, after a specified amount of time, generates a "timer" event at the end of the queue. Catch is, if you allow sleep() to trigger and pull these timer events for you, then you can't so easily listen out for the redstone events that'll indicate you should pause / resume your clock.

So the idea is to ditch sleep and implement the timer event management directly into your script. Eg:

local myTimer = os.startTimer(1)

while j > 0 or i > 0 do
  local event, par1 = os.pullEvent()

  if event == "redstone" then
    print("Timer paused!")
    os.pullEvent("redstone")
    myTimer = os.startTimer(1)

  elseif event == "timer" and par1 == myTimer then
    -- Update your counters, draw the clock.

    myTimer = os.startTimer(1)
  end
end
Kristopher_Jones #3
Posted 13 November 2015 - 02:56 PM
After placing i got these:

rs.setOutput("right",true)
print("Set countdown to game") --only need minutes
print("Minutes?") --only need minutes
write("-> ")
minute = tonumber(read()) --input directly as number(avoid string)
print("Seconds") --only need minutes
write("-> ")
sec = tonumber(read()) --input directly as number(avoid string)
print("TIme added, press button to start countdown")
local j = sec   --declare seconds variable
local i = minute   ---declare minutes variable
min = i
		    sleep(1)
		    --Returning Results
		    mon.setTextScale(5)
		 
		    mon.setCursorPos(7,5)
		    mon.write(min..":"..sec)
local myTimer = os.startTimer(1)
while j > 0 or i > 0 do
  local event, par1 = os.pullEvent()
  if event == "redstone" then
    print("Timer paused!")
    os.pullEvent("redstone")
    myTimer = os.startTimer(1)
  elseif event == "timer" and par1 == myTimer then
		    if i > 0 then
						    if j > 0 then
										    j = j - 1
						    else
										    j = 59
										    i = i - 1
						    end
		    else
						    if j > 0 then
										    j = j - 1
						    else
										    done = true
						    end
		    end
		    if j > 9 then
						    sec = j
		    else
						    sec = "0"..j
		    end
		    min = i
		    sleep(1)

		    --Returning Results
		    mon.setTextScale(5)
		
				 mon.setCursorPos(7,5)
 
		    mon.write(min..":"..sec.." ")
		    until j == 0 and  i == 0
	 myTimer = os.startTimer(1)
  end
end
mon.setCursorPos(8,3)
mon.write("1")
rs.setOutput("right",true)						 -- trigger redstone output
sleep(1)


end expected (to close'if' at line 25)

what i did wrong?
Bomb Bloke #4
Posted 14 November 2015 - 12:15 AM
Seems you've left an "until" statement in there for some reason. It certainly wouldn't be expecting that, as there's no "repeat".

While it'll technically work, this:

		if i > 0 then
			if j > 0 then
				j = j - 1
			else
				j = 59
				i = i - 1
			end
		else
			if j > 0 then
				j = j - 1
			else
				done = true
			end
		end

… would serve just as well if cut down to this:

		if j > 0 then
			j = j - 1
		else
			j = 59
			i = i - 1
		end
Edited on 13 November 2015 - 11:19 PM
Kristopher_Jones #5
Posted 14 November 2015 - 09:15 AM

rs.setOutput("right",true)
print("Set countdown to game") --only need minutes
print("Minutes?") --only need minutes
write("-> ")
minute = tonumber(read()) --input directly as number(avoid string)
print("Seconds") --only need minutes
write("-> ")
sec = tonumber(read()) --input directly as number(avoid string)
print("TIme added, press button to start countdown")
local j = sec   --declare seconds variable
local i = minute   ---declare minutes variable
min = i
			sleep(1)
			--Returning Results
			mon.setTextScale(5)
		
			mon.setCursorPos(7,5)
			mon.write(min..":"..sec)

	os.pullEvent("redstone")
	if rs.getInput("left") then
	rs.setOutput("right",true)
local myTimer = os.startTimer(1)
while j > 0 or i > 0 do
  local event, par1 = os.pullEvent()
  if event == "redstone" then
	print("Timer paused!")
	os.pullEvent("redstone")
	myTimer = os.startTimer(1)
  elseif event == "timer" and par1 == myTimer then
			 if i > 0 then
						if j > 0 then
								j = j - 1
						else
								j = 59
								i = i - 1
						end
				else
						if j > 0 then
								j = j - 1
						else
								done = true
						end
				end
			min = i
			sleep(1)

			--Returning Results
			mon.setTextScale(5)
		
				 mon.setCursorPos(7,5)

			mon.write(min..":"..sec.." ")
		  
	myTimer = os.startTimer(1)
  end
end
mon.setCursorPos(8,3)
mon.write("1")
rs.setOutput("right",true)						 -- trigger redstone output
sleep(1)
end

16: Atemping to index (a nil value)

Getting this error after putting time, after 2 sec getting this error.
Edited on 14 November 2015 - 08:16 AM
Bomb Bloke #6
Posted 14 November 2015 - 10:09 AM
Seems you forgot to wrap your monitor. Before calling mon.setTextScale() (or mon.anything() for that matter), you must first do something along the lines of:

local mon = peripheral.find("monitor")
Kristopher_Jones #7
Posted 14 November 2015 - 01:02 PM

local monitors = {peripheral.find("monitor")} --# finding all of the monitors and putting them in a table
local mon = {} --# defining a table to store the functions we are about to create
for k,v in pairs(monitors[1]) do --# looping through the functions of the first monitor
  mon[k] = function(...) --# creates a new function in the mon table with the name k.  k is the name of one of the functions from the monitor we are looping through
	    for i = 1, #monitors do --# looping through all of the monitors in the monitors table
		  monitors[i][k](...) --# executing the original function for each monitor with the original arguments
	    end
  end
end
rs.setOutput("right",true)
print("Set countdown to game") --only need minutes
print("Minutes?") --only need minutes
write("-> ")
minute = tonumber(read()) --input directly as number(avoid string)
print("Seconds") --only need minutes
write("-> ")
sec = tonumber(read()) --input directly as number(avoid string)
print("TIme added, press button to start countdown")
local j = sec   --declare seconds variable
local i = minute   ---declare minutes variable
min = i
		    sleep(1)
		    --Returning Results
		    mon.setTextScale(5)
		 
		    mon.setCursorPos(7,5)
		    mon.write(min..":"..sec)

  
local myTimer = os.startTimer(1)
while j > 0 or i > 0 do
  local event, par1 = os.pullEvent()
  if event == "redstone" then
    print("Timer paused!")
    os.pullEvent("redstone")
    myTimer = os.startTimer(1)
  elseif event == "timer" and par1 == myTimer then
			 if i > 0 then
					    if j > 0 then
							    j = j - 1
					    else
							    j = 59
							    i = i - 1
					    end
			    else
					    if j > 0 then
							    j = j - 1
					    else
							    done = true
					    end
			    end
		    min = i
		    sleep(1)

		    --Returning Results
		    mon.setTextScale(5)
		
				 mon.setCursorPos(7,5)
 
		    mon.write(min..":"..sec.." ")
		   
    myTimer = os.startTimer(1)
  end
end
mon.setCursorPos(8,3)
mon.write("1")
rs.setOutput("right",true)						 -- trigger redstone output
sleep(1)


Ok now time appears and no errors. But time not running when i press button to start time, get message " timer paused" and all time….
Engineer #8
Posted 14 November 2015 - 11:05 PM
In all honesty I have not read the entire thread, but I think I know where you are stuck. Do not mess around with too many variables, because confusion will hit you :P/>

print("Input amount of minutes:")
local minutes = tonumber(read())
print("Input amount of seconds:")
local seconds = tonumber(read())

-- Calculate the total in minutes with in mind that people can input 1.6 minutes for instance
local total = (minutes - math.floor(minutes)) * 60 + math.floor(minutes) * 60 + seconds

display(total) -- inital display

local timer = os.startTimer(1) -- Timer for one second
while total > 0 do
      local event, par1 = os.pullEvent()
      if event == "timer" and par1 == timer then
          total = total - 1
          timer = os.startTimer(1)
          display(total) -- update the dsiplay
      elseif event == "redstone" then
          -- What to do when the redstone changed?
      end
end

Now we got the main algorithm, we only need to implement the display function where we process the amount of minutes and seconds, like so:

local function display(nSeconds)
    local minutes = math.floor(nSeconds / 60)
    local seconds = nSeconds % 60
    -- now we got the amount of minutes and seconds, display them below yourself! 
    -- Im just doing a simple print
    print(string.format("%02d:%02d", minutes, seconds))
end

Disclaimer: I have been out of Lua for quite a while and this code might throw several errors as this is untested.. My point to make here that it is about the algorithm, not if everything is typed correctly ;)/>
Good luck!
Edited on 14 November 2015 - 10:06 PM