Add KSP task grabber [untested]
This commit is contained in:
parent
50a6864c12
commit
e0818aa61c
1 changed files with 82 additions and 0 deletions
82
frontend/src/ksp-task-grabber.ts
Normal file
82
frontend/src/ksp-task-grabber.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
export type TaskAssignmentData = {
|
||||
id: string,
|
||||
name: string,
|
||||
points: number,
|
||||
description: HTMLElement
|
||||
}
|
||||
|
||||
type TaskLocation = {
|
||||
/** Relative location of HTML file containing this task */
|
||||
url: string
|
||||
/** id of the element where the specific task begins */
|
||||
startElement: string
|
||||
}
|
||||
|
||||
function getLocation(id: string, solution: boolean): TaskLocation {
|
||||
const m = /^(\d+)-(Z?)(\d)-(\d)$/.exec(id)
|
||||
if (!m) throw new Error(`Invalid task id: ${m}`)
|
||||
const [_, rocnik, z, serie, uloha] = m[1]
|
||||
if (z == 'Z') {
|
||||
const urlX = solution ? "reseni" : "zadani"
|
||||
return {
|
||||
url: `z/ulohy/${rocnik}/${urlX}${serie}.html`,
|
||||
startElement: `task${uloha}`
|
||||
}
|
||||
} else {
|
||||
const urlX = solution ? "solution" : "tasks"
|
||||
return {
|
||||
url: `tasks/${rocnik}/${urlX}${serie}.html`,
|
||||
startElement: `task${uloha}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseTask(startElementId: string, html: string, contentType: DOMParserSupportedType): string {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(html, contentType)
|
||||
|
||||
const titleElement = doc.getElementById(startElementId)
|
||||
if (!titleElement)
|
||||
throw new Error(`Document does not contain ${startElementId}`)
|
||||
const elements = []
|
||||
|
||||
let e = titleElement
|
||||
|
||||
while (e.nextElementSibling &&
|
||||
e.nextElementSibling?.tagName.toLowerCase() == "hr")
|
||||
e = e.nextElementSibling as HTMLElement
|
||||
|
||||
while (!e.classList.contains("story") &&
|
||||
// !e.classList.contains("clearfloat") &&
|
||||
e.tagName.toLowerCase() != "h3" &&
|
||||
e.innerText.trim() != "Řešení"
|
||||
)
|
||||
{
|
||||
elements.push(e)
|
||||
if (!e.nextElementSibling) break;
|
||||
e = e.nextElementSibling as HTMLElement
|
||||
}
|
||||
|
||||
let r = ""
|
||||
for (const e of elements)
|
||||
r += e.outerHTML + "\n"
|
||||
return r
|
||||
}
|
||||
|
||||
async function loadTask({ url, startElement }: TaskLocation) {
|
||||
const r = await fetch(url, { headers: { "Accept": "text/html,application/xhtml+xml" } })
|
||||
if (r.status >= 400) {
|
||||
throw Error("Bad request")
|
||||
}
|
||||
const rText = await r.text()
|
||||
const contentType = r.headers.get("Content-Type") as DOMParserSupportedType || "text/html"
|
||||
return parseTask(startElement, rText, contentType)
|
||||
}
|
||||
|
||||
export function loadAssignment(id: string) {
|
||||
return loadTask(getLocation(id, false))
|
||||
}
|
||||
|
||||
export function loadSolution(id: string) {
|
||||
return loadTask(getLocation(id, true))
|
||||
}
|
Reference in a new issue