summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpolwex <polwex@sortug.com>2025-08-16 15:50:10 +0700
committerpolwex <polwex@sortug.com>2025-08-16 15:50:10 +0700
commit7f2cdbe5da583010466d725197137f503e1fb771 (patch)
tree09e10e50aed0fe3fc11139163fbca165fb9fe814
parent274a7bbb1f82e99cdc9876f6d0de430585282797 (diff)
damn good
-rw-r--r--src/components/tones/ToneSelectorClient.tsx19
-rw-r--r--src/lib/db/prosodydb.ts4
-rw-r--r--src/lib/types/phonetics.ts25
-rw-r--r--src/pages/tones.tsx16
4 files changed, 55 insertions, 9 deletions
diff --git a/src/components/tones/ToneSelectorClient.tsx b/src/components/tones/ToneSelectorClient.tsx
index 8abbd38..438fc8a 100644
--- a/src/components/tones/ToneSelectorClient.tsx
+++ b/src/components/tones/ToneSelectorClient.tsx
@@ -1,6 +1,7 @@
"use client";
import { Spinner } from "@/components/ui/spinner";
+import "../Flashcard/cards.css";
import { useState, useEffect, useTransition, useRef, useCallback } from "react";
import { WordData } from "@/zoom/logic/types";
import {
@@ -25,7 +26,7 @@ import {
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Skeleton } from "@/components/ui/skeleton"; // For loading state
-import { MutationOrder, ToneQuery } from "@/lib/types/phonetics";
+import { MutationOrder, PhoneticData, ToneQuery } from "@/lib/types/phonetics";
import { ProsodySyllable } from "@/lib/types/cards";
import { ArrowLeft, ArrowRight, Volume2, FlipHorizontal2 } from "lucide-react";
@@ -131,9 +132,10 @@ export default function ToneSelectorClient({
initialData,
initialTones,
}: {
- initialData: any[];
+ initialData: PhoneticData[];
initialTones: ToneQuery;
}) {
+ console.log({ initialData });
const [data, setData] = useState<any[]>(initialData);
const [currentIdx, setCurrentIdx] = useState(0);
const [isLoading, startTransition] = useTransition();
@@ -187,7 +189,7 @@ export default function ToneSelectorClient({
}
type IProps = {
isLoading: boolean;
- currentWord: any;
+ currentWord: PhoneticData;
goPrev: () => void;
goNext: () => void;
};
@@ -225,6 +227,7 @@ function Inner({ isLoading, currentWord, goPrev, goNext }: IProps) {
</Card>
);
}
+ console.log({ currentWord });
return (
<div className="relative w-full max-w-2xl mx-auto h-100 perspective">
@@ -242,7 +245,10 @@ function Inner({ isLoading, currentWord, goPrev, goNext }: IProps) {
}`}
>
{/* Front */}
- <div className="absolute inset-0 bg-white dark:bg-slate-800 rounded-xl backface-hidden flex flex-col">
+ <div
+ id="frontside"
+ className="absolute inset-0 bg-white dark:bg-slate-800 rounded-xl backface-hidden flex flex-col"
+ >
<div className="px-6 pt-6 pb-2">
<h3 className="text-center text-lg font-semibold">Current Word</h3>
</div>
@@ -256,7 +262,10 @@ function Inner({ isLoading, currentWord, goPrev, goNext }: IProps) {
</div>
{/* Back */}
- <div className="absolute inset-0 bg-slate-50 dark:bg-slate-700 rounded-xl backface-hidden rotate-y-180 flex flex-col">
+ <div
+ id="backside"
+ className="absolute inset-0 bg-slate-50 dark:bg-slate-700 rounded-xl backface-hidden rotate-y-180 flex flex-col"
+ >
<div className="px-6 pt-6 pb-2">
<h3 className="text-center text-lg font-semibold">Details</h3>
</div>
diff --git a/src/lib/db/prosodydb.ts b/src/lib/db/prosodydb.ts
index fdadafb..513b195 100644
--- a/src/lib/db/prosodydb.ts
+++ b/src/lib/db/prosodydb.ts
@@ -1,5 +1,5 @@
import Database from "bun:sqlite";
-import { MutationOrder, Phoneme, Tone } from "../types/phonetics";
+import { MutationOrder, Phoneme, PhoneticData, Tone } from "../types/phonetics";
import { ProsodyWord, ProsodyWordDB } from "../types/cards";
type Str = string | null;
type ItemType = "word" | "syllable" | "idiom";
@@ -101,7 +101,7 @@ class DatabaseHandler {
return query.all(onset) as any[];
}
// tones
- fetchWordsByToneAndSyls(tones: Array<string | null>) {
+ fetchWordsByToneAndSyls(tones: Array<string | null>): PhoneticData[] {
const toneString = tones
.reduce((acc: string, item) => {
if (!item) return `${acc},%`;
diff --git a/src/lib/types/phonetics.ts b/src/lib/types/phonetics.ts
index f7289c7..1d0db5a 100644
--- a/src/lib/types/phonetics.ts
+++ b/src/lib/types/phonetics.ts
@@ -24,3 +24,28 @@ export type Syllable = {
export type ToneQuery = Array<string | null>;
export type MutationType = { change: string } | { keep: string };
export type MutationOrder = MutationType[];
+
+export type PhoneticData = {
+ word_id: number;
+ tone_sequence: string;
+ syllable_count: number;
+ syl_seq: string;
+ spelling: string;
+ ipa: string;
+ frequency: number;
+};
+
+export const thaiTones: Record<string, string> = {
+ "˧": "mid",
+ "˨˩": "low",
+ "˥˩": "falling",
+ "˦˥": "high",
+ "˩˩˦": "rising",
+};
+export const thaiToneNums: Record<string, number> = {
+ "˧": 33,
+ "˨˩": 21,
+ "˥˩": 41,
+ "˦˥": 45,
+ "˩˩˦": 214,
+};
diff --git a/src/pages/tones.tsx b/src/pages/tones.tsx
index 8658401..20c1237 100644
--- a/src/pages/tones.tsx
+++ b/src/pages/tones.tsx
@@ -3,18 +3,30 @@ import { Suspense } from "react";
import { fetchWordsByToneAndSyllables } from "@/actions/tones";
import ToneSelectorClient from "@/components/tones/ToneSelectorClient";
import { Skeleton } from "@/components/ui/skeleton"; // For Suspense fallback
+import { thaiTones } from "@/lib/types/phonetics";
+import { randomFromArray } from "@/lib/utils";
export const getConfig = async () => {
return {
render: "static", // Or 'dynamic' if you prefer SSR for every request
};
};
+async function randomTones(tries = 0) {
+ const syllables = Math.floor(Math.random() * 5);
+ const toneStrings = Object.values(thaiTones);
+ const tones = Array.from(Array(syllables)).map((_) =>
+ randomFromArray(toneStrings),
+ );
+ console.log({ tones, toneStrings });
+ const initialWords = await fetchWordsByToneAndSyllables(tones);
+ if (!initialWords || initialWords.length === 0) return randomTones(tries + 1);
+ else return {initialWords, tones};
+}
// Function to fetch the initial word on the server
async function InitialWordLoader() {
// Fetch a random 1-syllable Thai word with any tone initially
- const tones = ["falling", "falling"];
- const initialWords = await fetchWordsByToneAndSyllables(tones);
+ const {initialWords, tones]} = await randomTones();
return <ToneSelectorClient initialData={initialWords} initialTones={tones} />;
}