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

Clock with a Timer? Is it possible?

Started by TheTiceisRight, 04 April 2015 - 04:48 AM
TheTiceisRight #1
Posted 04 April 2015 - 06:48 AM
So I've been trying to make a subway system similar to the Moscow Metro, By that I mean that there is a Display at the end of each platform that displays the current time and the time since the last train has passed, So I've been trying to write a program to do that… And thats when I got here, I don't really know how the Lua Language works so I need some help, I tried combining both a clock function and timer function in a program but only the clock apears.

m = peripheral.wrap("front")
min = 0
hrs = 0
m.clear()
m.setTextScale(2)
function updateClock(m)
  while true do
		mcT = os.time()
		m.setCursorPos(6,1)
		m.write(textutils.formatTime(mcT, true))
		sleep(0.1)
  end	
end
updateClock(m)
function timer(m)
for sec = 0, 60, 1 do
  m.setCursorPos(6,2)
  m.print(min, ":", sec)
   if sec == (60) then
	min = min + 1
	timer()
   end
   if min == (60) then
	hrs = hrs + 1
	min = 0
   end
   sleep (1)
  end
sec = 0
end
timer(m)	
if rs.getInput("back") then
		min = 0
		sec = 0
		hrs = 0
end	 
This is the program that I've written so far, but it doesn't appear to work. Bassicly Im trying to get it to where the timer resets when a train passes over it using an activator rail. As mentioned before I don't reallt know the way Lua works so… I need help with this… Please…
Bomb Bloke #2
Posted 04 April 2015 - 07:44 AM
The script runs top to bottom, and every time you call a function, that function has to complete before the script will continue past that point.

Once you call updateClock(), you start a while loop that repeats forever. You therefore never get on to defining and executing your timer() function.

The parallel API provides a simple fix (though how it does what it does it quite complex). Without going into too much detail, it allows you to refactor like this, by (more or less) running functions at the same time:

local m = peripheral.wrap("front")
m.clear()
m.setTextScale(2)

local function updateClock()
	while true do
		mcT = os.time()
		m.setCursorPos(6,1)
		m.clearLine()
		m.write(textutils.formatTime(mcT, true))
		sleep(1)  -- 0.1 is overkill here!
	end   
end

local function timer()
	local hrs = 0
	
	while true do
		for min = 0, 59 do
			for sec = 0, 59 do  -- For loops count for you, no need to do it yourself!
				m.setCursorPos(6,2)
				m.clearLine()
				m.write(tostring(hrs) .. ":" .. tostring(min) .. ":" .. tostring(sec))  -- "print" isn't available to monitors, and "write" doesn't format/concatenate for you.
				sleep(1)
			end
		end
		
		hrs = hrs + 1
	end
end

local function reset()
	while true do
		os.pullEvent("redstone")
		if rs.getInput("back") then break end  -- "break" exits the while loop, after which the function ends.
	end
end

while true do
	parallel.waitForAny(updateClock, timer, reset)
	-- Once any function ends (eg reset() when it spots a redstone signal), this while loop will start them all from scratch.
end

This works by switching execution between functions whenever they yield - which they do whenever they go to pull an event. Just about any function that pauses yields - for example, sleep. You'll find it well worth reading up on events, os.pullEvent() in particular.

It's also worth noting that you can't really play with the counter value used by a for loop. You can use the value, but if you attempt to alter it, then the loop will set it back to what it thinks it should be as soon as the next iteration begins. Not all languages clamp onto the counter variable like that, but Lua does.
Edited on 04 April 2015 - 05:47 AM
TheTiceisRight #3
Posted 05 April 2015 - 12:28 AM
Thanks, It seems to work but just out of curiosity is there a way to make the seconds count up differently? What I mean is it appears like this currently -> 0:1, 0:2, … 0:10, 0:11, etc. Is there a way to make it count up like 0:01, 0:02, etc.? Is it a simple code change or complete redo of the timer function?
hbomb79 #4
Posted 05 April 2015 - 01:04 PM
Thanks, It seems to work but just out of curiosity is there a way to make the seconds count up differently? What I mean is it appears like this currently -> 0:1, 0:2, … 0:10, 0:11, etc. Is there a way to make it count up like 0:01, 0:02, etc.? Is it a simple code change or complete redo of the timer function?

The only way I can think of doing that is by checking the seconds (sec) by converting it to an integer, if its less than 10 then prefix is with a zero, else display the number.

Another way of doing that is to check the length of the sec variable and see if its 1 or more, depending on its length prefix a zero to the front. Heres my example code for your for loop that creates the second variable (Not tested):


for sec = 0, 59 do  -- For loops count for you, no need to do it yourself!
	m.setCursorPos(6,2)
	m.clearLine()
		-- Check length of sec integer.
		if sec < 10
		 sec = "0"+tostring(sec)
		 sec = tonumber(sec) --Allows manipulation of the two digit number in the future.
		end
	 m.write(tostring(hrs) .. ":" .. tostring(min) .. ":" .. tostring(sec))  -- "print" isn't available to monitors, and "write" doesn't format/concatenate for you.
	 sleep(1)
end

Apologies for the indentation, for some reason CTRL+V messed it up completely when pasting into the browser.

I was tired when writing this, syntax may be incorrect because i'm in a Java mindset today, sorry for any minor mistakes ( and major ).
Edited on 05 April 2015 - 11:07 AM
Bomb Bloke #5
Posted 05 April 2015 - 01:43 PM
That'd probably work if you removed the "sec = tonumber(sec)" line, which is naturally going to remove your attempt at manually formatting the string.

If only because Lua should set the value back to a number for you when the loop repeats. Which as I mentioned, isn't something every language does.