Spiking the Pomodoro Timer

I recently wrote about the beginning of phase 2 of the Full Stack project, in which we are PomodoroTimer building a Pomodoro timer (see also).  To get started, I decided to “spike” a quick and dirty version, if only to explore some of the technical challenges of the project. 

In the next couple postings I will walk through some of the spiked code, starting with an exploration of the timer. 

The timer is declared as a private member instance of DispatcherTimer and is supported by a private member boolean,

private bool _timerIsRunning = false;
private DispatcherTimer _timer = new DispatcherTimer();

The timer interval is set in the constructor as is the event handler for each “tick” of the timer,

 _timer.Interval = TimeSpan.FromSeconds( 1 );
 _timer.Tick += timer_Tick;

The timer_tick method calls SetTimeDisplay() which in turn calls a method on the Pomodoro object, GetDisplayString.

The Pomodoro object know the time it started, and it also knows its intervals (the length of a pomodoro, of a short break and of a long break).  Further, it knows the RedInterval, the amount of time that indicates you are approaching the end of the pomodoro.  For now, these values are hard coded as follows (in minutes) in the constructor of the Pomodoro,

 PomodoroInterval = 25;
 ShortRestInterval = 5;
 LongRestInterval = 20;
 RedInterval = 5;

 

Of course, these values will be moved to a configuration that will be stored in isolated storage.

GetDisplayString compute how much time has passed and whether or not the current Pomodoro is completed,

 public string GetDisplayString(
     out Color newColor, out bool isCompleted)
 {
     TimeSpan timePassed = DateTime.Now - startTime;
     double totalMinutesPassed = timePassed.TotalMinutes;
     int minutesPassed = timePassed.Minutes;
     int secondsPassed = timePassed.Seconds;
     isCompleted = false;

It then adds a minute if the seconds passed is greater than zero and computes whether we’ve passed a pomodoro interval and/or whether we’re in the red zone,

 if (secondsPassed > 0)
 {
     minutesPassed++;
 }

 if (totalMinutesPassed >= PomodoroInterval)
 {
     minutesPassed = 0;
     secondsPassed = 0;
     isCompleted = true;
 }

 if (totalMinutesPassed > PomodoroInterval - RedInterval)
 {
     newColor = Colors.Red;
 }
 else
 {
     newColor = Colors.White;
 }

 

Because this is “spiking” I can live with having this code know the specific display colors, but of course when we refactor this code the color will be owned by the UI.

Next, I set up a display string for the remaining minutes and seconds,

     string displayString = string.Format( "{0:D2}", 
         PomodoroInterval - minutesPassed ) + ":";

     if (secondsPassed == 0)
     {
         displayString += "00";
     }
     else
     {
         displayString += string.Format( 
             "{0:D2}", 60 - secondsPassed );
     }

    return displayString;
 }

 

The boolean _timerIsRunning is used to enable or disable various buttons and to toggle between starting and stopping the Pomodoro,

private void StartStopPomodoro()
{
    ToggleButton.Content = _timerIsRunning ? "Stop" : "Start";
    Interrupt.IsEnabled = _timerIsRunning;
    NewTaskButton.IsEnabled = !_timerIsRunning;
    Configure.IsEnabled = !_timerIsRunning;
    TaskListBox.IsEnabled = !_timerIsRunning;


    if (_timerIsRunning)
    {

        StartPomodoro();
        SetTimeDisplay();
    }
    else
    {
        StopPomodoro();
    }

}

About Jesse Liberty

Jesse Liberty is an independent consultant and programmer with three decades of experience writing and delivering software projects. He is the author of 2 dozen books and multiple Pluralsight courses, and has been a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Xamarin Certified Mobile Developer and a Xamarin MVP, Microsoft MVP and Telerik MVP.
This entry was posted in Full Stack, Mango, Patterns & Skills. Bookmark the permalink.

Leave a Reply

Your email address will not be published.