hanchu/server/db.ts
2024-10-23 23:54:41 +07:00

317 lines
8.5 KiB
TypeScript

import { Database } from "bun:sqlite";
import { wordFactorial } from "./utils";
// read
export function fetchResource(db: Database, spelling: string) {
const query = db.query(`
SELECT
spelling,
ipa,
frequency,
type,
subtype,
GROUP_CONCAT(c.name, ',') AS category,
FROM expressions
JOIN word_categories wc ON wc.word_id = words.id
JOIN categories c ON c.id = wc.category_id
WHERE spelling = $spelling
GROUP BY words.id
`);
return query.get({ spelling });
}
export function fetchFrequent(db: Database, count: number, page: number) {
const offset = (page - 1) * count;
const query = db.query(`
SELECT
spelling,
ipa,
frequency,
GROUP_CONCAT(c.name, ',') AS category
FROM expressions e
JOIN word_categories wc ON wc.word_id = e.id
JOIN categories c ON c.id = wc.category_id
ORDER BY e.frequency DESC
LIMIT $count
OFFSET $offset
`);
return query.get({ count, offset });
}
export function fetchExpressionsByCard(db: Database, cid: number) {
const queryString = `
SELECT
e.spelling, e.id as eid, e.ipa
FROM cards_expressions ce
JOIN expressions e ON ce.expression_id = e.id
WHERE ce.card_id = $cid AND e.spelling IS NOT NULL
ORDER BY e.frequency DESC
`;
const query = db.query(queryString);
return query.all({ cid });
}
export function fetchLessons(db: Database, count: number, page: number) {
const p = page < 1 ? 1 : page;
const offset = (p - 1) * count;
// const queryString = `
// SELECT
// l.id, l.text as ltext, cards.text as ctext, cards.note as cnote, cards.id as cid
// FROM cards_lessons cl
// JOIN cards ON cards.id = cl.card_id
// JOIN lessons l ON l.id = cl.lesson_id
// LIMIT $count
// OFFSET $offset
// `;
const queryString = `
SELECT
l.id AS lesson_id,
l.text AS lesson_text,
c.id AS card_id,
c.text AS card_text,
c.note AS card_note,
e.id AS expression_id,
e.spelling AS expression_spelling,
e.ipa AS expression_ipa,
e.type AS expression_type,
e.subtype AS expression_subtype,
GROUP_CONCAT(cat.name, ', ') AS categories
FROM
lessons l
JOIN
cards_lessons cl ON l.id = cl.lesson_id
JOIN
cards c ON c.id = cl.card_id
JOIN
cards_expressions ce ON c.id = ce.card_id
JOIN
expressions e ON e.id = ce.expression_id
LEFT JOIN
word_categories wc ON wc.word_id = e.id
LEFT JOIN
categories cat ON cat.id = wc.category_id
GROUP BY
l.id, c.id, e.id
ORDER BY
l.id ASC, c.id ASC, e.id ASC
LIMIT $count OFFSET $offset;
`;
const query = db.query(queryString);
return query.all({ count, offset });
}
// SELECT l.id, l.text, cards.text, cards.note FROM cards_lessons cl LEFT JOIN lessons l ON l.id = cl.lesson_id LEFT JOIN cards ON cards.id = cl.card_id ORDER BY l.id ASC LIMIT 20 OFFSET 0;
export function fetchLesson(db: Database, lesson: number) {
const queryString = `
SELECT
l.id, l.text, cards.text, cards.note, cards.id as cid,
spelling, ipa, frequency, e.id as eid,
GROUP_CONCAT(cg.name, ',') AS category
FROM cards_lessons cl
JOIN lessons l ON l.id = cl.lesson_id
JOIN cards ON cards.id = lc.card_id
JOIN cards_expressions ce ON cards.id = ce.card_id
JOIN expressions e ON e.id = ce.expression_id
JOIN word_categories wc ON wc.word_id = e.id
JOIN categories cg ON cg.id = wc.category_id
WHERE l.id = $lesson
`;
const query = db.query(queryString);
return query.all({ lesson });
}
export function fetchCard(db: Database, cid: number, userid: number) {
const query = db.query(`
SELECT
l.id, l.text, cards.text, cards.note
FROM cards_lessons cl
JOIN lessons l ON l.id = cl.lesson_id
JOIN cards ON cards.id = lc.card_id
JOIN attempts a ON a.card_id = cards.id AND a.user_id = $userid
WHERE cards.id = $cid
`);
return query.all({ cid, userid });
}
// write
export function addLesson(db: Database, text: string) {
const query = db.query(`
INSERT
INTO lessons(text)
VALUES($text)
`);
const res = query.run({ text });
return res.lastInsertRowid;
}
export function addCard(
db: Database,
lesson_id: number | bigint | null,
text: string,
mnote?: string,
) {
const note = mnote ? mnote : null;
const query = db.query(`
INSERT
INTO cards(text, note)
VALUES($text, $note)
`);
const params = { text, note, spel: text };
const res = query.run(params);
const cid = res.lastInsertRowid;
const wquery = db.query(`
INSERT OR IGNORE
INTO cards_expressions(card_id, expression_id)
VALUES($cid, (
SELECT id FROM expressions e
WHERE e.spelling LIKE $spelling
))
`);
const wtr = db.transaction((pairs) => {
// console.log("adding to ce", { pairs, cid, text });
for (const pair of pairs) wquery.run(pair);
});
const words = text
.replace(/[^\w\s]/g, "")
.replace(/\s+/g, " ")
.trim()
.split(" ");
const combinations = wordFactorial(words);
const richWords = Array.from(combinations).map((spelling) => {
return { spelling, cid };
});
wtr(richWords);
if (lesson_id) {
const query = db.query(`
INSERT INTO cards_lessons(card_id, lesson_id)
VALUES($cid, $lesson_id)
`);
query.run({ lesson_id, cid });
}
}
export function addUser(db: Database, name: string, creds: string) {
const query = db.query(`
INSERT
INTO users(name, creds)
VALUES($name, $creds)
`);
query.run({ $name: name, $creds: creds });
}
export function addWord(
db: Database,
spelling: string,
ipa: string,
language: string,
type: string,
subtype: string | null,
) {
const queryString = `
INSERT
INTO expressions(spelling, ipa, type, subtype, frequency, language_id)
VALUES($spelling, $ipa, $type, $subtype, 0, (
SELECT id FROM languages
WHERE name = $language
))
`;
const query = db.prepare(queryString);
const res = query.run({ spelling, ipa, language, type, subtype });
return res.lastInsertRowid;
}
export function addCat(
db: Database,
wordId: number | bigint,
category: string,
) {
const queryString = `
INSERT
INTO word_categories(word_id, category_id)
VALUES($wordId, (
SELECT id FROM categories
WHERE name = $category
))
`;
const query = db.query(queryString);
const res = query.run({ wordId, category });
return res.lastInsertRowid;
}
export const poss: Record<string, string> = {
CC: "conjunction",
DT: "determiner",
IN: "preposition",
MD: "auxiliar",
PRP: "nominative", // TODO oi
PRP$: "gemitive",
WDT: "determiner",
WP: "interrogative",
WP$: "interrogative",
};
export const domains: Record<string, string> = {
"adj.all": "adjective",
"adj.pert": "adjective",
"adj.ppl": "adjective",
"adv.all": "adverb",
"noun.Tops": "",
"noun.act": "abstract",
"noun.animal": "animate",
"noun.artifact": "inanimate",
"noun.attribute": "abstract",
"noun.body": "inanimate",
"noun.cognition": "abstract",
"noun.communication": "abstract",
"noun.event": "abstract",
"noun.feeling": "abstract",
"noun.food": "inanimate",
"noun.group": "noun",
"noun.location": "spatial",
"noun.motive": "abstract",
"noun.object": "inanimate",
"noun.person": "animate",
"noun.phenomenon": "abstract",
"noun.plant": "noun",
"noun.possession": "noun",
"noun.process": "noun",
"noun.quantity": "uncountable",
"noun.relation": "noun",
"noun.shape": "noun",
"noun.state": "noun",
"noun.substance": "uncountable",
"noun.time": "temporal",
"verb.body": "verb",
"verb.change": "verb",
"verb.cognition": "verb",
"verb.communication": "verb",
"verb.competition": "verb",
"verb.consumption": "verb",
"verb.contact": "verb",
"verb.creation": "verb",
"verb.emotion": "mental",
"verb.motion": "verb",
"verb.perception": "mental",
"verb.possession": "verb",
"verb.social": "verb",
"verb.stative": "verb",
"verb.weather": "verb",
};
export function addFrequency(
db: Database,
spelling: string,
frequency: number,
) {
const queryString = `
UPDATE expressions
SET frequency = $frequency
WHERE expressions.spelling = $spelling
`;
const query = db.query(queryString);
const res = query.run({ spelling, frequency });
}
export function addIPA(db: Database, spelling: string, ipa: string) {
const queryString = `
UPDATE expressions
SET ipa= $ipa
WHERE expressions.spelling = $spelling
`;
const query = db.query(queryString);
const res = query.run({ spelling, ipa });
}