chore(textbooks): убрать сторонних авторов — все учебники наши (author=LearnSpace)
Политика «все учебники наши»: нигде не упоминаются сторонние авторы. - Миграции (15 файлов): колонка author → 'LearnSpace'; из описаний убран оборот «по учебнику <автор>:»; авторские фамилии вычищены из комментариев. Покрыты Арефьева/Пирютко, Казаков, Латотин/Чеботаревский/Горбунова/Цыбулько, Исаченкова, Жилко/Маркович/Сокольский, Герасимов/Лобанов. - HTML: physics_9_ch5 («по канве учебника Исаченковой» → «по учебной программе»), physics_11_hub (hdr-sub с авторами → описание курса), mocks-redesign (карточки-авторы → LearnSpace). - Генераторы gen_phys9_ch.js/gen_phys11_stubs.js — шаблоны без авторов. - НОВОЕ: update_textbook_authors.js — идемпотентный апдейтер ЖИВОЙ БД (миграции уже применены): author→'LearnSpace' у всех 107 учебников + чистка описаний. DRY-RUN по умолч. ⚠️ Живую БД правит ПОЛЬЗОВАТЕЛЬ: node backend/scripts/update_textbook_authors.js --apply (в БД сейчас author пуст у всех, видимые упоминания были в описаниях «по учебнику …»). review_geom10/11.js не тронуты — там фамилии как поисковые шаблоны детектора, не атрибуция. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
'use strict';
|
||||
/* ───────────────────────────────────────────────────────────────────────────
|
||||
update_textbook_authors.js
|
||||
Приводит метаданные учебников к политике «все учебники наши»:
|
||||
• колонка textbooks.author → 'LearnSpace' (у всех учебников и их глав);
|
||||
• в textbooks.description убирается оборот «по учебнику <автор>:» → «:».
|
||||
|
||||
Миграции 004/008/017–027/031/038/049/050 уже применены к БД с фамилиями сторонних
|
||||
авторов — их исходники почищены, но ЖИВУЮ БД правит этот идемпотентный скрипт.
|
||||
|
||||
Запуск:
|
||||
node backend/scripts/update_textbook_authors.js # DRY-RUN (по умолчанию)
|
||||
node backend/scripts/update_textbook_authors.js --apply # запись в БД
|
||||
|
||||
⚠️ Массовую запись в БД запускает ПОЛЬЗОВАТЕЛЬ вручную. Без --apply ничего не пишется.
|
||||
─────────────────────────────────────────────────────────────────────────── */
|
||||
|
||||
const { DatabaseSync } = require('node:sqlite');
|
||||
const path = require('path');
|
||||
|
||||
const APPLY = process.argv.includes('--apply');
|
||||
const AUTHOR = 'LearnSpace';
|
||||
const DB = path.join(__dirname, '..', 'data', 'learnspace.db');
|
||||
|
||||
const stripDesc = d => (d ? d.replace(/ по учебнику [^:]*:/g, ':') : d);
|
||||
|
||||
const db = new DatabaseSync(DB);
|
||||
|
||||
// есть ли таблица/колонки
|
||||
const cols = db.prepare(`PRAGMA table_info(textbooks)`).all().map(c => c.name);
|
||||
if (!cols.includes('author')) { console.error('✗ В таблице textbooks нет колонки author. Прерывание.'); db.close(); process.exit(1); }
|
||||
|
||||
const rows = db.prepare(`SELECT id, slug, author, description FROM textbooks`).all();
|
||||
const changes = [];
|
||||
for (const r of rows) {
|
||||
const newDesc = stripDesc(r.description);
|
||||
const authorChange = (r.author || '') !== AUTHOR;
|
||||
const descChange = newDesc !== r.description;
|
||||
if (authorChange || descChange) changes.push({ id: r.id, slug: r.slug, oldAuthor: r.author, authorChange, descChange, newDesc });
|
||||
}
|
||||
|
||||
console.log(`\n=== update_textbook_authors (учебников: ${rows.length}) ===`);
|
||||
console.log(`Режим: ${APPLY ? 'APPLY (запись)' : 'DRY-RUN (только показ)'}\n`);
|
||||
console.log(`Под изменение: ${changes.length}`);
|
||||
for (const c of changes) {
|
||||
const tags = [c.authorChange ? `author: ${c.oldAuthor || '∅'} → ${AUTHOR}` : null, c.descChange ? 'описание: убран «по учебнику …»' : null].filter(Boolean).join('; ');
|
||||
console.log(` ${String(c.slug).padEnd(20)} ${tags}`);
|
||||
}
|
||||
|
||||
if (!changes.length) { console.log('\nНечего менять — БД уже чистая.'); db.close(); process.exit(0); }
|
||||
|
||||
if (!APPLY) {
|
||||
console.log('\nDRY-RUN: ничего не записано. Для записи: node backend/scripts/update_textbook_authors.js --apply\n');
|
||||
db.close();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const upd = db.prepare(`UPDATE textbooks SET author = ?, description = ? WHERE id = ?`);
|
||||
let n = 0;
|
||||
db.exec('BEGIN');
|
||||
try {
|
||||
for (const c of changes) { upd.run(AUTHOR, c.newDesc, c.id); n++; }
|
||||
db.exec('COMMIT');
|
||||
console.log(`\n✓ Обновлено строк: ${n}. Все учебники → author='${AUTHOR}', обороты «по учебнику …» убраны.\n`);
|
||||
} catch (e) {
|
||||
db.exec('ROLLBACK');
|
||||
console.error('\n✗ Ошибка записи, откат:', e.message);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
db.close();
|
||||
Reference in New Issue
Block a user