// struct-activity.mjs import { logger } from '../utils/logger.mjs'; let clubSchema = { academicYear: null, category: null, description: null, duration: { endDate: null, isRecurringWeekly: null, startDate: null }, grades: { max: null, min: null }, id: null, isPreSignup: null, isStudentLed: null, materials: [], meeting: { day: null, endTime: null, location: { block: null, room: null, site: null }, startTime: null }, name: null, photo: null, poorWeatherPlan: null, requirements: [], schedule: null, semesterCost: null, staff: [], staffForReports: [], studentLeaders: [] } async function applyFields(field, structuredActivityData) { switch (true) { case field.fID == "academicyear": structuredActivityData.academicYear = field.fData; break; case field.fID == "schedule": structuredActivityData.schedule = field.fData; break; case field.fID == "category": structuredActivityData.category = field.fData; break; case field.fID == "activityname": structuredActivityData.name = field.fData; break; case field.fID == "day": structuredActivityData.meeting.day = field.fData; break; case field.fID == "start": structuredActivityData.meeting.startTime = field.fData; break; case field.fID == "end": structuredActivityData.meeting.endTime = field.fData; break; case field.fID == "site": structuredActivityData.meeting.location.site = field.fData; break; case field.fID == "block": structuredActivityData.meeting.location.block = field.fData; break; case field.fID == "room": structuredActivityData.meeting.location.room = field.fData; break; case field.fID == "staff": let staff = field.fData.split(", "); structuredActivityData.staff = staff; break; case field.fID == "runsfrom": structuredActivityData.duration.startDate = field.fData; break; case field.fID == "runsto": structuredActivityData.duration.endDate = field.fData; break; case field.fData == "Recurring Weekly": structuredActivityData.duration.isRecurringWeekly = true; break; default: logger.debug(`No matching case for field: fID=${field.fID}, fType=${field.fType}`); break; } } async function postProcess(structuredActivityData) { structuredActivityData.description = structuredActivityData.description.replaceAll("
","\n"); structuredActivityData.description = structuredActivityData.description.replaceAll("\u000B","\v"); if (structuredActivityData.name.search("Student-led") != -1 || structuredActivityData.name.search("学生社团") != -1 || structuredActivityData.name.search("(SL)") != -1) { structuredActivityData.isStudentLed = true; } else { structuredActivityData.isStudentLed = false; } try { let grades = structuredActivityData.schedule.match(/G(\d+)-(\d+)/) || structuredActivityData.schedule.match(/KG(\d+)-KG(\d+)/); if (!grades || grades.length < 3) { throw new Error('Invalid grade format in schedule'); } structuredActivityData.grades.min = grades[1]; structuredActivityData.grades.max = grades[2]; } catch (error) { logger.error(`Failed to parse grades: ${error.message}`); structuredActivityData.grades.min = null; structuredActivityData.grades.max = null; } } export async function structActivityData(rawActivityData) { let structuredActivityData = JSON.parse(JSON.stringify(clubSchema)); let rows = rawActivityData.newRows; // Load club id - "rID": "3350:1:0:0" structuredActivityData.id = rows[0].rID.split(":")[0]; for (const rowObject of rows) { for (let i = 0; i < rowObject.fields.length; i++) { const field = rowObject.fields[i]; // Optimize: no fData, just skip if (!field.fData) { continue; } // Process hard cases first if (field.fData == "Description") { if (i + 1 < rowObject.fields.length) { structuredActivityData.description = rowObject.fields[i + 1].fData; } continue; } else if (field.fData == "Name To Appear On Reports") { if (i + 1 < rowObject.fields.length) { let staffForReports = rowObject.fields[i + 1].fData.split(", "); structuredActivityData.staffForReports = staffForReports; } } else if (field.fData == "Upload Photo") { if (i + 1 < rowObject.fields.length) { structuredActivityData.photo = rowObject.fields[i + 1].fData; } } else if (field.fData == "Poor Weather Plan") { if (i + 1 < rowObject.fields.length) { structuredActivityData.poorWeatherPlan = rowObject.fields[i + 1].fData; } } else if (field.fData == "Activity Runs From") { if (i + 4 < rowObject.fields.length) { structuredActivityData.duration.isRecurringWeekly = rowObject.fields[i + 4].fData == "Recurring Weekly"; } } else if (field.fData == "Is Pre Sign-up") { if (i + 1 < rowObject.fields.length) { structuredActivityData.isPreSignup = rowObject.fields[i + 1].fData !== ""; } } else if (field.fData == "Semester Cost") { if (i + 1 < rowObject.fields.length) { structuredActivityData.semesterCost = rowObject.fields[i + 1].fData === "" ? null : rowObject.fields[i + 1].fData; } } else { // Pass any other easy cases to helper function applyFields(field, structuredActivityData); } } } postProcess(structuredActivityData); return structuredActivityData }