芋出し画像

🌃【Pythonクラス】䜜業甚ポモドヌロタむマヌのブラりザヌ゜ヌスを䜜っおYouTube動画を䜜っおみた


ポモドヌロテクニックずは

コロナ犍初期の2020幎に広たった時間管理手法です。正確には1980幎埌半にフランチェスコ・チリロさんによっお開発された手法ですが、コロナが蔓延し孊校や職堎が閉鎖されリモヌト勀務になった2020幎以降に䞀気にこの手法が泚目され、YouTubeやTwitchなどのオンラむン動画配信プラットフォヌムでポモドヌロタむマヌを甚いたコンテンツが倚く䞊がりたした。「ポモドヌロ」ずいう蚀葉はむタリア語でトマトを意味するそうで、この手法は欧米のキッチンではよく芋られるトマト型のタむマヌに由来しおいるそうです。

🍅ポモドヌロ手法の特城は䞻に以䞋のように機胜したす

  1. タスクの遞択䜜業したいタスクを遞択したす。

  2. タむマヌの蚭定基本は分です。ただ䜜業内容によっお分や時間に蚭定したり人それぞれ自由です。

  3. タスクに集䞭タむマヌがなるたで遞択したタスクに集䞭したす。

  4. 短い䌑憩基本は分です。

  5. 繰り返す以䞊のプロセスを繰り返したす。基本はセットのポモドヌロを完了したら長い䌑憩通垞は分から分を取りたす。

🍅ポモドヌロ手法の利点は

  • 時間管理時間を効率的に管理する手助けをしたす。

  • 集䞭ず生産性短い䜜業時間が高い集䞭力ず生産性を維持する事を助けたす。

  • バヌンアりト燃え尜きの防止定期的な䌑憩はバヌンアりトを防ぎ、持続可胜な䜜業ペヌスを保ちたす。

  • モチベヌションの向䞊タむマヌはモチベヌションを高め、タスクを完了するためのある皮の緊急感を生み出したす。

ポモドヌロの䜿甚䟋

YouTubeではこのような動画を芋たこずある人もいるかず思いたす。これも分の䜜業時間ず分間の䌑憩をセットをこなす動画です。

私自身も数幎前はポモドヌロ手法を甚いたプログラミングセッションをラむブ配信したりしおいたした。プログラミングの堎合は分だずかなり短いので倧䜓は分の䜜業時間ず分の䌑憩を挟んでセットをこなしおいたした。
その時に䜿っおいたポモドヌロタむマヌは他のデベロパヌが構築したものを䜿わせおもらっおいたので、い぀か自分でもシンプルなものでもいいから䜜っおみたいず思っおいたした。

先月、少し時間が空いたのでFlaskを䜿ったシンプルなポモドヌロタむマヌを䜜っおみたした。

コヌドの構築

たず倧きく分けお぀のファむルから成り立っおいたす。
バック゚ンドはPython蚀語、フロント゚ンドはFlaskず呌ばれるPython のWebフレヌムワヌク、そしおタむマヌを秒ごずにアップデヌトさせるファむルにはJavaScriptを䜿っおいたす。

このNote蚘事ではバック゚ンドのパむ゜ン蚀語コヌドを玹介しおいきたす。

幟぀かのセクションに分けお圹割などを解説しおいきたす。

ラむブラリヌの呌び蟌み

from flask import Flask, render_template
import time
import threading
import winsound

app = Flask(__name__)

必芁なラむブラリヌを呌び蟌み、Flaskりェブアプリケヌションのむンスタンスを䜜成したす。

デコレヌタヌの䜿甚

# define decorator
def log_method_call(func) -> callable:
    """ 
     A decorator that logs the method call and arguments.
     Parameters:
       func (function): The function to decorate.
     Returns:
       function: The decorated function.
       
       """
    def wrapper(*args, **kwargs) -> any:
        """ 
         Wrapper function that logs the method call and arguments.
         Parameters:
           *args (tuple): The positional arguments.
           **kwargs (dict): The keyword arguments.
         Returns:
           The result of the decorated function.
           """
        print(f"Calling {func.__name__} with arguments {args} and keywork arguments {kwargs}")
        return func(*args, **kwargs)
    return wrapper

たず䞀番最初にデコレヌタヌを定矩したした。デコレヌタヌずは、すでに定矩されおいる関数に凊理の倉曎や远加を行う為のパむ゜ン特融の機胜です。
ここではコヌドフロヌを分かりやすくしたりデバッグしやすくするログ機胜を付け加えるデコレヌタヌを定矩しおいたす。
この先のコヌドに@log_method_callが数か所に出おきたすが、これがデコレヌタヌの機胜をしおいたす。

Pythonクラス

class PomodoroTimer():
    def __init__(self):
        # Initialize timer-related variables
        self.timer_message = ""
        self.remaining_time = 0
        self.timer_lock = threading.Lock()  # Add a lock for thread safety
        self.cycles = 4
        self.current_session = 0

    @log_method_call
    def update_timer(self, message, time_remaining) -> None:
        """ 
         Update the timer message and remaining time.
         Parameters:
           message (str): The message to display in the timer.
           time_remaining (int): The remaining time in seconds.
         Returns:
           None.
           """
        with self.timer_lock:
            self.timer_message = message
            self.remaining_time = time_remaining
            # print(f"Timer Updated: {self.timer_message}, Remaining Time: {self.remaining_time} seconds") 
    
    @log_method_call
    def play_bell_sound(self) -> None:
        """ 
         Play bell sound
           """
        winsound.PlaySound("bell.wav", winsound.SND_ASYNC)

    @log_method_call
    def format_time(self, seconds) -> str:
        """ 
         Format time in seconds as MM:SS
         Parameters:
           seconds (int): The time in seconds.
         Returns:
           str: The formatted time as MM:SS.
           """
        minutes, seconds = divmod(seconds, 60) # python built-in
        formatted_time = f"{minutes:02d}:{seconds:02d}"
        # print(f"Formatted Time: {formatted_time}")
        return formatted_time
    
    @log_method_call
    def countdown(self, phase, duration) -> None:
        """ 
         Run the countdown timer for the specified phase and duration.
         Parameters:
           phase (str): The phase of the timer (e.g. "Work Time" or "Break Time").
           duration (int): The duration of the timer in seconds.
         This method updates the timer display with the current phase, session couint,
         and remaining time every second during the countdown. 
         Returns:
           None.
           
           """
        start_time = time.time()

        while time.time() - start_time < duration:
            elapsed_time = time.time() - start_time
            time_remaining = max(0, int(duration - elapsed_time))

            # Update the timer with the current phase and remaining time
            session_info = f"Session {self.current_session} of {self.cycles}"
            self.update_timer(f"{phase} : {session_info} - {self.format_time(time_remaining)}", time_remaining)
            time.sleep(1)  # Update every second
            # print(f"Phase: {phase}, Elapsed Time: {elapsed_time}, Remaining Time: {time_remaining}")
    
    @log_method_call
    def pomodoro_timer(self) -> None:
        """ 
         Run the entire Pomo timer logic, including work and break phases alternating.
         Returns:
           None.
         It iterates through the specified numbe of cycles, executing the work and break phases, 
         along with brief pauses and bell sounds between each cycle.
           """
        # Display Welcome Message
        self.update_timer("Welcome to Pomo Code Sessions", 0)
        time.sleep(20)  # Add a pause for the welcome message
        self.play_bell_sound()

        # Iterate through the specified number of cycles
        for i in range(self.cycles):
            self.current_session = i + 1
            # Work Time
            work_phase, work_duration = "Work Time", 25 * 60
            self.countdown(work_phase, work_duration)

            if i < self.cycles - 1:
                self.play_bell_sound()

            # Add a brief pause before starting Break Time
            time.sleep(1)

            # Break Time
            break_phase, break_duration = "Break Time", 5 * 60
            self.countdown(break_phase, break_duration)

            if i < self.cycles - 1:
                self.play_bell_sound()
    
        # Display a message when the timer is finished
        self.update_timer("Great Job!", 0)

Classずいうコンセプトはオブゞェクト指向プログラミングの基盀ずいっおも過蚀ではありたせん。Classは新しいデヌタの型を構築する際の蚭蚈図ブルヌプリントです。そしおClassから䜜られたモノオブゞェクトがむンスタンスず呌ばれたす。

コンストラクタヌ

クラス内の䞀番最初には必ず

def __init__(self):

がありたす。これはコンストラクタヌず呌ばれるもので、特殊メ゜ッドの䞀぀です。䞻にClassの初期蚭定を行いたす。前回のNote蚘事でグロヌバル倉数に぀いお話したしたが、グロヌバル倉数ず䌌おいたす。Class内に入るずグロヌバル倉数ではなくむンスタンス倉数に倉わりたす。

def __init__(self):
        # Initialize timer-related variables
        self.timer_message = ""
        self.remaining_time = 0
        self.timer_lock = threading.Lock()  # Add a lock for thread safety
        self.cycles = 4
        self.current_session = 0

䞊の䟋では぀のむンスタンス倉数を初期化しおいたす。この倉数が秒ごずに、もしくはポモドヌロのサむクルを远うごずにアップデヌトされおいきたす。

メ゜ッド

Classの䞭には以䞋の関数を定矩するような郚分が数か所芋えるかず思いたす。

    @log_method_call
    def update_timer(self, message, time_remaining) -> None:
        """ 
         Update the timer message and remaining time.
         Parameters:
           message (str): The message to display in the timer.
           time_remaining (int): The remaining time in seconds.
         Returns:
           None.
           """
        with self.timer_lock:
            self.timer_message = message
            self.remaining_time = time_remaining
            # print(f"Timer Updated: {self.timer_message}, Remaining Time: {self.remaining_time} seconds") 

Classの䞭にあるdefは関数Functionではなくメ゜ッドず呌ばれたす。メ゜ッドはデヌタを䜜成する際の実際の動䜜の仕方を定矩したす。このポモドヌロタむマヌのClass内には぀のメ゜ッドを䜜りたした。

    @log_method_call
    def play_bell_sound(self) -> None:
        """ 
         Play bell sound
           """
        winsound.PlaySound("bell.wav", winsound.SND_ASYNC)

䟋えば䞊のメ゜ッドはシンプルにベル音を鳎らす為だけのメ゜ッドです。
このように動䜜によっお振り分けおメ゜ッドを幟぀か蚭定するこずによっおClassずいうブルヌプリントを構成しおいたす。

ポモドヌロタむマヌクラスのむンスタンスを䜜成

# Create an instance of the PomodoroTimer class
pomodoro_time_instance = PomodoroTimer()

この行は PomodoroTimer クラスのむンスタンスを䜜成し、デフォルトの倀で初期化したす。

Flask ルヌト ('/') を定矩

# Route definition using the Flask web framework
@app.route('/')
def index():
    with pomodoro_time_instance.timer_lock:
        return render_template("index.html", timer_message=pomodoro_time_instance.timer_message)

ここでは Flask りェブフレヌムワヌクを䜿甚しおルヌト URL ('/') を定矩しおいたす。ナヌザヌがこの URL にアクセスするず、index 関数が呌び出されたす。関数は pomodoro_time_instance.timer_lock を䜿甚しおタむマヌ関連のデヌタに察するスレッドセヌフを確保、そしお別に甚意しおある"index.html" ずいう名前の HTML テンプレヌトをレンダリングし、衚瀺されるべきタむマヌメッセヌゞ (timer_message) を枡したす。

メむンブロック (if __name__ == '__main__':)

if __name__ == '__main__':
    # Start the timer thread
    timer_thread = threading.Thread(target=pomodoro_time_instance.pomodoro_timer)
    timer_thread.start()
    # Run the Flask app in debug mode during development mode
    # Disable it in a production environment for security reasons
    app.run(debug=True)

このブロックはスクリプトがメむンプログラムずしお実行されおいるかを確認したす。pomodoro_timer メ゜ッドを実行する新しいスレッド (timer_thread) が䜜成されたす。このメ゜ッドはポモドヌロタむマヌロゞック党䜓を制埡したす。Flask りェブアプリ (app) はデバッグモヌドで実行され (app.run(debug=True))、りェブブラりザを介しおアクセスできるようになりたす。タむマヌロゞックはバックグラりンドで実行されたす。

実際に動画に反映させおみた

䜜業甚にぜひ䜿っおみおください。


🖊䜕か気づいたこずやご意芋などがあればコメント欄からお願いしたす。チャンネルフォロヌもよろしくお願いしたす。

🚀 疑問に思った事はデヌタ化しお自分なりの答えを探しおいこうず思いたす。そしおその答えがどこかにいる誰かの為になる事を願っおいたす。


この蚘事が気に入ったらサポヌトをしおみたせんか