Skip to content

Instantly share code, notes, and snippets.

@Sharlottes
Last active July 22, 2023 12:15
Show Gist options
  • Save Sharlottes/1a53287189f76a3f02860cceb7b9e032 to your computer and use it in GitHub Desktop.
Save Sharlottes/1a53287189f76a3f02860cceb7b9e032 to your computer and use it in GitHub Desktop.
경남대학교 학정시 강의 표가 보기 싫어서 직접 만든 재처리기. 강의시간표및수업계획서열람에서 원하는 표의 아무 셀에서 우클릭하여 검사를 누르고, 콘솔에 이 스크립트를 입력하면 됨.
// @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