🕛

MATLABでポモドーロタイマーを作ってみた

2024/12/09に公開

はじめに

私は制御工学の研究者です。あるとき気づきました。一番制御できていないのは自分自身であることを。

作業時間管理の有名な方法の一つとしてポモドーロテクニックというものが知られています。簡単にご説明しますと、作業時間を区切って適度に休憩を取ることで作業効率を上げようというものです。この時間の管理に使われるツールをポモドーロタイマーといいます。

この読者であられる皆様方におきましては、MATLABを常に起動されていると思われますので、このポモドーロタイマーをコマンド一つで起動できるようにしておきましょう。

仕様

ポモドーロテクニックとは作業時間を区切って適度に休憩を取ることで作業効率を上げる方法です。
概念としては以下のように作業時間と休憩時間を繰り返します。
Pomodoro Timer Concept

ポモドーロテクニックの説明をWikipediaから引用します[1]

具体的な手順は以下の通りである。

  1. 達成しようとするタスクを選ぶ
  2. キッチンタイマーで25分を設定する
  3. タイマーが鳴るまでタスクに集中する
  4. 少し休憩する(5分程度)
  5. ステップ2 - 4を4回繰り返したら、少し長めに休憩する(15分 - 30分)

また注意として以下も記載されております。

注意点

  • ポモドーロ(上図でいうとサイクルのこと)の途中で急用が入りタスクが中断された場合は、そのポモドーロは終了とみなし、はじめから新しいポモドーロを開始する。
  • 25分間の作業の中では、一つの作業に没頭する。
  • タイマーは音が鳴るものが良い。音が鳴らないタイマーだと、常にタイマーに注意を払う必要があり、集中の妨げとなる。

ここから、時間の一時停止などの機能を省略してよいことと、アラーム音が鳴らせると良いことが読み取れます。

インストール

MATLABのホームタブのアドオン(Add-Ons)からAdd-On Explorerを開いてください。pomodoro-timerと検索していただけますと引っかかると思いますのでAdd -> Add to MATLABの順にクリックすれば完了です。
もしAdd-On Explorerが使えない場合には、File Exchangeから直接ダウンロードしてください。

アンインストールしたい場合には、コマンドパレットに以下のコマンドを入力してください。

matlab.addons.uninstall("pomodoro timer");

実行

MATLABのコマンドウィンドウで以下のコマンドを入力してください。

pomodoroTimer

起動するとまずは25分のタイマーがスタートします。作業を始めましょう。
Work timer
タイマースタート時にはゴングの音がなります。
25分のタイマーが終わると、ピヨピヨという音とともに5分のタイマーがスタートします。短い休憩を取りましょう。
Short break timer
5分のタイマーが終わると25分タイマーに戻ります。
特殊なケースとして4回目の25分のタイマーが終わると、ハレルヤとともに30分のタイマーがスタートします。長い休憩を取りましょう。
Long break timer
30分のタイマーが終わった場合も25分タイマーに戻ります。
以上が繰り返されます。

実装

ソースコードはGitHubで公開しております。

https://github.com/kimushun1101/pomodoro-timer

以下では、その実装の詳細を解説していきます。

状態管理に構造体を使う

ポモドーロタイマーは「作業中」「短い休憩」「長い休憩」の3つの状態を持ちます。また、それぞれの状態は「状態名」「設定時間」「画面の色」「アラーム音」の情報を持つため、それらを構造体で管理することで可読性の高いコードとなります。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L32-L46

現在の状態はcurrentStatusという変数で保持します。状態の切り替わり先の状態は、現在の状態currentStatus.Nameと現在のサイクル数currentCycleに応じて決まります。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L81-L95

状態の切り替わりの際に行われる共通の動作をcurrentStatusに対して行う形でまとめることが可能です。
このswitchStatus関数の続きは以下のとおりです。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L96-L105

switchStatus関数は、現在のタイマーの値が0になる度に呼び出されます。残り時間がある場合には時刻の表示を更新します。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L66-L73

時間の取り扱い

つぎに、updataTimer関数の呼び出しと残り時間の計算について説明します。timerを用いて、1秒に1回画面の時刻を書き換える処理を実装しました。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L55

この設定を行うことで、一定時間(1秒)おきにupdateTimer関数が動作します。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L67-L68

updateTimerで最初に行う残り時間の計算ですが、MATLABの変数型としてdatetimedurationがあることに注意が必要です。
datetimeはある一点の時刻を格納する変数の型であり、durationは時間の間隔を格納する変数の型です。MathWorksが提供するdurationのドキュメントページの説明がわかりやすいです。


durationのドキュメントページより

初期設定としてタイマーがスタートした時刻を基準時刻と定義してbaseTimedatetimeとして格納しておきます。また、各状態が継続する時間を設定時間と定義してwork.durationなどにdurationとして格納しておきます。

以上を踏まえて、残り時間の計算は以下のように計算しています。

remainingTime = currentStatus.duration - (datetime("now") - baseTime);
% 残り時間 = 現在状態の設定時間 - (現在時刻 - 基準時刻)

ここで、

  • 残り時間remainingTimeduration
  • 現在の状態の設定時間currentStatus.durationduration
  • 現在時刻datetime("now")datetime
  • 基準時刻baseTimedatetime
    となります。

感覚的には当たり前ですが型の概念から混乱しそうな点として、datetimeの和や差はdurationの型になるということにご留意ください。

timerはバックグラウンドで実行されておりますので、timerを止める前にこのプログラムを終了してしまうと、変数にアクセスできなくなることから、

Error while evaluating TimerFcn for timer 'timer-1'

というエラーメッセージが出てしまいます。
Figureを閉じる際にtimerを停止してから終了するように、コールバック関数で終了時の動作を拡張しました。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L107-L111

表示について

一般的なfigureではなくuifigureuilabelを使用しました。上記のcloseRequest関数の紐付けも、timerのときと類似の書き方です。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L54-L57

uifigureの良い点としては、デフォルトでメニューバーやナンバータイトルなどがないためスッキリとした見た目であることと、figureと別管理がされているため、本筋の開発でclose allなどをしてしまっても閉じることがありません。
イマイチな点としては、uifigureが表示されるまでの時間がfigureに比べると若干遅い(3秒くらい?かかる)ことです。MathWorks様の今後のアップデートに期待しております。

サイズの指定はマジックナンバーとなってしまいましたが、3桁の分数まで表示されることを想定して"000:00"という表示がされたときに収まるように、フォントサイズをfigureサイズの「横幅の0.3倍」または「縦の高さの0.7倍」の小さい方に合わせて適当に調整しました。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L74-L78

この処理がupdateTimer関数の中にあることにより、動作中にウィンドウサイズをドラッグなどで変更されても表示が崩れないように制御されます。

アラーム音

MATLABで音を出すことはsound関数を使えば簡単です。

一例をあげると
https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L36

として、currentStatus = workであったとすると、

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L101-L102

これでゴングの音を鳴らせます。

今回は、アラーム音を途中で止めることはなく単発を垂れ流しますが、より柔軟に制御したい場合にはaudioplayer関数を使用するとよいでしょう。
MATLABに標準搭載されている音の種類ですが、上記らの関数のドキュメントには記載されておりませんが、以下のページを見るとchirp, gong, handel, laughter, splat, trainの6つオーディオファイルが存在していることがわかります。

https://jp.mathworks.com/help/stats/extract-mixed-signals.html

引数

25分作業5分休憩のポモドーロテクニックに類似したものとして、作業時間と休憩時間を52分と17分とする52/17ルールと言うものもあるようです。

https://note.com/benkyo_cafe/n/n2e58c69162b2

いずれにしても時間を設定できた方が嬉しい人も多そうということで、MATLAB関数のオプション引数を設定しました。
後で説明しますが通常の引数Cyclesに加えて、optionsという構造体引数を設定します。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L1

これにより、optionsの要素の引数はコマンドウィンドウやエディターウィンドウで補完が効くようになります。
また以下で、引数のデフォルト値とスカラー値かつ正の整数で来ているかもチェックも記述していきます。

https://github.com/kimushun1101/pomodoro-timer/blob/c3e784a379f2b8dce4f67c3212127af8a748e74c/pomodoroTimer.m#L25-L30

引数なしで実行した場合にはここで定義された値で実行され、引数ありで実行された場合には誤った引数を入れるとエラーとして弾いてくれるため、とても便利です。
options引数の与え方は、plotfigureなどと同じようにpomodoroTimer(引数名, 値, ...)で実行する形となります。具体例は以下の通りです。

pomodoroTimer("WorkTime", 52, "ShortBreakTime", 17)

つぎにCyclesという引数ですが、こちらは作業と休憩を何サイクル繰り返したら長い休憩をとるかという値も引数として設定したものです。これは通常引数であるため

pomodoroTimer(3)

のような実行のさせ方をします。options引数と組み合わせることも可能です。

pomodoroTimer(3, "WorkTime", 52, "ShortBreakTime", 17, "LongBreakTime", 60)

まとめ

ポモドーロテクニックを使うことで、作業時間を制御、もとい自分自身が制御されることができるでしょう。ポモドーロテクニックは強力な方法ではありますが、作業内容や人によって向き不向きがあるため、適材適所に取り入れていただければと思います。一方でマトラーボテクニックは、研究・開発・MATLAB芸のためになんぼあっても困りませんので、ぜひ体得してください。皆様の今後の作品に期待しております。

  • MATLABで動くポモドーロタイマーで自分の作業を制御しよう。
  • 構造体を活用しましょう。
  • timerを使うときには注意が必要。
  • uifigureでGUIを作ってみよう。
  • 音を出すのは簡単です。
  • 引数定義は便利です。

参考

類似でよりシンプルなものを作られている先駆者が居られましたのでご紹介します。コールバック関数周りコードを参考にさせていただき、非常にスッキリ書き直すことができました。

https://qiita.com/sanmojih/items/0bd8a326a6a022c4b615

脚注
  1. https://ja.wikipedia.org/wiki/ポモドーロ・テクニック ↩︎

GitHubで編集を提案

Discussion