Files
2026-08-21 01:27:30 +07:00

186 lines
3.8 KiB
JavaScript

const { readFile } = require("node:fs/promises")
const FILES = [
"01.json",
"06.json",
"10.json"
]
// just some asumption, usually if there's a class in a certain day, the room is open for the entire day
const OPEN_TIME = "08:00"
const CLOSE_TIME = "17:00"
const DAY_ORDER = {
"Senin": 1,
"Selasa": 2,
"Rabu": 3,
"Kamis": 4,
"Jumat": 5,
"Sabtu": 6,
"Minggu": 7
}
async function loadFiles()
{
const results = await Promise.all(FILES.map(async file =>
{
const content = await readFile(file, "utf8")
const json = JSON.parse(content)
return json.data
}))
return results.flat()
}
function parseDateRoom(value)
{
/*
* Senin, 10:00-11:40 (A1.51 (Ged Baru))
* Selasa, 10.00-11.50 (A6.12 (Ged Baru))
*
* some entries is malformed (top 1 uni btw)
* so why even bother to match the closing ")" lolol
*/
const match = value.match(/^([^,]+),\s*(\d{2}[:.]\d{2})-(\d{2}[:.]\d{2})\s+\((.*)$/)
if (!match) return null
const [ , day, rawStart, rawEnd, rawRoom] = match
const start = rawStart.replace(".", ":")
const end = rawEnd.replace(".", ":")
/*
* Remove the outer ')' from normal entries.
*
* "(A1.51 (Ged Baru))"
* ^ remove only the final ')'
*
* For malformed entries:
* "(Lab A1.04+Lab A3.02 - Gabungan (Gd. Baru)"
* the final ')' is also removed.
*/
const room = rawRoom.endsWith(")") ? rawRoom.slice(0, -1) : rawRoom
return { day, start, end, room }
}
function timeToMinutes(time)
{
const [hours, minutes] = time.split(":").map(Number)
return hours * 60 + minutes
}
function buildSchedule(classes)
{
/*
* Map
* room
* -> day
* -> classes
*/
const schedule = new Map()
for (const classInfo of classes)
{
if (!Array.isArray(classInfo.dates_rooms))
{
console.warn(`Skipping ${classInfo.classname}: invalid dates_rooms`)
continue
}
for (const dateRoom of classInfo.dates_rooms)
{
const parsed = parseDateRoom(dateRoom)
if (!parsed)
{
console.warn(`Could not parse: ${dateRoom}`)
continue
}
const { day, start, end, room } = parsed
if (!schedule.has(room))
{
schedule.set(room, new Map())
}
const roomSchedule = schedule.get(room)
if (!roomSchedule.has(day))
{
roomSchedule.set(day, [])
}
roomSchedule.get(day).push({
start,
end,
className: classInfo.classname
})
}
}
return schedule
}
function formatSchedule(schedule)
{
const lines = []
const rooms = [...schedule.keys()].sort((a, b) => a.localeCompare(b))
for (const room of rooms)
{
const roomSchedule = schedule.get(room)
lines.push(`## ${room} \`${OPEN_TIME} - ${CLOSE_TIME}\``)
const days = [...roomSchedule.keys()].sort((a, b) => DAY_ORDER[a] - DAY_ORDER[b])
for (const day of days)
{
const classes = roomSchedule.get(day).sort((a, b) => timeToMinutes(a.start) - timeToMinutes(b.start))
lines.push(` - **${day}:**`)
for (const classInfo of classes)
{
lines.push(` - \`${classInfo.start} - ${classInfo.end}\`: **${classInfo.className}**`)
}
}
lines.push("\n")
}
return lines.join("\n")
}
/////////////////
async function main()
{
const cl = await loadFiles()
const sc = buildSchedule(cl)
console.log(formatSchedule(sc))
}
main().catch(error =>
{
console.error(error)
process.exitCode = 1
})