久しぶりに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で保存すると、上の四角に保存される
そして、希望日がダメな日をクリックする、それで再度保存
それを各々の名前で繰り返して、最後の当直票を割り当てる
希望日が被った場合はおそらく最初に指摘した方が優先か
当直回数や当直間隔は開けるように設定しています
調整さんでええやんっていうのは言わない約束です
完全に自己満足の世界です
病棟マップみたいなんも作ってみたいので、いつか作ってみます
以上参考になれば幸いです
コメント