🎯 系列目標:用 30 天時間,從零開始打造一個專屬輔大學生的課表生成 Chrome 擴充功能
💻 作者:輔大智慧資安 412580084
📅 Day 22:多時段處理與課程資料結構化
昨天 Day 21 我們建立了基礎的時間轉換器,今天我們要進一步處理複雜的多時段課程,讓系統能正確解析像是「1,2,3」或「5~7」這樣的時段組合。
今天我們要完成:
在原有的 TimeConverter 類別中新增多時段解析功能:
// 在 TimeConverter 類別中新增以下方法
class TimeConverter {
// ... 原有的 constructor 和其他方法 ...
// 解析複合時段 (如: "1,2,3" 或 "5~7")
parsePeriods(periodString) {
if (!periodString) return [];
const periods = [];
const parts = periodString.split(',');
parts.forEach(part => {
part = part.trim();
// 處理範圍 (如: "5~7")
if (part.includes('~')) {
const [start, end] = part.split('~');
const startOrder = this.periodTimeMap[start]?.order || parseInt(start);
const endOrder = this.periodTimeMap[end]?.order || parseInt(end);
for (let i = startOrder; i <= endOrder; i++) {
const period = this.findPeriodByOrder(i);
if (period) periods.push(period);
}
} else {
// 單一時段
periods.push(part);
}
});
return periods;
}
// 根據順序查找時段
findPeriodByOrder(order) {
for (const [period, info] of Object.entries(this.periodTimeMap)) {
if (info.order === order) {
return period;
}
}
return null;
}
}
新增格式化時間顯示的功能:
// 在 TimeConverter 類別中繼續新增
class TimeConverter {
// ... 原有方法 ...
// 格式化時間顯示
formatTimeDisplay(timeInfo) {
const dayNumber = this.convertDayToNumber(timeInfo.星期);
const periods = this.parsePeriods(timeInfo.節次);
const timeRanges = periods.map(period => {
const info = this.convertPeriodToTime(period);
return info.time;
});
return {
day: this.convertNumberToDay(dayNumber),
dayNumber: dayNumber,
periods: periods,
timeRanges: timeRanges,
classroom: timeInfo.教室 || '未指定教室',
fullDisplay: `星期${this.convertNumberToDay(dayNumber)} ${timeRanges.join(', ')} (${timeInfo.教室 || '未指定教室'})`
};
}
}
// 課程時間處理器
class CourseTimeProcessor {
constructor() {
this.timeConverter = new TimeConverter();
this.log('📚 課程時間處理器初始化完成');
}
// 處理單一課程的所有時間
processCourseTime(course) {
if (!course.上課時間 || !Array.isArray(course.上課時間)) {
this.log(`⚠️ 課程 ${course.課程名稱} 缺少時間資訊`);
return course;
}
const processedTimes = course.上課時間.map((timeInfo, index) => {
try {
const formattedTime = this.timeConverter.formatTimeDisplay(timeInfo);
return {
...timeInfo,
索引: index,
格式化資訊: formattedTime,
時段列表: this.timeConverter.parsePeriods(timeInfo.節次)
};
} catch (error) {
this.log(`❌ 處理課程 ${course.課程名稱} 第 ${index + 1} 個時間時出錯: ${error.message}`);
return timeInfo;
}
});
return {
...course,
上課時間: processedTimes,
總時段數: processedTimes.reduce((total, time) => {
return total + (time.時段列表?.length || 0);
}, 0)
};
}
// 日誌輸出
log(message) {
console.log(`[CourseTimeProcessor] ${message}`);
}
}
// 在 TimeConverter 類別中新增衝突檢測
class TimeConverter {
// ... 原有方法 ...
// 檢查時間衝突
checkTimeConflict(time1, time2) {
if (!time1.星期 || !time2.星期 || time1.星期 !== time2.星期) {
return false; // 不同星期不衝突
}
const periods1 = this.parsePeriods(time1.節次);
const periods2 = this.parsePeriods(time2.節次);
// 檢查是否有重疊的時段
return periods1.some(p1 => periods2.includes(p1));
}
}
// 多時段處理測試
function testMultiPeriodProcessing() {
console.log('🔄 開始測試多時段處理功能');
const converter = new TimeConverter();
// 測試複合時段解析
const testComplexPeriods = ['1,2,3', '5~7', 'E1,E2', 'DN'];
testComplexPeriods.forEach(periods => {
const parsed = converter.parsePeriods(periods);
console.log(`複合時段 ${periods} 解析為:`, parsed);
});
// 測試時間衝突檢測
const time1 = { 星期: '一', 節次: '1,2' };
const time2 = { 星期: '一', 節次: '2,3' };
const conflict = converter.checkTimeConflict(time1, time2);
console.log(`時間衝突檢測 (${time1.星期} ${time1.節次} vs ${time2.星期} ${time2.節次}):`, conflict);
console.log('✅ 多時段處理測試完成');
}
ℹ️ 重要提示:在加入新功能時,請將以下程式碼加到 content.js 的適當位置:
// 新增到 TimeConverter 類別中的方法:
// - parsePeriods() 方法
// - findPeriodByOrder() 方法
// - formatTimeDisplay() 方法
// - checkTimeConflict() 方法
// 新增 CourseTimeProcessor 類別
// 新增測試函數:
// testMultiPeriodProcessing();
// 執行測試
testMultiPeriodProcessing();
然後重新載入插件後,我們在選課清單
的日誌中會看到以下輸出即成功
今天我們建立了多時段處理能力,明天我們要將這些資料安全地儲存起來!