当直表アプリをchat GPTに作ってもらって自動作成する part2

雑記

久しぶりにchatGPTにcodeを書いてもらうこととしました。

tkinterを使ったGUIです

chatGPT4.5で制作しようと思ったのですが、制限かかってしまったので、4oになります

全体のcodeは200行くらいあるのですが、codeの記述めちゃくちゃ速くなってますね

1分くらいでは200行は書いてくれるので、かなり進化していますね

ということでcodeを記載します

実際のcode

import tkinter as tk

import calendar

from datetime import datetime

import csv

from collections import defaultdict

# 初期データ

ng_days = defaultdict(set)

prefer_days = defaultdict(set)

duty_schedule = {}

users = set()

# 表示年月

today = datetime.today()

current_year = today.year

current_month = today.month

# 名前手入力と保存

def save_user():

global current_user

name = name_entry.get().strip()

if not name:

return

users.add(name)

current_user = name

name_entry.delete(0, tk.END)

update_user_list()

def update_user_list():

user_list.delete(0, tk.END)

for user in sorted(users):

user_list.insert(tk.END, user)

def select_user(event):

global current_user

selection = user_list.curselection()

if not selection:

return

current_user = user_list.get(selection[0])

update_list()

draw_calendar()

def toggle_mark(day):

if not current_user:

return

key = (current_year, current_month, day)

if mark_mode.get() == “NG”:

if key in ng_days[current_user]:

ng_days[current_user].remove(key)

else:

ng_days[current_user].add(key)

prefer_days[current_user].discard(key)

else:

if key in prefer_days[current_user]:

prefer_days[current_user].remove(key)

else:

prefer_days[current_user].add(key)

ng_days[current_user].discard(key)

draw_calendar()

update_list()

def update_list():

ng_list.delete(0, tk.END)

prefer_list.delete(0, tk.END)

if not current_user:

return

for y, m, d in sorted(prefer_days[current_user]):

prefer_list.insert(tk.END, f”{y}-{m:02d}-{d:02d}”)

for y, m, d in sorted(ng_days[current_user]):

ng_list.insert(tk.END, f”{y}-{m:02d}-{d:02d}”)

def draw_calendar():

for widget in cal_frame.winfo_children():

widget.destroy()

tk.Label(cal_frame, text=f”{current_year}年 {current_month}月”).grid(row=0, column=0, columnspan=7)

for i, day in enumerate([“月”, “火”, “水”, “木”, “金”, “土”, “日”]):

tk.Label(cal_frame, text=day, width=5).grid(row=1, column=i)

cal = calendar.Calendar()

row = 2

for day, weekday in cal.itermonthdays2(current_year, current_month):

if day == 0:

continue

text = str(day)

if current_user:

if (current_year, current_month, day) in ng_days[current_user]:

text = f”{day}×”

elif (current_year, current_month, day) in prefer_days[current_user]:

text = f”{day}◯”

btn = tk.Button(cal_frame, text=text, width=5, command=lambda d=day: toggle_mark(d))

btn.grid(row=row, column=weekday)

if weekday == 6:

row += 1

def prev_month():

global current_year, current_month

current_month -= 1

if current_month == 0:

current_month = 12

current_year -= 1

draw_calendar()

def next_month():

global current_year, current_month

current_month += 1

if current_month == 13:

current_month = 1

current_year += 1

draw_calendar()

def assign_duties():

duty_schedule.clear()

cal = calendar.Calendar()

day_list = [day for day, weekday in cal.itermonthdays2(current_year, current_month) if day != 0]

count = defaultdict(int)

last_duty_day = defaultdict(lambda: -10) # 初期は十分離れている

all_users = list(users)

for day in day_list:

assigned = False

prefer_users = [u for u in all_users if (current_year, current_month, day) in prefer_days[u] and (current_year, current_month, day) not in ng_days[u] and abs(day – last_duty_day[u]) >= 2]

possible_users = [u for u in all_users if (current_year, current_month, day) not in ng_days[u] and abs(day – last_duty_day[u]) >= 2]

sorted_users = sorted(prefer_users or possible_users, key=lambda u: count[u])

for user in sorted_users:

duty_schedule[(current_year, current_month, day)] = user

count[user] += 1

last_duty_day[user] = day

assigned = True

break

if not assigned:

duty_schedule[(current_year, current_month, day)] = “未割当”

draw_result_calendar()

def draw_result_calendar():

for widget in result_frame.winfo_children():

widget.destroy()

tk.Label(result_frame, text=f”{current_year}年 {current_month}月 当直表”).grid(row=0, column=0, columnspan=7)

for i, day in enumerate([“月”, “火”, “水”, “木”, “金”, “土”, “日”]):

tk.Label(result_frame, text=day, width=12).grid(row=1, column=i)

cal = calendar.Calendar()

row = 2

for day, weekday in cal.itermonthdays2(current_year, current_month):

if day == 0:

continue

duty = duty_schedule.get((current_year, current_month, day), “”)

tk.Label(result_frame, text=f”{day} : {duty}”, width=12).grid(row=row, column=weekday)

if weekday == 6:

row += 1

root = tk.Tk()

root.title(“当直表アプリ”)

current_user = “”

# 上部

top_frame = tk.Frame(root)

top_frame.pack()

tk.Label(top_frame, text=”名前:”).pack(side=tk.LEFT)

name_entry = tk.Entry(top_frame)

name_entry.pack(side=tk.LEFT)

tk.Button(top_frame, text=”保存”, command=save_user).pack(side=tk.LEFT)

mark_mode = tk.StringVar(value=”NG”)

tk.Radiobutton(top_frame, text=”バツ(NG)”, variable=mark_mode, value=”NG”).pack(side=tk.LEFT)

tk.Radiobutton(top_frame, text=”マル(希望)”, variable=mark_mode, value=”OK”).pack(side=tk.LEFT)

tk.Button(top_frame, text=”←”, command=prev_month).pack(side=tk.LEFT)

tk.Button(top_frame, text=”→”, command=next_month).pack(side=tk.LEFT)

# ユーザーリスト

user_list = tk.Listbox(root, width=20)

user_list.pack()

user_list.bind(“<<ListboxSelect>>”, select_user)

# カレンダー

cal_frame = tk.Frame(root)

cal_frame.pack()

draw_calendar()

# リスト表示

lists_frame = tk.Frame(root)

lists_frame.pack()

ng_list = tk.Listbox(lists_frame, width=25)

ng_list.pack(side=tk.LEFT)

prefer_list = tk.Listbox(lists_frame, width=25)

prefer_list.pack(side=tk.LEFT)

# 割り当てボタン

btn_frame = tk.Frame(root)

btn_frame.pack()

tk.Button(btn_frame, text=”当直を割り当てる”, command=assign_duties).pack()

# 結果カレンダー

result_frame = tk.Frame(root)

result_frame.pack()

root.mainloop()

出来上がり

前回より幾分かスマートに仕上がりました

名前を例えばxで保存すると、上の四角に保存される

そして、希望日がダメな日をクリックする、それで再度保存

それを各々の名前で繰り返して、最後の当直票を割り当てる

希望日が被った場合はおそらく最初に指摘した方が優先か

当直回数や当直間隔は開けるように設定しています

調整さんでええやんっていうのは言わない約束です

完全に自己満足の世界です

病棟マップみたいなんも作ってみたいので、いつか作ってみます

以上参考になれば幸いです

コメント

タイトルとURLをコピーしました