株式会社ソニックガーデン主催、第5回 SG Tech スキルアップ勉強会「あなたもチャレンジ!コードレビューライブ 〜伊藤淳一からの挑戦状 Part 2〜」の提出用リポジトリです。
この企画に参加してコードレビューを受けてみたい方はこのリポジトリをフォークし、自分の書いたコードでプルリクエストを作成してください。
第5回 SG Tech スキルアップ勉強会では第4回に引き続き、コードレビューをテーマにした勉強会を開催します。
この勉強会では参加者のみなさんから実際にコードを提出してもらい、勉強会の中でソニックガーデンのプログラマ・伊藤淳一がリアルタイムにコードレビューを実施します。
プロのRubyプログラマからコードレビュー受けてみたい、という方はぜひチャレンジしてください!
(挑戦者の方はコードを提出するだけで大丈夫です。当日発言してもらう必要はありません。)
なお、時間の都合により、全員のコードレビューが行えない可能性があります。その点はあらかじめご了承ください。
興味がある方は初心者・上級者を問わず、どなたでもOKです。
イベント当日までにコードを書いてプルリクエストを作成すれば、それで申込み完了です!
(注)プルリクエストの作成は任意です。「プルリクエストを作らないと勉強会に参加できない」というわけではないのでご心配なく。
今回のお題は「見にくくてあまり実用性のない、変なカレンダーの生成」です。
たとえば2024年であれば、次のようなカレンダーが生成されます。
calendar = SgStrangeCalendar.new(2024)
puts calendar.generate
実行結果
2024 Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo
Jan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Feb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Mar 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Apr 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
May 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Jun 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Jul 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Aug 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Sep 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Oct 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Nov 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Dec 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
2025年であれば次のようなカレンダーが生成されます。
2025 Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo
Jan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Feb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Mar 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Apr 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
May 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Jun 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Jul 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Aug 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Sep 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Oct 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Nov 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Dec 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
このカレンダーの仕様は以下の通りです。
- 月の1日から最終日までを横並びに出力する
- 曜日の列は固定されており、実際の曜日と表示上の曜日が一致するようにカレンダーの開始位置を右にシフトする
- 上から順番に1月(Jan)から12月(Dec)まで1年分のカレンダーを出力する
- 年はカレンダーの左上に出力する
「こんなの簡単!」という人には次のステップとして「レベル2」を用意しています。
レベル2では今日の日付を[ ]
で囲んで強調表示します。
以下は2024年12月9日を強調表示する出力例です。
today = Date.new(2024, 12, 9)
calendar = SgStrangeCalendar.new(2024, today)
puts calendar.generate
実行結果
2024 Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo
Jan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Feb 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Mar 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Apr 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
May 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Jun 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Jul 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Aug 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Sep 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Oct 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Nov 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Dec 1 2 3 4 5 6 7 8 [9]10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
レベル2の仕様は以下の通りです。
- 今日の日付は
new
の第2引数で指定する - 指定された日付が
[ ]
で囲まれる
「レベル2も楽勝でしたwww」というあなたにはレベル3を用意しています!
レベル3は縦向きバージョンです。
today = Date.new(2024, 12, 9)
calendar = SgStrangeCalendar.new(2024, today)
puts calendar.generate(vertical: true)
実行結果
2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Su 1 1
Mo 1 1 1 2 2
Tu 2 2 2 3 1 3
We 3 3 1 3 4 2 4
Th 4 1 4 2 4 1 5 3 5
Fr 5 2 1 5 3 5 2 6 4 1 6
Sa 6 3 2 6 4 1 6 3 7 5 2 7
Su 7 4 3 7 5 2 7 4 8 6 3 8
Mo 8 5 4 8 6 3 8 5 9 7 4 [9]
Tu 9 6 5 9 7 4 9 6 10 8 5 10
We 10 7 6 10 8 5 10 7 11 9 6 11
Th 11 8 7 11 9 6 11 8 12 10 7 12
Fr 12 9 8 12 10 7 12 9 13 11 8 13
Sa 13 10 9 13 11 8 13 10 14 12 9 14
Su 14 11 10 14 12 9 14 11 15 13 10 15
Mo 15 12 11 15 13 10 15 12 16 14 11 16
Tu 16 13 12 16 14 11 16 13 17 15 12 17
We 17 14 13 17 15 12 17 14 18 16 13 18
Th 18 15 14 18 16 13 18 15 19 17 14 19
Fr 19 16 15 19 17 14 19 16 20 18 15 20
Sa 20 17 16 20 18 15 20 17 21 19 16 21
Su 21 18 17 21 19 16 21 18 22 20 17 22
Mo 22 19 18 22 20 17 22 19 23 21 18 23
Tu 23 20 19 23 21 18 23 20 24 22 19 24
We 24 21 20 24 22 19 24 21 25 23 20 25
Th 25 22 21 25 23 20 25 22 26 24 21 26
Fr 26 23 22 26 24 21 26 23 27 25 22 27
Sa 27 24 23 27 25 22 27 24 28 26 23 28
Su 28 25 24 28 26 23 28 25 29 27 24 29
Mo 29 26 25 29 27 24 29 26 30 28 25 30
Tu 30 27 26 30 28 25 30 27 29 26 31
We 31 28 27 29 26 31 28 30 27
Th 29 28 30 27 29 31 28
Fr 29 31 28 30 29
Sa 30 29 31 30
Su 31 30
Mo
レベル3の仕様は以下の通りです。
- レベル1、2で作成したカレンダーの行と列を入れ替えて出力する(
generate
メソッドにvertical
オプションを追加する) - レベル2の問題と同様、今日の日付を
[ ]
で強調することもできる
- Ruby 3.3以上で動作すること(GitHub ActionsのRubyバージョンは3.3.5です)
- 3rd party gemを使用しないこと(gem installなしで動作すること)
- Bundlerは使用しないこと
lib/sg_strange_calendar.rb
に自分が考えたロジックを書くこと- 予めクラス定義と空のメソッド定義が書いてあるので、ここにロジックを書いていく
みなさんが自力で考えたコードをレビューしたいので、以下のルールを守ってください。
- GitHub CopilotのようなAIコード支援機能はオフにしてください
- ネット上に公開されている変換アルゴリズムを見たり、ChatGPTに聞いたりしないようにしてください
- 他の人のプルリクエストを見ないようにしてください
ただし、自分の解答を提出し終わってこれ以上絶対に変更しない、と誓ったらあとは自由です!
テストコードは test/sg_strange_calendar_test.rb
にあるので、このテストが全部パスするようにコードを実装してください。
レベル1、レベル2、レベル3、それぞれについてこちらでテストコードを用意しています。
レベル2とレベル3のテストコードはskip
されているので、チャレンジする人はこの行を削除してからテストコードを実行してください。
def test_level_2_for_2024_01_01
- skip "レベル2にチャレンジする人はこの行を削除してください"
expected = <<~TXT.chomp
テストコードはskip
行を削除する以外の変更は不可です。
テストコードがすべてパス(またはskip)すること。テストコードは以下のようにして実行できる。
# Running:
FSSSSFSSSSS
Finished in 0.026042s, 422.3946 runs/s, 76.7990 assertions/s.
1) Failure:
SgStrangeCalendarTest#test_level_1_for_2024 [test/sg_strange_calendar_test.rb:23]:
# 省略
2) Failure:
SgStrangeCalendarTest#test_level_1_for_2025 [test/sg_strange_calendar_test.rb:43]:
# 省略
11 runs, 2 assertions, 2 failures, 0 errors, 9 skips
You have skipped tests. Run with --verbose for details.
初期状態ではレベル2とレベル3用のテストがskip
されているため、実行結果にはS
が9つ出力される。
レベル1の状態でコードを提出する場合は、それらのテストはskip
したままでOK(レベル1用の2つのテストをパスさせるのが提出の条件)。
レベル3まで進む場合、全テストをskip
せずにパスさせる必要があるため、実行結果にS
は出力されなくなる。
$ ruby test/sg_strange_calendar_test.rb --no-plugins
Run options: --seed 16463
# Running:
...........
Finished in 0.131037s, 83.9458 runs/s, 5639.6285 assertions/s.
11 runs, 739 assertions, 0 failures, 0 errors, 0 skips
なお、レベル1〜3のいずれも対応するテストパターンはテストコード内のパターンだけでOKとする。
不正な年を入力するなど、異常系の考慮は不要。
- この雛形リポジトリをフォークする
- コードが書けたらプルリクエストを作る
- GitHub ActionsのテストがパスすればOK(運営メンバーが手動実行します)
プルリクエストのタイトルにはレベル1、2、3のどのレベルまで解いたのかわかるようにしてください。
例「変なカレンダー生成プログラムの作成(レベル3)」
プルリクエストのdescriptionには以下のような内容を含めてください。
- 自分が解いたレベル(レベル1〜3)
- コードのアピールポイント
- 頑張ったところ
- 苦労したところ
- 工夫したところ
- 自慢したいところ
- etc
- コードを書くのにかかった時間(ざっくりでよいです。10分、1時間、3日、etc.)
- だいたいのプログラミング歴
- 実際に解いてみた感想
- 伊藤さんにメッセージ(もしあればw)
何か不明な点があれば、このリポジトリのissuesへ投稿してください。
https://github.com/SonicGarden/sg-strange-calendar/issues
みなさんからカッコいいコードがたくさん届くのを楽しみにしています!