Skip to content

Commit 86e39e9

Browse files
authored
Merge pull request #80 from coderdojo-japan/refactor-time-table-validator
refactor: タイムテーブル重複検知を CI 上で動かせるテストに移行
2 parents ea3e8b6 + 2ec6f74 commit 86e39e9

File tree

2 files changed

+47
-27
lines changed

2 files changed

+47
-27
lines changed

_pages/time-table.html

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -119,31 +119,4 @@ <h2 class="text-4xl text-center mb-8">
119119
</tbody>
120120
</table>
121121
</div>
122-
123-
<script>
124-
// 重複検知(後勝ち)
125-
(function () {
126-
const data = {
127-
slot: {{ slot | jsonify }},
128-
dayStart: {{ day_start_min | jsonify }},
129-
dayEnd: {{ day_end_min | jsonify }},
130-
rooms: {{ rooms | jsonify }},
131-
events: {{ tt.events | jsonify }}
132-
};
133-
const map = new Map();
134-
data.rooms.forEach(r => map.set(r, []));
135-
const toMin = t => { const [h,m]=String(t).split(':').map(Number); return h*60+m; };
136-
for (const ev of data.events) (map.get(ev.room)||map.set(ev.room,[]).get(ev.room)).push(ev);
137-
for (const [room, list] of map) {
138-
list.sort((a,b)=>toMin(a.start)-toMin(b.start));
139-
for (let i=0;i<list.length-1;i++){
140-
const a=list[i], b=list[i+1];
141-
const as=Math.max(toMin(a.start), data.dayStart);
142-
const ae=Math.min(toMin(a.end), data.dayEnd);
143-
const bs=Math.max(toMin(b.start), data.dayStart);
144-
if (ae>bs) console.warn(`[time-table] Overlap in "${room}":`, a, b, '→ later wins');
145-
}
146-
}
147-
})();
148-
</script>
149122
</section>

_tests/custom_checks.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@
33

44
require 'json'
55
require 'yaml'
6+
require 'time'
67

78
class CustomChecks < ::HTMLProofer::Check
89
BASE_PATH = '_site'
910

1011
def run
1112
filename = @runner.current_filename
1213
puts "\tchecking ... " + filename.delete_prefix('_site')
14+
1315
check_directory_structure(filename) if filename.end_with?('.html')
16+
check_time_table_overlaps if filename.end_with?('time-table/index.html')
1417
end
1518

1619
# Check directory structure to ensure all pages are generated as index.html
@@ -45,4 +48,48 @@ def is_redirect_file?(filename)
4548
content.include?("<meta http-equiv='refresh'") ||
4649
content.include?('<meta http-equiv=refresh')
4750
end
51+
52+
# Check time table overlaps using Range#cover?
53+
def check_time_table_overlaps
54+
data = YAML.load_file('_data/time_table.yml')
55+
56+
# 会議室ごとにイベントをグループ化
57+
room_events = Hash.new { |h, k| h[k] = [] }
58+
59+
data['events'].each do |event|
60+
start_time = Time.parse(event['start'])
61+
end_time = Time.parse(event['end'])
62+
63+
room_events[event['room']] << {
64+
title: event['title'],
65+
start_str: event['start'],
66+
end_str: event['end'],
67+
range: (start_time...end_time) # 終了時間を含まない範囲
68+
}
69+
end
70+
71+
# 各会議室で重複チェック
72+
room_events.each do |room, events|
73+
# 開始時間でソート
74+
sorted = events.sort_by { |e| e[:range].begin }
75+
76+
# 隣接するイベント間で重複をチェック
77+
sorted.each_cons(2) do |a, b|
78+
# Range#cover? で重複検出
79+
if a[:range].cover?(b[:range].begin)
80+
add_failure(
81+
<<~ERROR_MESSAGE
82+
タイムテーブルに重複があります [#{room}]:
83+
\s #{a[:start_str]}-#{a[:end_str]}: #{a[:title]}
84+
\s #{b[:start_str]}-#{b[:end_str]}: #{b[:title]}
85+
ERROR_MESSAGE
86+
)
87+
end
88+
end
89+
end
90+
91+
puts "\t✓ タイムテーブル重複検知完了"
92+
rescue => e
93+
add_failure("タイムテーブル検証エラー: #{e.message}")
94+
end
4895
end

0 commit comments

Comments
 (0)