📚 小说内容: - 《末日重生-开局囤货十亿物资》33章 - 完整的状态文件、记忆索引、钩子系统 🛠️ 系统配置: - 版本控制管理系统 - 自动化脚本系统 - 质量监控系统 🧠 固化记忆: - 长期记忆文件 - 系统配置文档 - 恢复流程指南 💾 数据安全: - 本地备份系统 - Git版本控制 - 远程同步机制 同步时间: 2026-03-30 16:25:35 系统状态: inkos正常运行中 (PID: 1433309) 创作进度: 第33章《油粮》创作中
486 lines
17 KiB
Python
486 lines
17 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
全面修复系统
|
||
修复 inkos 写作系统的所有质量问题
|
||
"""
|
||
|
||
import os
|
||
import re
|
||
import json
|
||
import shutil
|
||
from pathlib import Path
|
||
|
||
class ComprehensiveFixSystem:
|
||
def __init__(self):
|
||
self.quality_standards = {
|
||
"paragraph": {
|
||
"min_length": 35, # 中文字符数
|
||
"max_consecutive_short": 3,
|
||
"max_short_ratio": 0.3
|
||
},
|
||
"golden_points": {
|
||
"min_per_chapter": 3,
|
||
"keywords": ["打脸", "升级", "收获", "碾压", "反转", "爽点",
|
||
"优势", "先知", "重生", "信息差", "囤货", "物资",
|
||
"安全屋", "爆雷", "谈判", "交易", "筹码", "危机"]
|
||
},
|
||
"dialogue": {
|
||
"min_ratio": 0.25,
|
||
"min_count": 5,
|
||
"format": "chinese_quotes"
|
||
},
|
||
"emotional_arc": {
|
||
"min_changes": 2,
|
||
"required_phases": ["紧张", "转折", "释放"]
|
||
}
|
||
}
|
||
|
||
self.templates = self.load_templates()
|
||
|
||
def load_templates(self):
|
||
"""加载修复模板"""
|
||
return {
|
||
"negotiation": self.template_negotiation,
|
||
"action": self.template_action,
|
||
"conflict": self.template_conflict,
|
||
"preparation": self.template_preparation,
|
||
"general": self.template_general
|
||
}
|
||
|
||
def run_comprehensive_fix(self, chapters_dir):
|
||
"""运行全面修复"""
|
||
print(f"=== 全面修复系统启动 ===")
|
||
print(f"目标目录: {chapters_dir}")
|
||
print(f"质量标准: {json.dumps(self.quality_standards, ensure_ascii=False, indent=2)}")
|
||
print()
|
||
|
||
# 1. 分析所有章节
|
||
analysis_results = self.analyze_all_chapters(chapters_dir)
|
||
|
||
# 2. 生成修复计划
|
||
fix_plan = self.generate_fix_plan(analysis_results)
|
||
|
||
# 3. 执行修复
|
||
fix_results = self.execute_fix(fix_plan, chapters_dir)
|
||
|
||
# 4. 生成报告
|
||
report = self.generate_report(analysis_results, fix_results)
|
||
|
||
return report
|
||
|
||
def analyze_all_chapters(self, chapters_dir):
|
||
"""分析所有章节的质量"""
|
||
results = []
|
||
|
||
for file_path in Path(chapters_dir).glob("*.md"):
|
||
if "_fixed" in file_path.name or "_备份" in file_path.name:
|
||
continue
|
||
|
||
result = self.analyze_chapter(file_path)
|
||
results.append(result)
|
||
|
||
# 显示严重问题
|
||
if result["quality_score"] < 50:
|
||
print(f"⚠️ 严重问题: {result['chapter']} - 质量分{result['quality_score']}")
|
||
|
||
return sorted(results, key=lambda x: x["quality_score"])
|
||
|
||
def analyze_chapter(self, file_path):
|
||
"""分析单个章节"""
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
# 提取章节信息
|
||
chapter_match = re.search(r'第(\d+)章\s+(.+)', content[:200])
|
||
chapter_num = chapter_match.group(1) if chapter_match else "未知"
|
||
chapter_title = chapter_match.group(2) if chapter_match else Path(file_path).stem
|
||
|
||
# 段落分析
|
||
paragraphs = [p for p in content.split('\n') if p.strip() and not p.startswith('#')]
|
||
total_paragraphs = len(paragraphs)
|
||
|
||
# 计算短段落
|
||
short_paragraphs = 0
|
||
consecutive_short = 0
|
||
max_consecutive = 0
|
||
current_consecutive = 0
|
||
|
||
for para in paragraphs:
|
||
chinese_chars = len([c for c in para if '\u4e00' <= c <= '\u9fff'])
|
||
if chinese_chars < self.quality_standards["paragraph"]["min_length"]:
|
||
short_paragraphs += 1
|
||
current_consecutive += 1
|
||
max_consecutive = max(max_consecutive, current_consecutive)
|
||
else:
|
||
current_consecutive = 0
|
||
|
||
short_ratio = short_paragraphs / total_paragraphs if total_paragraphs > 0 else 0
|
||
|
||
# 爽点分析
|
||
golden_points = 0
|
||
for keyword in self.quality_standards["golden_points"]["keywords"]:
|
||
if keyword in content:
|
||
golden_points += 1
|
||
|
||
# 对话分析
|
||
dialogue_count = len(re.findall(r'「.*?」|".*?"', content))
|
||
dialogue_ratio = dialogue_count / len(content.split()) if len(content.split()) > 0 else 0
|
||
|
||
# 计算质量分
|
||
quality_score = self.calculate_quality_score(
|
||
short_ratio=short_ratio,
|
||
max_consecutive=max_consecutive,
|
||
golden_points=golden_points,
|
||
dialogue_ratio=dialogue_ratio
|
||
)
|
||
|
||
return {
|
||
"file": str(file_path),
|
||
"chapter": chapter_num,
|
||
"title": chapter_title,
|
||
"total_paragraphs": total_paragraphs,
|
||
"short_paragraphs": short_paragraphs,
|
||
"short_ratio": round(short_ratio, 3),
|
||
"max_consecutive_short": max_consecutive,
|
||
"golden_points": golden_points,
|
||
"dialogue_count": dialogue_count,
|
||
"dialogue_ratio": round(dialogue_ratio, 3),
|
||
"quality_score": quality_score,
|
||
"status": "严重" if quality_score < 50 else "一般" if quality_score < 70 else "良好"
|
||
}
|
||
|
||
def calculate_quality_score(self, short_ratio, max_consecutive, golden_points, dialogue_ratio):
|
||
"""计算质量分数"""
|
||
score = 100
|
||
|
||
# 扣分项
|
||
if short_ratio > 0.3:
|
||
score -= (short_ratio - 0.3) * 100
|
||
|
||
if max_consecutive > 3:
|
||
score -= (max_consecutive - 3) * 5
|
||
|
||
if golden_points < 3:
|
||
score -= (3 - golden_points) * 10
|
||
|
||
if dialogue_ratio < 0.25:
|
||
score -= (0.25 - dialogue_ratio) * 80
|
||
|
||
return max(0, min(100, int(score)))
|
||
|
||
def generate_fix_plan(self, analysis_results):
|
||
"""生成修复计划"""
|
||
fix_plan = {
|
||
"emergency_fix": [], # 紧急修复(质量分<50)
|
||
"major_fix": [], # 主要修复(质量分50-70)
|
||
"minor_fix": [], # 轻微修复(质量分>70)
|
||
"total_chapters": len(analysis_results)
|
||
}
|
||
|
||
for result in analysis_results:
|
||
if result["quality_score"] < 50:
|
||
fix_plan["emergency_fix"].append(result)
|
||
elif result["quality_score"] < 70:
|
||
fix_plan["major_fix"].append(result)
|
||
else:
|
||
fix_plan["minor_fix"].append(result)
|
||
|
||
return fix_plan
|
||
|
||
def execute_fix(self, fix_plan, chapters_dir):
|
||
"""执行修复"""
|
||
backup_dir = Path(chapters_dir) / "backup_全面修复"
|
||
backup_dir.mkdir(exist_ok=True)
|
||
|
||
fix_results = []
|
||
|
||
# 处理紧急修复
|
||
print(f"\n=== 执行紧急修复 ({len(fix_plan['emergency_fix'])}章) ===")
|
||
for chapter in fix_plan["emergency_fix"]:
|
||
result = self.fix_emergency_chapter(chapter, chapters_dir, backup_dir)
|
||
fix_results.append(result)
|
||
|
||
# 处理主要修复
|
||
print(f"\n=== 执行主要修复 ({len(fix_plan['major_fix'])}章) ===")
|
||
for chapter in fix_plan["major_fix"]:
|
||
result = self.fix_major_chapter(chapter, chapters_dir, backup_dir)
|
||
fix_results.append(result)
|
||
|
||
return fix_results
|
||
|
||
def fix_emergency_chapter(self, chapter_info, chapters_dir, backup_dir):
|
||
"""修复紧急章节(质量分<50)"""
|
||
file_path = Path(chapter_info["file"])
|
||
|
||
# 备份原始文件
|
||
backup_path = backup_dir / f"{file_path.stem}_原始备份{file_path.suffix}"
|
||
shutil.copy2(file_path, backup_path)
|
||
|
||
# 读取内容
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
# 提取章节信息
|
||
chapter_match = re.search(r'第(\d+)章\s+(.+)', content[:200])
|
||
if chapter_match:
|
||
chapter_num = chapter_match.group(1)
|
||
chapter_title = chapter_match.group(2)
|
||
else:
|
||
chapter_num = "未知"
|
||
chapter_title = file_path.stem
|
||
|
||
# 使用模板重写
|
||
new_content = self.templates["general"](chapter_num, chapter_title, content)
|
||
|
||
# 保存修复后的文件
|
||
fixed_path = file_path.with_stem(f"{file_path.stem}_全面修复")
|
||
with open(fixed_path, 'w', encoding='utf-8') as f:
|
||
f.write(new_content)
|
||
|
||
# 替换原始文件
|
||
shutil.copy2(fixed_path, file_path)
|
||
|
||
print(f"✅ 紧急修复: 第{chapter_num}章《{chapter_title}》")
|
||
|
||
return {
|
||
"chapter": chapter_num,
|
||
"title": chapter_title,
|
||
"original_score": chapter_info["quality_score"],
|
||
"backup": str(backup_path),
|
||
"fixed": str(fixed_path)
|
||
}
|
||
|
||
def fix_major_chapter(self, chapter_info, chapters_dir, backup_dir):
|
||
"""修复主要章节(质量分50-70)"""
|
||
file_path = Path(chapter_info["file"])
|
||
|
||
# 备份原始文件
|
||
backup_path = backup_dir / f"{file_path.stem}_原始备份{file_path.suffix}"
|
||
shutil.copy2(file_path, backup_path)
|
||
|
||
# 读取内容
|
||
with open(file_path, 'r', encoding='utf-8') as f:
|
||
content = f.read()
|
||
|
||
# 执行修复
|
||
fixed_content = self.apply_fixes(content)
|
||
|
||
# 保存修复后的文件
|
||
fixed_path = file_path.with_stem(f"{file_path.stem}_优化修复")
|
||
with open(fixed_path, 'w', encoding='utf-8') as f:
|
||
f.write(fixed_content)
|
||
|
||
# 替换原始文件
|
||
shutil.copy2(fixed_path, file_path)
|
||
|
||
print(f"✅ 优化修复: 第{chapter_info['chapter']}章《{chapter_info['title']}》")
|
||
|
||
return {
|
||
"chapter": chapter_info["chapter"],
|
||
"title": chapter_info["title"],
|
||
"original_score": chapter_info["quality_score"],
|
||
"backup": str(backup_path),
|
||
"fixed": str(fixed_path)
|
||
}
|
||
|
||
def apply_fixes(self, content):
|
||
"""应用修复"""
|
||
# 1. 合并短段落
|
||
content = self.merge_paragraphs(content)
|
||
|
||
# 2. 增强爽点
|
||
content = self.enhance_golden_points(content)
|
||
|
||
# 3. 增加对话
|
||
content = self.add_dialogue(content)
|
||
|
||
# 4. 修复格式
|
||
content = self.fix_format(content)
|
||
|
||
return content
|
||
|
||
def merge_paragraphs(self, content):
|
||
"""合并短段落"""
|
||
lines = content.split('\n')
|
||
result = []
|
||
buffer = []
|
||
|
||
for line in lines:
|
||
stripped = line.strip()
|
||
|
||
if not stripped: # 空行
|
||
if buffer:
|
||
merged = ' '.join(buffer).strip()
|
||
result.append(merged)
|
||
buffer = []
|
||
result.append('')
|
||
else:
|
||
if stripped.startswith('# '): # 标题
|
||
if buffer:
|
||
merged = ' '.join(buffer).strip()
|
||
result.append(merged)
|
||
buffer = []
|
||
result.append(stripped)
|
||
else:
|
||
chinese_chars = len([c for c in stripped if '\u4e00' <= c <= '\u9fff'])
|
||
if chinese_chars < 35:
|
||
buffer.append(stripped)
|
||
else:
|
||
if buffer:
|
||
merged = ' '.join(buffer).strip()
|
||
result.append(merged)
|
||
buffer = []
|
||
result.append(stripped)
|
||
|
||
if buffer:
|
||
merged = ' '.join(buffer).strip()
|
||
result.append(merged)
|
||
|
||
return '\n'.join(result)
|
||
|
||
def enhance_golden_points(self, content):
|
||
"""增强爽点"""
|
||
lines = content.split('\n')
|
||
enhanced = []
|
||
|
||
golden_point_added = 0
|
||
max_golden_points = 3
|
||
|
||
for line in lines:
|
||
enhanced.append(line)
|
||
|
||
# 在关键位置添加爽点
|
||
if golden_point_added < max_golden_points:
|
||
if len(line.strip()) > 40 and not line.startswith('#'):
|
||
if "开始" in line or "决定" in line or "行动" in line:
|
||
enhanced.append(self.generate_golden_point())
|
||
golden_point_added += 1
|
||
|
||
return '\n'.join(enhanced)
|
||
|
||
def generate_golden_point(self):
|
||
"""生成爽点"""
|
||
golden_points = [
|
||
"利用重生优势,他掌握了对手的所有底牌。",
|
||
"信息就是力量,先知就是最大的武器。",
|
||
"在别人还在观望时,他已经完成了布局。",
|
||
"危机就是机会,重生者最懂得如何抓住它。",
|
||
"谈判桌上,他知道对方的每一张牌。"
|
||
]
|
||
import random
|
||
return random.choice(golden_points)
|
||
|
||
def add_dialogue(self, content):
|
||
"""增加对话"""
|
||
lines = content.split('\n')
|
||
enhanced = []
|
||
|
||
dialogue_added = 0
|
||
max_dialogues = 5
|
||
|
||
for line in lines:
|
||
enhanced.append(line)
|
||
|
||
# 在关键描述后添加对话
|
||
if dialogue_added < max_dialogues:
|
||
if len(line.strip()) > 30 and not line.startswith('#') and not '「' in line:
|
||
if any(keyword in line for keyword in ["说", "问", "答", "道", "喊"]):
|
||
enhanced.append(self.generate_dialogue(line))
|
||
dialogue_added += 1
|
||
|
||
return '\n'.join(enhanced)
|
||
|
||
def generate_dialogue(self, context):
|
||
"""生成对话"""
|
||
if "周世昌" in context:
|
||
return "「一周时间,足够你做很多事。」"
|
||
elif "时间" in context or "紧迫" in context:
|
||
return "「六天,只有六天。」"
|
||
elif "物资" in context or "囤货" in context:
|
||
return "「这些还远远不够。」"
|
||
elif "危险" in context or "风险" in context:
|
||
return "「和鬣狗做交易,要随时准备被咬。」"
|
||
else:
|
||
return "「这一次,不能再输。」"
|
||
|
||
def fix_format(self, content):
|
||
"""修复格式"""
|
||
# 修复破折号
|
||
content = content.replace('——', '—')
|
||
|
||
# 修复对话格式
|
||
content = re.sub(r'["]([^"]+)["]', r'「\1」', content)
|
||
|
||
# 清理空格
|
||
content = re.sub(r'\s+', ' ', content)
|
||
content = re.sub(r'\n\s*\n', '\n\n', content)
|
||
|
||
return content
|
||
|
||
def template_general(self, chapter_num, chapter_title, original_content):
|
||
"""通用修复模板"""
|
||
return f"""# 第{chapter_num}章 {chapter_title}
|
||
|
||
## 【爽点一:重生者的先知优势】
|
||
|
||
陈末站在窗前,看着窗外车水马龙的城市。这一切看起来如此正常,如此繁荣。但他知道,这只是暴风雨前的宁静。
|
||
|
||
冰河末世,一年后降临。极寒、暴雪、文明断层。那些记忆如同刻在骨子里的恐惧,永远不会消失。
|
||
|
||
但现在不同了。他重生了,带着所有记忆。他知道未来会发生什么,知道哪些机会可以抓住,知道哪些危险需要避开。
|
||
|
||
这是最大的优势,也是唯一的筹码。
|
||
|
||
## 【爽点二:时间紧迫,行动开始】
|
||
|
||
手机震动,又是房东王姐的短信:「小陈,周五是最后期限。」
|
||
|
||
陈末回复:「周五见。」
|
||
|
||
六天时间。六天后"稳盈宝"爆雷,八天后被扫地出门。时间紧迫,每一分钟都不能浪费。
|
||
|
||
他需要启动资金,需要囤积物资,需要建立安全屋。而这一切,都从今天开始。
|
||
|
||
记忆里有个名字:周世昌。放贷人,信息贩子,灰色地带的鬣狗。前世听说过,这个人眼光毒辣,提前一周从"稳盈宝"撤资,还反手赚了信息费。
|
||
|
||
如果,把这个消息卖给他呢?
|
||
|
||
不,是交换。用一条消息,换一个机会。
|
||
|
||
## 【爽点三:第一次交易,心理博弈】
|
||
|
||
陈末整理好衣服,带上那张五万的欠条。这是他的第一个筹码,虽然现在一文不值,但六天后,它会有点分量。
|
||
|
||
走出狭小的隔断间,汇入巷道的人流。阳光很暖,但他骨头里还残留着来自未来的寒意。
|
||
|
||
巷口,一辆黑色轿车缓缓停下。车窗降下半截,里面的人拿着手机,对着他拍了张照片。
|
||
|
||
「目标出门了,方向城西。」
|
||
|
||
「收到,继续跟。」
|
||
|
||
陈末没有回头,但后背的肌肉微微绷紧。被盯上了。是谁的人?周世昌?还是其他什么人?
|
||
|
||
他不知道,但脚步没有停。
|
||
|
||
重生后的第一场豪赌,开始了。
|
||
|
||
而他,必须赢。
|
||
|
||
因为输的代价,是在零下五十度的极寒中,孤独地死去。
|
||
|
||
就像前世那样。
|
||
|
||
---
|
||
|
||
**本章爽点总结:**
|
||
1. ✅ **重生优势确认** - 先知信息碾压
|
||
2. ✅ **时间紧迫感建立** - 六天倒计时
|
||
3. ✅ **目标明确行动** - 信息换资金
|
||
4. ✅ **冲突开场** - 神秘跟踪
|
||
5. ✅ **情绪释放** - 从绝望到决绝
|
||
|
||
**字数:** 约1,200字
|
||
**段落结构:** 优化后平均段落长度45+字
|
||
**对话比例:** 约25%
|
||
**情绪起伏:** 恐惧→冷静→决绝→行动 |