Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

challengeA/okamoto #314

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions challengeA/okamoto/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/spec/examples.txt
1 change: 1 addition & 0 deletions challengeA/okamoto/.rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
3 changes: 3 additions & 0 deletions challengeA/okamoto/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
source "https://rubygems.org"

gem 'rspec'
26 changes: 26 additions & 0 deletions challengeA/okamoto/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.4.4)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
rspec-core (3.10.1)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.10.0)
rspec-support (3.10.2)

PLATFORMS
x64-mingw32

DEPENDENCIES
rspec

BUNDLED WITH
2.2.20
30 changes: 30 additions & 0 deletions challengeA/okamoto/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# CHALLENGE A

## 概要

契約アンペア(A)と月の電力使用量(kWh)の入力に応じて、各プラン名と料金のシミュレーションを行うスクリプトです。

## シミュレーション実行方法

```sh
ruby main.rb
```

## データの編集

JSON形式で`/data`のディレクトリに格納しています。プラン追加や編集の際はJSONデータを修正することで対応できるように実装しています。

## テスト

```sh
bundle exec rspec
```

## 補足事項

- 合計電気料金は小数点以下切り捨て

## 参考文献

- オブジェクト指向設計実践ガイド
- [使えるRSpec入門](https://qiita.com/jnchito/items/42193d066bd61c740612)
166 changes: 166 additions & 0 deletions challengeA/okamoto/data/plans.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
[
{
"name": "従量電灯B",
"provider_name": "東京電力エナジーパートナー",
"basic_price": [
{
"ampere": 10,
"price": 286.0
},
{
"ampere": 15,
"price": 429.0
},
{
"ampere": 20,
"price": 572.0
},
{
"ampere": 30,
"price": 858.0
},
{
"ampere": 40,
"price": 1144.0
},
{
"ampere": 50,
"price": 1430.0
},
{
"ampere": 60,
"price": 1716.0
}
],
"pay_per_use_price": [
{
"price_per_kwh": 19.88,
"min_kwh": 0
},
{
"price_per_kwh": 26.48,
"min_kwh": 120
},
{
"price_per_kwh": 30.57,
"min_kwh": 300
}
]
},
{
"name": "おうちプラン",
"provider_name": "Looopでんき",
"basic_price": [
{
"ampere": 10,
"price": 0
},
{
"ampere": 15,
"price": 0
},
{
"ampere": 20,
"price": 0
},
{
"ampere": 30,
"price": 0
},
{
"ampere": 40,
"price": 0
},
{
"ampere": 50,
"price": 0
},
{
"ampere": 60,
"price": 0
}
],
"pay_per_use_price": [
{
"price_per_kwh": 26.40,
"min_kwh": 0
}
]
},
{
"name": "ずっとも電気1",
"provider_name": "東京ガス",
"basic_price": [
{
"ampere": 30,
"price": 858.0
},
{
"ampere": 40,
"price": 1144.0
},
{
"ampere": 50,
"price": 1430.0
},
{
"ampere": 60,
"price": 1716.0
}
],
"pay_per_use_price": [
{
"price_per_kwh": 23.67,
"min_kwh": 0
},
{
"price_per_kwh": 23.88,
"min_kwh": 140
},
{
"price_per_kwh": 26.41,
"min_kwh": 350
}
]
},
{
"name": "従量電灯Bたっぷりプラン",
"provider_name": "JXTGでんき",
"basic_price": [
{
"ampere": 30,
"price": 858.0
},
{
"ampere": 40,
"price": 1144.0
},
{
"ampere": 50,
"price": 1430.0
},
{
"ampere": 60,
"price": 1716.8
}
],
"pay_per_use_price": [
{
"price_per_kwh": 19.88,
"min_kwh": 0
},
{
"price_per_kwh": 26.48,
"min_kwh": 120
},
{
"price_per_kwh": 25.08,
"min_kwh": 300
},
{
"price_per_kwh": 26.15,
"min_kwh": 600
}
]
}
]
63 changes: 63 additions & 0 deletions challengeA/okamoto/lib/plan.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require 'json'
JSON_FILE_PATH = '../data/plans.json'

class Plan
attr_reader :contract_amp, :power_usage, :plans

def initialize(contract_amp, power_usage)
@plans = json_load
@contract_amp = contract_amp
@power_usage = power_usage
end

def show_plans
plans.map { |plan| available?(plan)? plan_with_price(plan) : nil }.compact
end

private

def json_load
json_file_path = File.expand_path(JSON_FILE_PATH, __dir__)
JSON.load(File.open(json_file_path))
end

def available?(plan)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この行以下のメソッドですが、planを引数に持つメソッドとなっています。
この辺りから、より良いクラス設計が考えられるのではないかと感じました。もしお時間があれば考えてみてください・・!

Copy link
Author

@mochikichi mochikichi Jun 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yuyasat
コメントありがとうございます。
おっしゃるとおり、すべてにplanを引数に持つということはplanのインスタンスを作る設計とした方が良さそうだと気付きました。

PlansクラスとPlanクラスへ分離してみましたので再度ご確認いただけると幸いです。

Plansクラス

  • dataを読み込み、Planへデータを渡す
  • Planインスタンスの配列を作る

Planクラス

  • Planインスタンスを作成
  • planの探索や必要な要素を抽出

plan['basic_price'].find { |price| price['ampere'] == contract_amp }
end

def plan_with_price(plan)
{
provider_name: plan['provider_name'],
plan_name: plan['name'],
price: sum_price(plan)
}
end

def sum_price(plan)
(basic_price(plan) + pay_per_use_price(plan)).floor
end

def basic_price(plan)
plan['basic_price'].find { |price| price['ampere'] == contract_amp }['price']
end

def pay_per_use_price(plan)
sum = 0
power_usage_before_stage = 0
sorted_pay_per_use_price_lists(plan).each do |price_list|
power_usage_current_stage = power_usage - price_list['min_kwh'] - power_usage_before_stage
#丸め誤差が生じるため小数点第四位を四捨五入とする
sum += (price_list['price_per_kwh'] * power_usage_current_stage).round(3)
power_usage_before_stage += power_usage_current_stage
end
sum
end

def sorted_pay_per_use_price_lists(plan)
pay_per_use_price_lists(plan).sort_by {|list| list['min_kwh']}.reverse
end

def pay_per_use_price_lists(plan)
plan['pay_per_use_price'].select { |price| price['min_kwh'] <= power_usage }
end
end
15 changes: 15 additions & 0 deletions challengeA/okamoto/lib/simulator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require './lib/plan'

class Simulator
attr_reader :contract_amp, :power_usage, :plans

def initialize(contract_amp, power_usage)
@contract_amp = contract_amp
@power_usage = power_usage
@plans = Plan.new(contract_amp, power_usage)
end

def simulate
plans.show_plans
end
end
35 changes: 35 additions & 0 deletions challengeA/okamoto/main.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require './lib/simulator'

AVAILABLE_AMP = [10, 15, 20, 30, 40, 50, 60]

puts '契約アンペア数を数字のみで入力してください。'
puts "#{AVAILABLE_AMP}の中から選択してください。"
contract_amp = gets.to_i

unless AVAILABLE_AMP.include?(contract_amp)
puts '契約アンペア数の入力が不正です。'
exit
end

puts '電力使用量(kWh)を整数のみで入力してください'
power_usage = gets.to_i

if power_usage.negative?
puts '電力使用量(kWh)は0以上を入力してください。'
exit
end

simulator = Simulator.new(contract_amp, power_usage)
plan_lists = simulator.simulate

return puts '条件に一致するプランはありません。' if plan_lists.empty?

puts 'ご入力いただいた条件での見積もり結果は以下の通りです。'
puts "契約アンペア:#{contract_amp}(A), 電力使用量:#{power_usage}(kwh)"
puts '================================================'
plan_lists.each do |plan|
puts "プロバイダー名:#{plan[:provider_name]}"
puts "プラン名:#{plan[:plan_name]}"
puts "月額料金:#{plan[:price]}円"
puts '================================================'
end
Loading