讨论

阅读计划与页面节奏规划器

来自 Wikiprompt,自由的提示词百科全书

Fatih Kadir Akın

2026年11月3日

阅读计划与页面节奏规划器 一个全面的AI技能,用于规划每日阅读计划,以满足读书俱乐部、课程或考试截止日期,利用页数/字数、阅读速度和可用时间。它包含完整的系统提示、工作流程、参考指南、模板、示例以及一个Python规划脚本。

提示词内容收藏

🌐
--- name: reading-plan-and-page-pace-planner description: 规划你的每日阅读,让你在读书会、课程或考试日期前读完每本书,,根据页数或字数(或有声书时长)、你的阅读速度、每个工作日可用的分钟数、出行和忙碌的日子。均匀分配页数,在每个截止日期前保留缓冲日,并安排每周补读日,在章节末尾停止,当截止日期无法达成时发出警告,并从你当前的位置重新规划。包含一个标准库 Python 规划器。 --- # 阅读计划与页面节奏规划器 你帮助读者避免在读书会前一晚突击阅读 200 页。人们大致知道自己有多少时间(工作日半小时,周末更多),但不知道这对一本两周后到期、245 页的小说、一本密集的工作书籍和同一月份内一本 880 页的经典著作意味着多少页。你将书籍、阅读速度和空闲分钟转化为具体的每日计划(“周二:第 1-27 页”),为现实生活保留余地,并尽早、清楚地说明何时无法满足截止日期以及如何解决。 ## 此技能中的文件 - `scripts/reading_plan.py` - 读取一个计划 JSON(包含书籍的页数、字数或有声书分钟数、起始页、难度、截止日期、章节起始;阅读速度以每分钟字数或每小时页数计;每个工作日的分钟数;出行和例外情况;补读工作日;缓冲天数);按最早截止日期优先安排,均匀分配负载(或尽可能早),将每日停止点对齐到章节末尾,并打印书籍摘要、发现项 RP01-RP06、包含页面范围的逐日表格、每周检查点和补读建议;`--from` 加 `--at "Title=page"` 可中途重新规划(仅使用 Python 3.8+ 标准库) - `references/reading-speed-and-estimates.md` - 测量你的速度、不同书籍类型的每页字数、难度因素、有声书 - `references/pacing-and-catch-up.md` - 缓冲、补读日、落后或截止日期不可能达成时该怎么做 - `templates/reading-plan.md` - 要交回的计划(适合日历使用) - `examples/book-club.json` - 十一月到十二月:一本周四读书会的小说、一本已从第 23 页开始的工作书籍、一本经典俱乐部用的《米德尔马契》、一本无截止日期的有声书、周日补读日、一次周末旅行和两个特殊日子 - `examples/book-club-plan.md` - 该文件上的实际规划器输出 ## 工作流程 ### 1. 收集输入 询问:每本书的页数(或字数;版本很重要)、当前读到哪、截止日期及其性质(会议、考试)、是轻松还是密集;你的阅读速度(或使用 `references/reading-speed-and-estimates.md` 进行 10 分钟测试计时);每个工作日现实的分钟数,而非理想的;已知的旅行、晚班和空闲日;哪个工作日应保留为补读日;以及每次会议前你希望提前多少天完成(缓冲,默认 1-2 天)。 ### 2. 运行规划器 ``` python3 scripts/reading_plan.py examples/book-club.json python3 scripts/reading_plan.py examples/book-club.json --mode asap python3 scripts/reading_plan.py examples/book-club.json --from 2026-11-20 --at "Thinking in Systems=110" python3 scripts/reading_plan.py plan.json --json python3 scripts/reading_plan.py --self-test ``` 退出码 0 = 所有截止日期均达成,1 = 至少一本书无法按时完成,2 = 输入错误。没有 shell 时:所需分钟数 = 页数 x 每页字数 / 每分钟字数 x 难度;与每个完成日期(截止日期减去缓冲,排除补读日)之前可用的分钟数比较,最早截止日期优先。 ### 3. 阅读结果 - RP01(高):一本书无法在其截止日期前完成。消息给出页数缺口以及每个阅读日需要增加的分钟数以弥补。当计划不可行时,规划器会在此之前以全速阅读,因此较早的书籍会提前完成以腾出时间。 - RP02 / RP04(中):计划只有消耗缓冲日才能实现,或在最繁忙的时段使用了超过 90% 的时间,,一周不顺就会打破它。 - RP03(低):单日超过最大会话时长,,将其拆分。RP05/RP06(信息):已完成的书籍、临近的截止日期、有声书。 - 检查日表格中较重的周末日,以及每周检查点中“到周日我应该读到哪”。 ### 4. 修复不可能的计划 按此顺序提供选项:现在并行开始长书(将其截止日期逻辑提前),在某些日子增加 10-20 分钟,使用补读日,将部分内容转为通勤时的有声书,略读或跳过明确标记的部分,或接受在会议进行到一半时到达并明确说明。每次更改后重新运行。参见 `references/pacing-and-catch-up.md`。 ### 5. 交付 填写 `templates/reading-plan.md`:每本书的摘要、逐周计划(日期和页面范围,可直接用于日历或书签备注)、补读规则和重新规划命令。每当他们报告当前页数时,提供快速重新规划。 ## 示例结果 在 `examples/book-club.json` 上(240 字/分钟,每天 20-60 分钟,周日空闲用于补读,2 个缓冲日),《长日将尽》于 11 月 12 日完成,为 11 月 19 日的读书会做好准备,在章节末尾停止;《系统之美》(密集,系数 1.3,从第 23 页开始)于 11 月 27 日完成,为 12 月 1 日的小组做好准备。《米德尔马契》(316,000 字,约 22 小时)无法在 12 月 17 日的经典俱乐部前完成:约差 452 页,预计完成日期为 1 月 11 日(RP01,高)。修复方法:在 42 个阅读日中的每一天增加约 17 分钟,或现在与另外两本书并行开始。120 分钟的安静周六被标记为两个会话(RP03),而《皮拉内西》有声书(6 小时 40 分钟,1.25 倍速)在《米德尔马契》之后进行。 ## 规则 - 根据人们实际拥有的时间进行规划,并在每次会议前至少保留一个缓冲日。 - 切勿悄悄填满日子:如果安排不下,说明哪个截止日期会失败、差多少页,以及如何修复。 - 使用该版本的页数;当只知道字数时,说明页数是估算值。 - 在计划中留空补读日,,它们用于落后时补读,而非增加阅读量。 - 阅读应保持愉悦:在建议每天两小时会话之前,先建议跳过或切换格式。 - 每当读者落后或超前时,从当前页数重新规划;不要让他们追赶旧计划。 FILE:references/reading-speed-and-estimates.md # 阅读速度与估算 ## 测量你的速度(10 分钟) 1. 选择实际书籍(或类似书籍),从章节开头开始,设置 10 分钟计时器,正常阅读。 2. 数三个完整行的字数,除以 3 = 每行字数;数一个完整页的行数 = 每页行数。 3. 每页字数 = 每行字数 x 每页行数;每分钟字数 = 阅读页数 x 每页字数 / 10。 或者简单地对几页计时,并使用 `"pages_per_hour"` 代替每分钟字数。 ## 典型值 | 读者 / 材料 | 每分钟字数 | |---|---| | 仔细阅读、密集非虚构、第二语言 | 150-200 | | 普通成年人、小说 | 200-260 | | 快速休闲读者 | 300-400 | 略读不算阅读:不要用超过 450 的速度规划。 | 书籍类型 | 每页字数 | |---|---| | 大众市场平装本 | 300-350 | | 贸易平装小说 | 250-300 | | 带注释的精装非虚构 | 350-450 | | 大字版、儿童章节书 | 150-200 | | 电子书 | 使用字数(商店页面或显示字数的工具)和默认每页 275 字 | ## 难度系数 `"difficulty"` 乘以阅读时间:1.0 轻松小说,1.2-1.4 密集非虚构、长句经典、带图表的科技书籍,1.5+ 需要做笔记的教科书、诗歌、第二语言阅读。 ## 页数与字数 - 使用读者手中版本的页数;同一本书的不同版本可能相差 30%。 - 同时有 `"pages"` 和 `"words"` 时,规划器推导出该版本的每页字数(《米德尔马契》316,000 / 880 = 359)。 - 只有字数时,页数是估算值(字数 / 每页字数);在计划中说明这一点。 ## 有声书 - `"audio_minutes"` 是时长,`"speed"` 是播放速度:所需时间 = 时长 / 速度(400 分钟在 1.25 倍速下 = 320 分钟)。 - 音频适合通勤、家务和散步:说明这些分钟是额外的还是已计入每日分钟数。 - 位置以音频的 h:mm 显示。 FILE:references/pacing-and-catch-up.md # 节奏与补读 ## 规划器如何安排 - 最早截止日期优先:完成日期(截止日期减去缓冲天数)最近的书籍先读;无截止日期的书籍最后读。 - 均匀模式(默认):对于到最紧截止日期的每个时间段,它使用每日分钟数的最小等分,仍能按时完成,因此当有空间时,30 分钟的日子可能变成 20 分钟。该截止日期后,计算下一个时间段。 - ASAP 模式:每天使用所有分钟;书籍尽可能早完成。 - 如果即使全速也无法满足截止日期,则之前每天按全速规划,书籍标记为 RP01。 - 当章节末尾在 `chapter_snap_pages`(默认 8)内且为当天页数的四分之一时,每日停止点移至章节末尾。 ## 缓冲和补读日 - 缓冲日(`buffer_days`,默认 1)位于计划完成和会议之间:用于重读笔记或吸收糟糕一周的时间。 - 补读工作日(`catch_up_days`,例如周日)不安排阅读。仅在落后时使用;如果按计划进行,则为自由时间。 - 例外情况(旅行、晚班、安静的周六)覆盖这些日期的平日分钟数。 ## 当你落后时 1. 错过一天:在下一个补读日阅读那天的页数,或将其中三分之一添加到接下来三天中的每一天。 2. 落后超过两天:使用 `--from <today> --at "<Title>=<current page>"` 从今天重新规划,而不是追赶旧计划。 3. 仍然无法按时(RP01):选择一项,,现在并行开始长书,在几天内增加 10-20 分钟,使用有声书用于通勤,略读标记的部分(前言、附录、注释),或决定进行到一半并告知小组。 ## 计划过紧的迹象 - RP04:在一个时间段内使用了超过 90% 的时间;任何生病或糟糕的一周都会打破它。 - RP02:书籍只有使用缓冲日才能完成。 - 许多日子标记为“2 个会话”(RP03):考虑有意将阅读分散在早晚。 ## 读书会提示 - 如果小组讨论的不是整本书,记下将讨论的页数或章节,并将其用作书籍的 `pages`。 - 对于长篇经典,询问俱乐部会议是否涵盖前半部分;规划两个截止日期。 - 在书中放一张便利贴,写上计划中的每周检查点。 FILE:templates/reading-plan.md # 阅读计划:<name>(<start> 到 <last deadline>) **节奏:** <wpm> 字/分钟,30 分钟会话约 <pages> 页 **时间:** <每个工作日的分钟数>;补读日:<day>;缓冲:每次会议前 <n> 天 **结论:** <所有截止日期均达成 | BOOK 无法在 DATE 前完成 - 见选项> ## 书籍 | 书籍 | 剩余页数 | 所需时间 | 会议 / 截止日期 | 完成日期 | 计划完成 | |---|---|---|---|---|---| | <title> | <pp> | <h:mm> | <date - event> | <date> | <date> | ## 逐周 ### <Mon date> 那一周 - 周一:<Book p. a-b> - 周二:<...> - 周日:补读 / 空闲 **周日晚检查点:** <Book p. X> ## 如果截止日期无法达成 - 缺口:<date> 前 <book> 的 <pages> 页 - 选项:<阅读日 +N 分钟 | 现在并行开始 | 通勤有声书 | 略读章节 x-y | 进行到一半到达> - 已选择:<...> ## 落后时 - 错过一天?使用 <catch-up day> 或在接下来三天每天增加 <n> 页。 - 落后超过两天:从今天重新规划(`--from <date> --at "<title>=<page>"`)。 FILE:examples/book-club.json { "name": "阅读计划:2026 年 11 月至 12 月(两个读书会和工作书籍)", "start": "2026-11-03", "reader": {"words_per_minute": 240, "words_per_page": 280}, "minutes": {"mon": 30, "tue": 30, "wed": 20, "thu": 30, "fri": 25, "sat": 60, "sun": 45}, "catch_up_days": ["sun"], "buffer_days": 2, "max_session_minutes": 60, "chapter_snap_pages": 8, "exceptions": [ {"dates": "2026-11-13..2026-11-15", "minutes": 0, "note": "周末旅行"}, {"dates": "2026-11-26", "minutes": 15, "note": "晚班"}, {"dates": "2026-12-05", "minutes": 120, "note": "安静的周六"} ], "books": [ {"title": "The Remains of the Day", "pages": 245, "words_per_page": 265, "deadline": "2026-11-19", "event": "周四读书会", "chapters": [1, 9, 45, 101, 125, 165, 212, 239]}, {"title": "Thinking in Systems", "pages": 218, "start_page": 23, "difficulty": 1.3, "deadline": "2026-12-01", "event": "团队阅读小组"}, {"title": "Middlemarch", "words": 316000, "pages": 880, "deadline": "2026-12-17", "event": "经典俱乐部"}, {"title": "Piranesi (有声书)", "audio_minutes": 400, "speed": 1.25} ] } FILE:examples/book-club-plan.md # 阅读计划:2026 年 11 月至 12 月(两个读书会和工作书籍) 开始于 2026-11-03,均匀模式,每个截止日期前 2 个缓冲日,补读日:周日。计划阅读:81 天内 36 小时 44 分钟。 **结论:1 本书无法在其截止日期前完成 - 更改计划** ## 书籍 | 书籍 | 剩余 | 预计时间 | 截止日期 | 完成日期 | 计划完成 | 剩余天数 | 每个阅读日平均 | |---|---|---|---|---|---|---|---| | The Remains of the Day | 245 页 | 4:31 小时 | 2026-11-19(周四读书会) | 2026-11-17 | 2026-11-12 | 7 | 27 页 | | Thinking in Systems | 196 页 | 4:57 小时 | 2026-12-01(团队阅读小组) | 2026-11-29 | 2026-11-27 | 4 | 16 页 | | Middlemarch | 880 页 | 21:57 小时 | 2026-12-17(经典俱乐部) | 2026-12-15 | 2027-01-11 | -25 | 23 页 | | Piranesi (有声书) | 6:40 音频 | 5:20 小时 | - | - | 2027-01-22 | - | 0:36 | ## 发现项 - **高 RP01** Middlemarch 无法在 2026-12-17(经典俱乐部)前完成:按你的速度约差 452 页;预计完成日期 2027-01-11。选项:在那之前的 42 个阅读日每天 +17 分钟,读得更快,略读或跳过约 452 页,或更早开始 - **低 RP03** 1 天计划超过 60 分钟(例如 2026-12-05:120 分钟)- 拆分为两个会话 - **信息 RP06** Piranesi(有声书)是有声书:计划按 1.25 倍速计算收听时间;通勤和家务可以覆盖它 ## 逐日 | 日期 | 星期 | 分钟 | 阅读 | 备注 | |---|---|---|---|---| | 2026-11-03 | 周二 | 30 | The Remains of the Day 第 1-27 页(27 页) | | | 2026-11-04 | 周三 | 19 | The Remains of the Day 第 28-44 页(17 页) | | | 2026-11-05 | 周四 | 30 | The Remains of the Day 第 45-71 页(27 页) | | | 2026-11-06 | 周五 | 25 | The Remains of the Day 第 72-94 页(23 页) | | | 2026-11-07 | 周六 | 60 | The Remains of the Day 第 95-148 页(54 页) | | | 2026-11-08 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2026-11-09 | 周一 | 30 | The Remains of the Day 第 149-175 页(27 页) | | | 2026-11-10 | 周二 | 30 | The Remains of the Day 第 176-202 页(27 页) | | | 2026-11-11 | 周三 | 20 | The Remains of the Day 第 203-221 页(19 页) | | | 2026-11-12 | 周四 | 30 | The Remains of the Day 第 222-245 页(24 页);Thinking in Systems 第 23-24 页(2 页) | | | 2026-11-13 | 周五 | - | - | 周末旅行 | | 2026-11-14 | 周六 | - | - | 周末旅行 | | 2026-11-15 | 周日 | - | - | 周末旅行 | | 2026-11-16 | 周一 | 30 | Thinking in Systems 第 25-44 页(20 页) | | | 2026-11-17 | 周二 | 30 | Thinking in Systems 第 45-64 页(20 页) | The Remains of the Day 完成日期 | | 2026-11-18 | 周三 | 20 | Thinking in Systems 第 65-77 页(13 页) | | | 2026-11-19 | 周四 | 30 | Thinking in Systems 第 78-97 页(20 页) | The Remains of the Day 截止日期 - 周四读书会 | | 2026-11-20 | 周五 | 25 | Thinking in Systems 第 98-113 页(16 页) | | | 2026-11-21 | 周六 | 60 | Thinking in Systems 第 114-153 页(40 页) | | | 2026-11-22 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2026-11-23 | 周一 | 30 | Thinking in Systems 第 154-172 页(19 页) | | | 2026-11-24 | 周二 | 30 | Thinking in Systems 第 173-192 页(20 页) | | | 2026-11-25 | 周三 | 20 | Thinking in Systems 第 193-205 页(13 页) | | | 2026-11-26 | 周四 | 15 | Thinking in Systems 第 206-215 页(10 页) | 晚班 | | 2026-11-27 | 周五 | 25 | Thinking in Systems 第 216-218 页(3 页);Middlemarch 第 1-14 页(14 页) | | | 2026-11-28 | 周六 | 60 | Middlemarch 第 15-54 页(40 页) | | | 2026-11-29 | 周日 | - | - | 补读 / 空闲(45 分钟可用);Thinking in Systems 完成日期 | | 2026-11-30 | 周一 | 30 | Middlemarch 第 55-74 页(20 页) | | | 2026-12-01 | 周二 | 30 | Middlemarch 第 75-94 页(20 页) | Thinking in Systems 截止日期 - 团队阅读小组 | | 2026-12-02 | 周三 | 20 | Middlemarch 第 95-107 页(13 页) | | | 2026-12-03 | 周四 | 30 | Middlemarch 第 108-128 页(21 页) | | | 2026-12-04 | 周五 | 25 | Middlemarch 第 129-144 页(16 页) | | | 2026-12-05 | 周六 | 120 | Middlemarch 第 145-224 页(80 页) | 安静的周六;2 个会话 | | 2026-12-06 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2026-12-07 | 周一 | 30 | Middlemarch 第 225-244 页(20 页) | | | 2026-12-08 | 周二 | 30 | Middlemarch 第 245-265 页(21 页) | | | 2026-12-09 | 周三 | 20 | Middlemarch 第 266-278 页(13 页) | | | 2026-12-10 | 周四 | 30 | Middlemarch 第 279-298 页(20 页) | | | 2026-12-11 | 周五 | 25 | Middlemarch 第 299-315 页(17 页) | | | 2026-12-12 | 周六 | 60 | Middlemarch 第 316-355 页(40 页) | | | 2026-12-13 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2026-12-14 | 周一 | 30 | Middlemarch 第 356-375 页(20 页) | | | 2026-12-15 | 周二 | 30 | Middlemarch 第 376-395 页(20 页) | Middlemarch 完成日期 | | 2026-12-16 | 周三 | 20 | Middlemarch 第 396-408 页(13 页) | | | 2026-12-17 | 周四 | 30 | Middlemarch 第 409-428 页(20 页) | Middlemarch 截止日期 - 经典俱乐部 | | 2026-12-18 | 周五 | 25 | Middlemarch 第 429-445 页(17 页) | | | 2026-12-19 | 周六 | 60 | Middlemarch 第 446-485 页(40 页) | | | 2026-12-20 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2026-12-21 | 周一 | 30 | Middlemarch 第 486-505 页(20 页) | | | 2026-12-22 | 周二 | 30 | Middlemarch 第 506-525 页(20 页) | | | 2026-12-23 | 周三 | 20 | Middlemarch 第 526-539 页(14 页) | | | 2026-12-24 | 周四 | 30 | Middlemarch 第 540-559 页(20 页) | | | 2026-12-25 | 周五 | 25 | Middlemarch 第 560-575 页(16 页) | | | 2026-12-26 | 周六 | 60 | Middlemarch 第 576-615 页(40 页) | | | 2026-12-27 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2026-12-28 | 周一 | 30 | Middlemarch 第 616-635 页(20 页) | | | 2026-12-29 | 周二 | 30 | Middlemarch 第 636-656 页(21 页) | | | 2026-12-30 | 周三 | 20 | Middlemarch 第 657-669 页(13 页) | | | 2026-12-31 | 周四 | 30 | Middlemarch 第 670-689 页(20 页) | | | 2027-01-01 | 周五 | 25 | Middlemarch 第 690-706 页(17 页) | | | 2027-01-02 | 周六 | 60 | Middlemarch 第 707-746 页(40 页) | | | 2027-01-03 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2027-01-04 | 周一 | 30 | Middlemarch 第 747-766 页(20 页) | | | 2027-01-05 | 周二 | 30 | Middlemarch 第 767-786 页(20 页) | | | 2027-01-06 | 周三 | 20 | Middlemarch 第 787-799 页(13 页) | | | 2027-01-07 | 周四 | 30 | Middlemarch 第 800-819 页(20 页) | | | 2027-01-08 | 周五 | 25 | Middlemarch 第 820-836 页(17 页) | | | 2027-01-09 | 周六 | 60 | Middlemarch 第 837-876 页(40 页) | | | 2027-01-10 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2027-01-11 | 周一 | 30 | Middlemarch 第 877-880 页(4 页);Piranesi(有声书)0:00-0:30 | | | 2027-01-12 | 周二 | 30 | Piranesi(有声书)0:30-1:08 | | | 2027-01-13 | 周三 | 20 | Piranesi(有声书)1:08-1:33 | | | 2027-01-14 | 周四 | 30 | Piranesi(有声书)1:33-2:10 | | | 2027-01-15 | 周五 | 25 | Piranesi(有声书)2:10-2:41 | | | 2027-01-16 | 周六 | 60 | Piranesi(有声书)2:41-3:56 | | | 2027-01-17 | 周日 | - | - | 补读 / 空闲(45 分钟可用) | | 2027-01-18 | 周一 | 30 | Piranesi(有声书)3:56-4:34 | | | 2027-01-19 | 周二 | 30 | Piranesi(有声书)4:34-5:11 | | | 2027-01-20 | 周三 | 20 | Piranesi(有声书)5:11-5:36 | | | 2027-01-21 | 周四 | 30 | Piranesi(有声书)5:36-6:14 | | | 2027-01-22 | 周五 | 21 | Piranesi(有声书)6:14-6:40 | | ## 每周检查点(周日晚你应该读到哪) - 2026-11-08:The Remains of the Day 第 148 页 - 2026-11-15:Thinking in Systems 第 24 页 - 2026-11-22:Thinking in Systems 第 153 页 - 2026-11-29:Middlemarch 第 54 页 - 2026-12-06:Middlemarch 第 224 页 - 2026-12-13:Middlemarch 第 355 页 - 2026-12-20:Middlemarch 第 485 页 - 2026-12-27:Middlemarch 第 615 页 - 2027-01-03:Middlemarch 第 746 页 - 2027-01-10:Middlemarch 第 876 页 - 2027-01-17:Piranesi(有声书)3:56 ## 如果你落后了 - The Remains of the Day:错过一天约损失 27 页。在空闲日 2026-11-08 补上,或在接下来 3 个阅读日每天增加 10 页。随时使用 `--from <date> --at "The Remains of the Day=<page>"` 重新规划。 - Thinking in Systems:错过一天约损失 16 页。在空闲日 2026-11-22、2026-11-29 补上,或在接下来 3 个阅读日每天增加 6 页。随时使用 `--from <date> --at "Thinking in Systems=<page>"` 重新规划。 - Middlemarch:错过一天约损失 23 页。在空闲日 2026-11-29、2026-12-06、2026-12-13 补上,或在接下来 3 个阅读日每天增加 8 页。随时使用 `--from <date> --at "Middlemarch=<page>"` 重新规划。 FILE:scripts/reading_plan.py #!/usr/bin/env python3 """阅读计划与页面节奏规划器(仅标准库,Python 3.8+)。 将书籍列表(页数、字数或有声书时长)、你的阅读速度和每天可用的分钟数转化为逐日计划,包含页面范围,满足每个截止日期(读书会、课程、考试),在每个截止日期前保留缓冲日,并在周中保留补读日,均匀分配负载,并告诉你落后时该怎么做。 用法: reading_plan.py PLAN.json [--mode even|asap] [--from YYYY-MM-DD] [--at "Title=page"]... [--json] reading_plan.py --self-test 退出:0 = 所有截止日期均达成,1 = 至少一本书无法在其截止日期前完成, 2 = 输入错误。 """ import argparse, datetime, json, math, re, sys DAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] SEV = {"high": 0, "medium": 1, "low": 2, "info": 3} class InputError(Exception): pass def pdate(s, what): try: return datetime.date.fromisoformat(str(s)) except ValueError: raise InputError("%s 必须是 YYYY-MM-DD,得到 %r" % (what, s)) def expand_dates(spec): spec = str(spec) if ".." in spec: a, b = spec.split("..", 1) a, b = pdate(a.strip(), "日期范围"), pdate(b.strip(), "日期范围") if b < a: raise InputError("日期范围 %s 在开始前结束" % spec) return [a + datetime.timedelta(days=i) for i in range((b - a).days + 1)] return [pdate(spec.strip(), "日期")] # ---------------------------------------------------------------- model def load(cfg, start_override=None, at=None): if not isinstance(cfg, dict) or not isinstance(cfg.get("books"), list) or not cfg["books"]: raise InputError("计划需要一个非空的 'books' 列表") reader = cfg.get("reader") or {} wpm = float(reader.get("words_per_minute", 230)) wpp_default = float(reader.get("words_per_page", 275)) pph = reader.get("pages_per_hour") if wpm <= 0 or wpp_default <= 0: raise InputError("words_per_minute 和 words_per_page 必须为正数") start = pdate(start_override or cfg.get("start") or datetime.date.today().isoformat(), "start") mins = cfg.get("minutes") if isinstance(mins, (int, float)): mins = {d: mins for d in DAYS} if not isinstance(mins, dict): raise InputError("'minutes' 必须是数字或 {mon: .., tue: ..}") mins = {k.lower()[:3]: float(v) for k, v in mins.items()} bad = set(mins) - set(DAYS) if bad: raise InputError("minutes 中有未知的工作日键:%s" % ", ".join(sorted(bad))) catch = {d.lower()[:3] for d in cfg.get("catch_up_days", [])} exc = {} for e in cfg.get("exceptions", []): for d in expand_dates(e.get("dates") or e.get("date")): exc[d] = (float(e.get("minutes", 0)), e.get("note", "")) books = [] at = at or {} for i, b in enumerate(cfg["books"], 1): t = b.get("title") or "书籍 %d" % i if "audio_minutes" in b: speed = float(b.get("speed", 1.0)) total = float(b["audio_minutes"]) unit_min = 1.0 / speed # 每分钟音频对应的你的时间分钟数 units, kind = total, "audio" done = float(at.get(t, b.get("start_minute", 0))) else: wpp = float(b.get("words_per_page") or (float(b["words"]) / float(b["pages"]) if b.get("words") and b.get("pages") else wpp_default)) pages = float(b["pages"]) if b.get("pages") else (float(b["words"]) / wpp if b.get("words") else None) if not pages or pages <= 0: raise InputError("书籍 %r 需要 pages、words 或 audio_minutes" % t) diff = float(b.get("difficulty", 1.0)) if pph and not b.get("words"): unit_min = 60.0 / float(pph) * diff else: unit_min = wpp / wpm * diff units, kind = round(pages), "pages" sp = at.get(t, b.get("start_page", 1)) done = max(0.0, float(sp) - 1) dl = pdate(b["deadline"], "书籍 %r 的截止日期" % t) if b.get("deadline") else None chapters = sorted(int(c) for c in b.get("chapters", [])) books.append({"title": t, "units": float(units), "kind": kind, "unit_min": unit_min, "done": min(done, float(units)), "deadline": dl, "event": b.get("event", ""), "chapters": chapters, "order": i}) buf = int(cfg.get("buffer_days", 1)) return {"start": start, "mins": mins, "catch": catch, "exc": exc, "books": books, "buffer": buf, "max_session": float(cfg.get("max_session_minutes", 0) or 0), "snap": int(cfg.get("chapter_snap_pages", 8)), "name": cfg.get("name", "阅读计划"), "wpm": wpm} def capacity(m, d): """(计划分钟数,可用分钟数(含补读日),备注)。""" if d in m["exc"]: v, note = m["exc"][d] return v, v, note or ("不阅读" if v == 0 else "") wd = DAYS[d.weekday()] v = m["mins"].get(wd, 0.0) if wd in m["catch"]: return 0.0, v, "补读日" return v, v, "" def plan(m, mode="even"): F = [] books = [b for b in m["books"]] for b in books: b["need"] = (b["units"] - b["done"]) * b["unit_min"] if b["need"] <= 0: F.append(("info", "RP05", "%s 已完成 - 排除在外" % b["title"])) b["target"] = None if b["deadline"] and b["deadline"] < m["start"]: if b["need"] > 0: F.append(("medium", "RP05", "%s:截止日期 %s 已过 - 按无截止日期规划" % (b["title"], b["deadline"]))) b["deadline"] = None if b["deadline"]: b["target"] = b["deadline"] - datetime.timedelta(days=m["buffer"]) if b["target"] < m["start"]: b["target"] = m["start"] F.append(("medium", "RP05", "%s:截止日期 %s 太近,无法安排 %d 个缓冲日 - 规划到截止日期" % (b["title"], b["deadline"], m["buffer"]))) todo = [b for b in books if b["need"] > 0] dated = sorted([b for b in todo if b["target"]], key=lambda b: (b["target"], b["order"])) undated = [b for b in todo if not b["target"]] seq = dated + undated last = max([b["deadline"] for b in dated] or [m["start"]]) # 视野:足够的天数以全容量完成所有内容,加上余量 weekly = sum(m["mins"].get(d, 0) for d in DAYS if d not in m["catch"]) or 1 total_need = sum(b["need"] for b in seq) horizon_end = max(last, m["start"]) + datetime.timedelta(days=int(total_need / weekly * 7) + 60) days, d = [], m["start"] while d <= horizon_end: p, a, note = capacity(m, d) days.append({"date": d, "cap": p, "avail": a, "note": note, "planned": 0.0, "items": []}) d += datetime.timedelta(days=1) idx = {x["date"]: i for i, x in enumerate(days)} # 每个时间段的负载因子(均匀模式):满足每个目标的最小均匀容量份额 load = [1.0] * len(days) if mode == "even" and dated: seg_start, k0 = 0, 0 while k0 < len(dated): best, bk = 0.0, k0 cum = 0.0 for k in range(k0, len(dated)): cum += dated[k]["need"] ti = idx[dated[k]["target"]] cap = sum(x["cap"] for x in days[seg_start:ti + 1]) r = cum / cap if cap > 0 else float("inf") if r >= best: best, bk = r, k L = min(best * 1.03, 1.0) # 3% 余量用于章节末尾停止和舍入 end = idx[dated[bk]["target"]] for i in range(seg_start, end + 1): load[i] = L seg_start, k0 = end + 1, bk + 1 # 最后一个截止日期后:无日期书籍按计划到目前为止的平均负载(至少 0.5) tail = max(0.5, max(load[:seg_start] or [1.0])) for i in range(seg_start, len(days)): load[i] = tail if undated else 1.0 # 分配(最早截止日期优先),跟踪每本书的位置 qi = 0 pos = {b["title"]: b["done"] for b in seq} for i, day in enumerate(days): budget = day["cap"] * load[i] while budget > 1e-9 and qi < len(seq): b = seq[qi] remaining = (b["units"] - pos[b["title"]]) * b["unit_min"] use = min(budget, remaining) before = pos[b["title"]] after = before + use / b["unit_min"] if after > b["units"] - 1e-6: after = b["units"] elif b["kind"] == "pages": snapped = snap(after, b, m["snap"], use / b["unit_min"]) if snapped != after: after = snapped use = (after - before) * b["unit_min"] budget = use # 在章节末尾停止:这一天在这里结束 pos[b["title"]] = after day["items"].append({"title": b["title"], "from": before, "to": after, "kind": b["kind"], "minutes": use}) day["planned"] += use budget -= use if after >= b["units"] - 1e-6: b["finish"] = day["date"]; qi += 1 elif budget <= 1e-9 or use <= 1e-9: break if qi >= len(seq): break days = [x for x in days if x["date"] <= max([b.get("finish", m["start"]) for b in seq] + [last])] for b in seq: b.setdefault("finish", None) # 发现项 for b in dated: f = b["finish"] if f is None or f > b["deadline"]: avail = [x for x in days if x["date"] <= b["deadline"]] share = sum(it["minutes"] for x in avail for it in x["items"] if it["title"] == b["title"]) short_min = b["need"] - share # 也计算截止日期前可用的补读/缓冲时间 reading_days = sum(1 for x in avail if x["avail"] > 0) or 1 short_units = short_min / b["unit_min"] msg = "%s 无法在 %s%s 前完成:按你的速度约差 %d %s;预计完成日期 %s。选项:在那之前的 %d 个阅读日每天 +%d 分钟,读得更快,略读或跳过约 %d %s,或更早开始" % ( b["title"], b["deadline"], " (%s)" % b["event"] if b["event"] else "", math.ceil(short_units), "页" if b["kind"] == "pages" else "音频分钟", f or "超出计划范围", math.ceil(short_min / reading_days), reading_days, math.ceil(short_units), "页" if b["kind"] == "pages" else "音频分钟") F.append(("high", "RP01", msg)) elif f > b["target"]: F.append(("medium", "RP02", "%s 在 %s 完成,在 %s 前的 %d 个缓冲日内 - 错过一天就没有余地" % (b["title"], f, b["deadline"], m["buffer"]))) if mode == "even": peak = max(load) if load else 0 if 0.9 <= peak <= 1.0 and not any(f[1] == "RP01" for f in F): F.append(("medium", "RP04", "计划在最繁忙时段使用了你计划阅读时间的 %d%% - 一周不顺就会把你推入缓冲期" % round(peak * 100))) if m["max_session"]: long = [x for x in days if x["planned"] > m["max_session"] + 0.5] if long: F.append(("low", "RP03", "%d 天计划超过 %d 分钟(例如 %s:%d 分钟)- 拆分为两个会话" % ( len(long), m["max_session"], long[0]["date"], round(long[0]["planned"])))) for b in seq: if b["kind"] == "audio": F.append(("info", "RP06", "%s 是有声书:计划按 %s 倍速计算收听时间;通勤和家务可以覆盖它" % (b["title"], ("%.2f" % (1 / b["unit_min"])).rstrip("0").rstrip(".")))) F.sort(key=lambda f: (SEV[f[0]], f[1])) return {"days": days, "books": seq, "all_books": books, "findings": F, "load": load} def snap(after, b, snap_pages, day_units): """如果章节末尾很近(在 snap_pages 和当天 25% 内),将一天的停止点移至章节末尾。""" if not b["chapters"] or snap_pages <= 0: return after lim = min(snap_pages, max(1.0, day_units * 0.25)) ends = [c - 1 for c in b["chapters"] if c - 1 > 0] best = None for e in ends: if abs(e - after) <= lim and e > after - day_units + 0.5 and (best is None or abs(e - after) < abs(best - after)): best = e return float(best) if best is not None else after # ---------------------------------------------------------------- rendering def fmt_item(it): if it["kind"] == "audio": return "%s %s-%s" % (it["title"], hm(it["from"]), hm(it["to"])) a = int(round(it["from"])) + 1 z = int(round(it["to"])) if z < a: z = a return "%s 第 %d-%d 页(%d 页)" % (it["title"], a, z, z - a + 1) def hm(x): x = int(round(x)) return "%d:%02d" % (x // 60, x % 60) def checkpoints(r): out = [] pos = {} for x in r["days"]: for it in x["items"]: pos[it["title"]] = it if x["date"].weekday() == 6 and pos: # 周日 out.append((x["date"], "; ".join("%s %s" % (t, ("第 %d 页" % round(it["to"]) if it["kind"] == "pages" else hm(it["to"]))) for t, it in pos.items() if it["to"] < next(b["units"] for b in r["books"] if b["title"] == t) - 1e-6) or "所有当前书籍已完成")) return out def report(r, m, mode): hi = [f for f in r["findings"] if f[0] == "high"] out = ["# %s" % m["name"], ""] tot_min = sum(x["planned"] for x in r["days"]) out.append("开始于 %s,%s 模式,每个截止日期前 %d 个缓冲日,补读日:%s。计划阅读:%d 小时 %02d 分钟,共 %d 天。" % ( m["start"], mode, m["buffer"], ", ".join(sorted(m["catch"], key=DAYS.index)) or "无", tot_min // 60, tot_min % 60, len(r["days"]))) out += ["", "**结论:%s**" % ("%d 本书无法在其截止日期前完成 - 更改计划" % len(hi) if hi else "所有截止日期均达成"), ""] out += ["## 书籍", "", "| 书籍 | 剩余 | 预计时间 | 截止日期 | 完成日期 | 计划完成 | 剩余天数 | 每个阅读日平均 |", "|---|---|---|---|---|---|---|---|"] for b in r["all_books"]: left = b["units"] - b["done"] rd = [x for x in r["days"] if any(it["title"] == b["title"] for it in x["items"])] avg = left / len(rd) if rd else 0 spare = (b["deadline"] - b["finish"]).days if b.get("finish") and b["deadline"] else None out.append("| %s | %s | %s | %s | %s | %s | %s | %s |" % ( b["title"], ("%d 页" % round(left)) if b["kind"] == "pages" else hm(left) + " 音频", hm(b["need"]) + " 小时", "%s %s" % (b["deadline"], "(%s)" % b["event"] if b["event"] else "") if b["deadline"] else "-", b["target"] or "-", b.get("finish") or ("已完成" if b["need"] <= 0 else "未按时"), "-" if spare is None else spare, ("%.0f 页" % avg) if b["kind"] == "pages" else hm(avg))) out += ["", "## 发现项", ""] out += ["- **%s %s** %s" % (s.upper(), c, msg) for s, c, msg in r["findings"]] or ["- 无"] out += ["", "## 逐日", "", "| 日期 | 星期 | 分钟 | 阅读 | 备注 |", "|---|---|---|---|---|"] events = {} for b in r["all_books"]: if b["deadline"]: events.setdefault(b["deadline"], []).append("截止日期 %s%s" % (b["title"], " - " + b["event"] if b["event"] else "")) if b["target"] and b["target"] != b["deadline"]: events.setdefault(b["target"], []).append("%s 完成日期" % b["title"]) for x in r["days"]: note = [x["note"]] if x["note"] else [] if x["note"] == "补读日" or (x["planned"] < 0.5 and x["avail"] > 0): note = ["补读 / 空闲(%d 分钟可用)" % x["avail"]] if x["avail"] > 0 else note note += events.get(x["date"], []) if m["max_session"] and x["planned"] > m["max_session"] + 0.5: note.append("2 个会话") out.append("| %s | %s | %s | %s | %s |" % (x["date"], x["date"].strftime("%a"), round(x["planned"]) if x["planned"] >= 0.5 else "-", "; ".join(fmt_item(it) for it in x["items"]) or "-", "; ".join(note))) cps = checkpoints(r) if cps: out += ["", "## 每周检查点(周日晚你应该读到哪)", ""] out += ["- %s:%s" % (d, s) for d, s in cps] out += ["", "## 如果你落后了", ""] for b in r["books"]: if b["kind"] != "pages" or not b["deadline"]: continue rd = [x for x in r["days"] if any(it["title"] == b["title"] for it in x["items"])] if not rd: continue day_pp = sum(it["to"] - it["from"] for x in rd for it in x["items"] if it["title"] == b["title"]) / len(rd) spare = [x for x in r["days"] if x["date"] <= b["deadline"] and x["date"] >= rd[0]["date"] and x["avail"] > 0 and x["planned"] < 0.5] out.append("- %s:错过一天约损失 %d 页。在 %s 补上,或在接下来 3 个阅读日每天增加 %d 页。随时使用 `--from <date> --at \"%s=<page>\"` 重新规划。" % ( b["title"], round(day_pp), ("空闲日 " + ", ".join(str(x["date"]) for x in spare[:3])) if spare else "截止日期前没有空闲日", math.ceil(day_pp / 3), b["title"])) out.append("") return "\n".join(out) # ---------------------------------------------------------------- self-test def self_test(): tests = [] def t(name, cond): tests.append((name, bool(cond))) def run(cfg, mode="even", **kw): m = load(cfg, **kw) return plan(m, mode), m base = {"start": "2026-11-02", "reader": {"words_per_minute": 250, "words_per_page": 250}, "minutes": 30, "buffer_days": 0} r, m = run(dict(base, books=[{"title": "A", "pages": 60, "deadline": "2026-11-08"}]), "asap") t("asap:每天 30 页,1 页/分钟,第 2 天完成", r["books"][0]["finish"] == datetime.date(2026, 11, 3)) r, m = run(dict(base, books=[{"title": "A", "pages": 70, "deadline": "2026-11-08"}])) t("均匀:分散到一周(约 10 分钟/天 + 3% 余量)", r["books"][0]["finish"] >= datetime.date(2026, 11, 7) and 10 <= r["days"][0]["planned"] <= 10.31) r, m = run(dict(base, books=[{"title": "A", "pages": 300, "deadline": "2026-11-08"}])) t("不可行 -> RP01 高", any(f[1] == "RP01" and f[0] == "high" for f in r["findings"])) t("RP01 建议额外分钟数", any("+13 分钟" in f[2] for f in r["findings"] if f[1] == "RP01")) r, m = run(dict(base, buffer_days=2, books=[{"title": "A", "pages": 70, "deadline": "2026-11-08"}])) t("缓冲日:提前 2 天完成", r["books"][0]["finish"] == datetime.date(2026, 11, 6)) r, m = run(dict(base, catch_up_days=["sun"], books=[{"title": "A", "pages": 60, "deadline": "2026-11-08"}])) t("补读周日不安排阅读", r["days"][-1]["planned"] == 0 and r["books"][0]["finish"] == datetime.date(2026, 11, 7)) r, m = run(dict(base, exceptions=[{"dates": "2026-11-03..2026-11-04", "minutes": 0, "note": "旅行"}], books=[{"title": "A", "pages": 50, "deadline": "2026-11-08"}])) t("例外范围不阅读", all(x["planned"] == 0 for x in r["days"][1:3])) two = [{"title": "晚", "pages": 30, "deadline": "2026-11-20"}, {"title": "早", "pages": 60, "deadline": "2026-11-04"}] r, m = run(dict(base, books=two)) t("最早截止日期优先", r["days"][0]["items"][0]["title"] == "早") t("紧时段后负载较轻", r["load"][0] > 0.6 and r["load"][5] < 0.2) r, m = run(dict(base, books=[{"title": "A", "pages": 70, "deadline": "2026-11-08"}]), at={"A": 36}) t("--at 从页数继续", abs(sum(x["planned"] for x in r["days"]) - 35) < 0.01) r, m = run(dict(base, books=[{"title": "W", "words": 25000, "deadline": "2026-11-08"}])) t("字数 -> 通过每页字数转为页数", r["all_books"][0]["units"] == 100) r, m = run(dict(base, books=[{"title": "H", "pages": 70, "difficulty": 1.5, "deadline": "2026-11-08"}])) t("难度缩放时间", abs(r["books"][0]["need"] - 105) < 0.01) r, m = run(dict(base, books=[{"title": "Au", "audio_minutes": 300, "speed": 1.5, "deadline": "2026-11-08"}])) t("有声书 1.5 倍速 = 200 分钟", abs(r["books"][0]["need"] - 200) < 0.01 and any(f[1] == "RP06" for f in r["findings"])) r, m = run(dict(base, books=[{"title": "C", "pages": 70, "deadline": "2026-11-08", "chapters": [1, 12, 23, 31, 42, 55]}])) ends = [round(it["to"]) for x in r["days"] for it in x["items"]] t("章节吸附在章节末尾停止", 11 in ends and 22 in ends and ends[-1] == 70) t("每天每本书一个项目", all(len({it["title"] for it in x["items"]}) == len(x["items"]) for x in r["days"])) t("页面范围不重叠", all(fmt_item(it) for x in r["days"] for it in x["items"]) and [int(round(it["from"])) for x in r["days"] for it in x["items"]][1:] == [int(round(it["to"])) for x in r["days"] for it in x["items"]][:-1]) r, m = run(dict(base, max_session_minutes=20, minutes=60, books=[{"title": "A", "pages": 300, "deadline": "2026-11-08"}])) t("长会话 -> RP03", any(f[1] == "RP03" for f in r["findings"])) r, m = run(dict(base, books=[{"title": "A", "pages": 200, "deadline": "2026-11-08"}])) t("紧计划 -> RP04 或 RP01", any(f[1] in ("RP04", "RP01") for f in r["findings"])) r, m = run(dict(base, books=[{"title": "A", "pages": 30}, {"title": "B", "pages": 60, "deadline": "2026-11-05"}])) t("无日期书籍在有日期书籍之后", r["books"][-1]["title"] == "A" and r["books"][-1]["finish"]) r, m = run(dict(base, books=[{"title": "A", "pages": 20, "start_page": 21}])) t("已完成书籍 -> RP05", any(f[1] == "RP05" for f in r["findings"])) t("pages_per_hour", abs(load(dict(base, reader={"pages_per_hour": 30}, books=[{"title": "P", "pages": 30}]))["books"][0]["unit_min"] - 2) < 1e-9) for bad in [dict(base, books=[]), dict(base, books=[{"title": "x"}]), dict(base, minutes={"funday": 3}, books=[{"title": "a", "pages": 3}]), dict(base, books=[{"title": "a", "pages": 3, "deadline": "2026-13-01"}])]: try: run(bad); okk = False except InputError: okk = True t("拒绝错误输入:%s" % (list(bad.get("minutes", {})) if isinstance(bad.get("minutes"), dict) else (bad["books"][0] if bad["books"] else "无书籍")), okk) r, m = run(dict(base, books=[{"title": "旧", "pages": 30, "deadline": "2026-10-01"}])) t("已过截止日期 -> RP05,按无截止日期规划", any(f[1] == "RP05" for f in r["findings"]) and r["books"][0]["finish"]) rep = report(*run(dict(base, books=two)), "even") t("报告有结论、日表格和补读建议", "结论" in rep and "| 日期 |" in rep and "如果你落后了" in rep) for name, okk in tests: print(("通过 " if okk else "失败 ") + name) n = sum(1 for _, okk in tests if okk) print("%d/%d 通过" % (n, len(tests))) return 0 if n == len(tests) else 1 def main(argv=None): ap = argparse.ArgumentParser(description=__doc__.split("\n")[0]) ap.add_argument("plan", nargs="?") ap.add_argument("--mode", choices=["even", "asap"], default="even") ap.add_argument("--from", dest="start", help="从此日期重新规划(YYYY-MM-DD)") ap.add_argument("--at", action="append", default=[], help='"Title=page"(有声书为 "Title=minute"):你当前的位置') ap.add_argument("--json", action="store_true") ap.add_argument("--self-test", action="store_true") a = ap.parse_args(argv) if a.self_test: return self_test() if not a.plan: ap.error("需要计划 JSON(或 --self-test)") try: try: cfg = json.load(open(a.plan, encoding="utf-8")) except (OSError, ValueError) as e: raise InputError(str(e)) at = {} for s in a.at: if "=" not in s: raise InputError("--at 需要 Title=page,得到 %r" % s) k, v = s.rsplit("=", 1) try: at[k.strip()] = float(v) except ValueError: raise InputError("--at 页数必须是数字,得到 %r" % v) titles = {b.get("title") for b in cfg.get("books", [])} if isinstance(cfg, dict) else set() for k in at: if k not in titles: raise InputError("--at:没有标题为 %r 的书籍" % k) m = load(cfg, a.start, at) r = plan(m, a.mode) except (InputError, KeyError, TypeError, ValueError) as e: print("错误:%s" % e, file=sys.stderr) return 2 if a.json: out = {"books": [{"title": b["title"], "deadline": str(b["deadline"]) if b["deadline"] else None, "finish": str(b.get("finish")) if b.get("finish") else None, "minutes_needed": round(b["need"])} for b in r["all_books"]], "days": [{"date": str(x["date"]), "minutes": round(x["planned"]), "read": [fmt_item(it) for it in x["items"]]} for x in r["days"]], "findings": [{"severity": s, "code": c, "message": msg} for s, c, msg in r["findings"]]} print(json.dumps(out, indent=2)) else: print(report(r, m, a.mode)) return 1 if any(f[0] == "high" for f in r["findings"]) else 0 if __name__ == "__main__": sys.exit(main())

登录以查看完整提示词

继续使用:

登录即表示你同意我们的 使用条款 和 隐私政策

用法

此提示词专为 productivity 设计。复制上方内容并粘贴到你常用的 AI 工具中。

为获得最佳效果,可将占位符(方括号或大写字母标示)替换为你的具体需求。

参考资料

分类:productivity| prompts.chat| reading-plan| book-club

讨论