def 小児科医():

かけだし小児科医が仕事の合間にプログラミングを勉強するブログです。

必要カロリーを計算するアプリ③

前々から作っていたカロリー計算アプリがリニューアルしたので報告。

 

まず、そもそものカロリー計算に関して、

流石に活動係数1.7は盛りすぎ。

働いてて、下っ端といえど意外と座ってる時間長いし、通勤も徒歩の時間があるにしても少ない。というわけで1.5にした。

 

次に、最近youtubeでダイエット、筋トレ動画をよくみるのだが、

どうやらタンパク質は2g/kgくらいはとったほうがいいらしい。

というわけでタンパク質2g/kg、脂質は20%に変更した。

 

 

ここからはコードの話。

今まで一度選択を間違えるとアプリを閉じないとリセットできなかったのだが、

リセットボタンを作成した。

def reset():
combobox1.set("")
combobox2.set("")
combobox3.set("")
combobox4.set("")
combobox5.set("")
label_2c.forget()
label_2d.forget()
button_3b = Button(frame2, text='リセット', cursor='hand2', command=reset)
button_3b.pack()

 

それと、データベースに該当の食事がない場合、csvに直接データを出力できるようにした。

def ExportCsvFile():
# 入力値を変数に格納
name_data = name_info.get()
Cal_data = Cal_info.get()
TP_data = TP_info.get()
CA_data = CA_info.get()
FA_data = FA_info.get()
# 入力フォームの値がない場合は、CSV出力処理しない
if name_data == '' or TP_data == '' or CA_data == "" or FA_data == "" or Cal_data == "":
messagebox.showinfo("お知らせ", "データが入力されていません")
else:
df_enter = pd.DataFrame({'商品名':[name_data], 'カロリー':[Cal_data], '炭水化物':[CA_data], 'タンパク質':[TP_data], '脂質':[FA_data]})
df_enter.to_csv("食事表.csv", mode='a', header=False, index=False)
messagebox.showinfo("お知らせ", "CSV出力が完了しました")



#入力値を保持
name_info = tkinter.StringVar()
Cal_info = tkinter.StringVar()
TP_info = tkinter.StringVar()
CA_info = tkinter.StringVar()
FA_info = tkinter.StringVar()

# 種類ラベルフォーム
label_X1 = Label(frame3, text="商品名", font=('', 14))
label_X1.place(x=50, y=25)

# 種類入力テキストフォーム
txtbox_species = tkinter.Entry(frame3, width=10, textvariable=name_info)
txtbox_species.place(x=150, y=20)


# カロリーラベルフォーム
label_X2 = tkinter.Label(frame3, text="カロリー", font=('', 14))
label_X2.place(x=50, y=65)

# カロリー入力テキストフォーム
txtbox_Cal = tkinter.Entry(frame3, width=10, textvariable=Cal_info)
txtbox_Cal.place(x=150, y=60)

# CAラベルフォーム
label_X3 = tkinter.Label(frame3, text="炭水化物", font=('', 14))
label_X3.place(x=50, y=105)

# CA入力テキストフォーム
txtbox_CA = tkinter.Entry(frame3, width=10, textvariable=CA_info)
txtbox_CA.place(x=150, y=100)

# TPラベルフォーム
label_X4 = tkinter.Label(frame3, text="タンパク質", font=('', 14))
label_X4.place(x=50, y=145)

# TP入力テキストフォーム
txtbox_TP = tkinter.Entry(frame3, width=10, textvariable=TP_info)
txtbox_TP.place(x=150, y=140)

# FAラベルフォーム
label_X5 = tkinter.Label(frame3, text="脂質", font=('', 14))
label_X5.place(x=50, y=185)

# FA入力テキストフォーム
txtbox_FA = tkinter.Entry(frame3, width=10, textvariable=FA_info)
txtbox_FA.place(x=150, y=180)

# CSV出力ボタン関係の設定
btn_seldata = tkinter.Button(frame3, text="CSV出力", command=ExportCsvFile)
btn_seldata.place(x=150, y=220)

参考はこちらの方のサイト

anotools.com

いうわけでできたのがこんな感じ。

50kgの人はプロテイン5回飲めば2g/kg/day取れるみたいですねw

僕はもっと太ってるから結構きついな、、、

 

 

 

↓更新後のコード

import math
import tkinter

import pandas as pd
from tkinter import *
import tkinter.ttk as ttk
from tkinter import messagebox

#食事のデータを読み込み
df_info=pd.read_csv("食事表.csv", parse_dates=[0], index_col=0)

#デスクトップアプリ設定
root = Tk()
root.title('自己管理アプリ') # 画面タイトル設定
root.geometry('800x550') # 画面サイズ設定
root.resizable(False, False) # リサイズ設定

#フレームを設定
frame1 = Frame(root, width=500, height=250, borderwidth=2, relief='solid')
frame2 = Frame(root, width=500, height=300, borderwidth=2, relief='solid')
frame3 = Frame(root, width=300, height=550, borderwidth=2, relief='solid')


# フレームを配置(grid
frame1.grid(row=0, column=0)
frame2.grid(row=1, column=0)
frame3.grid(row=0, column=1, rowspan=2)

# フレームサイズを固定するときはFalse
frame1.propagate(False)
frame2.propagate(False)
frame3.propagate(False)


# label(フレーム左上)
label_1a = Label(frame1, text='体重を入力してください', font=('', 30))
label_1a.pack()#配置

data_dict = {} #必要栄養素を入れる空の辞書

#必要カロリーを計算する関数
def control():
BW =float(entry_2b.get())#フォームから得た体重を使用

# TDR=BMR*AF*SF
# BMRはハリスベネディクトで計算

#標準体重を計算し、実際の体重と比べて軽い方を採用
IBW = 1.66 ** 2 * 22
if BW > IBW:
cBW = IBW
else:
cBW = BW

BMR = 66.47 + (13.75 * cBW) + (5 * 166) - (6.76 * 27)
AF = 1.5
SF = 1
TDR = math.floor(BMR * AF * SF)
intake = math.floor(TDR - 500)

# タンパク質2g/kg
TP = BW * 2 * 4
gram_TP = math.floor(BW * 2)

# 脂質はintake20%
FA = intake * 0.2
gram_FA = math.floor(FA / 9)

# 炭水化物は残り
Ca = intake - TP - FA
gram_Ca = math.floor(Ca / 4)

#結果を表示
label_2b = Label(frame2, text="一日必要カロリーは" + str(TDR) + "です\n一日摂取カロリーは" + str(intake)
+ "です\n炭水化物は" + str(gram_Ca) + "gまで\nタンパク質は" + str(gram_TP)
+ "gまで\n脂質は" + str(gram_FA) + "gまで", font=('', 14))
label_2b.pack(side= tkinter.TOP)
button_2e.pack(side= tkinter.BOTTOM)
button_3b.pack()

# 前の画面を消す
label_1a.forget()
entry_2b.forget()
button_2b.forget()

#食事選択フォームを表示
combobox1.pack()
combobox2.pack()
combobox3.pack()
combobox4.pack()
combobox5.pack()
data_dict2 = {"カロリー":intake, "炭水化物":gram_Ca, "タンパク質":gram_TP, "脂質":gram_FA}
data_dict.update(data_dict2) #辞書に計算結果を追加

#合計カロリーと残りカロリーを計算する関数
label_2c = Label(frame2, text="", font=('', 14))
label_2d = Label(frame2, text="", font=('', 14))

def select_combo():
#それぞれのデータを取得
select_info1 = df_info.loc[combobox1.get()]
select_dict1 = select_info1.to_dict()
select_info2 = df_info.loc[combobox2.get()]
select_dict2 = select_info2.to_dict()
select_info3 = df_info.loc[combobox3.get()]
select_dict3 = select_info3.to_dict()
select_info4 = df_info.loc[combobox4.get()]
select_dict4 = select_info4.to_dict()
select_info5 = df_info.loc[combobox5.get()]
select_dict5 = select_info5.to_dict()

#合計栄養素を入れる空の辞書
sum_dict = {}
#各項目を足す
for value in (select_dict1.keys() | select_dict2.keys() | select_dict3.keys() | select_dict4.keys() | select_dict5.keys()):
num_1 = float(select_dict1.get(value) or 0)
num_2 = float(select_dict2.get(value) or 0)
num_3 = float(select_dict3.get(value) or 0)
num_4 = float(select_dict4.get(value) or 0)
num_5 = float(select_dict5.get(value) or 0)

num_total = num_1 + num_2 + num_3 + num_4 + num_5

sum_dict[value] = num_total

label_2c["text"] = "合計カロリーは" + str(sum_dict['カロリー']) + "\n炭水化物は" + str(sum_dict["炭水化物"]) + "g\nタンパク質は" + str(sum_dict["タンパク質"]) + "g\n脂質は" + str(sum_dict['脂質']) + "g"



#残り栄養素を入れる辞書
remain_dict = {}
#各項目で必要栄養素から合計栄養素を引く
for value2 in (data_dict.keys() | sum_dict.keys()):
num_3 = float(data_dict.get(value2) or 0)
num_4 = float(sum_dict.get(value2) or 0)

num_total2 = num_3 - num_4

remain_dict[value2] = num_total2
#結果を表示
label_2d["text"] = "残りカロリーは" + str(remain_dict['カロリー']) + "\n炭水化物は" + str(remain_dict["炭水化物"]) + "g\nタンパク質は" + str(remain_dict["タンパク質"]) + "g\n脂質は" + str(remain_dict['脂質']) + "g"

# 食事選択フォームの設定
combobox1 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox2 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox3 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox4 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox5 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox1.bind('<<ComboboxSelected>>', select_combo)
combobox2.bind('<<ComboboxSelected>>', select_combo)
combobox3.bind('<<ComboboxSelected>>', select_combo)
combobox4.bind('<<ComboboxSelected>>', select_combo)
combobox5.bind('<<ComboboxSelected>>', select_combo)

def reset():
combobox1.set("")
combobox2.set("")
combobox3.set("")
combobox4.set("")
combobox5.set("")
label_2c.forget()
label_2d.forget()

#食事選択フォームの設定
combobox1 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox2 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox3 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox4 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))
combobox5 = ttk.Combobox(frame1, height=5, width=30, values=list(df_info.index))

#体重記入フォームと決定ボタン
entry_2b = Entry(frame2, width=14)
button_2b = Button(frame2, text='決定', cursor='hand2', command=control)
button_3b = Button(frame2, text='リセット', cursor='hand2', command=reset)
button_2e = Button(frame1, text='計算', cursor='hand2', command=select_combo)
entry_2b.pack()
button_2b.pack()


#結果を表示
label_2c.pack()
label_2d.pack()

def ExportCsvFile():
# 入力値を変数に格納
name_data = name_info.get()
Cal_data = Cal_info.get()
TP_data = TP_info.get()
CA_data = CA_info.get()
FA_data = FA_info.get()
# 入力フォームの値がない場合は、CSV出力処理しない
if name_data == '' or TP_data == '' or CA_data == "" or FA_data == "" or Cal_data == "":
messagebox.showinfo("お知らせ", "データが入力されていません")
else:
df_enter = pd.DataFrame({'商品名':[name_data], 'カロリー':[Cal_data], '炭水化物':[CA_data], 'タンパク質':[TP_data], '脂質':[FA_data]})
df_enter.to_csv("食事表.csv", mode='a', header=False, index=False)
messagebox.showinfo("お知らせ", "CSV出力が完了しました")



#入力値を保持
name_info = tkinter.StringVar()
Cal_info = tkinter.StringVar()
TP_info = tkinter.StringVar()
CA_info = tkinter.StringVar()
FA_info = tkinter.StringVar()

# 種類ラベルフォーム
label_X1 = Label(frame3, text="商品名", font=('', 14))
label_X1.place(x=50, y=25)

# 種類入力テキストフォーム
txtbox_species = tkinter.Entry(frame3, width=10, textvariable=name_info)
txtbox_species.place(x=150, y=20)


# カロリーラベルフォーム
label_X2 = tkinter.Label(frame3, text="カロリー", font=('', 14))
label_X2.place(x=50, y=65)

# カロリー入力テキストフォーム
txtbox_Cal = tkinter.Entry(frame3, width=10, textvariable=Cal_info)
txtbox_Cal.place(x=150, y=60)

# CAラベルフォーム
label_X3 = tkinter.Label(frame3, text="炭水化物", font=('', 14))
label_X3.place(x=50, y=105)

# CA入力テキストフォーム
txtbox_CA = tkinter.Entry(frame3, width=10, textvariable=CA_info)
txtbox_CA.place(x=150, y=100)

# TPラベルフォーム
label_X4 = tkinter.Label(frame3, text="タンパク質", font=('', 14))
label_X4.place(x=50, y=145)

# TP入力テキストフォーム
txtbox_TP = tkinter.Entry(frame3, width=10, textvariable=TP_info)
txtbox_TP.place(x=150, y=140)

# FAラベルフォーム
label_X5 = tkinter.Label(frame3, text="脂質", font=('', 14))
label_X5.place(x=50, y=185)

# FA入力テキストフォーム
txtbox_FA = tkinter.Entry(frame3, width=10, textvariable=FA_info)
txtbox_FA.place(x=150, y=180)

# CSV出力ボタン関係の設定
btn_seldata = tkinter.Button(frame3, text="CSV出力", command=ExportCsvFile)
btn_seldata.place(x=150, y=220)

root.mainloop()