hanchu/server/db.ts
2024-10-22 11:35:21 +07:00

243 lines
6.4 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 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 lessons l ON l.id = cl.lesson_id
JOIN cards ON cards.id = cl.card_id
LIMIT $count
OFFSET $offset
`;
const query = db.query(queryString);
const res = query.all({ count, offset });
return res;
}
// 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
FROM cards_lessons cl
JOIN lessons l ON l.id = cl.lesson_id
JOIN cards ON cards.id = lc.card_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 };
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) => {
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 = 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, domain: string) {
const queryString = `
INSERT
INTO word_categories(word_id, category_id)
VALUES($wordId, (
SELECT id FROM categories
WHERE name = $category
))
`;
const category = domains[domain] || 'unknown';
const query = db.query(queryString);
const res = query.run({ wordId, category });
return res.lastInsertRowid;
}
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 });
console.log(res, 'added frequency');
}