workout_menu 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +135 -0
- data/Rakefile +12 -0
- data/exe/workout_menu +6 -0
- data/lib/workout_menu/catalog.rb +45 -0
- data/lib/workout_menu/cli.rb +91 -0
- data/lib/workout_menu/exercise.rb +11 -0
- data/lib/workout_menu/exercises.yml +65 -0
- data/lib/workout_menu/menu.rb +25 -0
- data/lib/workout_menu/version.rb +5 -0
- data/lib/workout_menu.rb +12 -0
- data/sig/workout_menu.rbs +4 -0
- metadata +58 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: affc512b58e73f670c740957dfa8def3cc53e6e462ec7aa8a32fec11c782130f
|
|
4
|
+
data.tar.gz: 4772495becc710e6ca3508bbfa670f2631cf592f4b17d5468bd97aa1885801f2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 2f8b3c18ec96356a132d73736eb50c193ed78678867f541698ed8ec74532089db352e53c65543e564a04adba5b7285653c7630e42d67fa6bf5d1f1563fc9a02e
|
|
7
|
+
data.tar.gz: 4ac9922e776437792a48d72ced012eb10380db1b8387c232d74f1d8650bc69d7f4911f55d59e67abe54a5f6a49ba3fd67a9546ae1c22da349d44335520ddd255
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 T-REX1970
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# WorkoutMenu
|
|
2
|
+
|
|
3
|
+
「今日、何を鍛えよう?」と迷う時間をなくす、筋トレメニュー提案コマンドです。
|
|
4
|
+
鍛えたい部位と場所を指定すると、ランダムに種目を選んで、セット数と回数つきで表示します。
|
|
5
|
+
|
|
6
|
+
```console
|
|
7
|
+
$ workout_menu --part chest --place home
|
|
8
|
+
今日のメニュー: 胸 / 自宅
|
|
9
|
+
1. ワイドプッシュアップ 3セット × 12回
|
|
10
|
+
2. 腕立て伏せ 3セット × 15回
|
|
11
|
+
3. デクラインプッシュアップ 3セット × 12回
|
|
12
|
+
4. インクラインプッシュアップ 3セット × 15回
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
gem install workout_menu
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Bundler を使う場合は、Gemfile に次の行を追加します。
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
gem "workout_menu"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Ruby 3.2 以上が必要です。
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```console
|
|
32
|
+
$ workout_menu --part PART [options]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
| オプション | 説明 | 既定値 |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `-p`, `--part PART` | 鍛える部位(**必須**) | - |
|
|
38
|
+
| `-l`, `--place PLACE` | 場所 | `home` |
|
|
39
|
+
| `-n`, `--count N` | 種目数 | `4` |
|
|
40
|
+
| `-s`, `--seed N` | 乱数のシード。同じ値なら同じメニューになる | ランダム |
|
|
41
|
+
| `-v`, `--version` | バージョンを表示 | - |
|
|
42
|
+
| `-h`, `--help` | ヘルプを表示 | - |
|
|
43
|
+
|
|
44
|
+
### 部位 (`--part`)
|
|
45
|
+
|
|
46
|
+
| 値 | 部位 |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `chest` | 胸 |
|
|
49
|
+
| `back` | 背中 |
|
|
50
|
+
| `legs` | 脚 |
|
|
51
|
+
| `shoulders` | 肩 |
|
|
52
|
+
| `arms` | 腕 |
|
|
53
|
+
| `abs` | 腹筋 |
|
|
54
|
+
|
|
55
|
+
### 場所 (`--place`)
|
|
56
|
+
|
|
57
|
+
| 値 | 内容 |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `home` | 自宅。器具を使わない種目だけを提案する |
|
|
60
|
+
| `gym` | ジム。マシンやバーベルを使う種目も提案する |
|
|
61
|
+
|
|
62
|
+
### 例
|
|
63
|
+
|
|
64
|
+
```console
|
|
65
|
+
# ジムで脚を鍛える(種目数は 5)
|
|
66
|
+
$ workout_menu -p legs -l gym -n 5
|
|
67
|
+
|
|
68
|
+
# 同じシードなら、いつも同じメニューになる
|
|
69
|
+
$ workout_menu -p back -s 42
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
時間で行う種目(プランクなど)は、回数ではなく秒数で表示されます。
|
|
73
|
+
|
|
74
|
+
```console
|
|
75
|
+
$ workout_menu -p abs -l gym -n 3 -s 2
|
|
76
|
+
今日のメニュー: 腹筋 / ジム
|
|
77
|
+
1. ケーブルクランチ 3セット × 15回
|
|
78
|
+
2. ハンギングレッグレイズ 3セット × 10回
|
|
79
|
+
3. マウンテンクライマー 3セット × 30秒
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### エラー
|
|
83
|
+
|
|
84
|
+
指定が正しくないときは、メッセージを標準エラー出力に出して、終了ステータス 1 で終了します。
|
|
85
|
+
|
|
86
|
+
```console
|
|
87
|
+
$ workout_menu
|
|
88
|
+
workout_menu: --part is required (chest, back, legs, shoulders, arms, abs)
|
|
89
|
+
Try 'workout_menu --help' for usage.
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Ruby から使う
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
require "workout_menu"
|
|
96
|
+
|
|
97
|
+
menu = WorkoutMenu::Menu.new
|
|
98
|
+
menu.suggest(part: :chest, place: :home, count: 3).each do |exercise|
|
|
99
|
+
puts "#{exercise.name} #{exercise.volume}"
|
|
100
|
+
end
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## 種目を追加・変更するには
|
|
104
|
+
|
|
105
|
+
種目は [`lib/workout_menu/exercises.yml`](lib/workout_menu/exercises.yml) に定義されています。
|
|
106
|
+
次の形式で追記すると、提案の対象になります。
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
- { name: 腕立て伏せ, part: chest, places: [home, gym], sets: 3, reps: 15 }
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
時間で行う種目は、`unit: 秒` を加えます。
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
リポジトリを clone したあと、`bin/setup` で依存をインストールします。
|
|
117
|
+
`bundle exec rake` で、テストと RuboCop を実行します。`bin/console` で、対話的に試せます。
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
bin/setup
|
|
121
|
+
bundle exec rake
|
|
122
|
+
bundle exec exe/workout_menu --part chest
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
このgemをローカルにインストールするには `bundle exec rake install` を実行します。
|
|
126
|
+
新しいバージョンをリリースするには、`lib/workout_menu/version.rb` のバージョンを更新して、`bundle exec rake release` を実行します。
|
|
127
|
+
gitタグの作成、コミットとタグの push、`.gem` ファイルの [rubygems.org](https://rubygems.org) への公開が行われます。
|
|
128
|
+
|
|
129
|
+
## Contributing
|
|
130
|
+
|
|
131
|
+
バグ報告やプルリクエストは、GitHub の https://github.com/T-REX1996/workout_menu で歓迎します。
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
このgemは、[MIT License](https://opensource.org/licenses/MIT) の条件のもとでオープンソースとして公開されています。
|
data/Rakefile
ADDED
data/exe/workout_menu
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "yaml"
|
|
4
|
+
|
|
5
|
+
module WorkoutMenu
|
|
6
|
+
# 種目データの読み込みと絞り込みを担当する。
|
|
7
|
+
class Catalog
|
|
8
|
+
PARTS = {
|
|
9
|
+
chest: "胸",
|
|
10
|
+
back: "背中",
|
|
11
|
+
legs: "脚",
|
|
12
|
+
shoulders: "肩",
|
|
13
|
+
arms: "腕",
|
|
14
|
+
abs: "腹筋"
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
PLACES = {
|
|
18
|
+
home: "自宅",
|
|
19
|
+
gym: "ジム"
|
|
20
|
+
}.freeze
|
|
21
|
+
|
|
22
|
+
DEFAULT_PATH = File.expand_path("exercises.yml", __dir__)
|
|
23
|
+
DEFAULT_UNIT = "回"
|
|
24
|
+
|
|
25
|
+
def self.load(path = DEFAULT_PATH)
|
|
26
|
+
data = YAML.safe_load_file(path, symbolize_names: true)
|
|
27
|
+
new(data.fetch(:exercises).map { |attrs| build_exercise(attrs) })
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.build_exercise(attrs)
|
|
31
|
+
Exercise.new(unit: DEFAULT_UNIT, **attrs, part: attrs[:part].to_sym, places: attrs[:places].map(&:to_sym))
|
|
32
|
+
end
|
|
33
|
+
private_class_method :build_exercise
|
|
34
|
+
|
|
35
|
+
def initialize(exercises)
|
|
36
|
+
@exercises = exercises.freeze
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
attr_reader :exercises
|
|
40
|
+
|
|
41
|
+
def select(part:, place:)
|
|
42
|
+
exercises.select { |e| e.part == part && e.places.include?(place) }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "optparse"
|
|
4
|
+
|
|
5
|
+
module WorkoutMenu
|
|
6
|
+
# コマンドライン入力を解釈して、メニューを出力する。
|
|
7
|
+
class CLI
|
|
8
|
+
DEFAULT_PLACE = "home"
|
|
9
|
+
DEFAULT_COUNT = 4
|
|
10
|
+
|
|
11
|
+
def self.run(argv, out: $stdout, err: $stderr)
|
|
12
|
+
new(out: out, err: err).run(argv)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(out:, err:)
|
|
16
|
+
@out = out
|
|
17
|
+
@err = err
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# 終了ステータスを返す(成功: 0、失敗: 1)。
|
|
21
|
+
def run(argv)
|
|
22
|
+
options = { place: DEFAULT_PLACE, count: DEFAULT_COUNT }
|
|
23
|
+
parser = build_parser(options)
|
|
24
|
+
parser.parse(argv)
|
|
25
|
+
dispatch(options, parser)
|
|
26
|
+
0
|
|
27
|
+
rescue OptionParser::ParseError, Error => e
|
|
28
|
+
@err.puts "workout_menu: #{e.message}"
|
|
29
|
+
@err.puts "Try 'workout_menu --help' for usage."
|
|
30
|
+
1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def dispatch(options, parser)
|
|
36
|
+
if options[:help]
|
|
37
|
+
@out.puts parser.help
|
|
38
|
+
elsif options[:version]
|
|
39
|
+
@out.puts VERSION
|
|
40
|
+
else
|
|
41
|
+
print_menu(options)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def build_parser(options)
|
|
46
|
+
OptionParser.new do |parser|
|
|
47
|
+
parser.banner = "Usage: workout_menu --part PART [options]"
|
|
48
|
+
define_target_options(parser, options)
|
|
49
|
+
define_amount_options(parser, options)
|
|
50
|
+
define_info_options(parser, options)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def define_target_options(parser, options)
|
|
55
|
+
parts = Catalog::PARTS.keys
|
|
56
|
+
places = Catalog::PLACES.keys
|
|
57
|
+
parser.on("-p", "--part PART", parts.map(&:to_s), "鍛える部位 (#{parts.join(", ")})") { |v| options[:part] = v }
|
|
58
|
+
parser.on("-l", "--place PLACE", places.map(&:to_s), "場所 (#{places.join(", ")}) 既定: #{DEFAULT_PLACE}") do |v|
|
|
59
|
+
options[:place] = v
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def define_amount_options(parser, options)
|
|
64
|
+
parser.on("-n", "--count N", Integer, "種目数 既定: #{DEFAULT_COUNT}") { |v| options[:count] = v }
|
|
65
|
+
parser.on("-s", "--seed N", Integer, "乱数のシード(同じ値なら同じメニュー)") { |v| options[:seed] = v }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def define_info_options(parser, options)
|
|
69
|
+
parser.on("-v", "--version", "バージョンを表示") { options[:version] = true }
|
|
70
|
+
parser.on("-h", "--help", "ヘルプを表示") { options[:help] = true }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def print_menu(options)
|
|
74
|
+
raise Error, "--part is required (#{Catalog::PARTS.keys.join(", ")})" unless options[:part]
|
|
75
|
+
|
|
76
|
+
part = options[:part].to_sym
|
|
77
|
+
place = options[:place].to_sym
|
|
78
|
+
menu = Menu.new(random: random_for(options[:seed]))
|
|
79
|
+
print_exercises(part, place, menu.suggest(part: part, place: place, count: options[:count]))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def random_for(seed)
|
|
83
|
+
seed ? Random.new(seed) : Random.new
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def print_exercises(part, place, exercises)
|
|
87
|
+
@out.puts "今日のメニュー: #{Catalog::PARTS[part]} / #{Catalog::PLACES[place]}"
|
|
88
|
+
exercises.each.with_index(1) { |e, i| @out.puts "#{i}. #{e.name} #{e.volume}" }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# 種目データ
|
|
2
|
+
# part: chest / back / legs / shoulders / arms / abs
|
|
3
|
+
# places: home(自宅・器具なし) / gym(ジム)
|
|
4
|
+
# unit: 省略すると「回」。時間で行う種目は「秒」を指定する
|
|
5
|
+
exercises:
|
|
6
|
+
# --- 胸 ---
|
|
7
|
+
- { name: 腕立て伏せ, part: chest, places: [home, gym], sets: 3, reps: 15 }
|
|
8
|
+
- { name: ワイドプッシュアップ, part: chest, places: [home, gym], sets: 3, reps: 12 }
|
|
9
|
+
- { name: デクラインプッシュアップ, part: chest, places: [home], sets: 3, reps: 12 }
|
|
10
|
+
- { name: インクラインプッシュアップ, part: chest, places: [home], sets: 3, reps: 15 }
|
|
11
|
+
- { name: ベンチプレス, part: chest, places: [gym], sets: 3, reps: 8 }
|
|
12
|
+
- { name: インクラインダンベルプレス, part: chest, places: [gym], sets: 3, reps: 10 }
|
|
13
|
+
- { name: ダンベルフライ, part: chest, places: [gym], sets: 3, reps: 12 }
|
|
14
|
+
- { name: チェストプレス, part: chest, places: [gym], sets: 3, reps: 10 }
|
|
15
|
+
|
|
16
|
+
# --- 背中 ---
|
|
17
|
+
- { name: バックエクステンション, part: back, places: [home, gym], sets: 3, reps: 15 }
|
|
18
|
+
- { name: スーパーマン, part: back, places: [home], sets: 3, reps: 15 }
|
|
19
|
+
- { name: リバーススノーエンジェル, part: back, places: [home], sets: 3, reps: 12 }
|
|
20
|
+
- { name: 懸垂, part: back, places: [gym], sets: 3, reps: 8 }
|
|
21
|
+
- { name: ラットプルダウン, part: back, places: [gym], sets: 3, reps: 10 }
|
|
22
|
+
- { name: ベントオーバーロウ, part: back, places: [gym], sets: 3, reps: 10 }
|
|
23
|
+
- { name: シーテッドロウ, part: back, places: [gym], sets: 3, reps: 10 }
|
|
24
|
+
- { name: デッドリフト, part: back, places: [gym], sets: 3, reps: 5 }
|
|
25
|
+
|
|
26
|
+
# --- 脚 ---
|
|
27
|
+
- { name: スクワット, part: legs, places: [home, gym], sets: 3, reps: 15 }
|
|
28
|
+
- { name: ブルガリアンスクワット, part: legs, places: [home, gym], sets: 3, reps: 10 }
|
|
29
|
+
- { name: ランジ, part: legs, places: [home, gym], sets: 3, reps: 12 }
|
|
30
|
+
- { name: カーフレイズ, part: legs, places: [home, gym], sets: 3, reps: 20 }
|
|
31
|
+
- { name: ヒップリフト, part: legs, places: [home, gym], sets: 3, reps: 15 }
|
|
32
|
+
- { name: ワイドスクワット, part: legs, places: [home], sets: 3, reps: 15 }
|
|
33
|
+
- { name: バーベルスクワット, part: legs, places: [gym], sets: 3, reps: 8 }
|
|
34
|
+
- { name: レッグプレス, part: legs, places: [gym], sets: 3, reps: 12 }
|
|
35
|
+
- { name: レッグカール, part: legs, places: [gym], sets: 3, reps: 12 }
|
|
36
|
+
|
|
37
|
+
# --- 肩 ---
|
|
38
|
+
- { name: パイクプッシュアップ, part: shoulders, places: [home], sets: 3, reps: 10 }
|
|
39
|
+
- { name: ショルダータップ, part: shoulders, places: [home], sets: 3, reps: 20 }
|
|
40
|
+
- { name: プランクアップダウン, part: shoulders, places: [home, gym], sets: 3, reps: 12 }
|
|
41
|
+
- { name: アームサークル, part: shoulders, places: [home], sets: 3, reps: 20 }
|
|
42
|
+
- { name: ショルダープレス, part: shoulders, places: [gym], sets: 3, reps: 10 }
|
|
43
|
+
- { name: サイドレイズ, part: shoulders, places: [gym], sets: 3, reps: 12 }
|
|
44
|
+
- { name: フロントレイズ, part: shoulders, places: [gym], sets: 3, reps: 12 }
|
|
45
|
+
- { name: リアレイズ, part: shoulders, places: [gym], sets: 3, reps: 12 }
|
|
46
|
+
|
|
47
|
+
# --- 腕 ---
|
|
48
|
+
- { name: ナロープッシュアップ, part: arms, places: [home, gym], sets: 3, reps: 12 }
|
|
49
|
+
- { name: ダイヤモンドプッシュアップ, part: arms, places: [home, gym], sets: 3, reps: 10 }
|
|
50
|
+
- { name: ベンチディップス, part: arms, places: [home, gym], sets: 3, reps: 12 }
|
|
51
|
+
- { name: アームカール, part: arms, places: [gym], sets: 3, reps: 12 }
|
|
52
|
+
- { name: ハンマーカール, part: arms, places: [gym], sets: 3, reps: 12 }
|
|
53
|
+
- { name: トライセプスエクステンション, part: arms, places: [gym], sets: 3, reps: 12 }
|
|
54
|
+
- { name: ケーブルプレスダウン, part: arms, places: [gym], sets: 3, reps: 12 }
|
|
55
|
+
|
|
56
|
+
# --- 腹筋 ---
|
|
57
|
+
- { name: クランチ, part: abs, places: [home, gym], sets: 3, reps: 20 }
|
|
58
|
+
- { name: レッグレイズ, part: abs, places: [home, gym], sets: 3, reps: 15 }
|
|
59
|
+
- { name: バイシクルクランチ, part: abs, places: [home, gym], sets: 3, reps: 20 }
|
|
60
|
+
- { name: プランク, part: abs, places: [home, gym], sets: 3, reps: 45, unit: 秒 }
|
|
61
|
+
- { name: サイドプランク, part: abs, places: [home, gym], sets: 3, reps: 30, unit: 秒 }
|
|
62
|
+
- { name: マウンテンクライマー, part: abs, places: [home, gym], sets: 3, reps: 30, unit: 秒 }
|
|
63
|
+
- { name: アブローラー, part: abs, places: [gym], sets: 3, reps: 10 }
|
|
64
|
+
- { name: ハンギングレッグレイズ, part: abs, places: [gym], sets: 3, reps: 10 }
|
|
65
|
+
- { name: ケーブルクランチ, part: abs, places: [gym], sets: 3, reps: 15 }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WorkoutMenu
|
|
4
|
+
# 部位と場所からトレーニングメニューを提案する。
|
|
5
|
+
class Menu
|
|
6
|
+
def initialize(catalog: Catalog.load, random: Random.new)
|
|
7
|
+
@catalog = catalog
|
|
8
|
+
@random = random
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# 条件に合う種目を、重複なしでランダムに count 個まで選ぶ。
|
|
12
|
+
def suggest(part:, place:, count: 4)
|
|
13
|
+
validate!(part, place, count)
|
|
14
|
+
@catalog.select(part: part, place: place).sample(count, random: @random)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def validate!(part, place, count)
|
|
20
|
+
raise Error, "unknown part: #{part}" unless Catalog::PARTS.key?(part)
|
|
21
|
+
raise Error, "unknown place: #{place}" unless Catalog::PLACES.key?(place)
|
|
22
|
+
raise Error, "count must be positive: #{count}" unless count.positive?
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/workout_menu.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "workout_menu/version"
|
|
4
|
+
|
|
5
|
+
module WorkoutMenu
|
|
6
|
+
class Error < StandardError; end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require_relative "workout_menu/exercise"
|
|
10
|
+
require_relative "workout_menu/catalog"
|
|
11
|
+
require_relative "workout_menu/menu"
|
|
12
|
+
require_relative "workout_menu/cli"
|
metadata
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: workout_menu
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- T-REX1996
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: workout_menu suggests a workout menu by body part and place, so you can
|
|
13
|
+
decide what to train without thinking.
|
|
14
|
+
email:
|
|
15
|
+
- bump12@icloud.com
|
|
16
|
+
executables:
|
|
17
|
+
- workout_menu
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- CHANGELOG.md
|
|
22
|
+
- LICENSE.txt
|
|
23
|
+
- README.md
|
|
24
|
+
- Rakefile
|
|
25
|
+
- exe/workout_menu
|
|
26
|
+
- lib/workout_menu.rb
|
|
27
|
+
- lib/workout_menu/catalog.rb
|
|
28
|
+
- lib/workout_menu/cli.rb
|
|
29
|
+
- lib/workout_menu/exercise.rb
|
|
30
|
+
- lib/workout_menu/exercises.yml
|
|
31
|
+
- lib/workout_menu/menu.rb
|
|
32
|
+
- lib/workout_menu/version.rb
|
|
33
|
+
- sig/workout_menu.rbs
|
|
34
|
+
homepage: https://github.com/T-REX1996/workout_menu
|
|
35
|
+
licenses:
|
|
36
|
+
- MIT
|
|
37
|
+
metadata:
|
|
38
|
+
source_code_uri: https://github.com/T-REX1996/workout_menu
|
|
39
|
+
changelog_uri: https://github.com/T-REX1996/workout_menu/blob/main/CHANGELOG.md
|
|
40
|
+
rubygems_mfa_required: 'true'
|
|
41
|
+
rdoc_options: []
|
|
42
|
+
require_paths:
|
|
43
|
+
- lib
|
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: 3.2.0
|
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
requirements: []
|
|
55
|
+
rubygems_version: 4.0.16
|
|
56
|
+
specification_version: 4
|
|
57
|
+
summary: A command-line tool that suggests a workout menu for your training day.
|
|
58
|
+
test_files: []
|