Last active
July 22, 2023 12:15
-
-
Save Sharlottes/1a53287189f76a3f02860cceb7b9e032 to your computer and use it in GitHub Desktop.
경남대학교 학정시 강의 표가 보기 싫어서 직접 만든 재처리기. 강의시간표및수업계획서열람에서 원하는 표의 아무 셀에서 우클릭하여 검사를 누르고, 콘솔에 이 스크립트를 입력하면 됨.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @ts-check | |
/** | |
* @typedef Lesson | |
* @property category {"교필" | "전필" | "교선" | "전선"} | |
* @property id {string} | |
* @property name {string} | |
* @property grade {string} | |
* @property point {string} | |
* @property time {string} | |
* @property professor {string} | |
* @property classroom {string} | |
* @property duration {string} | |
* @property etc {string} | |
*/ | |
/** | |
* @typedef ShowTableOptions | |
* @property grade {'1' | '2' | '3' | '4'} 학년 | |
* @property categories {Array<"교필" | "전필" | "교선" | "전선">} 강의 분류 | |
* @property categoryFilter {Partial<Record<"교필" | "전필" | "교선" | "전선", (lesson: Lesson) => boolean>>} 강의 분류 당 필터 | |
*/ | |
/** | |
* ### 강의 수집자 생성 함수 | |
* --- | |
* 반환된 `collectMore`로 표에 기제된 강의들을 모두 수집할 수 있으며 반환된 `lessons`는 매번 갱신됩니다. | |
* | |
* 수집 시 강의id + 강의반id에 의해 중복없이 수집됩니다. 저장은 `localStorage`를 통해 영구히 저장됩니다. | |
* @returns {{ lessons: Lesson[], collectMore: () => Lesson[]}} | |
*/ | |
function makeLessons() { | |
/** @type {Lesson[]} */ | |
const lessons = [...JSON.parse(localStorage.getItem("lessons") || "[]")]; | |
/** @type {Record<Lesson['id'], Omit<Lesson ,'id'>>} */ | |
const LUT = lessons.length == 0 ? {} : Object.fromEntries(lessons.map(({ id, ...lesson }) => [id, lesson])); | |
const collectMore = () => { | |
const newLessonList = Array.from(document.querySelectorAll("#DivScroll1 > table tr")).map((tr) => { | |
const [category, id, classid, name, grade, lesson_type, point, time, professor, classroom, duration, etc] = | |
Array.from(tr.querySelectorAll("td")).map((td) => td.textContent ?? ""); | |
return { | |
/** @type {"교필" | "전필" | "교선" | "전선"} */ | |
// @ts-ignore | |
category, | |
id: `${id}-${classid}`, | |
name, | |
grade, | |
lesson_type, | |
point, | |
time, | |
professor, | |
classroom, | |
duration, | |
etc, | |
}; | |
}); | |
for (const newLesson of newLessonList) { | |
if (newLesson.id in LUT) continue; | |
LUT[newLesson.id] = newLesson; | |
lessons.push(newLesson); | |
} | |
localStorage.setItem("lessons", JSON.stringify(lessons)); | |
console.log("saved successfully"); | |
return lessons; | |
}; | |
return { lessons, collectMore }; | |
} | |
/** | |
* 주어진 강의 객체를 문자열로 이쁘게 바꿔줍니다. | |
* @param {Lesson} lesson 문자열화할 lesson 객체 | |
*/ | |
function lessonToString(lesson) { | |
return `${lesson.name}(${lesson.point}) ${lesson.time}(${lesson.duration}) - ${lesson.category}`; | |
} | |
/** | |
* 각 강의들의 중복된 이름을 묶은 이름을 출력합니다. | |
* * @param {Lesson[]} originLessons 참고할 강의 리스트 | |
* * @param {Partial<ShowTableOptions>} requirements 표 요구사항 | |
*/ | |
function showTable(originLessons, requirements) { | |
const lessons = originLessons.filter((lesson) => { | |
if (lesson.grade != requirements.grade) return false; | |
if (requirements.categories && !requirements.categories.includes(lesson.category)) return false; | |
if ( | |
requirements.categoryFilter && | |
requirements.categoryFilter[lesson.category] && | |
!requirements.categoryFilter[lesson.category]?.call(null, lesson) | |
) | |
return false; | |
return true; | |
}); | |
/** @type {Record<string, Lesson[]>} */ | |
const lessonsObj = {}; | |
const resObj = {}; | |
/** @type {[string, Lesson][]} */ | |
const mappedLessons = lessons.map((lesson) => [lesson.name.replace(/([^(]*)\(.*\)$/g, "$1"), lesson]); | |
for (const [name, lesson] of mappedLessons) { | |
lessonsObj[name] ??= []; | |
lessonsObj[name].push(lesson); | |
} | |
for (const [name, lessons] of Object.entries(lessonsObj)) { | |
const filted = lessons.filter( | |
(lesson) => | |
lesson.name.replace(/[^(]*\((.*)\)$/g, "$1").includes("컴공") || | |
lesson.name.replace(/[^(]*\((.*)\)$/g, "$1").includes("교내가상강좌") | |
); | |
if (filted.length == 0 && lessons.length != 1 && /[^(]*\((.*)\)$/g.test(lessons[0].name)) continue; | |
const out = filted.length != 0 ? filted : lessons; | |
resObj[name] = { | |
분류: lessons[0].category, | |
학점: lessons[0].point, | |
시간: `(${lessons[0].duration}) ${Array.from(new Set(out.map((lesson) => lesson.time))).join(" | ")}`, | |
}; | |
} | |
console.table(resObj); | |
} | |
// 1-2 컴공 교필 강의 | |
const requiredGELessons = ["창의글쓰기", "대학수학I", "일반물리학및실험II", "한마드림하이세미나"]; | |
showTable(makeLessons().collectMore(), { | |
grade: "1", | |
categories: ["교필", "전선", "전필"], | |
categoryFilter: { | |
교필: (lesson) => | |
lesson.name.replace(/[^(]*\((.*)\)$/g, "$1").includes("컴공") || | |
requiredGELessons.some((GELesson) => lesson.name.includes(GELesson)), | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment