Files
ainovel-clients/state/foreshadow.go
voocel 27bd85ef90 init
2026-03-07 21:25:55 +08:00

77 lines
1.9 KiB
Go

package state
import (
"fmt"
"os"
"strings"
"github.com/voocel/ainovel-cli/domain"
)
// SaveForeshadowLedger 全量写入 foreshadow_ledger.json + foreshadow_ledger.md。
func (s *Store) SaveForeshadowLedger(entries []domain.ForeshadowEntry) error {
if err := s.writeJSON("foreshadow_ledger.json", entries); err != nil {
return err
}
return s.writeMarkdown("foreshadow_ledger.md", renderForeshadow(entries))
}
// LoadForeshadowLedger 读取伏笔账本。
func (s *Store) LoadForeshadowLedger() ([]domain.ForeshadowEntry, error) {
var entries []domain.ForeshadowEntry
if err := s.readJSON("foreshadow_ledger.json", &entries); err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
return entries, nil
}
// UpdateForeshadow 批量应用伏笔增量操作。
func (s *Store) UpdateForeshadow(chapter int, updates []domain.ForeshadowUpdate) error {
entries, err := s.LoadForeshadowLedger()
if err != nil {
return err
}
idx := make(map[string]int, len(entries))
for i, e := range entries {
idx[e.ID] = i
}
for _, u := range updates {
switch u.Action {
case "plant":
entries = append(entries, domain.ForeshadowEntry{
ID: u.ID,
Description: u.Description,
PlantedAt: chapter,
Status: "planted",
})
case "advance":
if i, ok := idx[u.ID]; ok {
entries[i].Status = "advanced"
}
case "resolve":
if i, ok := idx[u.ID]; ok {
entries[i].Status = "resolved"
entries[i].ResolvedAt = chapter
}
}
}
return s.SaveForeshadowLedger(entries)
}
func renderForeshadow(entries []domain.ForeshadowEntry) string {
var b strings.Builder
b.WriteString("# 伏笔账本\n\n")
for _, e := range entries {
status := e.Status
if e.ResolvedAt > 0 {
status = fmt.Sprintf("已回收(第 %d 章)", e.ResolvedAt)
}
fmt.Fprintf(&b, "- **[%s]** %s — 埋设于第 %d 章,状态:%s\n",
e.ID, e.Description, e.PlantedAt, status)
}
return b.String()
}