feat: add word-type pairs + difficulty_level to auto create
- Claude now generates 40 pairs: +10 × word type (positive_words / negative_words) - difficulty easy→1, medium→2 stored as difficulty_level on each pair - findOrCreateWord() looks up or creates words by title before linking - savePairsForObject handles all 4 pair types (text/yes_no/question/word) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -890,9 +890,21 @@ async function callClaudeForPairs(picture, allObjects, selectedObjectId) {
|
||||
return res.pairs;
|
||||
}
|
||||
|
||||
async function findOrCreateWord(title, lang) {
|
||||
try {
|
||||
const results = await apiFetch(`/words?search=${encodeURIComponent(title.trim())}&limit=5`);
|
||||
const exact = Array.isArray(results)
|
||||
? results.find(w => (w[`titel_${lang}`] || w.titel_de || '').toLowerCase() === title.trim().toLowerCase())
|
||||
: null;
|
||||
if (exact) return exact;
|
||||
return await apiPost('/words', { [`titel_${lang}`]: title.trim() });
|
||||
} catch { return null; }
|
||||
}
|
||||
|
||||
async function savePairsForObject(pairs, objectId, lang, onPairSaved, onProgress) {
|
||||
for (let i = 0; i < pairs.length; i++) {
|
||||
const p = pairs[i];
|
||||
const difficultyLevel = p.difficulty === 'easy' ? 1 : p.difficulty === 'medium' ? 2 : null;
|
||||
|
||||
let questionId = null;
|
||||
if (p.type !== 'text' && p.question?.trim()) {
|
||||
@@ -901,22 +913,41 @@ async function savePairsForObject(pairs, objectId, lang, onPairSaved, onProgress
|
||||
}
|
||||
|
||||
let posStmtId = null;
|
||||
if ((p.type === 'text' || p.type === 'question') && p.positive?.trim()) {
|
||||
let negStmtId = null;
|
||||
|
||||
if (p.type === 'text' && p.positive?.trim()) {
|
||||
const s = await apiPost('/statements', { status: 'draft', [`positive_sentence_${lang}`]: p.positive.trim() });
|
||||
posStmtId = s.id;
|
||||
} else if (p.type === 'yes_no') {
|
||||
const s = await apiPost('/statements', { status: 'draft', answer: p.answer ?? null });
|
||||
posStmtId = s.id;
|
||||
}
|
||||
|
||||
let negStmtId = null;
|
||||
if (p.type === 'question' && p.negative?.trim()) {
|
||||
const s = await apiPost('/statements', { status: 'draft', [`negative_sentence_${lang}`]: p.negative.trim() });
|
||||
negStmtId = s.id;
|
||||
} else if (p.type === 'question') {
|
||||
if (p.positive?.trim()) {
|
||||
const s = await apiPost('/statements', { status: 'draft', [`positive_sentence_${lang}`]: p.positive.trim() });
|
||||
posStmtId = s.id;
|
||||
}
|
||||
if (p.negative?.trim()) {
|
||||
const s = await apiPost('/statements', { status: 'draft', [`negative_sentence_${lang}`]: p.negative.trim() });
|
||||
negStmtId = s.id;
|
||||
}
|
||||
} else if (p.type === 'word') {
|
||||
if (p.positive_words?.length) {
|
||||
const s = await apiPost('/statements', { status: 'draft' });
|
||||
posStmtId = s.id;
|
||||
const words = await Promise.all(p.positive_words.map(w => findOrCreateWord(w, lang)));
|
||||
await Promise.all(words.filter(Boolean).map(w => apiLink(`/statements/${posStmtId}/positive-words/${w.id}`)));
|
||||
}
|
||||
if (p.negative_words?.length) {
|
||||
const s = await apiPost('/statements', { status: 'draft' });
|
||||
negStmtId = s.id;
|
||||
const words = await Promise.all(p.negative_words.map(w => findOrCreateWord(w, lang)));
|
||||
await Promise.all(words.filter(Boolean).map(w => apiLink(`/statements/${negStmtId}/negative-words/${w.id}`)));
|
||||
}
|
||||
}
|
||||
|
||||
const created = await apiPost('/pairs', {
|
||||
answer_type: p.type,
|
||||
difficulty_level: difficultyLevel,
|
||||
question_id: questionId,
|
||||
positive_statement_id: posStmtId,
|
||||
negative_statement_id: negStmtId,
|
||||
|
||||
Reference in New Issue
Block a user