Skip to content

Commit

Permalink
Merge pull request #30 from anggoran/dev
Browse files Browse the repository at this point in the history
release/v0.2.0
  • Loading branch information
anggoran authored May 5, 2024
2 parents bcb1fe7 + 5ca22c0 commit 41bba5f
Show file tree
Hide file tree
Showing 11 changed files with 10,043 additions and 101 deletions.
4 changes: 2 additions & 2 deletions controllers/blueprint.ts → controllers/listening.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PinyinModel } from "../models/pinyin.ts";
import { randomize } from "../utils/randomize.ts";
import { readJSON } from "../utils/read-json.ts";

export const getBlueprint = async (
export const getListening = async (
req: Request,
ctx: FreshContext,
) => {
Expand Down Expand Up @@ -39,7 +39,7 @@ export const getBlueprint = async (
});
};

export const postBlueprint = async (
export const postListening = async (
req: Request,
_ctx: FreshContext,
) => {
Expand Down
105 changes: 105 additions & 0 deletions controllers/reading.ts
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);
};
8 changes: 6 additions & 2 deletions fresh.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import * as $_404 from "./routes/_404.tsx";
import * as $_app from "./routes/_app.tsx";
import * as $api_joke from "./routes/api/joke.ts";
import * as $blueprint from "./routes/blueprint.tsx";
import * as $greet_name_ from "./routes/greet/[name].tsx";
import * as $index from "./routes/index.tsx";
import * as $listening_index from "./routes/listening/index.tsx";
import * as $reading_quiz_ from "./routes/reading/[quiz].tsx";
import * as $reading_index from "./routes/reading/index.tsx";
import * as $Counter from "./islands/Counter.tsx";
import * as $Dropdown from "./islands/Dropdown.tsx";
import * as $Label from "./islands/Label.tsx";
Expand All @@ -20,9 +22,11 @@ const manifest = {
"./routes/_404.tsx": $_404,
"./routes/_app.tsx": $_app,
"./routes/api/joke.ts": $api_joke,
"./routes/blueprint.tsx": $blueprint,
"./routes/greet/[name].tsx": $greet_name_,
"./routes/index.tsx": $index,
"./routes/listening/index.tsx": $listening_index,
"./routes/reading/[quiz].tsx": $reading_quiz_,
"./routes/reading/index.tsx": $reading_index,
},
islands: {
"./islands/Counter.tsx": $Counter,
Expand Down
8 changes: 8 additions & 0 deletions models/pinyin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ export interface AnswerModel {
final_id: number;
tone_id: number;
}

export interface HanziModel {
character: string;
pinyin: string[];
definition: string;
decomposition: string;
radical: string;
}
24 changes: 14 additions & 10 deletions routes/blueprint.tsx → routes/listening/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { signal } from "@preact/signals";
import { Dropdown } from "../islands/Dropdown.tsx";
import { Menu } from "../islands/Menu.tsx";
import { SoundButton } from "../islands/SoundButton.tsx";
import { Label } from "../islands/Label.tsx";
import { Dropdown } from "../../islands/Dropdown.tsx";
import { Menu } from "../../islands/Menu.tsx";
import { SoundButton } from "../../islands/SoundButton.tsx";
import { Label } from "../../islands/Label.tsx";
import { Handlers, PageProps } from "$fresh/server.ts";
import { AnswerModel, PinyinModel, PinyinPartModel } from "../models/pinyin.ts";
import { getBlueprint, postBlueprint } from "../controllers/blueprint.ts";
import {
AnswerModel,
PinyinModel,
PinyinPartModel,
} from "../../models/pinyin.ts";
import { getListening, postListening } from "../../controllers/listening.ts";

interface Data {
pinyins: PinyinModel[];
Expand All @@ -19,14 +23,14 @@ interface Data {

export const handler: Handlers<Data> = {
async GET(req, ctx) {
return await getBlueprint(req, ctx);
return await getListening(req, ctx);
},
async POST(req, ctx) {
return await postBlueprint(req, ctx);
return await postListening(req, ctx);
},
};

export default function Page(props: PageProps<Data>) {
export default function ListeningPage(props: PageProps<Data>) {
const { pinyins, initials, finals, tones, question, answer, truth } =
props.data;

Expand Down Expand Up @@ -82,7 +86,7 @@ export default function Page(props: PageProps<Data>) {
</div>
</form>
{truth !== null
? <a href="/blueprint">Continue</a>
? <a href="/listening">Continue</a>
: (
<div className="flex flex-row space-x-8">
<button form="quiz" type="reset">Clear</button>
Expand Down
110 changes: 110 additions & 0 deletions routes/reading/[quiz].tsx
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>
);
}
35 changes: 35 additions & 0 deletions routes/reading/index.tsx
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>
);
}
Loading

0 comments on commit 41bba5f

Please sign in to comment.