【今更ながらChatGPT②】前回作ったRubyプログラムを対話を繰り返し改良してみた

- 『[【今更ながらChatGPT①】ラフなやり取りだけで元金均等返済を算出する簡易的なRubyプログラムが出来た](https://qiita.com/sam-ple/items/e236daf40919e1568546)』のプログラムを改良してみた。

## 改良01

- 元本返済額を修正できる様に改良。
- 年月日並びに曜日の表示。曜日の日本語化は一度できたが、営業略式表記になったので、また別途改良予定。
- csv吐き出し結果はおかしかったのでまた次回にて別途改良予定。
- 元本のみ千円単位で入力にしたら、結果表示等もおかしくなったのでまた別途改良予定。
- また、ソースを綺麗にする様依頼した。

<details><summary>【折り畳み】改良01のソースを綺麗にする前のプログラム</summary><div>

```ruby:sample01.rb　ソースを綺麗にする前
require 'bigdecimal'
require 'date'

def format_integer_with_commas(number)
  parts = number.to_i.to_s.reverse.scan(/.{1,3}/).join(',').reverse
  parts
end

def calculate_principal_payment(principal, num_payments)
  (principal / BigDecimal(num_payments)).ceil
end

def truncate_to_thousands(number)
  (number / BigDecimal('1000')).floor * BigDecimal('1000')
end

def display_initial_principal_payment(principal, num_payments)
  initial_principal_payment = truncate_to_thousands(calculate_principal_payment(principal, num_payments))
  puts "\n元本返済額: #{format_integer_with_commas(initial_principal_payment)} 円"
end

def equal_principal_amortization(principal, annual_interest_rate, num_payments, start_date, modified_principal_payment = nil)
  monthly_interest_rate = BigDecimal(annual_interest_rate.to_s) / BigDecimal(12.to_s) / BigDecimal(100.to_s)

  # 修正がある場合は修正後の元本返済額を使用し、ない場合は計算する
  monthly_principal_payment = modified_principal_payment || calculate_principal_payment(principal, num_payments)

  remaining_principal = principal
  total_interest_payment = BigDecimal(0)

  puts "ローンの元本: #{format_integer_with_commas(principal)} 円"
  puts "年間利率: #{annual_interest_rate.to_i}%"
  puts "返済回数: #{num_payments} 回"
  puts "返済開始日: #{start_date.strftime('%Y年%m月%d日 (%^a)')}"

  # 最初に元本返済額を表示（1,000未満を切り捨て）
  display_initial_principal_payment(principal, num_payments)

  puts "\n返済スケジュール:"

  current_date = start_date

  (1..num_payments).each do |payment_num|
    interest_payment = remaining_principal * monthly_interest_rate
    total_interest_payment += interest_payment

    # 最後の月には残りの元金を全額返済
    if payment_num == num_payments
      truncated_principal_payment = remaining_principal
    else
      # 元金返済額を1,000未満の場合、1,000円に切り捨て
      truncated_principal_payment = truncate_to_thousands(monthly_principal_payment)
    end

    remaining_principal -= truncated_principal_payment

    # 曜日を日本語表記にする（略式）
    japanese_day_of_week = case current_date.wday
                          when 0 then "日"
                          when 1 then "月"
                          when 2 then "火"
                          when 3 then "水"
                          when 4 then "木"
                          when 5 then "金"
                          when 6 then "土"
                          end

    puts "#{payment_num}, #{current_date.strftime('%Y年%m月%d日 (%^a)')}, 利息支払額: #{format_integer_with_commas(interest_payment)} 円, 元金返済額: #{format_integer_with_commas(truncated_principal_payment)} 円, 残りの元金: #{format_integer_with_commas(remaining_principal)} 円"

    # 翌月へ移動
    current_date = current_date.next_month
  end

  puts "\n総利息支払額: #{format_integer_with_commas(total_interest_payment)} 円"
end

# ユーザーからの入力を受け取る
print "ローンの元本を入力してください（円単位）: "
principal = BigDecimal(gets.chomp)

print "年間利率を入力してください（%）: "
annual_interest_rate = BigDecimal(gets.chomp)

print "返済回数を入力してください: "
num_payments = gets.chomp.to_i

print "返済開始日（年月日、YYYY-MM-DD形式）を入力してください: "
start_date = Date.parse(gets.chomp)

# 最初に元本返済額を表示（1,000未満を切り捨て）
display_initial_principal_payment(principal, num_payments)

puts "\n元本返済額を修正しますか？ (y/n)"
modify_principal_payment = gets.chomp.downcase

if modify_principal_payment == 'y'
  print "新しい元本返済額を入力してください（円単位）: "
  new_principal_payment = BigDecimal(gets.chomp)
  equal_principal_amortization(principal, annual_interest_rate, num_payments, start_date, new_principal_payment)
else
  equal_principal_amortization(principal, annual_interest_rate, num_payments, start_date, truncate_to_thousands(calculate_principal_payment(principal, num_payments)))
end
```
</div></details>

```ruby:sample01.rb　ソースを綺麗にする様依頼後
require 'bigdecimal'
require 'date'

# 整数をカンマ区切りにフォーマットする関数
def format_integer_with_commas(number)
  number.to_i.to_s.reverse.scan(/.{1,3}/).join(',').reverse
end

# 元本返済額を計算する関数
def calculate_principal_payment(principal, num_payments)
  (principal / BigDecimal(num_payments)).ceil
end

# 1,000の倍数に切り捨てる関数
def truncate_to_thousands(number)
  (number / BigDecimal('1000')).floor * BigDecimal('1000')
end

# 初期の元本返済額を表示する関数
def display_initial_principal_payment(principal, num_payments)
  initial_principal_payment = truncate_to_thousands(calculate_principal_payment(principal, num_payments))
  puts "\n元本返済額: #{format_integer_with_commas(initial_principal_payment)} 円"
end

# 均等元本返済の計算と表示を行う関数
def equal_principal_amortization(principal, annual_interest_rate, num_payments, start_date, modified_principal_payment = nil)
  monthly_interest_rate = BigDecimal(annual_interest_rate.to_s) / BigDecimal('12') / BigDecimal('100')

  # 修正がある場合は修正後の元本返済額を使用し、ない場合は計算する
  monthly_principal_payment = modified_principal_payment || calculate_principal_payment(principal, num_payments)

  remaining_principal = principal
  total_interest_payment = BigDecimal('0')

  puts "ローンの元本: #{format_integer_with_commas(principal)} 円"
  puts "年間利率: #{annual_interest_rate.to_i}%"
  puts "返済回数: #{num_payments} 回"
  puts "返済開始日: #{start_date.strftime('%Y年%m月%d日 (%^a)')}"

  # 最初に元本返済額を表示（1,000未満を切り捨て）
  display_initial_principal_payment(principal, num_payments)

  puts "\n返済スケジュール:"

  current_date = start_date

  (1..num_payments).each do |payment_num|
    interest_payment = remaining_principal * monthly_interest_rate
    total_interest_payment += interest_payment

    # 最後の月には残りの元金を全額返済
    if payment_num == num_payments
      truncated_principal_payment = remaining_principal
    else
      # 元金返済額を1,000未満の場合、1,000円に切り捨て
      truncated_principal_payment = truncate_to_thousands(monthly_principal_payment)
    end

    remaining_principal -= truncated_principal_payment

    # 曜日を日本語表記にする（略式）
    japanese_day_of_week = %w[日 月 火 水 木 金 土][current_date.wday]

    puts "#{payment_num}, #{current_date.strftime('%Y年%m月%d日 (%^a)')}, 利息支払額: #{format_integer_with_commas(interest_payment)} 円, 元金返済額: #{format_integer_with_commas(truncated_principal_payment)} 円, 残りの元金: #{format_integer_with_commas(remaining_principal)} 円"

    # 翌月へ移動
    current_date = current_date.next_month
  end

  puts "\n総利息支払額: #{format_integer_with_commas(total_interest_payment)} 円"
end

# ユーザーからの入力を受け取る
print "ローンの元本を入力してください（円単位）: "
principal = BigDecimal(gets.chomp)

print "年間利率を入力してください（%）: "
annual_interest_rate = BigDecimal(gets.chomp)

print "返済回数を入力してください: "
num_payments = gets.chomp.to_i

print "返済開始日（年月日、YYYY-MM-DD形式）を入力してください: "
start_date = Date.parse(gets.chomp)

# 最初に元本返済額を表示（1,000未満を切り捨て）
display_initial_principal_payment(principal, num_payments)

puts "\n元本返済額を修正しますか？ (y/n)"
modify_principal_payment = gets.chomp.downcase

if modify_principal_payment == 'y'
  print "新しい元本返済額を入力してください（円単位）: "
  new_principal_payment = BigDecimal(gets.chomp)
  equal_principal_amortization(principal, annual_interest_rate, num_payments, start_date, new_principal_payment)
else
  equal_principal_amortization(principal, annual_interest_rate, num_payments, start_date, truncate_to_thousands(calculate_principal_payment(principal, num_payments)))
end
```

### 出力結果

```txt:出力結果（元本返済額を修正しない場合）
ローンの元本を入力してください（円単位）: 1000000
年間利率を入力してください（%）: 5.0
返済回数を入力してください: 12
返済開始日（年月日、YYYY-MM-DD形式）を入力してください: 20230925

元本返済額: 83,000 円

元本返済額を修正しますか？ (y/n)
n
ローンの元本: 1,000,000 円
年間利率: 5%
返済回数: 12 回
返済開始日: 2023年09月25日 (MON)

元本返済額: 83,000 円

返済スケジュール:
1, 2023年09月25日 (MON), 利息支払額: 4,166 円, 元金返済額: 83,000 円, 残りの元金: 917,000 円
2, 2023年10月25日 (WED), 利息支払額: 3,820 円, 元金返済額: 83,000 円, 残りの元金: 834,000 円
3, 2023年11月25日 (SAT), 利息支払額: 3,475 円, 元金返済額: 83,000 円, 残りの元金: 751,000 円
4, 2023年12月25日 (MON), 利息支払額: 3,129 円, 元金返済額: 83,000 円, 残りの元金: 668,000 円
5, 2024年01月25日 (THU), 利息支払額: 2,783 円, 元金返済額: 83,000 円, 残りの元金: 585,000 円
6, 2024年02月25日 (SUN), 利息支払額: 2,437 円, 元金返済額: 83,000 円, 残りの元金: 502,000 円
7, 2024年03月25日 (MON), 利息支払額: 2,091 円, 元金返済額: 83,000 円, 残りの元金: 419,000 円
8, 2024年04月25日 (THU), 利息支払額: 1,745 円, 元金返済額: 83,000 円, 残りの元金: 336,000 円
9, 2024年05月25日 (SAT), 利息支払額: 1,400 円, 元金返済額: 83,000 円, 残りの元金: 253,000 円
10, 2024年06月25日 (TUE), 利息支払額: 1,054 円, 元金返済額: 83,000 円, 残りの元金: 
170,000 円
11, 2024年07月25日 (THU), 利息支払額: 708 円, 元金返済額: 83,000 円, 残りの元金: 87,000 円
12, 2024年08月25日 (SUN), 利息支払額: 362 円, 元金返済額: 87,000 円, 残りの元金: 0 
円

総利息支払額: 27,175 円
```

```txt:出力結果（元本返済額を修正した場合）
ローンの元本を入力してください（円単位）: 1000000
年間利率を入力してください（%）: 5.0
返済回数を入力してください: 12
返済開始日（年月日、YYYY-MM-DD形式）を入力してください: 20230925

元本返済額: 83,000 円

元本返済額を修正しますか？ (y/n)
y
新しい元本返済額を入力してください（円単位）: 85000
ローンの元本: 1,000,000 円
年間利率: 5%
返済回数: 12 回
返済開始日: 2023年09月25日 (MON)

元本返済額: 83,000 円

返済スケジュール:
1, 2023年09月25日 (MON), 利息支払額: 4,166 円, 元金返済額: 85,000 円, 残りの元金: 915,000 円
2, 2023年10月25日 (WED), 利息支払額: 3,812 円, 元金返済額: 85,000 円, 残りの元金: 830,000 円
3, 2023年11月25日 (SAT), 利息支払額: 3,458 円, 元金返済額: 85,000 円, 残りの元金: 745,000 円
4, 2023年12月25日 (MON), 利息支払額: 3,104 円, 元金返済額: 85,000 円, 残りの元金: 660,000 円
5, 2024年01月25日 (THU), 利息支払額: 2,750 円, 元金返済額: 85,000 円, 残りの元金: 575,000 円
6, 2024年02月25日 (SUN), 利息支払額: 2,395 円, 元金返済額: 85,000 円, 残りの元金: 490,000 円
7, 2024年03月25日 (MON), 利息支払額: 2,041 円, 元金返済額: 85,000 円, 残りの元金: 405,000 円
8, 2024年04月25日 (THU), 利息支払額: 1,687 円, 元金返済額: 85,000 円, 残りの元金: 320,000 円
9, 2024年05月25日 (SAT), 利息支払額: 1,333 円, 元金返済額: 85,000 円, 残りの元金: 235,000 円
10, 2024年06月25日 (TUE), 利息支払額: 979 円, 元金返済額: 85,000 円, 残りの元金: 150,000 円
11, 2024年07月25日 (THU), 利息支払額: 625 円, 元金返済額: 85,000 円, 残りの元金: 65,000 円
12, 2024年08月25日 (SUN), 利息支払額: 270 円, 元金返済額: 65,000 円, 残りの元金: 0 
円

総利息支払額: 26,625 円
```