Stopwatch and Timer in Ruby [with source code]

Table of contents:

  1. Introduction
  2. Stopwatch in Ruby
    • Create class/initialize method
    • start method
    • handle_input method
    • stop method
  3. Timer in Ruby
    • Create class/initialize method
    • start/handle_input method
    • start_timer method
    • toggle_timer method
    • quit_program method
  4. 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.