Python_App_タスク＆スケジュール管理

# 目的
PC立ち上げ時「いつ」「何を」するかのタスクスケジューシングアプリを立ち上げ、
時間効率Up、記憶リソースの削減

# 完成品
![スクリーンショット 2024-12-25 2.47.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946669/bff3c108-afe9-e0e0-b11c-054e39f3df4f.png)

# 説明
### 前置き
・予定が多くていつ何をするべきか悩んでしまう
・最近何かしないといけないことがあったような、、何だっけ？
・あれいつまでだったっけ？確かどこどこに書いてたはず！確認しとこうか
・ヤバい今日XXがあるんだった、、
・Slack、Line、メール、お店のカード、あの予定はどこに書いてあるんだっけ？
・予定何回も見たのに忘れてた、、
・うわ、もうこんな時間、予定あるのは知っていたはずなのに、、

そんな時は(そんな事が起きる前に)事前に「何を」「いつ」行うのか、このアプリに伝えておけば勝手にリマインドしてくれます。

### App内容
![スクリーンショット 2024-12-25 2.47.04のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946669/f100c41e-7b65-2343-3a81-15edd0df5605.png)

### ①
・現在の時刻
### ②
・PC起動時から毎回行う定常作業を管理します。
　アプリ起動時からカウントダウンが始まりますので、
　定常作業をさっさと片付けるためにあります。
 >[タスク]　[残り時間]
 
### ③
・向こう1年の日時が決まっているタスクを管理します。
　日が近ずくにつれ何度も確認せずとも、
　あとどれぐらいで開始されるのか表示してくれます。　
　残りの日数や時間に応じて、あとX日やあとX時間X分と表示されます。
>[予定日時]　[残り時間]　[タスク]

### ④
・タスクは決まっているが、日時が決まってない物を表示します。
　目処感として、「Daily」「Weekly」「Monthly」「Yearly」があります。

②③④の内容を記入した3ファイル(.txt)とPythonファイルからなるアプリケーションになります。
これをPCの起動時に実行させることで、PC起動毎にタスクが表示される事になります。
つまり、一度アプリにタスクを渡してしまえば、あなたのマネージャーとしてタスクの時間管理を行なってくれます。

# 準備
・エディタ（この記事ではVScode使用しています。）

・python実行環境
　└標準ライブラリのみ
 
・PC（この記事ではMacをデフォルトで書いています。）

# 手順
## 1.フォルダを作成しその中に、textファイルを3つ作成。
・お好きなディレクトリにフォルダを作成。
　名フォルダ名はなんでもいいですが今回は「startup_app」フォルダとします。

 ・「startup_app」フォルダの中に以下textファイルを作成します。
　・countdown.txt
　・schedule.txt
　・daily.txt

 ## 2.Pythonファイルを作成
 ・「startup_app」フォルダの中にPythonファイルを作成します。
 　ファイル名はなんでもいいですが今回は「startup_task.py」とします。

 ・「startup_task.py」に以下コードをコピペし、保存します。
 ~~~
 import os
import tkinter as tk
from tkinter import scrolledtext
import datetime
import time
from threading import Thread

script_path = os.path.dirname(os.path.abspath(__file__))

# ファイルパスの設定
COUNTDOWN_TASKS_FILE_PATH = f"{script_path}/countdown.txt"
SCHEDULE_FILE_PATH = f"{script_path}/schedule.txt"
DAILY_TASKS_FILE_PATH = f"{script_path}/daily.txt"


# タスクを読み込む関数
def load_tasks(filename):
    tasks = {"year": [], "month": [], "week": [], "day": []}
    try:
        with open(filename, 'r') as file:
            current_scope = None
            for line in file:
                line = line.strip()
                if line in tasks:
                    current_scope = line
                elif current_scope and line:
                    tasks[current_scope].append(line)
    except FileNotFoundError:
        print(f"File '{filename}' not found. Starting with empty tasks.")
    return tasks

# カウントダウン用タスクを読み込む関数
def load_countdown_tasks(filename):
    tasks = []
    try:
        with open(filename, 'r') as file:
            for line in file:
                task_name, minutes = line.strip().split(',')
                tasks.append((task_name, int(minutes)))
    except FileNotFoundError:
        print(f"File '{filename}' not found. Starting with empty countdown tasks.")
    return tasks

# タスクを保存する関数
def save_tasks(filename, tasks):
    with open(filename, 'w') as file:
        for scope, task_list in tasks.items():
            file.write(f"{scope}\n")
            for task in task_list:
                file.write(f"{task}\n")

# スケジュールを読み込む関数
def fetch_schedule():
    schedule = []
    with open(SCHEDULE_FILE_PATH, "r", encoding="utf-8") as f:
        for line in f:
            year, month, day, hour, minute, task = line.strip().split(",")
            schedule.append([int(year), int(month), int(day), int(hour), int(minute), task])
    return schedule

# タスクを表示する関数
def display_tasks(tasks):
    display_text = ""
    display_text += "Daily tasks:\n"
    for task in tasks["day"]:
        display_text += f"- {task}\n"

    display_text += "\nWeekly tasks:\n"
    for task in tasks["week"]:
        display_text += f"- {task}\n"

    display_text += "\nMonthly tasks:\n"
    for task in tasks["month"]:
        display_text += f"- {task}\n"

    display_text += "\nYearly tasks:\n"
    for task in tasks["year"]:
        display_text += f"- {task}\n"

    return display_text

# スケジュールを表示する関数
def display_schedule(schedule):
    now = datetime.datetime.now()
    schedule_text = ""
    for year, month, day, hour, minute, task in schedule:
        task_time = datetime.datetime(year, month, day, hour, minute)
        if now < task_time:
            remaining = task_time - now
            total_seconds = int(remaining.total_seconds())
            days, remainder = divmod(total_seconds, 86400)
            hours, remainder = divmod(remainder, 3600)
            minutes, seconds = divmod(remainder, 60)
            if days >= 1:
                schedule_text += f"【{task_time:%Y-%m-%d %H:%M}】あと{days}日 {task}\n"
            else:
                schedule_text += f"【{task_time:%H:%M}】あと{hours:02d}:{minutes:02d}:{seconds:02d} {task}\n"
        else:
            schedule_text += f"【{task_time:%H:%M}】--- {task}\n"
    return schedule_text

# タスクのカウントダウン関数
def countdown(task_name, minutes, task_labels, index):
    seconds = minutes * 60
    while seconds > 0:
        mins, secs = divmod(seconds, 60)
        time_format = '{:02}:{:02}'.format(mins, secs)
        task_labels[index].config(text=f'{task_name} 残り {time_format}')
        time.sleep(1)
        seconds -= 1
    task_labels[index].config(text=f'{task_name} 終了しました！')

def start_all_tasks(task_list, task_labels):
    threads = []
    for index, (task_name, minutes) in enumerate(task_list):
        thread = Thread(target=countdown, args=(task_name, minutes, task_labels, index))
        thread.start()
        threads.append(thread)

# GUIのセットアップ
root = tk.Tk()
root.title("タスク&スケジュール")
root.geometry("600x800")

# 現在時刻の表示
now_display = tk.Label(root, text="00:00:00", font=("Arial", 24))
now_display.pack(pady=10)

# タスクカウントダウンの表示
task_frame = tk.Frame(root)
task_frame.pack(pady=20)
countdown_tasks = load_countdown_tasks(COUNTDOWN_TASKS_FILE_PATH)
task_labels = []
for index, (task_name, _) in enumerate(countdown_tasks):
    task_label = tk.Label(task_frame, text=f'{task_name} 残り --:--', font=("Arial", 14), anchor='w', width=60)
    task_label.pack()
    task_labels.append(task_label)

task_thread = Thread(target=start_all_tasks, args=(countdown_tasks, task_labels))
task_thread.start()

# スケジュールを表示するボックス
schedule_display = scrolledtext.ScrolledText(root, font=("Arial", 12), width=70, height=10)
schedule_display.pack(pady=10)

# タスクを表示するボックス
task_display = scrolledtext.ScrolledText(root, font=("Arial", 12), width=70, height=20)
task_display.pack(pady=10)

# 現在時刻の更新
def update_time():
    now = datetime.datetime.now()
    now_display["text"] = now.strftime("%H:%M:%S")
    root.after(1000, update_time)

# タスクとスケジュールの更新
daily_tasks = load_tasks(DAILY_TASKS_FILE_PATH)
sch = fetch_schedule()
def update_displays():
    task_display.delete(1.0, tk.END)
    task_display.insert(tk.END, display_tasks(daily_tasks))

    schedule_display.delete(1.0, tk.END)
    schedule_display.insert(tk.END, display_schedule(sch))

update_displays()

# GUIの開始
update_time()
root.mainloop()
 ~~~

これで必要ファイルは揃いました。

### ディレクトリ構造
・startup_app
　└・countdown.txt
　└・schedule.txt
　└・daily.txt
　└・startup_task.py

 ## 3.タスク＆スケジュールをtextに書き込む
 ・各textにタスクを書き込みます。
　各textには、入力規則があるのでテンプレを以下に表示します
 
　・countdown.txt
 >[タスク],[分]
~~~
タスク１	,1
タスク2	,2
~~~

 　
　・schedule.txt
 >[年],[月],[日],[時],[分],[タスク]
~~~
2024,12,19,13,00,タスク1
2024,12,31,0,50,タスク2
~~~

 　
　・daily.txt
 >day
 [デイリータスク]
 week
 [ウィークリータスク]
 ...
~~~
![スクリーンショット 2024-12-25 4.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946669/b60e2762-faf6-f802-aae4-48b134bd0144.png)
day
デイリータスク

week
ウィークリータスク

month
マンスリータスク

year
イヤーリータスク
~~~

・startup_task.pyを実行し、アプリが表示されることを確認してください。
![スクリーンショット 2024-12-25 4.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3946669/54ddd6ec-c5df-38d8-4f3c-5fd994c91b3b.png)

# 4.StartUpアプリに登録する
・StartUpアプリに登録の方法は↓こちらの記事から

https://qiita.com/mitsuha_003/items/d1b27c9401cac7fac65b