Skip to content

Commit

Permalink
feat: added enrollment numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
ImJustChew committed Jun 23, 2024
1 parent a949165 commit 3fba7c0
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 13 deletions.
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@types/react-dom": "18.3.0",
"@types/react-transition-group": "^4.4.10",
"@uiw/react-color-compact": "^2.3.0",
"@vercel/kv": "^2.0.0",
"algoliasearch": "^4.23.3",
"autoprefixer": "10.4.19",
"capacitor-set-version": "^2.2.0",
Expand Down
7 changes: 5 additions & 2 deletions src/app/api/scrape-archived-courses/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export const GET = async (request: NextRequest, _try = 0) => {
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "include"
"credentials": "include",
"cache": "no-cache"
});
const body = await res.text();
if(!body) {
Expand All @@ -74,13 +75,15 @@ export const GET = async (request: NextRequest, _try = 0) => {

const response = await fetch(baseUrl, {
body: new URLSearchParams({
"cache-control": "max-age=0",
'ACIXSTORE': `${ACIXSTORE}`,
'YS': `${yearSemester.slice(0, 3)}|${yearSemester.slice(3, 5)}`,
'cond': 'a',
'cou_code': `${department.code}`,
'auth_num': `${answer}`,
}),
method: "POST",
"cache": "no-cache"
});
return response;
}
Expand Down Expand Up @@ -264,9 +267,9 @@ export const GET = async (request: NextRequest, _try = 0) => {
prerequisites: prerequisites,
restrictions: course_restriction,
raw_id: course_id,
enrolled: parseInt(enrollment) ?? 0,
});

// console.log(normalizedCourses)

}
}));
Expand Down
65 changes: 60 additions & 5 deletions src/app/api/scrape-enrollment-status/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { departments } from '@/const/departments';
import { signInToCCXP } from '@/lib/headless_ais';
import { getLatestCourseEnrollment } from '@/lib/headless_ais/courses';
import { writeFileSync } from 'fs';
import { readFileSync, writeFileSync } from 'fs';
import {NextRequest, NextResponse} from 'next/server';
import {kv} from '@vercel/kv';
import supabase from '@/config/supabase';
import supabase_server from '@/config/supabase_server';

export const GET = async (request: NextRequest, _try = 0) => {
const authHeader = request.headers.get('authorization');
Expand All @@ -21,10 +24,62 @@ export const GET = async (request: NextRequest, _try = 0) => {

const {ACIXSTORE} = user;

console.log('ACIXSTORE', ACIXSTORE)
const res = await fetch("https://www.ccxp.nthu.edu.tw/ccxp/COURSE/JH/7/7.2/7.2.7/JH727001.php?ACIXSTORE="+ACIXSTORE, {
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "en-US,en;q=0.9",
"sec-ch-ua": "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"126\", \"Microsoft Edge\";v=\"126\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "frame",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "same-origin",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1"
},
"body": null,
"method": "GET",
"mode": "cors",
"credentials": "include",
"cache": "no-cache"
});

const html = await res.text();
if(html.includes('The system is not available now.')) {
return NextResponse.json({ sucesss: false, message: 'Not in course selection period' });
}

const courses = (await Promise.all(departments.map(async dept => await getLatestCourseEnrollment(ACIXSTORE, dept.code)))).flat();
//save into file
writeFileSync('courses.json', JSON.stringify(courses), 'utf8');
return NextResponse.json(courses);

const dedupedCourses = courses.filter((course, index, self) =>
index === self.findIndex((t) => (
t!.courseNumber === course!.courseNumber
))
);

// chunk by 1000 courses
const chunked = dedupedCourses.reduce((acc, cur, i) => {
const index = Math.floor(i / 1000);
acc[index] = acc[index] || [];
acc[index].push(cur);
return acc;
}, [] as Awaited<ReturnType<typeof getLatestCourseEnrollment>>[]);

// for each chunk, update supabase
for(const chunk of chunked) {
const { error } = await supabase_server.from('course_enroll_stats').upsert(chunk.map(m => ({
raw_id: m!.courseNumber,
limit: m!.sizeLimit == '無限制' ? null : parseInt(m!.sizeLimit),
confirmed: parseInt(m!.currentNumber),
waiting: parseInt(m!.toBeRandomed),
remaining: m!.sizeLimit == '無限制' ? null : parseInt(m!.sizeLimit) - parseInt(m!.currentNumber),
updated_at: new Date().toISOString()
})), { onConflict: 'raw_id' });

console.error(error);
}


await kv.set('ENROLL_STATUS_SYNCED_ON', new Date().toISOString());
return NextResponse.json({ sucesss: true });
}
3 changes: 2 additions & 1 deletion src/app/api/scrape-gpa/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ export const GET = async (request: NextRequest) => {
"body": `ACIXSTORE=${ACIXSTORE}&qyt=${semester.slice(0, 3)}|${semester.slice(3, 5)}&kwc=&kwt=&sort=ckey&Submit=%BDT%A9w+Submit`,
"method": "POST",
"mode": "cors",
"credentials": "include"
"credentials": "include",
"cache": "no-cache"
})
.then(res => res.arrayBuffer())
.then(arrayBuffer => new TextDecoder('big5').decode(new Uint8Array(arrayBuffer)))
Expand Down
3 changes: 3 additions & 0 deletions src/app/api/sync-algolia/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import supabase_server from '@/config/supabase_server';
import {Database} from '@/types/supabase';
import algolia from '@/config/algolia_server';
import {NextRequest, NextResponse} from 'next/server';
import { kv } from "@vercel/kv";


const syncCoursesToAlgolia = async (semester: string) => {
Expand All @@ -26,6 +27,8 @@ const syncCoursesToAlgolia = async (semester: string) => {
algolia.saveObjects(algoliaChunk);
}

await kv.set('COURSE_SYNCED_ON', new Date().toISOString());

}

export const GET = async (request: NextRequest) => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Courses/CourseListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ const CourseListItem: FC<{ course: CourseSyllabusView, hasTaken?: boolean }> = (
<p className='text-sm line-clamp-4 text-black dark:text-neutral-200'>
{course.brief}
</p>
<p className='text-sm whitespace-pre-line text-gray-400 dark:text-neutral-600'>{course.restrictions}</p>
<p className='text-sm whitespace-pre-line text-gray-400 dark:text-neutral-600'>{course.note}</p>
<p className='text-sm whitespace-pre-line text-gray-400 dark:text-neutral-500'>{course.restrictions}</p>
<p className='text-sm whitespace-pre-line text-gray-400 dark:text-neutral-500'>{course.note}</p>
<div className='space-y-1 @md:hidden'>
{course.venues?
course.venues.map((vn, i) => <p className='text-nthu-600 dark:text-nthu-400 text-sm'>{vn} <span className='text-black dark:text-white'>{course.times![i]}</span></p>) :
Expand Down
10 changes: 7 additions & 3 deletions src/components/Courses/CourseTagsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const HighlightItem: FC<PropsWithChildren<DetailedHTMLProps<HTMLAttributes<HTMLD
...props
}) => {
return <div
className={`flex flex-row items-center justify-center min-w-[65px] space-x-2 px-2 py-2 select-none rounded-md ${className ?? 'bg-indigo-50 text-indigo-900 dark:bg-indigo-950 dark:text-indigo-100'}`}
className={`flex flex-row items-center justify-center min-w-[60px] space-x-2 px-1 py-1.5 select-none rounded-md ${className ?? 'bg-indigo-50 text-indigo-900 dark:bg-indigo-950 dark:text-indigo-100'}`}
{...props}
>
{children}
Expand All @@ -30,9 +30,13 @@ const CourseTagList = ({ course }: { course: CourseDefinition }) => {
</span>
</HighlightItem>
<HighlightItem className='bg-violet-50 text-violet-900 dark:bg-violet-950 dark:text-violet-100'>
<span className="">
{`${course.enrolled} 選上 `}
</span>
</HighlightItem>
<HighlightItem>
<span className="">{course.credits}</span>
<span className="">{dict.course.credits}</span>
<span className="">{course.credits} {dict.course.credits}</span>
</HighlightItem>
{course.tags.includes('16周') && <HighlightItem className='bg-green-50 text-green-900 dark:bg-green-950 dark:text-green-100'>
<span className="">16 週</span>
Expand Down
31 changes: 31 additions & 0 deletions src/types/supabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,33 @@ export type Database = {
},
]
}
course_enroll_stats: {
Row: {
confirmed: number
limit: number | null
raw_id: string
remaining: number | null
updated_at: string
waiting: number
}
Insert: {
confirmed: number
limit?: number | null
raw_id: string
remaining?: number | null
updated_at?: string
waiting: number
}
Update: {
confirmed?: number
limit?: number | null
raw_id?: string
remaining?: number | null
updated_at?: string
waiting?: number
}
Relationships: []
}
course_hidden: {
Row: {
ckey: string
Expand Down Expand Up @@ -603,6 +630,7 @@ export type Database = {
cross_discipline: string[] | null
department: string
elective_for: string[] | null
enrolled: number
first_specialization: string[] | null
ge_target: string | null
ge_type: string | null
Expand Down Expand Up @@ -634,6 +662,7 @@ export type Database = {
cross_discipline?: string[] | null
department: string
elective_for?: string[] | null
enrolled?: number
first_specialization?: string[] | null
ge_target?: string | null
ge_type?: string | null
Expand Down Expand Up @@ -664,6 +693,7 @@ export type Database = {
cross_discipline?: string[] | null
department?: string
elective_for?: string[] | null
enrolled?: number
first_specialization?: string[] | null
ge_target?: string | null
ge_type?: string | null
Expand Down Expand Up @@ -815,6 +845,7 @@ export type Database = {
cross_discipline: string[] | null
department: string
elective_for: string[] | null
enrolled: number
first_specialization: string[] | null
ge_target: string | null
ge_type: string | null
Expand Down

0 comments on commit 3fba7c0

Please sign in to comment.