RubyでBPMを算出する


#問題#
以下の仕様を満たすアプリケーションを作成しなさい。また、注意書きを必ず読んでから実装に入りなさい。実装の際、注意の下に記載されている雛形を使用しなさい。

仕様
実行すると [1] : 登録する, [2] : データを確認する, [3] : 終了する という選択肢を表示し、ユーザーに入力を求め、その入力に従い以下のような処理を行う
[1]の処理
名前、年齢、身長、体重を入力させる
身長と体重からBMIを割り出す 名前、年齢、身長、体重、BMIを保存する
[2]の処理
投稿された情報から番号と名前で一覧を表示し（例 [1]山田）、見たい個人の番号の入力を求める
入力された個人の名前、年齢、身長、体重、BMIを表示する
[3]の処理
アプリケーションを終了する
[3]でアプリケーションを終了するまで、投稿や閲覧ができるように繰り返す

注意
正しく動作している箇所までが採点対象となるため、必ず動作確認しながら進めること。エラーはインターネットで調べるなりして解決すること。エラーが出たままその先の実装をしないこと。

```雛形
def register_data
  # 人の登録をするための関数を完成させなさい
  # 身長と体重では少数を扱えるようにto_iではなくto_fを使用すること
end

def calculate_bmi
  # BMIを求めるための関数を完成させなさい
end

def show_data_list
  puts '見たい人の番号を選択してください'
  # 保存された全て人の名前と番号を表示するための関数を完成させなさい
  # 表示形式が番号; 名前となるようにしなさい
end

def show_data
  # 一覧から選択された人の全ての情報を表示する関数を完成させなさい
end

data = []
while true
  puts '選択してください'
  puts '[0]登録する'
  puts '[1]データを確認する'
  puts '[2]終了する'
  input = gets.to_i

  if input == 0
    # 人の情報をするための関数を呼びなさい
  elsif input == 1
    # 保存されたデータを一覧で表示するための関数を呼びなさい
  elsif input == 2
    # アプリケーションを終了させなさい
  else
    puts '無効な値です'
  end
end
```


##while文##
まずdataという箱を作ってユーザーが入力したものを保存できるようにする。
ユーザーへコマンド入力を促すためputsで指示を記載する。gets文の.to_iメソッドは文字列を数値オブジェクトへ変更する。これは読み込む時に0,1,2で判断しているため。
==このイコール二つで左右の式が同じことを示している。プログラミングでの=イコール一つでは右式を左式に代入するという意味をもつ。

```
data = []
while true
  puts "選択してください"
  puts "[0]登録する"
  puts "[1]データを確認する"
  puts "[2]終了する"
  input = gets.to_i


  if input == 0
    register_data(data)
  elsif input == 1
    show_data_list(data)
  elsif input == 2
    exit
  else
    puts '無効な値です'
  end
end
```
次にinputの数字によって動かす式を指示する。もし0ならばregister、それ以外で1ならばshow_data、それ以外で2の場合は、終了させる必要があるのでここでexitしておく。それ以外で関係ない文字が入力された場合は、putsで"無効な値"としてwhile文の先頭に戻す。
if文に記載しているregister_data(data)やshow_data(data)の()は[]のdataからデータ引き出すため必要。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/169530/e3d58edc-a843-09f9-2e07-22db5b6fdf57.png "1.png")
<参照:http://prog-8.com/slides?displayed-id=188&lesson=4>


##データ入力##
ユーザーが最初に[0]と入力してデータの入力を選択した場合の画面作成である。
defでregister_data(data)という関数を定義します。ユーザーから入力してもらったnameやage、tall、weightをpersonにhashとして入れていきます。それをさらにdata0 << pesonでdata0という箱に入れます。register_data(data0)の()部分に入り、while文にあった(data)で使えるようになります。ここで定義しておかないと計算式などで読み込めません。
気をつける点として体重と身長には.to_fメソッドを使用して小数点を扱えるようにしています。
※while文の()内と0が違うのはどこまでが同じでなければいけないか示すためです。ユーザーが入力したものと箱を分けるため、あえて解答にはないinput_という文を追加して作成しています。

```
def register_data(data0)
  puts "名前を入力して下さい"
  input_name = gets.chomp
  puts "年齢を入力して下さい"
  input_age = gets.chomp
  puts "身長を入力して下さい[m]"
  input_tall = gets.to_f
  puts "体重を入力して下さい"
  input_weight = gets.to_f
  person = { name: input_name, age: input_age, tall: input_tall, weight: input_weight, bmi: calculate_bmi(input_tall, input_weight), proper: calculate_proper(input_tall)}
    data0 << person
end
```

![1.png](https://qiita-image-store.s3.amazonaws.com/0/169530/62e25dc3-668a-8346-e83a-bbe8abbacf66.png "1.png")
<参照：http://prog-8.com/slides?displayed-id=190&lesson=4>

##BMIの定義##
前回と同様にdefでcalculate_bmi(tall0, weight0)を定義します。BMIは身長÷体重÷体重で求めれるため、この数式をdefにあてがいます。もちろんregister_dataより後にこの式は定義しなければ箱にデータが入ってない状態ではエラーが起きるので注意。
※tall0やweight0の0はwhile文とdef内の同じでないといけない場所を示すためです。

```
def calculate_bmi(tall0, weight0)
  bmi = weight0 / tall0 / tall0
end
```

##名前データの読込##
ユーザーが最初に[1]と入力してデータの読込を選択した場合の画面作成である。
data.each_with_index do ||でためていたデータから羅列して引き出すことができる。||内はhashとなっており、名前を入力したpersonと入れた順番で割り振られている番号を出している。人が見るときに0からだと分かり辛いのでindexに1足している。入力時には1引いている。最後に選択した情報を出せるようにshow_data(data, input)を呼び出している。()内のdata0はこの文章内は全て統一する必要がある。

```
def show_data_list(data0)
  puts '見たい人の番号を選択してください'
  data0.each_with_index do |person0, index0|
    puts "#{index0 + 1}: #{person0[:name]}"
  end
  input = gets.to_i - 1
   #person = data0[input]を加えてperson = data0[input0]を消してもいい。その際はshow_data(person)に直すこと。
  show_data(data0, input)
end
```

##データアウトプット##
ここではユーザーが入力したデータの呼出しと計算したBMIの呼出しをしている。personに入っているname,age,tallなどのバリューをinputの番号ごとに呼び出している。また箱に命名しているdataとinputと別名でもいいがif文とperson文のdata0とinput0は同じにする必要がある。
\tでtagボタンのようにスペースを開けて表示ができる。
注意点として""ダブルクォーテーションで文字列を表示できるがここでrubyの式を入れるには#{}で囲む必要がある。また、BMIの値が小数点で桁が多すぎるので{key[:value].round}で四捨五入できる。

```
def show_data(data0, input0)
  person = data0[input0]
  puts "名前: \t #{person[:name]} \t 様"
  puts "年齢: \t #{person[:age]} \t 歳"
  puts "身長: \t #{person[:tall]} \t m"
  puts "体重: \t #{person[:weight]} \t kg"
  puts "BMI: \t #{person[:bmi].round} \t (22が標準値)"
  puts "適正体重: #{person[:proper]} \t "
end
```

##回答##
```
def register_data(data0)
  puts "名前を入力して下さい"
  input_name = gets.chomp
  puts "年齢を入力して下さい"
  input_age = gets.chomp
  puts "身長を入力して下さい[m]"
  input_tall = gets.to_f
  puts "体重を入力して下さい"
  input_weight = gets.to_f
  person = { name: input_name, age: input_age, tall: input_tall, weight: input_weight, bmi: calculate_bmi(input_tall, input_weight), proper: calculate_proper(input_tall)}
    data0 << person
end

def calculate_bmi(tall0, weight0)
  bmi = weight0 / tall0 / tall0
end

def calculate_proper(tall0)
  proper = tall0 * tall0 * 22
end

def show_data_list(data0)
  puts '見たい人の番号を選択してください'
  data0.each_with_index do |person0, index0|
    puts "#{index0 + 1}: #{person0[:name]}"
  end
  input = gets.to_i - 1
  show_data(data0, input)
end

def show_data(data0, input0)
  person = data0[input0]
  puts "名前: \t #{person[:name]} \t 様"
  puts "年齢: \t #{person[:age]} \t 歳"
  puts "身長: \t #{person[:tall]} \t m"
  puts "体重: \t #{person[:weight]} \t kg"
  puts "BMI: \t #{person[:bmi].round} \t (22が標準値)"
  puts "適正体重: #{person[:proper]} \t "
end

data = []
while true
  puts '選択してください'
  puts '[0]登録する'
  puts '[1]データを確認する'
  puts '[2]終了する'
  input = gets.to_i

  if input == 0
    register_data(data)
  elsif input == 1
    show_data_list(data)
  elsif input == 2
    exit
  else
    puts '無効な値です'
  end
end
```


##補足##
![3.png](https://qiita-image-store.s3.amazonaws.com/0/169530/82a91e4d-97f4-2837-74cd-9445f218d5e8.png "3.png")