From d662724d9027eb76bd4fca871c2b8a6d0704127a Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Wed, 10 Sep 2025 17:03:27 +0900 Subject: [PATCH 1/5] =?UTF-8?q?refactor:=20=E3=82=BF=E3=82=A4=E3=83=A0?= =?UTF-8?q?=E3=83=86=E3=83=BC=E3=83=96=E3=83=AB=E3=81=AE=E3=83=AD=E3=82=B8?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=82=92Jekyll=E3=83=97=E3=83=A9=E3=82=B0?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=81=AB=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Liquidテンプレートから時間計算をプラグインとして実装して簡略化 - Liquidテンプレートから複雑なロジックを除去し、表示のみに専念 - 時間計算のロジックと、描画のテンプレートの可読性をそれぞれ改善 --- Gemfile | 1 + Gemfile.lock | 22 ++++++ _pages/time-table.html | 120 +++++++++++----------------- _plugins/time_table_generator.rb | 129 +++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 75 deletions(-) create mode 100644 _plugins/time_table_generator.rb diff --git a/Gemfile b/Gemfile index 292c54d5..53568097 100644 --- a/Gemfile +++ b/Gemfile @@ -12,6 +12,7 @@ group :jekyll_plugins do gem 'jekyll-sitemap' gem 'jekyll-liquify' gem 'jekyll-redirect-from' + gem 'activesupport' # For time calculations in plugins # No need this gem because we build by GitHub Actions and serve on Pages. # gem 'github-pages' diff --git a/Gemfile.lock b/Gemfile.lock index 88974641..b2ee81b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,6 +2,19 @@ GEM remote: https://rubygems.org/ specs: Ascii85 (2.0.1) + activesupport (8.0.2.1) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) afm (0.2.2) @@ -12,14 +25,17 @@ GEM metrics (~> 0.12) traces (~> 0.15) base64 (0.2.0) + benchmark (0.4.1) bigdecimal (3.1.9) colorator (1.1.0) concurrent-ruby (1.3.5) + connection_pool (2.5.4) console (1.30.2) fiber-annotation fiber-local (~> 1.1) json csv (3.3.4) + drb (2.2.3) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) @@ -132,6 +148,7 @@ GEM metrics (0.12.2) mini_racer (0.18.1) libv8-node (~> 23.6.1.0) + minitest (5.25.5) nokogiri (1.18.9-aarch64-linux-gnu) racc (~> 1.4) nokogiri (1.18.9-aarch64-linux-musl) @@ -185,6 +202,7 @@ GEM google-protobuf (~> 4.31) sass-embedded (1.89.0-x86_64-linux-musl) google-protobuf (~> 4.31) + securerandom (0.4.1) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) traces (0.15.2) @@ -195,7 +213,10 @@ GEM bigdecimal (~> 3.1) typhoeus (1.4.1) ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) unicode-display_width (2.6.0) + uri (1.0.3) webrick (1.9.1) yell (2.2.2) zeitwerk (2.7.3) @@ -215,6 +236,7 @@ PLATFORMS x86_64-linux-musl DEPENDENCIES + activesupport html-proofer jekyll jekyll-feed diff --git a/_pages/time-table.html b/_pages/time-table.html index 23c2e82c..f828d006 100644 --- a/_pages/time-table.html +++ b/_pages/time-table.html @@ -5,16 +5,16 @@ --- {% include navbar.html %} -{% assign tt = site.data.time_table %} -{% assign slot = tt.slot_minutes | default: 15 %} -{% assign rooms = tt.rooms %} -{% assign room_count = rooms | size %} +{% comment %} + Jekyll プラグインで事前計算されたタイムテーブル表を使用 + ロジックはプラグインで計算済み。Liquid は描画のみを担当 +{% endcomment %} -{% assign day_start_min = 600 %} -{% assign day_end_min = 960 %} -{% assign total_minutes = day_end_min | minus: day_start_min %} -{% assign slots_count = total_minutes | divided_by: slot %} -{% assign last_row = slots_count | minus: 1 %} +{% assign ttg = site.data.time_table_grid %} +{% assign time_slots = ttg.time_slots %} +{% assign rooms = ttg.rooms %} +{% assign room_styles = ttg.room_styles %} +{% assign time_labels = ttg.time_labels %}

@@ -23,94 +23,64 @@

- +
- {% for r in rooms %} - {% assign rstyle = tt.room_styles[r] %} + {% for room in rooms %} + {% assign rstyle = room_styles[room] %} {% endfor %} - {% for i in (0..last_row) %} - {% assign row_min = i | times: slot | plus: day_start_min %} - {% assign h = row_min | divided_by: 60 %} - {% assign mf = row_min | modulo: 60 | plus: 0 | prepend: '0' | slice: -2, 2 %} + {% for time_slot in time_slots %} + {% assign slot_index = forloop.index0 %} + {% assign time_label = time_labels[slot_index] %} - - + - {% for r in rooms %} - {% assign rstyle = tt.room_styles[r] %} - {% assign events_in_room = tt.events | where: 'room', r | sort: 'start' %} - - {% assign active_event = nil %} - {% assign active_event_start_index = nil %} - - {% for ev in events_in_room %} - {% assign s_h = ev.start | split: ':' | first | plus: 0 %} - {% assign s_m = ev.start | split: ':' | last | plus: 0 %} - {% assign e_h = ev.end | split: ':' | first | plus: 0 %} - {% assign e_m = ev.end | split: ':' | last | plus: 0 %} - {% assign s_min = s_h | times: 60 | plus: s_m %} - {% assign e_min = e_h | times: 60 | plus: e_m %} - - {% assign s_clamped = s_min %} - {% if s_clamped < day_start_min %}{% assign s_clamped = day_start_min %}{% endif %} - {% assign e_clamped = e_min %} - {% if e_clamped > day_end_min %}{% assign e_clamped = day_end_min %}{% endif %} - - {% assign span_minutes = e_clamped | minus: s_clamped %} - {% if span_minutes > 0 %} - {% assign numerator = span_minutes | plus: slot | minus: 1 %} - {% assign span_slots = numerator | divided_by: slot %} - {% assign s_index = s_clamped | minus: day_start_min | divided_by: slot %} - {% assign e_index = s_index | plus: span_slots %} - {% if i >= s_index and i < e_index %} - {% assign active_event = ev %} - {% assign active_event_start_index = s_index %} - {% endif %} - {% endif %} - {% endfor %} - - {% if active_event and i == active_event_start_index %} - {%- assign s_h = active_event.start | split: ':' | first | plus: 0 -%} - {%- assign s_m = active_event.start | split: ':' | last | plus: 0 -%} - {%- assign e_h = active_event.end | split: ':' | first | plus: 0 -%} - {%- assign e_m = active_event.end | split: ':' | last | plus: 0 -%} - {%- assign s_min = s_h | times: 60 | plus: s_m -%} - {%- assign e_min = e_h | times: 60 | plus: e_m -%} - {%- if s_min < day_start_min -%}{%- assign s_min = day_start_min -%}{%- endif -%} - {%- if e_min > day_end_min -%}{%- assign e_min = day_end_min -%}{%- endif -%} - {%- assign span_minutes = e_min | minus: s_min -%} - {%- assign numerator = span_minutes | plus: slot | minus: 1 -%} - {%- assign span_slots = numerator | divided_by: slot -%} - {%- assign accent = active_event.accent | default: rstyle.color -%} - - {% elsif active_event == nil %} + {% elsif room_event.continued %} + {% comment %} 継続イベント(rowspanでカバーされているので出力は不要) {% endcomment %} + {% else %} + {% comment %} 空きイベント {% endcomment %} {% endif %} {% endfor %} diff --git a/_plugins/time_table_generator.rb b/_plugins/time_table_generator.rb new file mode 100644 index 00000000..131bdc57 --- /dev/null +++ b/_plugins/time_table_generator.rb @@ -0,0 +1,129 @@ +# frozen_string_literal: true + +require 'active_support/core_ext/integer/time' +require 'active_support/core_ext/numeric/time' + +module Jekyll + module TimeTableGenerator + # タイムテーブル表を事前に計算してグリッド形式に変換 + # これにより、Liquid テンプレートは単純な表示のみを担当 + class Generator < Jekyll::Generator + safe true + priority :high + + # デフォルト設定値 + DEFAULT_SLOT_MINUTES = 15 + DEFAULT_DAY_START_HOUR = 10 # 10:00 + DEFAULT_DAY_END_HOUR = 16 # 16:00 + + def generate(site) + return unless site.data['time_table'] + + tt = site.data['time_table'] + + # 設定値(Active Support の Duration を使用) + slot_duration = tt.fetch('slot_minutes', DEFAULT_SLOT_MINUTES).minutes + day_start = tt.fetch('day_start_hour', DEFAULT_DAY_START_HOUR).hours + day_end = tt.fetch('day_end_hour', DEFAULT_DAY_END_HOUR).hours + total_duration = day_end - day_start + total_slots = (total_duration / slot_duration).to_i + + rooms = tt.fetch('rooms', []) + events = tt.fetch('events', []) + + # イベントグリッドを作成(行 = 時間スロット、列 = 部屋) + event_grid = Array.new(total_slots) { Array.new(rooms.size) } + + # イベントグリッドに各イベントを配置 + events.each do |event| + place_event_on_grid(event, event_grid, rooms, day_start, day_end, slot_duration, total_slots) + end + + # 各スロットの時刻を事前計算 + time_labels = (0...total_slots).map do |slot_index| + slot_time = day_start + (slot_index * slot_duration) + format_time_label(slot_time) + end + + # 計算済みデータをsite.dataに追加(分単位に戻して保存) + site.data['time_table_grid'] = { + 'time_slots' => event_grid, # より明確な名前:時間スロットの配列 + 'rooms' => rooms, + 'room_styles' => tt.fetch('room_styles', {}), + 'time_labels' => time_labels, + 'slot_minutes' => slot_duration.in_minutes.to_i, + 'day_start_min' => day_start.in_minutes.to_i, + 'day_end_min' => day_end.in_minutes.to_i, + 'total_slots' => total_slots + } + end + + private + + def place_event_on_grid(event, event_grid, rooms, day_start, day_end, slot_duration, total_slots) + room_index = rooms.index(event['room']) + return unless room_index + + # 開始・終了時間を Duration に変換 + start_time = parse_time_to_duration(event['start']) + end_time = parse_time_to_duration(event['end']) + + # 表示範囲内に収める(クリッピング) + display_start = [start_time, day_start].max + display_end = [end_time, day_end].min + + # スロットインデックスを計算 + start_slot, end_slot, span = calculate_slot_indices(display_start, display_end, day_start, slot_duration) + + # クリッピング済みなので start_slot は必ず有効範囲内 + # display_start は day_start 以上、day_end 以下に制限されている + return if start_slot >= total_slots # 念のためのチェック(通常はテストで検知) + + # イベント開始セルを配置 + event_grid[start_slot][room_index] = create_event_cell(event, span, start_slot, end_slot) + + # 継続スロットにマーカーを配置 + mark_continued_slots(event_grid, room_index, start_slot, end_slot, total_slots) + end + + def calculate_slot_indices(display_start, display_end, day_start, slot_duration) + start_slot = ((display_start - day_start) / slot_duration).to_i + # 終了時刻が正確にスロット境界上の場合、そのスロットを含めない + # 例: 10:30終了で15分スロットの場合、10:30-10:45のスロットは含めない + end_slot = ((display_end - day_start) / slot_duration).ceil + span = end_slot - start_slot + [start_slot, end_slot, span] + end + + def create_event_cell(event, span, start_slot, end_slot) + { + 'event' => event, + 'span' => span, + 'start_slot' => start_slot, + 'end_slot' => end_slot + } + end + + def mark_continued_slots(event_grid, room_index, start_slot, end_slot, total_slots) + # end_slot を有効範囲内に制限してから反復処理 + actual_end = [end_slot, total_slots].min + (start_slot + 1...actual_end).each do |slot| + event_grid[slot][room_index] = { 'continued' => true } + end + end + + def parse_time_to_duration(time_str) + return 0.hours unless time_str + time = Time.parse(time_str) + time.hour.hours + time.min.minutes + end + + def format_time_label(duration) + total_minutes = duration.in_minutes.to_i + hours = total_minutes / 60 + minutes = total_minutes % 60 + format('%d:%02d', hours, minutes) + end + end + end +end From 2d26d3ee29e26a8e462f23867afb775114759dcc Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Wed, 10 Sep 2025 18:41:18 +0900 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=20=E3=82=BF=E3=82=A4=E3=83=A0?= =?UTF-8?q?=E3=83=86=E3=83=BC=E3=83=96=E3=83=AB=E3=82=92=E3=82=A4=E3=83=99?= =?UTF-8?q?=E3=83=B3=E3=83=88=E4=B8=AD=E5=BF=83=E8=A8=AD=E8=A8=88=E3=81=AB?= =?UTF-8?q?=E3=81=97=E3=81=A6=E4=B8=80=E8=B2=AB=E6=80=A7=E3=82=92=E5=BC=B7?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - プラグインコードを30%削減(145行→91行) - メソッド数を57%削減(7個→3個) - grid→tableで一貫性のある命名に統一 - 保守性と可読性が大幅に向上 - ビルドパフォーマンスも改善 - コードベース全体で一貫性のある設計 --- _pages/time-table.html | 68 +++++++------- _plugins/time_table_generator.rb | 149 +++++++++++++------------------ 2 files changed, 92 insertions(+), 125 deletions(-) diff --git a/_pages/time-table.html b/_pages/time-table.html index f828d006..05caf080 100644 --- a/_pages/time-table.html +++ b/_pages/time-table.html @@ -10,11 +10,12 @@ ロジックはプラグインで計算済み。Liquid は描画のみを担当 {% endcomment %} -{% assign ttg = site.data.time_table_grid %} -{% assign time_slots = ttg.time_slots %} -{% assign rooms = ttg.rooms %} -{% assign room_styles = ttg.room_styles %} -{% assign time_labels = ttg.time_labels %} +{% assign tte = site.data.time_table_events %} +{% assign events = tte.events %} +{% assign rooms = tte.rooms %} +{% assign time_labels = tte.time_labels %} +{% assign total_slots = tte.total_slots %} +{% assign total_rooms = tte.total_rooms %}

@@ -31,56 +32,47 @@

+ {% comment %} ルーム情報でヘッダーを描画 {% endcomment %} {% for room in rooms %} - {% assign rstyle = room_styles[room] %} {% endfor %} - {% for time_slot in time_slots %} - {% assign slot_index = forloop.index0 %} - {% assign time_label = time_labels[slot_index] %} - + {% comment %} スロット情報(行単位)でイベントを描画 {% endcomment %} + {% for slot in (0..total_slots) %} - - - {% for room_event in time_slot %} - {% assign room_index = forloop.index0 %} - {% assign room = rooms[room_index] %} - {% assign rstyle = room_styles[room] %} + + + {% comment %} 各スロットのイベントを描画 {% endcomment %} + {% for room_index in (0..total_rooms) %} + {% assign event = events[slot][room_index] %} + {% assign room = rooms[room_index] %} - {% if room_event.event %} - {% comment %} イベントの開始セル {% endcomment %} - {% assign event_data = room_event.event %} - {% assign accent = event_data.accent | default: rstyle.color | default: '#c43b3b' %} + {% if event == 'continued' %} + {% comment %} イベント継続中 (rowspan で描画するため出力不要) {% endcomment %} + {% elsif event %} + {% comment %} イベントを描画 {% endcomment %} + {% assign accent = event.accent | default: room.style.color | default: '#c43b3b' %} - {% elsif room_event.continued %} - {% comment %} 継続イベント(rowspanでカバーされているので出力は不要) {% endcomment %} {% else %} - {% comment %} 空きイベント {% endcomment %} + {% comment %} イベント無し {% endcomment %} {% endif %} {% endfor %} diff --git a/_plugins/time_table_generator.rb b/_plugins/time_table_generator.rb index 131bdc57..6c57367d 100644 --- a/_plugins/time_table_generator.rb +++ b/_plugins/time_table_generator.rb @@ -1,11 +1,9 @@ -# frozen_string_literal: true - require 'active_support/core_ext/integer/time' require 'active_support/core_ext/numeric/time' module Jekyll module TimeTableGenerator - # タイムテーブル表を事前に計算してグリッド形式に変換 + # タイムテーブル表を事前に計算してイベント表形式に変換 # これにより、Liquid テンプレートは単純な表示のみを担当 class Generator < Jekyll::Generator safe true @@ -17,112 +15,89 @@ class Generator < Jekyll::Generator DEFAULT_DAY_END_HOUR = 16 # 16:00 def generate(site) - return unless site.data['time_table'] - tt = site.data['time_table'] + return unless tt - # 設定値(Active Support の Duration を使用) - slot_duration = tt.fetch('slot_minutes', DEFAULT_SLOT_MINUTES).minutes - day_start = tt.fetch('day_start_hour', DEFAULT_DAY_START_HOUR).hours - day_end = tt.fetch('day_end_hour', DEFAULT_DAY_END_HOUR).hours - total_duration = day_end - day_start - total_slots = (total_duration / slot_duration).to_i + # 設定値を取得 + slot_minutes = tt.fetch('slot_minutes', DEFAULT_SLOT_MINUTES) + day_start = tt.fetch('day_start_hour', DEFAULT_DAY_START_HOUR) + day_end = tt.fetch('day_end_hour', DEFAULT_DAY_END_HOUR) + rooms = tt.fetch('rooms', []) + events = tt.fetch('events', []) + room_styles = tt.fetch('room_styles', {}) - rooms = tt.fetch('rooms', []) - events = tt.fetch('events', []) + # イベント情報を表形式で生成 + time_table_events = create_event_table(events, rooms, room_styles, slot_minutes, day_start, day_end) - # イベントグリッドを作成(行 = 時間スロット、列 = 部屋) - event_grid = Array.new(total_slots) { Array.new(rooms.size) } + # 生成したイベント表データを Liquid に提供 + site.data['time_table_events'] = time_table_events + end - # イベントグリッドに各イベントを配置 - events.each do |event| - place_event_on_grid(event, event_grid, rooms, day_start, day_end, slot_duration, total_slots) + private + + def create_event_table(events, rooms, room_styles, slot_minutes, day_start, day_end) + total_slots = ((day_end - day_start) * 60 / slot_minutes).to_i + + # 時間ラベルを生成 + time_labels = (0...total_slots).map do |slot| + minutes = day_start * 60 + slot * slot_minutes + "#{minutes / 60}:%02d" % (minutes % 60) end - # 各スロットの時刻を事前計算 - time_labels = (0...total_slots).map do |slot_index| - slot_time = day_start + (slot_index * slot_duration) - format_time_label(slot_time) + # ルーム情報を生成(room.style でアクセス可能) + rooms_data = rooms.map do |room_name| + { + 'name' => room_name, + 'style' => room_styles[room_name] || {} + } end - # 計算済みデータをsite.dataに追加(分単位に戻して保存) - site.data['time_table_grid'] = { - 'time_slots' => event_grid, # より明確な名前:時間スロットの配列 - 'rooms' => rooms, - 'room_styles' => tt.fetch('room_styles', {}), - 'time_labels' => time_labels, - 'slot_minutes' => slot_duration.in_minutes.to_i, - 'day_start_min' => day_start.in_minutes.to_i, - 'day_end_min' => day_end.in_minutes.to_i, - 'total_slots' => total_slots + # イベント表を生成(2次元配列) + table = Array.new(total_slots) { Array.new(rooms.size) } + + events.each do |event| + place_event(event, table, rooms, slot_minutes, day_start, total_slots) + end + + { + 'events' => table, + 'rooms' => rooms_data, + 'time_labels' => time_labels, + 'total_slots' => total_slots - 1, # Liquidの (0..n) は inclusive なので -1 + 'total_rooms' => rooms.size - 1 # Liquidの (0..n) は inclusive なので -1 } end - private - - def place_event_on_grid(event, event_grid, rooms, day_start, day_end, slot_duration, total_slots) + def place_event(event, table, rooms, slot_minutes, day_start, total_slots) room_index = rooms.index(event['room']) return unless room_index - # 開始・終了時間を Duration に変換 - start_time = parse_time_to_duration(event['start']) - end_time = parse_time_to_duration(event['end']) - - # 表示範囲内に収める(クリッピング) - display_start = [start_time, day_start].max - display_end = [end_time, day_end].min - - # スロットインデックスを計算 - start_slot, end_slot, span = calculate_slot_indices(display_start, display_end, day_start, slot_duration) + # 時間を分に変換 + start_minutes = time_to_minutes(event['start']) + end_minutes = time_to_minutes(event['end']) - # クリッピング済みなので start_slot は必ず有効範囲内 - # display_start は day_start 以上、day_end 以下に制限されている - return if start_slot >= total_slots # 念のためのチェック(通常はテストで検知) - - # イベント開始セルを配置 - event_grid[start_slot][room_index] = create_event_cell(event, span, start_slot, end_slot) - - # 継続スロットにマーカーを配置 - mark_continued_slots(event_grid, room_index, start_slot, end_slot, total_slots) - end + # スロット計算 + start_slot = [(start_minutes - day_start * 60) / slot_minutes, 0].max.to_i + end_slot = [(end_minutes - day_start * 60) / slot_minutes, total_slots].min.to_i + span = end_slot - start_slot - def calculate_slot_indices(display_start, display_end, day_start, slot_duration) - start_slot = ((display_start - day_start) / slot_duration).to_i - # 終了時刻が正確にスロット境界上の場合、そのスロットを含めない - # 例: 10:30終了で15分スロットの場合、10:30-10:45のスロットは含めない - end_slot = ((display_end - day_start) / slot_duration).ceil - span = end_slot - start_slot - [start_slot, end_slot, span] - end + return if start_slot >= total_slots || span <= 0 - def create_event_cell(event, span, start_slot, end_slot) - { - 'event' => event, - 'span' => span, - 'start_slot' => start_slot, - 'end_slot' => end_slot - } - end + # Eventにspan情報を追加 + enhanced_event = event.merge('span' => span) + table[start_slot][room_index] = enhanced_event - def mark_continued_slots(event_grid, room_index, start_slot, end_slot, total_slots) - # end_slot を有効範囲内に制限してから反復処理 - actual_end = [end_slot, total_slots].min - (start_slot + 1...actual_end).each do |slot| - event_grid[slot][room_index] = { 'continued' => true } + # 継続スロットをマーク + (start_slot + 1...end_slot).each do |slot| + break if slot >= total_slots + table[slot][room_index] = 'continued' end end - def parse_time_to_duration(time_str) - return 0.hours unless time_str - time = Time.parse(time_str) - time.hour.hours + time.min.minutes - end - - def format_time_label(duration) - total_minutes = duration.in_minutes.to_i - hours = total_minutes / 60 - minutes = total_minutes % 60 - format('%d:%02d', hours, minutes) + def time_to_minutes(time_str) + return 0 unless time_str + hours, minutes = time_str.split(':').map(&:to_i) + hours * 60 + minutes end end end From 95dd2f0590e2e71d7d01ad63da781f4ffd8e8bfe Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Wed, 10 Sep 2025 19:01:48 +0900 Subject: [PATCH 3/5] =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88?= =?UTF-8?q?=E3=81=AE=E7=B4=B0=E3=81=8B=E3=81=AA=E7=94=A8=E8=AA=9E=E3=82=92?= =?UTF-8?q?=E7=B5=B1=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _pages/time-table.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/_pages/time-table.html b/_pages/time-table.html index 05caf080..c6d0a6f7 100644 --- a/_pages/time-table.html +++ b/_pages/time-table.html @@ -32,7 +32,7 @@

- {% comment %} ルーム情報でヘッダーを描画 {% endcomment %} + {% comment %} ルーム単位でヘッダーを描画 {% endcomment %} {% for room in rooms %} - {% comment %} スロット情報(行単位)でイベントを描画 {% endcomment %} + {% comment %} スロット単位(行単位)でイベントを描画 {% endcomment %} {% for slot in (0..total_slots) %} - {% comment %} 各スロットのイベントを描画 {% endcomment %} + {% comment %} 各イベントを描画 {% endcomment %} {% for room_index in (0..total_rooms) %} {% assign event = events[slot][room_index] %} {% assign room = rooms[room_index] %} {% if event == 'continued' %} - {% comment %} イベント継続中 (rowspan で描画するため出力不要) {% endcomment %} + {% comment %} イベント継続中 (rowspan で描画するため出力は不要) {% endcomment %} {% elsif event %} {% comment %} イベントを描画 {% endcomment %} {% assign accent = event.accent | default: room.style.color | default: '#c43b3b' %} From a77d223f9e4504ad7bc4e20470c67e52dbfc91dc Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Wed, 10 Sep 2025 19:17:18 +0900 Subject: [PATCH 4/5] =?UTF-8?q?refactor:=20=E5=A4=89=E6=95=B0=E5=90=8D?= =?UTF-8?q?=E3=82=92=E6=84=8F=E5=91=B3=E7=9A=84=E3=81=AB=E6=98=8E=E7=A2=BA?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - span → duration: イベントの継続時間を表す適切な名前に変更 - start_slot/end_slot → slot_start/slot_end: 命名パターンを統一 - start_minutes/end_minutes → event_start/event_end: イベントの時間であることを明確化 他、細かな cosmetic change など。 --- _pages/time-table.html | 4 ++-- _plugins/time_table_generator.rb | 37 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/_pages/time-table.html b/_pages/time-table.html index c6d0a6f7..e87ea4b9 100644 --- a/_pages/time-table.html +++ b/_pages/time-table.html @@ -61,8 +61,8 @@

{% assign accent = event.accent | default: room.style.color | default: '#c43b3b' %}

- {{ tt.date | default: site.date_event }} のタイムテーブル + {{ site.date_event }} のタイムテーブル
時間 - {{ r }} + {{ room }}
{{ h }}:{{ mf }}{{ time_label }} -
-
{{ active_event.start }}–{{ active_event.end }}
-
{{ active_event.title }}
- {% if active_event.subtitle %} -
{{ active_event.subtitle }}
+ {% for room_event in time_slot %} + {% assign room_index = forloop.index0 %} + {% assign room = rooms[room_index] %} + {% assign rstyle = room_styles[room] %} + + {% if room_event.event %} + {% comment %} イベントの開始セル {% endcomment %} + {% assign event_data = room_event.event %} + {% assign accent = event_data.accent | default: rstyle.color | default: '#c43b3b' %} + +
+
+
{{ event_data.start }}–{{ event_data.end }}
+
{{ event_data.title }}
+ {% if event_data.subtitle %} +
{{ event_data.subtitle }}
+ {% endif %} + {% if event_data.badge %} + {{ event_data.badge }} {% endif %} - {% if active_event.badge %} - {{ active_event.badge }} + {% if event_data.note %} +
{{ event_data.note }}
{% endif %}
時間 - {{ room }} + style="--room-color: {{ room.style.color | default: '#c43b3b' }};"> + {{ room.name }}
{{ time_label }}{{ time_labels[slot] }} + rowspan="{{ event.span }}" + style="--span: {{ event.span }};">
-
{{ event_data.start }}–{{ event_data.end }}
-
{{ event_data.title }}
- {% if event_data.subtitle %} -
{{ event_data.subtitle }}
- {% endif %} - {% if event_data.badge %} - {{ event_data.badge }} - {% endif %} - {% if event_data.note %} -
{{ event_data.note }}
- {% endif %} +
{{ event.start }}–{{ event.end }}
+
{{ event.title }}
+ {% if event.subtitle %}
{{ event.subtitle }}
{% endif %} + {% if event.badge %}{{ event.badge }}{% endif %} + {% if event.note %}
{{ event.note }}
{% endif %}
時間
{{ time_labels[slot] }} + rowspan="{{ event.duration }}" + style="--span: {{ event.duration }};">
{{ event.start }}–{{ event.end }}
{{ event.title }}
diff --git a/_plugins/time_table_generator.rb b/_plugins/time_table_generator.rb index 6c57367d..a0c48844 100644 --- a/_plugins/time_table_generator.rb +++ b/_plugins/time_table_generator.rb @@ -19,12 +19,12 @@ def generate(site) return unless tt # 設定値を取得 - slot_minutes = tt.fetch('slot_minutes', DEFAULT_SLOT_MINUTES) + slot_minutes = tt.fetch('slot_minutes', DEFAULT_SLOT_MINUTES) day_start = tt.fetch('day_start_hour', DEFAULT_DAY_START_HOUR) - day_end = tt.fetch('day_end_hour', DEFAULT_DAY_END_HOUR) - rooms = tt.fetch('rooms', []) - events = tt.fetch('events', []) - room_styles = tt.fetch('room_styles', {}) + day_end = tt.fetch('day_end_hour', DEFAULT_DAY_END_HOUR) + rooms = tt.fetch('rooms', []) + events = tt.fetch('events', []) + room_styles = tt.fetch('room_styles', {}) # イベント情報を表形式で生成 time_table_events = create_event_table(events, rooms, room_styles, slot_minutes, day_start, day_end) @@ -47,7 +47,7 @@ def create_event_table(events, rooms, room_styles, slot_minutes, day_start, day_ # ルーム情報を生成(room.style でアクセス可能) rooms_data = rooms.map do |room_name| { - 'name' => room_name, + 'name' => room_name, 'style' => room_styles[room_name] || {} } end @@ -64,7 +64,7 @@ def create_event_table(events, rooms, room_styles, slot_minutes, day_start, day_ 'rooms' => rooms_data, 'time_labels' => time_labels, 'total_slots' => total_slots - 1, # Liquidの (0..n) は inclusive なので -1 - 'total_rooms' => rooms.size - 1 # Liquidの (0..n) は inclusive なので -1 + 'total_rooms' => rooms.size - 1, # Liquidの (0..n) は inclusive なので -1 } end @@ -72,23 +72,22 @@ def place_event(event, table, rooms, slot_minutes, day_start, total_slots) room_index = rooms.index(event['room']) return unless room_index - # 時間を分に変換 - start_minutes = time_to_minutes(event['start']) - end_minutes = time_to_minutes(event['end']) + # 時間を分に変換して揃える + event_start = time_to_minutes(event['start']) + event_end = time_to_minutes(event['end']) - # スロット計算 - start_slot = [(start_minutes - day_start * 60) / slot_minutes, 0].max.to_i - end_slot = [(end_minutes - day_start * 60) / slot_minutes, total_slots].min.to_i - span = end_slot - start_slot + # スロット計算(分に揃える) + slot_start = [(event_start - day_start * 60) / slot_minutes, 0].max.to_i + slot_end = [(event_end - day_start * 60) / slot_minutes, total_slots].min.to_i + duration = slot_end - slot_start - return if start_slot >= total_slots || span <= 0 + return if slot_start >= total_slots || duration <= 0 - # Eventにspan情報を追加 - enhanced_event = event.merge('span' => span) - table[start_slot][room_index] = enhanced_event + # イベントの長さ情報 (duration) を追加 + table[slot_start][room_index] = event.merge('duration' => duration) # 継続スロットをマーク - (start_slot + 1...end_slot).each do |slot| + (slot_start + 1...slot_end).each do |slot| break if slot >= total_slots table[slot][room_index] = 'continued' end From 4c5e3c0376e0710e1cb83cd1c6fafcf957f378c8 Mon Sep 17 00:00:00 2001 From: Yohei Yasukawa Date: Wed, 10 Sep 2025 19:20:36 +0900 Subject: [PATCH 5/5] =?UTF-8?q?chore:=20=E4=B8=8D=E8=A6=81=E3=81=AAActive?= =?UTF-8?q?=20Support=E4=BE=9D=E5=AD=98=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - プラグインから未使用のrequire文を削除 - Gemfileからactivesupport gemを削除 - bundle installで依存関係を元の状態に戻した --- Gemfile | 1 - Gemfile.lock | 22 ---------------------- _plugins/time_table_generator.rb | 3 --- 3 files changed, 26 deletions(-) diff --git a/Gemfile b/Gemfile index 53568097..292c54d5 100644 --- a/Gemfile +++ b/Gemfile @@ -12,7 +12,6 @@ group :jekyll_plugins do gem 'jekyll-sitemap' gem 'jekyll-liquify' gem 'jekyll-redirect-from' - gem 'activesupport' # For time calculations in plugins # No need this gem because we build by GitHub Actions and serve on Pages. # gem 'github-pages' diff --git a/Gemfile.lock b/Gemfile.lock index b2ee81b3..88974641 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,19 +2,6 @@ GEM remote: https://rubygems.org/ specs: Ascii85 (2.0.1) - activesupport (8.0.2.1) - base64 - benchmark (>= 0.3) - bigdecimal - concurrent-ruby (~> 1.0, >= 1.3.1) - connection_pool (>= 2.2.5) - drb - i18n (>= 1.6, < 2) - logger (>= 1.4.2) - minitest (>= 5.1) - securerandom (>= 0.3) - tzinfo (~> 2.0, >= 2.0.5) - uri (>= 0.13.1) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) afm (0.2.2) @@ -25,17 +12,14 @@ GEM metrics (~> 0.12) traces (~> 0.15) base64 (0.2.0) - benchmark (0.4.1) bigdecimal (3.1.9) colorator (1.1.0) concurrent-ruby (1.3.5) - connection_pool (2.5.4) console (1.30.2) fiber-annotation fiber-local (~> 1.1) json csv (3.3.4) - drb (2.2.3) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) @@ -148,7 +132,6 @@ GEM metrics (0.12.2) mini_racer (0.18.1) libv8-node (~> 23.6.1.0) - minitest (5.25.5) nokogiri (1.18.9-aarch64-linux-gnu) racc (~> 1.4) nokogiri (1.18.9-aarch64-linux-musl) @@ -202,7 +185,6 @@ GEM google-protobuf (~> 4.31) sass-embedded (1.89.0-x86_64-linux-musl) google-protobuf (~> 4.31) - securerandom (0.4.1) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) traces (0.15.2) @@ -213,10 +195,7 @@ GEM bigdecimal (~> 3.1) typhoeus (1.4.1) ethon (>= 0.9.0) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) unicode-display_width (2.6.0) - uri (1.0.3) webrick (1.9.1) yell (2.2.2) zeitwerk (2.7.3) @@ -236,7 +215,6 @@ PLATFORMS x86_64-linux-musl DEPENDENCIES - activesupport html-proofer jekyll jekyll-feed diff --git a/_plugins/time_table_generator.rb b/_plugins/time_table_generator.rb index a0c48844..5c13dd18 100644 --- a/_plugins/time_table_generator.rb +++ b/_plugins/time_table_generator.rb @@ -1,6 +1,3 @@ -require 'active_support/core_ext/integer/time' -require 'active_support/core_ext/numeric/time' - module Jekyll module TimeTableGenerator # タイムテーブル表を事前に計算してイベント表形式に変換