-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from anggoran/dev
release/v0.2.0
- Loading branch information
Showing
11 changed files
with
10,043 additions
and
101 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { FreshContext } from "$fresh/server.ts"; | ||
import { HanziModel, PinyinModel, PinyinPartModel } from "../models/pinyin.ts"; | ||
import { readJSON } from "../utils/read-json.ts"; | ||
|
||
export const getReading = ( | ||
_req: Request, | ||
ctx: FreshContext, | ||
) => { | ||
return ctx.render(); | ||
}; | ||
|
||
export const postReading = async ( | ||
req: Request, | ||
_ctx: FreshContext, | ||
) => { | ||
const url = new URL(req.url); | ||
const form = await req.formData(); | ||
const path = form.get("hanzis"); | ||
return Response.redirect(url + "/" + path, 303); | ||
}; | ||
|
||
export const getReadingQuiz = async ( | ||
req: Request, | ||
ctx: FreshContext, | ||
) => { | ||
const url = new URL(req.url); | ||
const hanziParams = url.searchParams.get("question"); | ||
const answerParams = url.searchParams.get("answer"); | ||
|
||
const name = Deno.cwd() + "/static/data/hanzis.txt"; | ||
const text = await Deno.readTextFile(name); | ||
const array = text.split("\n"); | ||
|
||
const pinyins: PinyinModel[] = await readJSON("pinyins"); | ||
const initials: PinyinPartModel[] = await readJSON("initials"); | ||
const finals: PinyinPartModel[] = await readJSON("finals"); | ||
const tones: PinyinPartModel[] = await readJSON("tones"); | ||
|
||
const params = ctx.params["quiz"]; | ||
const hanziList = decodeURIComponent(params).split(""); | ||
const randomIndex = Math.floor(Math.random() * hanziList.length); | ||
const selectedHanzi = hanziParams ?? hanziList[randomIndex]; | ||
|
||
const rawQuestion = array.find((e) => | ||
e.includes(`"character":"${selectedHanzi}"`) | ||
)!; | ||
const hanzi: HanziModel = JSON.parse(rawQuestion); | ||
|
||
const { initial_id, final_id, tone_id } = | ||
pinyins.find((e) => e.name === answerParams) ?? | ||
{ initial_id: 0, final_id: 0, tone_id: 0 }; | ||
const answer = { initial_id, final_id, tone_id }; | ||
|
||
let truth = null; | ||
|
||
if (hanziParams !== null && answerParams !== null) { | ||
const userAnswer = pinyins.find((e) => e.name === answerParams)!; | ||
truth = hanzi.pinyin[0] === userAnswer.name; | ||
} | ||
|
||
return ctx.render({ hanzi, answer, truth, pinyins, initials, finals, tones }); | ||
}; | ||
|
||
export const postReadingQuiz = async ( | ||
req: Request, | ||
_ctx: FreshContext, | ||
) => { | ||
const url = new URL(req.url); | ||
const form = await req.formData(); | ||
const question = form.get("question"); | ||
const initial = form.get("initial"); | ||
const final = form.get("final"); | ||
const tone = form.get("tone"); | ||
|
||
const pinyins: PinyinModel[] = await readJSON("pinyins"); | ||
const initials: PinyinPartModel[] = await readJSON("initials"); | ||
const finals: PinyinPartModel[] = await readJSON("finals"); | ||
const tones: PinyinPartModel[] = await readJSON("tones"); | ||
|
||
const file = Deno.cwd() + "/static/data/hanzis.txt"; | ||
const text = await Deno.readTextFile(file); | ||
const array = text.split("\n"); | ||
|
||
const rawAnswer = { | ||
initial_id: initials.find((e) => e.name == initial)!.id, | ||
final_id: finals.find((e) => e.name == final)!.id, | ||
tone_id: tones.find((e) => e.name == tone)!.id, | ||
}; | ||
const answer = pinyins.find((e) => | ||
e.initial_id === rawAnswer.initial_id && | ||
e.final_id === rawAnswer.final_id && | ||
e.tone_id === rawAnswer.tone_id | ||
); | ||
let answerURI = "N.A."; | ||
if (answer !== undefined) { | ||
answerURI = encodeURIComponent(answer.name); | ||
} | ||
|
||
const rawHanzi = array.find((e) => e.includes(`"character":"${question}"`))!; | ||
const hanzi: HanziModel = JSON.parse(rawHanzi); | ||
const questionURI = encodeURIComponent(hanzi.character); | ||
|
||
const params = `question=${questionURI}` + "&" + `answer=${answerURI}`; | ||
return Response.redirect(`${url}?${params}`, 303); | ||
}; |
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { Handlers, PageProps } from "$fresh/server.ts"; | ||
import { signal } from "https://esm.sh/v135/@preact/[email protected]/dist/signals-core.js"; | ||
import { getReadingQuiz, postReadingQuiz } from "../../controllers/reading.ts"; | ||
import { Dropdown } from "../../islands/Dropdown.tsx"; | ||
import { Label } from "../../islands/Label.tsx"; | ||
import { Menu } from "../../islands/Menu.tsx"; | ||
import { | ||
AnswerModel, | ||
HanziModel, | ||
PinyinModel, | ||
PinyinPartModel, | ||
} from "../../models/pinyin.ts"; | ||
|
||
interface Data { | ||
hanzi: HanziModel; | ||
answer: AnswerModel; | ||
truth: boolean | null; | ||
pinyins: PinyinModel[]; | ||
initials: PinyinPartModel[]; | ||
finals: PinyinPartModel[]; | ||
tones: PinyinPartModel[]; | ||
} | ||
|
||
export const handler: Handlers<Data> = { | ||
async GET(req, ctx) { | ||
return await getReadingQuiz(req, ctx); | ||
}, | ||
async POST(req, ctx) { | ||
return await postReadingQuiz(req, ctx); | ||
}, | ||
}; | ||
|
||
export default function ReadingQuizPage(props: PageProps<Data>) { | ||
const currentURL = decodeURIComponent(props.url.pathname); | ||
const { hanzi, answer, truth, pinyins, initials, finals, tones } = props.data; | ||
const { character: question, pinyin: solution, definition } = hanzi; | ||
const nextURL = currentURL.replace(question, ""); | ||
|
||
const { initial_id, final_id, tone_id } = answer; | ||
const myAnswer = signal({ initial_id, final_id, tone_id }); | ||
|
||
return ( | ||
<div | ||
className={`h-screen content-center ${ | ||
truth === true | ||
? "bg-green-300" | ||
: truth === false | ||
? "bg-red-300" | ||
: "bg-white" | ||
} `} | ||
> | ||
<div className="flex flex-col items-center space-y-4"> | ||
<div className="text-center"> | ||
<p> | ||
<b>Question:</b> {question} - {definition} | ||
</p> | ||
{truth !== null | ||
? ( | ||
<p> | ||
<b>Solution:</b> {solution} | ||
</p> | ||
) | ||
: <></>} | ||
</div> | ||
<Label | ||
props={{ | ||
models: pinyins, | ||
data: myAnswer, | ||
}} | ||
/> | ||
<form id="quiz"> | ||
<input type="hidden" name="question" value={question} /> | ||
<div className="flex flex-row space-x-8"> | ||
<Menu | ||
props={{ | ||
section: "initial", | ||
model: initials, | ||
data: myAnswer, | ||
}} | ||
/> | ||
<Menu | ||
props={{ | ||
section: "final", | ||
model: finals, | ||
data: myAnswer, | ||
}} | ||
/> | ||
<Dropdown | ||
props={{ | ||
section: "tone", | ||
model: tones, | ||
data: myAnswer, | ||
}} | ||
/> | ||
</div> | ||
</form> | ||
{truth !== null | ||
? <a href={nextURL}>Continue</a> | ||
: ( | ||
<div className="flex flex-row space-x-8"> | ||
<button form="quiz" type="reset">Clear</button> | ||
<button form="quiz" type="submit" formmethod="POST"> | ||
Submit | ||
</button> | ||
</div> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { Handlers } from "$fresh/server.ts"; | ||
import { getReading, postReading } from "../../controllers/reading.ts"; | ||
|
||
export const handler: Handlers = { | ||
async GET(req, ctx) { | ||
return await getReading(req, ctx); | ||
}, | ||
async POST(req, ctx) { | ||
return await postReading(req, ctx); | ||
}, | ||
}; | ||
|
||
export default function ReadingPage() { | ||
return ( | ||
<div | ||
className={`h-screen content-center ${"bg-white"} `} | ||
> | ||
<div className="flex flex-col items-center space-y-4"> | ||
<form id="quiz"> | ||
<div className="flex flex-row space-x-8"> | ||
<textarea | ||
name="hanzis" | ||
placeholder="Enter your hanzi list, without any separator." | ||
> | ||
</textarea> | ||
</div> | ||
</form> | ||
<div className="flex flex-row space-x-8"> | ||
<button form="quiz" type="reset">Clear</button> | ||
<button form="quiz" type="submit" formmethod="POST">Start</button> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.