asarashi
@asarashi (あざらし)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Rubyオブジェクト指向で料金表と料金シミュレーターを作りたい

解決したいこと

Rubyで適切なクラスを作成し、料金表をオブジェクト指向で作りたい。
作成した表から、時間帯(9~21)、月(1~12)、区分ごとの人数を入力して合計金額をシミュレートしたい。

Rubyで料金表を作成しようと思っています。
オブジェクト指向、エンジニア初心者なので、どのようなクラスが必要になるか
参考になるページや自分なら何クラスを作成するか教えてください。

作りたい料金表

区分 通常料金 夏季(7,8月) 夕方(17時以降)料金 団体利用料金
大人 830 1120 620 730
シルバー(65歳以上) 620 710 520 520
学生 410 500 310 310
3歳以上 310 400 0 200
2歳以下 0 0 0 0
子供*同伴の大人 620 830
シルバー同伴の大人 620 830
  • 夕方になれば、時期に関係なく夕方料金が適用される
  • *子供は3歳以上と学生区分
  • 子供またはシルバーと来た大人は全員同伴料金になる

実装イメージ

スクリーンショット 2022-05-29 230806.png
スクリーンショット 2022-05-29 230902.png
スクリーンショット 2022-05-29 230958.png
スクリーンショット 2022-05-29 231046.png

自分で試したこと

オブジェクト指向がまだ全然わかっていないのでこれクラスっぽそう?てやつを雰囲気で書いてみました

print "時間の入力:"
time = gets.to_i
print "利用月の入力:"
month = gets.to_i
# 計算クラス
class Culcs 
    # property
    def initialize(time,month)
        @time,@month = time,month
    end
    # method
    # 17時以降かどうか
    def checkTime(time)
        if time >= 17
            #夕方料金をセット
        end
    end
    # 夏季料金かどうか
    def checkMonth(month)
        if month == (7..8)
            #夏季料金をセット
        end

    # 20人以上かどうか
    def checkNum(num)
        if num >= 20
          #団体料金をセット
        end
    def sum
        sum = price1 + price2 + price3 + price4 + price5
    end
end
# ヒトクラス
class Humman
    # property
    # method
end
# 大人クラス
class Adults < Human
   def initialize 
    price1 = adult.price * num 
end
# シルバークラス
class Silvers < Human
    price2 = silver.price * num
end
# 学生クラス
class Students < Human
    price3 = student.price * num
end
# 子供クラス
class Children < Human
    price4 = child.price * num
end
# 幼児クラス
class Infants < Human
    price5 = infant.price * num
end
# 料金クラス
class BasicPrice
    # 通常料金
end
# 夏季料金クラス
class SummerPrice < BasicPrice
    # 夏季料金
end
# 団体料金クラス
class GroupPrice < BasicPrice
    # 団体料金
end
puts "お支払合計は#{sum}円です"
0

4Answer

このぐらいならクラス使わないほうが扱いやすいような

require "pry"

print "時間の入力:"
hour = gets.to_i
puts "#{hour}時"

print "利用月の入力:"
month = gets.to_i
puts "#{month}月"

SUMMER_MOMTHS = [7 ,8]
LATE_HOUR = 17
GROUP_PRICE_NUMBER_OF_PEOPLE = 5

tickets = {
  A: {
    name: "Adult",
    price: 830,
    summer_price: 1120,
    late_price: 620,
    group_price: 730,
    with_silver_price: 620,
    with_silver_summer_price: 830,
    with_child_price: 620,
    with_child_summer_price: 830,
  },
  B: {
    name: "Silver",
    price: 620,
    summer_price: 710,
    late_price: 520,
    group_price: 520
  },
  C: {
    name: "Student",
    price: 410,
    summer_price: 500,
    late_price: 310,
    group_price: 310
  },
  D: {
    name: "Child",
    price: 310,
    summer_price: 400,
    late_price: 0,
    group_price: 200
  },
  E: {
    name: "Baby",
    price: 0,
    summer_price: 0,
    late_price: 0,
    group_price: 0
  },
}

persons = []

loop do
  puts "利用者の入力: A.大人 B.シルバー(65歳以上)C.学生 D.3歳以上 E.2歳以下"

  person = gets.chomp
  persons.push person

  amount_price = 0

  persons.each do |person|
    price_lineups = []

    price_lineups.push tickets[person.to_sym][:price]
    price_lineups.push tickets[person.to_sym][:summer_price] if SUMMER_MOMTHS.include? month
    price_lineups.push tickets[person.to_sym][:late_price] if hour >= LATE_HOUR
    price_lineups.push tickets[person.to_sym][:group_price] if persons.size >= GROUP_PRICE_NUMBER_OF_PEOPLE

    add_price = price_lineups.min
    amount_price += add_price

    puts "+#{add_price}"
    puts amount_price
  end
end

2Like

料金表 クラス設計でググってみました。
これで練習してみるのはいかがでしょう?

1Like

Comments

  1. @asarashi

    Questioner

    わかりました!ありがとうございます
  • 学生とは年齢で制限なのか?学生証があれば100歳でも学生なのか?
  • 団体利用料金は何人からなのか?
1Like

Comments

  1. @asarashi

    Questioner

    抜けがありました
    1.考えてませんでした。学生という証明が出来れば学生ということにします(留年して100歳でも学生)。
    2. 20人から団体価格の予定です

    ご指摘ありがとうございます!
  2. もう書きませんが、学生であれば年齢が関係ないということなので、agesの配列に:studentを代わりに入れて内部でどうにか分岐するかですかね?
    小中学生は学生証がなくても義務教育なので年齢的に判別はできそうですが。
  3. 学生であれば年齢が関係ないという事は、100歳の学生証を持つ人が大人区分の人と来ると、この大人は「子供*同伴の大人」価格が適用されてしまうのか?

さらっとしか検証していませんが、こういう感じとか?

# こういう感じで実行します
EntranceFee.calculate(time_at: Time.now, ages: [40, 12]) # => 930 (夕方料金、子供同伴大人)
require "singleton"

class EntranceFee
  class AgeRange
    include Singleton

    def babies
      0..2
    end

    def infants
      # 小学1年生とは?
      babies.last.succ..6
    end

    def students
      # 高校3年生卒業時何歳?留年したら?学生証があれば100歳でも学生?
      infants.last.succ..18
    end

    def adults
      students.last.succ..64
    end

    def elders
      adults.last.succ..Float::INFINITY
    end
  end

  class << self
    # 時間帯(9~21)、月(1~12)、区分ごとの人数を入力して合計金額をシミュレートしたい。
    def calculate(time_at:, ages: [])
      with_children = children_in_the_group?(ages)
      with_elders = elders_in_the_group?(ages)
      group_rate_applied = group_rate?(ages)

      ages.sum do |age|
        new(
          time_at: time_at,
          age: age,
          with_children: with_children,
          with_elders: with_elders,
          group_rate_applied: group_rate_applied,
        ).price
      end
    end

    private

    def children_in_the_group?(ages)
      ages.any? do |age|
        (AgeRange.instance.infants.first..AgeRange.instance.students.last).cover? age
      end
    end

    def elders_in_the_group?(ages)
      ages.any? { |age| AgeRange.instance.elders.first <= age }
    end

    def group_rate?(ages)
      # 団体は20人からとして...
      20 <= ages.size
    end
  end

  def initialize(
    time_at:,
    age:,
    with_children: false,
    with_elders: false,
    group_rate_applied: false
  )
    @time_at = time_at
    @age = age
    @with_children = with_children
    @with_elders = with_elders
    @group_rate_applied = group_rate_applied
  end

  def price
    return evening_price if evening?
    return group_rate_price if group_rate_applied

    summer_season? ? summer_season_price : regular_price
  end

  private

  attr_reader :time_at, :age, :with_children, :with_elders, :group_rate_applied

  def regular_price
    price_by_age(
      babies: 0,
      infants: 310,
      students: 410,
      adults: ([with_children, with_elders].any? ? 620 : 830),
      elders: 620,
    )
  end

  def summer_season_price
    price_by_age(
      babies: 0,
      infants: 400,
      students: 500,
      adults: ([with_children, with_elders].any? ? 830 : 1120),
      elders: 710,
    )
  end

  def evening_price
    price_by_age(babies: 0, infants: 0, students: 310, adults: 620, elders: 520)
  end

  def group_rate_price
    price_by_age(babies: 0, infants: 200, students: 310, adults: 730, elders: 520)
  end

  def price_by_age(babies:, infants:, students:, adults:, elders:)
    case age
    when AgeRange.instance.babies
      babies
    when AgeRange.instance.infants
      infants
    when AgeRange.instance.students
      students
    when AgeRange.instance.elders
      elders
    else
      adults
    end
  end

  def summer_season?
    [7, 8].include? time_at.month
  end

  def evening?
    17 <= time_at.hour
  end
end
1Like

Your answer might help someone💌