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

201 lines
5.4 KiB
JavaScript

// this one written by claude, it is shit so dont blame me for any misaccuracy LOL
const { readFile } = require("node:fs/promises")
const FILES = [
"01.json",
"06.json",
"10.json"
]
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)
{
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(".", ":")
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 minutesToTime(minutes)
{
const hours = Math.floor(minutes / 60)
const mins = minutes % 60
return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`
}
function buildSchedule(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 buildEmptySchedule(schedule)
{
const emptySchedule = new Map()
const dayStartMin = timeToMinutes(OPEN_TIME)
const dayEndMin = timeToMinutes(CLOSE_TIME)
for (const [room, roomSchedule] of schedule)
{
emptySchedule.set(room, new Map())
// Process all days
for (const day of Object.keys(DAY_ORDER))
{
const classes = roomSchedule.get(day) || []
if (classes.length === 0)
{
// No classes = room won't be opened that day
continue
}
// Sort classes by start time
const sorted = classes.sort((a, b) => timeToMinutes(a.start) - timeToMinutes(b.start))
const emptySlots = []
let currentTime = dayStartMin
for (const classInfo of sorted)
{
const classStart = timeToMinutes(classInfo.start)
const classEnd = timeToMinutes(classInfo.end)
// Gap before this class
if (currentTime < classStart)
{
emptySlots.push({
start: minutesToTime(currentTime),
end: classInfo.start
})
}
// Move current time to after this class (or keep it if overlapping)
currentTime = Math.max(currentTime, classEnd)
}
// Gap after last class
if (currentTime < dayEndMin)
{
emptySlots.push({
start: minutesToTime(currentTime),
end: CLOSE_TIME
})
}
// Only add day if there are empty slots
if (emptySlots.length > 0)
{
emptySchedule.get(room).set(day, emptySlots)
}
}
}
return emptySchedule
}
function formatEmptySchedule(emptySchedule)
{
const lines = []
const rooms = [...emptySchedule.keys()].sort((a, b) => a.localeCompare(b))
for (const room of rooms)
{
const roomSchedule = emptySchedule.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 emptySlots = roomSchedule.get(day)
lines.push(` - **${day}:**`)
for (const slot of emptySlots)
{
lines.push(` - \`${slot.start} - ${slot.end}\` (KOSONG)`)
}
}
lines.push("")
}
return lines.join("\n")
}
/////////////////
async function main()
{
const cl = await loadFiles()
const sc = buildSchedule(cl)
const emptySchedule = buildEmptySchedule(sc)
console.log(formatEmptySchedule(emptySchedule))
}
main().catch(error =>
{
console.error(error)
process.exitCode = 1
})