Stopwatch and Timer in Ruby [with source code]
Table of contents:
- Introduction
- Stopwatch in Ruby
- Create class/initialize method
- start method
- handle_input method
- stop method
- Timer in Ruby
- Create class/initialize method
- start/handle_input method
- start_timer method
- toggle_timer method
- quit_program method
- Conclusion
Introduction
In this article at OpenGenus, we will take a look at how a stopwatch and a timer is produced using Ruby code. You will be able to pause and resume the stopwatch as needed.
Stopwatch in Ruby
First we create the Stopwatch class, this class will include multiple methods for our stopwatch. the first method we have is initialize, this sets some default variables @seconds to zero
because our stopwatch will start at zero, @paused as a boolean
and @stopwatch_thread to nil
for now. We also require io/console, this allows us to add keys that would be pressed to activate certain functions of the stopwatch.
Create class/initialize method
require 'io/console'
class Stopwatch
def initialize
@seconds = 0
@paused = false
@stopwatch_thread = nil
end
Start method
Next we add the start method, we will use the Thread class of ruby here and run a loop that calls the sleep method every 0.1 second we also in turn increment our @seconds by 0.1 unless @paused becomes true, we call the handle_input method(which we will create next) outside of this loop.
----previous code----
def start
@stopwatch_thread = Thread.new do
loop do
sleep 0.1
@seconds += 0.1 unless @paused
end
end
handle_input
end
Handle_input method
Next we create the handle_input method, this method handles the keys function of the keys we want to press in order to toggle the pause and stop the stopwatch. So we start with a loop again and we use a char variable and give it a value of the STDIN.getch method from io/console this return what ever key is pressed, now we say if char is the same as "\e"(stands for Esc key) we break the loop but if char is the same as "p" we will toggle our @paused variable to be either true or false. When the loop is broken we run the stop method that is outside of the loop.
----previous code----
def handle_input
loop do
char = STDIN.getch
break if char == "\e" # Exit when 'ESC' key is pressed
if char == 'p'
@paused = !@paused
puts @paused ? "stopwatch paused #{@seconds.round(2)} seconds." : 'stopwatch resumed.'
end
end
stop
end
Stop method
The last method is stop, here we call the kill method on the @stopwatch_thread if it is active and show the @seconds that passed, this also resets the @seconds to zero, so you would have to restart the program to run the stop watch again. To run the code we create a stopwatch variable and call Stopwatch.new and then call the start method, after this you can just run the program from your terminal with ruby stopwatch.rb(or whatever you have as your file name)
----previous code----
def stop
@stopwatch_thread.kill if @stopwatch_thread
puts "stopwatch stopped. Total time: #{@seconds.round(2)} seconds."
end
end
# Usage
stopwatch = Stopwatch.new
stopwatch.start
Complete stopwatch code below.
require 'io/console'
class Stopwatch
def initialize
@seconds = 0
@paused = false
@stopwatch_thread = nil
end
def start
@stopwatch_thread = Thread.new do
loop do
sleep 0.1
@seconds += 0.1 unless @paused
end
end
handle_input
end
def handle_input
loop do
char = STDIN.getch
break if char == "\e" # Exit when 'ESC' key is pressed
if char == 'p'
@paused = !@paused
puts @paused ? "stopwatch paused #{@seconds.round(2)} seconds." : 'stopwatch resumed.'
end
end
stop
end
def stop
@stopwatch_thread.kill if @stopwatch_thread
puts "stopwatch stopped. Total time: #{@seconds.round(2)} seconds."
end
end
# Usage
stopwatch = Stopwatch.new
stopwatch.start
Timer in Ruby
Here we will produce the code used to operate a timer. We first require the io/console as we did with the stopwatch and then we create the CountdownTimer class and our first initialize method. In this method we will have @seconds variable
to hold the time we will countdown from, @running
boolean and @timer_thread
.
Create class/initialize method
require 'io/console'
class CountdownTimer
def initialize
@seconds = 30
@running = false
@timer_thread = nil
end
Start/handle_input method
Next we have the start method and handle_input. The start method simply calls the handle_input method, this handle_imput method has a loop with the keys that will be used to activate the various fuctions of the timer s/Start, p/Pause and q/Quit
, each keypress with call the corresponding method in the code start_timer, toggle_timer and quit_program
.
----previous code----
def start
handle_input
end
def handle_input
loop do
char = STDIN.getch
case char
when 's' # Start timer
start_timer unless @running
when 'p' # Pause/resume timer
toggle_timer
when 'q' # Quit program
quit_program
break
end
end
end
Start_timer method
Next we have our start timer method, in this we first set out @running
variable to true and we give our thread variable the value of Thread.new as we did in the stopwatch , this time though we will be using a while loop since we are going to be counting down to zero, so we say while @seconds
is greater than zero we sleep for 1second each interval at the same time we minus 1 from the @seconds
value unless our @running
is false. When the timer is running and we have reached zero, we put let the user know time is up if its the first start of the timer we let them know the timer has started.
----previous code----
def start_timer
return if @running
@running = true
@timer_thread = Thread.new do
while @seconds > 0
sleep 1
@seconds -= 1 unless @running == false
end
if @running
@running = true
puts "Time's up!"
end
end
puts 'Timer started.'
end
Toggle_timer method
The toggle_timer method handles the pause and resume functionality of the timer, so when we press 'p' @running
will be set to false and we will let the user know that the timer has been paused and the time remaining, when we press 'p' again the timer will resume and @running
will be set to true
----previous code----
def toggle_timer
if @running
@running = false
puts "timer paused #{@seconds.round(2)} seconds."
elsif @seconds > 0
@running = true
puts 'Timer resumed.'
end
end
Finally the method to exit the program, here we set @running to false and call the join method from our Thread class(this is to ensure that the thread has been terminated) and let the user know that the program stopped. To start our timer we have a variable timer thats has CountdownTimer.new and we call the start method, you then just have to run ruby 'the name of your file'.rb
in the terminal and press 's' to start the timer. To increase the amount of countdown time you just have to increace the number of the @seconds
variable.
Quit_program method
----previous code----
def quit_program
if @running
@running = false
@timer_thread.join
end
puts 'Program exited.'
end
end
# Usage
timer = CountdownTimer.new
timer.start
Complete timer code below
require 'io/console'
class CountdownTimer
def initialize
@seconds = 30
@running = false
@timer_thread = nil
end
def start
handle_input
end
def handle_input
loop do
char = STDIN.getch
case char
when 's' # Start timer
start_timer unless @running
when 'p' # Pause/resume timer
toggle_timer
when 'q' # Quit program
quit_program
break
end
end
end
def start_timer
return if @running
@running = true
@timer_thread = Thread.new do
while @seconds > 0
sleep 1
@seconds -= 1 unless @running == false
end
if @running
@running = true
puts "Time's up!"
end
end
puts 'Timer started.'
end
def toggle_timer
if @running
@running = false
puts "timer paused #{@seconds.round(2)} seconds."
elsif @seconds > 0
@running = true
puts 'Timer resumed.'
end
end
def quit_program
if @running
@running = false
@timer_thread.join
end
puts 'Program exited.'
end
end
# Usage
timer = CountdownTimer.new
timer.start
Conclusion
Both of these codes can be used in a variaty of situations racing games, mazes, quizzes and to set alarms just to name a few. So give them a try in your next ruby project.