243 lines
6.4 KiB
TypeScript
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');
|
||
|
}
|