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

しげる:第5回SGTechスキルアップ勉強会「変なカレンダー生成プログラム」 #1

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.PHONY: test/calendar
test/calendar:
ruby test/sg_strange_calendar_test.rb --no-plugins

.PHONY: test/table
test/table:
ruby test/sg_strange_calendar/table_test.rb --no-plugins

.PHONY: test/horizonal
test/horizonal:
ruby test/sg_strange_calendar/presenter/horizonal_presenter_test.rb --no-plugins

.PHONY: test/vertical
test/vertical:
ruby test/sg_strange_calendar/presenter/vertical_presenter_test.rb --no-plugins
44 changes: 42 additions & 2 deletions lib/sg_strange_calendar.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,49 @@
require_relative 'sg_strange_calendar/table'
require_relative 'sg_strange_calendar/presenter/horizonal_presenter'
require_relative 'sg_strange_calendar/presenter/vertical_presenter'

class SgStrangeCalendar
def initialize(year, today = nil)
# write your code here
@year = year
@today = today
end

def generate(vertical: false)
# write your code here
return invalid_message unless valid?
# [
# %w[year Su Mo Tu We Th Fr ... Sa Su Mo]
# [Mon, nil, nil, ... Date1, Date2, ... Date31, nil, nil, ...]]
# ...
# ]
table = SgStrangeCalendar::Table.new(@year, @today).generate

if vertical
SgStrangeCalendar::Presenter::VerticalPresenter.new(@today).present(
table.transpose,
)
else
SgStrangeCalendar::Presenter::HorizonalPresenter.new(@today).present(
table,
)
end
end

private

def invalid_message
year = 1996
today = Date.new(1996, 3, 2)
table = SgStrangeCalendar::Table.new(year, today).generate
"\n==== error === invalid === year ====" \
+ "\n\n" + ("🎂" * 40) + "\n\n" \
+ SgStrangeCalendar::Presenter::HorizonalPresenter.new(today).present(
table,
today) \
+ "\n\n" + ("🎂" * 40) \
+ "\n\n" + "しげるの誕生日は 1996年3月2日 です!\n"
end

def valid?
1000 <= @year && @year <= 9999
end
end
55 changes: 55 additions & 0 deletions lib/sg_strange_calendar/presenter/base_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class BasePresenter
def initialize(today)
@today = today
end

def present(array)
(header(array) + content(array)).join("\n")
end

def header(array)
[(array[0]).join(' ')]
end

def content(array)
array[1..].map do |row|
str_row = normal_row(row)
# [xx] を含む row は今日を含んでいると判断する
if is_contain_today?(str_row)
str_row = update_today_str(str_row)
end
# rsrip is to remove trailing spaces
str_row.rstrip
end
end

def normal_row(row)
# row[0] is left-justified
# row[1..] is right-justified
[
row[0].ljust(4), # 4 equal years length
row[1..].map do |cell|
display_value(cell)
end
].join(' ')
end

def display_value(value)
# for debug
# return '-+' if(value.nil?)
return ' '.rjust(space_size) if(value.nil?)
return "[#{value.day}]".rjust(space_size) if(is_today?(value))
return value.day.to_s.rjust(space_size) if(value.is_a?(Date))

value.to_s.rjust(space_size)
end

def is_today?(value)
false if value.is_a?(Date)
value == @today
end

def is_contain_today?(str_row)
str_row.match?(/[\[|\]]/)
end
end
21 changes: 21 additions & 0 deletions lib/sg_strange_calendar/presenter/horizonal_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'date'
require_relative 'base_presenter'

class SgStrangeCalendar
class Presenter
class HorizonalPresenter < BasePresenter
SPACE_SIZE = 2
def space_size
SPACE_SIZE
end

def update_today_str(str_row)
# 2桁以上の場合は、左側へのはみ出しを削る
str_row = str_row.gsub(/ \[/, '[') if @today.day >= 10

# 右側へのはみ出しを削る
str_row.gsub(/\] /, ']')
end
end
end
end
21 changes: 21 additions & 0 deletions lib/sg_strange_calendar/presenter/vertical_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'date'
require_relative 'base_presenter'

class SgStrangeCalendar
class Presenter
class VerticalPresenter < BasePresenter
SPACE_SIZE = 3
def space_size
SPACE_SIZE
end

def update_today_str(str_row)
# 2桁以上は、右側へのはみ出しを削る
str_row = str_row.gsub(/\[/, ' [') if @today.day < 10

# 右側へのはみ出しを削る
str_row.gsub(/\] /, ']')
end
end
end
end
54 changes: 54 additions & 0 deletions lib/sg_strange_calendar/table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
class SgStrangeCalendar
class Table
WEEKDAYS = %w[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]

def initialize(year, today = nil)
@year = year
@today = today
end

def generate
# header + 12 months
table ||= [ header(@year) ] +
((0..11).to_a).map { |month| Row.new(@year, month, @today).generate }
end

private

def header(year)
[year] + WEEKDAYS
end

class Row
def initialize(year, month, today = nil)
@year = year
@month = month
@today = today || Date.today
end

def generate
date = start_of_month
[ start_of_month.strftime('%b') ] +
start_blank_days +
(start_of_month..end_of_month).to_a +
end_blank_days
end

def start_blank_days
start_of_month.strftime('%w').to_i.times.map { |_| nil }
end

def end_blank_days
(WEEKDAYS.size - start_blank_days.length - end_of_month.day ).times.map { |_| nil }
end

def start_of_month
Date.new(@year, @month + 1, 1)
end

def end_of_month
Date.new(@year, @month + 1, -1)
end
end
end
end
86 changes: 86 additions & 0 deletions test/sg_strange_calendar/presenter/horizonal_presenter_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
require 'minitest/autorun'
require_relative '../../../lib/sg_strange_calendar/presenter/horizonal_presenter'

class SgStrangeCalendar::Presenter::HorizonalPresenterTest < Minitest::Test
def test_present_with_no_nil
expected = <<~TXT.chomp
Jan b c d e f g
Feb i j k l m n
TXT
array = [
['Jan', 'b', 'c', 'd', 'e', 'f', 'g'],
['Feb', 'i', 'j', 'k', 'l', 'm', 'n']
]
today = Date.new(2025, 1, 1)
presenter = SgStrangeCalendar::Presenter::HorizonalPresenter.present(array, today)
assert_equal expected, presenter
end

def test_present_with_nil
expected = <<~TXT.chomp
Jan b c d e f g
Feb i j k l m
TXT
array = [
['Jan', 'b', 'c', 'd', 'e', 'f', 'g'],
['Feb', 'i', 'j', 'k', 'l', 'm', nil]
]
today = Date.new(2025, 1, 1)
presenter = SgStrangeCalendar::Presenter::HorizonalPresenter.present(array, today)
assert_equal expected, presenter
end

def test_present_date
expected = <<~TXT.chomp
Jan 1 2 3 4 5 6
Feb i j k l m
TXT
array = [
['Jan'] + (1..6).to_a.map { |i| Date.new(2024, 1, i) },
['Feb', 'i', 'j', 'k', 'l', 'm', nil]
]
today = Date.new(2025, 1, 1)
presenter = SgStrangeCalendar::Presenter::HorizonalPresenter.present(array, today)
assert_equal expected, presenter
end

def test_present_first_today
expected = <<~TXT.chomp
Jan [1] 2 3 4 5 6
Feb i j k l m
TXT
array = [
['Jan'] + (1..6).to_a.map { |i| Date.new(2024, 1, i) },
['Feb', 'i', 'j', 'k', 'l', 'm', nil]
]
today = Date.new(2024, 1, 1)
presenter = SgStrangeCalendar::Presenter::HorizonalPresenter.present(array, today)
assert_equal expected, presenter
end
def test_present_second_today
expected = <<~TXT.chomp
Jan 1 [2] 3 4 5 6
Feb i j k l m
TXT
array = [
['Jan'] + (1..6).to_a.map { |i| Date.new(2024, 1, i) },
['Feb', 'i', 'j', 'k', 'l', 'm', nil]
]
today = Date.new(2024, 1, 2)
presenter = SgStrangeCalendar::Presenter::HorizonalPresenter.present(array, today)
assert_equal expected, presenter
end
def test_present_end_today
expected = <<~TXT.chomp
Jan 26 27 28 29 30[31]
Feb i j k l m
TXT
array = [
['Jan'] + (26..31).to_a.map { |i| Date.new(2024, 1, i) },
['Feb', 'i', 'j', 'k', 'l', 'm', nil]
]
today = Date.new(2024, 1, 31)
presenter = SgStrangeCalendar::Presenter::HorizonalPresenter.present(array, today)
assert_equal expected, presenter
end
end
43 changes: 43 additions & 0 deletions test/sg_strange_calendar/presenter/vertical_presenter_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
require 'date'
require 'minitest/autorun'
require_relative '../../../lib/sg_strange_calendar/presenter/vertical_presenter'

class SgStrangeCalendar::Presenter::VerticalPresenterTest < Minitest::Test
def test_header
expected = <<~TXT.chomp
2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
TXT
array = [
%w[2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec]
]
today = Date.new(2024, 1, 1)
presenter = SgStrangeCalendar::Presenter::VerticalPresenter.present(array, today)
assert_equal expected, presenter
end
def test_first_row
expected = <<~TXT.chomp
2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Su 1 1
TXT
array = [
%w[2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec],
['Su', nil, nil, nil, nil, nil, nil, nil, nil, 1, nil, nil, 1]
]
today = Date.new(2024, 1, 1)
presenter = SgStrangeCalendar::Presenter::VerticalPresenter.present(array, today)
assert_equal expected, presenter
end
def test_today_row
expected = <<~TXT.chomp
2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Su [1] 1
TXT
array = [
%w[2024 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec],
['Su', nil, nil, nil, nil, nil, nil, nil, nil, Date.new(2024, 9, 1), nil, nil, 1]
]
today = Date.new(2024, 9, 1)
presenter = SgStrangeCalendar::Presenter::VerticalPresenter.present(array, today)
assert_equal expected, presenter
end
end
31 changes: 31 additions & 0 deletions test/sg_strange_calendar/table_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'minitest/autorun'
require 'date'
require_relative '../../lib/sg_strange_calendar/table'

class SgStrangeCalendar::TableTest < Minitest::Test
def test_header
expected = <<~TXT.chomp
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
TXT
table = SgStrangeCalendar::Table.new(2024).generate
assert_equal expected, table[0].join(' ')
end

def test_rows_count
expected = 12 + 1
table = SgStrangeCalendar::Table.new(2024).generate
assert_equal expected, table.size
end

def test_rows_length
expected = SgStrangeCalendar::Table::WEEKDAYS.size + 1
table = SgStrangeCalendar::Table.new(2024).generate
table.each do |row|
assert_equal expected, row.size
end
end

def test_contents
table = SgStrangeCalendar::Table.new(2024).generate
end
end
Loading
Loading