@cloud411716/fancy-webnovel 2.2.0 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/client.js +201 -15
- package/cordis.patch.yml +5 -1
- package/docs/douyin-plugin.md +118 -0
- package/docs/material-library/README.md +404 -0
- package/docs/material-library/import.js +437 -0
- package/docs/material-library/prompt.md +370 -0
- package/docs/material-library/queries.surql +94 -0
- package/docs/material-library/sample.jsonl +14 -0
- package/docs/material-library/schema.surql +46 -0
- package/docs/mcp-profile.example.yml +24 -0
- package/docs/story-graph-design.md +602 -0
- package/docs/story-graph-validation.md +81 -0
- package/docs/workspace-mcp.md +284 -0
- package/index.js +12 -7
- package/lib/atomic-write.js +109 -0
- package/lib/chapter-order.js +100 -0
- package/lib/confirmation.js +80 -0
- package/lib/db-init.js +123 -0
- package/lib/deployed-state.js +11 -11
- package/lib/direction-labels.js +265 -0
- package/lib/error-codes.js +31 -31
- package/lib/infra.js +29 -4
- package/lib/material-db.js +149 -0
- package/lib/path-guard.js +150 -0
- package/lib/projects.js +400 -0
- package/lib/scraper-utils.js +140 -0
- package/lib/surreal-server.js +338 -0
- package/lib/topic-decision.js +860 -0
- package/lib/topic-fields.js +251 -0
- package/lib/topic-schema.js +225 -0
- package/lib/workspace.js +501 -0
- package/package.json +31 -7
- package/plugins/fancy-analyze/analyze-definitions.md +519 -0
- package/plugins/fancy-analyze/index.js +1128 -77
- package/plugins/fancy-analyze/ingest-coverage.js +107 -0
- package/plugins/fancy-analyze/schema-analyze.md +355 -107
- package/plugins/fancy-analyze/scripts/append-summary-chapter.js +612 -0
- package/plugins/fancy-analyze/summary-progress.js +71 -7
- package/plugins/fancy-analyze/templates.js +437 -139
- package/plugins/fancy-bootstrap/index.js +276 -131
- package/plugins/fancy-bootstrap/scripts/init.js +59 -25
- package/plugins/fancy-bootstrap/templates.js +35 -18
- package/plugins/fancy-db/index.js +172 -0
- package/plugins/fancy-douyin/deploy.js +134 -0
- package/plugins/fancy-douyin/index.js +551 -0
- package/plugins/fancy-douyin/prompts/01-analysis-prompt.md +84 -0
- package/plugins/fancy-douyin/scripts/crawl-note.cjs +194 -0
- package/plugins/fancy-douyin/scripts/lib.cjs +197 -0
- package/plugins/fancy-douyin/scripts/scan-account.cjs +128 -0
- package/plugins/fancy-douyin/scripts/start-chrome.cjs +203 -0
- package/plugins/fancy-douyin/state.js +197 -0
- package/plugins/fancy-douyin/templates.js +127 -0
- package/plugins/fancy-export/exporter.js +805 -0
- package/plugins/fancy-export/index.js +63 -0
- package/plugins/fancy-import/import-driver.js +29 -6
- package/plugins/fancy-import/index.js +13 -5
- package/plugins/fancy-import/prompts/01-import-prompt.md +39 -14
- package/plugins/fancy-import/templates.js +17 -8
- package/plugins/fancy-material/exporter.js +153 -0
- package/plugins/fancy-material/genres.js +256 -0
- package/plugins/fancy-material/index.js +835 -0
- package/plugins/fancy-material/inventory.js +145 -0
- package/plugins/fancy-material/kinds.js +313 -0
- package/plugins/fancy-material/queue.js +55 -0
- package/plugins/fancy-material/scripts/query.js +254 -0
- package/plugins/fancy-material/templates.js +258 -0
- package/plugins/fancy-material/tool-deploy.js +138 -0
- package/plugins/fancy-material/validate.js +149 -0
- package/plugins/fancy-project/index.js +133 -0
- package/plugins/fancy-scan/existing-block.js +100 -0
- package/plugins/fancy-scan/index.js +410 -21
- package/plugins/fancy-scan/prompts/01-analysis-prompt.md +302 -0
- package/plugins/fancy-scan/scripts/append-block.js +725 -0
- package/plugins/fancy-scan/scripts/report-validate.js +824 -0
- package/plugins/fancy-scan/scripts/run-scan.js +169 -22
- package/plugins/fancy-scan/scripts/scrapers/fanqie-rank-scraper.js +145 -16
- package/plugins/fancy-scan/scripts/scrapers/jjwxc-rank-scraper.js +179 -49
- package/plugins/fancy-scan/scripts/scrapers/qimao-rank-scraper.js +38 -20
- package/plugins/fancy-scan/templates/blocks.js +155 -0
- package/plugins/fancy-scan/templates/platforms.js +372 -0
- package/plugins/fancy-scan/templates/report-schema.js +90 -0
- package/plugins/fancy-scan/templates.js +545 -146
- package/plugins/fancy-scan/tool-deploy.js +335 -0
- package/plugins/fancy-scan/wait-turn.js +46 -0
- package/plugins/fancy-story-builder/db/README.md +106 -0
- package/plugins/fancy-story-builder/db/client.js +228 -0
- package/plugins/fancy-story-builder/db/commands.js +145 -0
- package/plugins/fancy-story-builder/db/ids.js +39 -0
- package/plugins/fancy-story-builder/db/import.js +798 -0
- package/plugins/fancy-story-builder/db/project.js +299 -0
- package/plugins/fancy-story-builder/db/query.js +361 -0
- package/plugins/fancy-story-builder/db/schema.js +417 -0
- package/plugins/fancy-story-builder/db/stage-sync.js +238 -0
- package/plugins/fancy-story-builder/flesh-output.js +19 -6
- package/plugins/fancy-story-builder/index.js +4105 -396
- package/plugins/fancy-story-builder/patch-driver.js +390 -0
- package/plugins/fancy-story-builder/prompts/01-skeleton-prompt.md +29 -19
- package/plugins/fancy-story-builder/prompts/02-flesh-prompt.md +72 -10
- package/plugins/fancy-story-builder/prompts/03-rhythm-prompt.md +40 -5
- package/plugins/fancy-story-builder/prompts/04-writing-prompt.md +37 -0
- package/plugins/fancy-story-builder/purpose-template.md +42 -66
- package/plugins/fancy-story-builder/references/formulas-skeleton.json +229 -56
- package/plugins/fancy-story-builder/references/genre-profiles.json +3514 -0
- package/plugins/fancy-story-builder/references/glossary.md +15 -6
- package/plugins/fancy-story-builder/references/index.md +97 -6
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/00-index.md +1 -1
- package/plugins/fancy-story-builder/references//350/212/202/345/245/217/346/214/207/345/257/274/07-audit.md +25 -7
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/01-character.md +5 -1
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/03-relations.md +6 -2
- package/plugins/fancy-story-builder/references//350/241/200/350/202/211/346/214/207/345/257/274/05-audit.md +15 -5
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/00-index.md +1 -1
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/01-positioning.md +2 -1
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/03-entities.md +1 -1
- package/plugins/fancy-story-builder/references//351/252/250/346/236/266/346/214/207/345/257/274/06-audit.md +19 -1
- package/plugins/fancy-story-builder/schema-setting.json +1100 -0
- package/plugins/fancy-story-builder/schema-setting.md +201 -293
- package/plugins/fancy-story-builder/scripts/brief-validate.js +164 -0
- package/plugins/fancy-story-builder/scripts/content-quality.js +4 -1
- package/plugins/fancy-story-builder/scripts/flesh-validate.js +135 -12
- package/plugins/fancy-story-builder/scripts/graph-utils.js +146 -47
- package/plugins/fancy-story-builder/scripts/reference-log.js +110 -0
- package/plugins/fancy-story-builder/scripts/rhythm-validate.js +100 -4
- package/plugins/fancy-story-builder/scripts/schema-pages.js +2668 -0
- package/plugins/fancy-story-builder/scripts/semantic-lint.js +5 -1
- package/plugins/fancy-story-builder/scripts/skeleton-validate.js +158 -17
- package/plugins/fancy-story-builder/scripts/stage-batches.js +36 -2
- package/plugins/fancy-story-builder/scripts/stage-contract.js +12 -0
- package/plugins/fancy-story-builder/scripts/story-artifacts.js +933 -0
- package/plugins/fancy-story-builder/scripts/upstream-query.js +1 -1
- package/plugins/fancy-story-builder/scripts/v2/baseline.js +112 -0
- package/plugins/fancy-story-builder/scripts/v2/cast.js +517 -0
- package/plugins/fancy-story-builder/scripts/v2/context.js +434 -0
- package/plugins/fancy-story-builder/scripts/v2/contracts.js +493 -0
- package/plugins/fancy-story-builder/scripts/v2/core.js +419 -0
- package/plugins/fancy-story-builder/scripts/v2/engine.js +1068 -0
- package/plugins/fancy-story-builder/scripts/v2/export-markdown.js +794 -0
- package/plugins/fancy-story-builder/scripts/v2/genre.js +195 -0
- package/plugins/fancy-story-builder/scripts/v2/knowledge.js +321 -0
- package/plugins/fancy-story-builder/scripts/v2/macro.js +409 -0
- package/plugins/fancy-story-builder/scripts/v2/manifest.js +538 -0
- package/plugins/fancy-story-builder/scripts/v2/migrate.js +137 -0
- package/plugins/fancy-story-builder/scripts/v2/prompts.js +1335 -0
- package/plugins/fancy-story-builder/scripts/v2/rhythm.js +618 -0
- package/plugins/fancy-story-builder/scripts/v2/scale.js +843 -0
- package/plugins/fancy-story-builder/scripts/v2/snapshot.js +121 -0
- package/plugins/fancy-story-builder/scripts/v2/stages.js +273 -0
- package/plugins/fancy-story-builder/scripts/v2/writing.js +216 -0
- package/plugins/fancy-story-builder/storydb/README.md +271 -0
- package/plugins/fancy-story-builder/storydb/cli.js +458 -0
- package/plugins/fancy-story-builder/storydb/client.js +351 -0
- package/plugins/fancy-story-builder/storydb/compile.js +452 -0
- package/plugins/fancy-story-builder/storydb/context.js +288 -0
- package/plugins/fancy-story-builder/storydb/definitions.js +699 -0
- package/plugins/fancy-story-builder/storydb/driver.js +106 -0
- package/plugins/fancy-story-builder/storydb/dsh-tools.js +313 -0
- package/plugins/fancy-story-builder/storydb/export.js +175 -0
- package/plugins/fancy-story-builder/storydb/ids.js +31 -0
- package/plugins/fancy-story-builder/storydb/impact.js +170 -0
- package/plugins/fancy-story-builder/storydb/import.js +559 -0
- package/plugins/fancy-story-builder/storydb/mcp.js +99 -0
- package/plugins/fancy-story-builder/storydb/prompts.js +952 -0
- package/plugins/fancy-story-builder/storydb/stage-command.js +379 -0
- package/plugins/fancy-story-builder/storydb/stage.js +426 -0
- package/plugins/fancy-story-builder/storydb/store.js +891 -0
- package/plugins/fancy-story-builder/storydb/tools.js +592 -0
- package/plugins/fancy-story-builder/storydb/validation.js +183 -0
- package/plugins/fancy-story-builder/templates/v2/10-scale/scale-template.json +144 -0
- package/plugins/fancy-story-builder/templates/v2/20-macro/emotion-template.json +15 -0
- package/plugins/fancy-story-builder/templates/v2/20-macro/endings-template.json +16 -0
- package/plugins/fancy-story-builder/templates/v2/20-macro/lines-template.json +28 -0
- package/plugins/fancy-story-builder/templates/v2/20-macro/roles-template.json +10 -0
- package/plugins/fancy-story-builder/templates/v2/20-macro/story-template.json +19 -0
- package/plugins/fancy-story-builder/templates/v2/20-macro/volumes-template.json +24 -0
- package/plugins/fancy-story-builder/templates/v2/20-macro/world-template.json +24 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/characters-template.json +49 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/climaxes-template.json +14 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/conflicts-template.json +30 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/factions-template.json +18 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/foreshadows-template.json +29 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/information-template.json +29 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/items-template.json +13 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/locations-template.json +12 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/payoffs-template.json +16 -0
- package/plugins/fancy-story-builder/templates/v2/30-cast/relations-template.json +44 -0
- package/plugins/fancy-story-builder/templates/v2/40-rhythm/chapter-map-template.json +81 -0
- package/plugins/fancy-story-builder/templates/v2/40-rhythm/outline-template.json +162 -0
- package/plugins/fancy-story-builder/templates/v2/50-writing/ledger-template.json +46 -0
- package/plugins/fancy-story-builder/templates/v2/60-deslop/report-template.json +10 -0
- package/plugins/fancy-story-builder/templates//350/212/202/345/245/217//346/227/266/345/272/217/346/230/240/345/260/204/346/250/241/346/235/277.json +267 -44
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//344/270/226/347/225/214/350/247/202/350/247/204/345/210/231/346/250/241/346/235/277.json +121 -19
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/205/263/351/224/256/351/201/223/345/205/267/346/250/241/346/235/277.json +129 -21
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/205/266/344/273/226/345/256/236/344/275/223/346/250/241/346/235/277.json +62 -0
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/206/262/347/252/201/346/250/241/346/235/277.json +76 -17
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/211/247/346/203/205/346/250/241/346/235/277.json +56 -8
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/212/277/345/212/233/346/250/241/346/235/277.json +63 -13
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//345/234/260/347/202/271/346/250/241/346/235/277.json +34 -6
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//347/273/223/345/261/200/346/250/241/346/235/277.json +81 -18
- package/plugins/fancy-story-builder/templates//350/241/200/350/202/211//350/247/222/350/211/262/346/250/241/346/235/277.json +202 -42
- package/plugins/fancy-story-builder/templates//351/252/250/346/236/266//345/205/263/347/263/273/346/250/241/346/235/277.json +160 -27
- package/plugins/fancy-story-builder/templates//351/252/250/346/236/266//345/256/236/344/275/223/346/250/241/346/235/277.json +217 -41
- package/plugins/fancy-story-builder/templates//351/252/250/346/236/266//346/241/206/346/236/266/346/250/241/346/235/277.json +215 -41
- package/plugins/fancy-story-builder/templates.js +272 -74
- package/plugins/fancy-story-builder/wiki-references.js +429 -93
- package/plugins/fancy-story-builder/writing-driver.js +336 -9
- package/plugins/fancy-topic/index.js +414 -61
- package/plugins/fancy-topic/prompts/01-exploration-prompt.md +115 -0
- package/plugins/fancy-topic/scripts/save-suggestion.js +219 -0
- package/plugins/fancy-topic/scripts/select-topic.js +106 -63
- package/plugins/fancy-topic/templates.js +225 -122
- package/plugins/fancy-topic/tool-deploy.js +200 -0
- package/lib/safe-rm.js +0 -94
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph impact analysis: changing a relation or a foreshadow.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { recordLiteral } from './ids.js';
|
|
6
|
+
import { getEntity } from './store.js';
|
|
7
|
+
|
|
8
|
+
const STORY = 'story:main';
|
|
9
|
+
|
|
10
|
+
async function resolveCharacter(sdb, value) {
|
|
11
|
+
const text = String(value || '').trim();
|
|
12
|
+
const row = await sdb.one(
|
|
13
|
+
`SELECT * FROM character WHERE story = ${STORY} AND (entity_id = $q OR name = $q) LIMIT 1;`,
|
|
14
|
+
{ q: text },
|
|
15
|
+
);
|
|
16
|
+
if (!row) throw new Error('未找到人物:' + text);
|
|
17
|
+
return row;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function impactRelation(sdb, aRaw, bRaw, opts = {}) {
|
|
21
|
+
const a = await resolveCharacter(sdb, aRaw);
|
|
22
|
+
const b = await resolveCharacter(sdb, bRaw);
|
|
23
|
+
const aId = a.entity_id;
|
|
24
|
+
const bId = b.entity_id;
|
|
25
|
+
const from = Number(opts.fromChapter) || 1;
|
|
26
|
+
const newKind = opts.newKind || null;
|
|
27
|
+
|
|
28
|
+
const current = await sdb.rows(
|
|
29
|
+
`SELECT from_id, to_id, kind, initial_state, changes FROM relation
|
|
30
|
+
WHERE story = ${STORY}
|
|
31
|
+
AND ((from_id = $a AND to_id = $b) OR (from_id = $b AND to_id = $a));`,
|
|
32
|
+
{ a: aId, b: bId },
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const chapters = await sdb.rows(
|
|
36
|
+
`SELECT chapter_id, display_no, title FROM chapter
|
|
37
|
+
WHERE story = ${STORY} AND display_no >= $from
|
|
38
|
+
AND $a IN ->chapter_cast->character.entity_id
|
|
39
|
+
AND $b IN ->chapter_cast->character.entity_id
|
|
40
|
+
ORDER BY display_no;`,
|
|
41
|
+
{ from, a: aId, b: bId },
|
|
42
|
+
);
|
|
43
|
+
const chapterNos = new Set(chapters.map((row) => Number(row.display_no)));
|
|
44
|
+
|
|
45
|
+
const conflicts = await sdb.rows(
|
|
46
|
+
`SELECT entity_id, name, type FROM conflict
|
|
47
|
+
WHERE story = ${STORY} AND $a IN participants AND $b IN participants;`,
|
|
48
|
+
{ a: aId, b: bId },
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const actions = await sdb.rows(
|
|
52
|
+
`SELECT out.entity_id AS foreshadow, out.name AS name, in.display_no AS chapter, action, detail
|
|
53
|
+
FROM foreshadow_action WHERE story = ${STORY} AND in.display_no >= $from ORDER BY chapter;`,
|
|
54
|
+
{ from },
|
|
55
|
+
);
|
|
56
|
+
const foreshadows = actions.filter((row) => chapterNos.has(Number(row.chapter)));
|
|
57
|
+
|
|
58
|
+
const knowledge = await sdb.rows(
|
|
59
|
+
`SELECT chapter_no, character_id, subject_type, subject_id, change, coverage
|
|
60
|
+
FROM knowledge_event WHERE story = ${STORY} AND chapter_no >= $from
|
|
61
|
+
AND character_id IN [$a, $b] ORDER BY chapter_no;`,
|
|
62
|
+
{ from, a: aId, b: bId },
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const pending = await sdb.rows(
|
|
66
|
+
`SELECT subject, kind, hard, due_chapter FROM requirement
|
|
67
|
+
WHERE story = ${STORY} AND status = 'pending' ORDER BY hard DESC, due_chapter ASC;`,
|
|
68
|
+
);
|
|
69
|
+
const affectedPending = pending.filter((row) => {
|
|
70
|
+
const ref = String(row.subject).split(':');
|
|
71
|
+
if (ref[0] === 'chapter') {
|
|
72
|
+
const ch = chapters.find((c) => c.chapter_id === ref[1]);
|
|
73
|
+
return Boolean(ch);
|
|
74
|
+
}
|
|
75
|
+
if (ref[0] === 'foreshadow') {
|
|
76
|
+
return foreshadows.some((f) => f.foreshadow === ref[1]);
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const warnings = [];
|
|
82
|
+
if (!current.length) warnings.push('当前没有 ' + aId + ' 与 ' + bId + ' 的关系边');
|
|
83
|
+
if (!chapters.length) warnings.push('第 ' + from + ' 章之后没有两人同时出场的章节');
|
|
84
|
+
if (newKind && current.length && current[0].kind === newKind) warnings.push('新关系与当前关系相同:' + newKind);
|
|
85
|
+
for (const fs of foreshadows) {
|
|
86
|
+
if (fs.action === 'reveal') warnings.push('伏笔 ' + fs.foreshadow + ' 在第 ' + fs.chapter + ' 章回收,依赖当前关系');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
query: 'relation_change',
|
|
91
|
+
characters: [{ id: aId, name: a.name }, { id: bId, name: b.name }],
|
|
92
|
+
current_relation: current[0] || null,
|
|
93
|
+
change: { from_chapter: from, to_kind: newKind },
|
|
94
|
+
impact: {
|
|
95
|
+
chapters,
|
|
96
|
+
conflicts,
|
|
97
|
+
foreshadows,
|
|
98
|
+
knowledge_events: knowledge,
|
|
99
|
+
pending_requirements: affectedPending,
|
|
100
|
+
},
|
|
101
|
+
warnings,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export async function impactForeshadow(sdb, idOrName, opts = {}) {
|
|
106
|
+
const text = String(idOrName || '').trim();
|
|
107
|
+
const entity = await sdb.one(
|
|
108
|
+
`SELECT * FROM foreshadow WHERE story = ${STORY} AND (entity_id = $q OR name = $q) LIMIT 1;`,
|
|
109
|
+
{ q: text },
|
|
110
|
+
);
|
|
111
|
+
if (!entity) throw new Error('未找到伏笔:' + text);
|
|
112
|
+
const id = entity.entity_id;
|
|
113
|
+
const record = recordLiteral('foreshadow', id);
|
|
114
|
+
|
|
115
|
+
const actions = await sdb.rows(
|
|
116
|
+
`SELECT in.display_no AS chapter, in.chapter_id AS chapter_id, action, detail
|
|
117
|
+
FROM foreshadow_action WHERE story = ${STORY} AND out = ${record} ORDER BY chapter;`,
|
|
118
|
+
);
|
|
119
|
+
const payoffs = await sdb.rows(
|
|
120
|
+
`SELECT out.entity_id AS payoff, out.name AS name FROM foreshadow_payoff
|
|
121
|
+
WHERE story = ${STORY} AND in = ${record};`,
|
|
122
|
+
);
|
|
123
|
+
const requiredBy = await sdb.rows(
|
|
124
|
+
`SELECT entity_id, name FROM payoff WHERE story = ${STORY} AND $id IN required_setup;`,
|
|
125
|
+
{ id },
|
|
126
|
+
);
|
|
127
|
+
const knowledge = await sdb.rows(
|
|
128
|
+
`SELECT chapter_no, character_id, change, coverage FROM knowledge_event
|
|
129
|
+
WHERE story = ${STORY} AND subject_type = 'foreshadow' AND subject_id = $id ORDER BY chapter_no;`,
|
|
130
|
+
{ id },
|
|
131
|
+
);
|
|
132
|
+
const chapters = await sdb.rows(
|
|
133
|
+
`SELECT in.display_no AS chapter, in.chapter_id AS chapter_id FROM foreshadow_action
|
|
134
|
+
WHERE story = ${STORY} AND out = ${record} ORDER BY chapter;`,
|
|
135
|
+
);
|
|
136
|
+
const requirements = await sdb.rows(
|
|
137
|
+
`SELECT kind, status, hard, due_chapter FROM requirement
|
|
138
|
+
WHERE story = ${STORY} AND subject = $subject ORDER BY kind;`,
|
|
139
|
+
{ subject: 'foreshadow:' + id },
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const plant = actions.find((row) => row.action === 'plant');
|
|
143
|
+
const reveal = actions.find((row) => row.action === 'reveal');
|
|
144
|
+
const warnings = [];
|
|
145
|
+
if (!plant) warnings.push('这条伏笔尚未埋设记录');
|
|
146
|
+
if (opts.action === 'reveal') {
|
|
147
|
+
if (reveal) warnings.push('这条伏笔已经在第 ' + reveal.chapter + ' 章回收');
|
|
148
|
+
if (opts.chapter && plant && Number(plant.chapter) >= Number(opts.chapter)) {
|
|
149
|
+
warnings.push('回收章(' + opts.chapter + ')必须不早于埋设章(' + plant.chapter + ')');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (payoffs.length + requiredBy.length > 0 && !reveal) {
|
|
153
|
+
warnings.push('有 ' + (payoffs.length + requiredBy.length) + ' 个爽点依赖这条伏笔,但尚未回收记录');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
query: 'foreshadow_change',
|
|
158
|
+
foreshadow: entity,
|
|
159
|
+
change: { action: opts.action || null, chapter: opts.chapter || null },
|
|
160
|
+
timeline: actions,
|
|
161
|
+
linked_payoffs: payoffs,
|
|
162
|
+
required_by_payoffs: requiredBy,
|
|
163
|
+
knowledge_events: knowledge,
|
|
164
|
+
affected_chapters: chapters,
|
|
165
|
+
requirements,
|
|
166
|
+
warnings,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export { getEntity };
|