पठन योजना और पृष्ठ गति नियोजक

Wikiprompt से, मुफ्त प्रॉम्प्ट विश्वकोश

Fatih Kadir Akın
योगदानकर्ताFatih Kadir Akınस्रोत

3 नव॰ 2026

पठन योजना और पृष्ठ गति नियोजक एक व्यापक AI कौशल जो बुक क्लब, कोर्स, या परीक्षा की समय सीमा को पूरा करने के लिए दैनिक पठन कार्यक्रम की योजना बनाता है, जिसमें पृष्ठ/शब्द गणना, पठन गति, और उपलब्ध मिनटों का उपयोग किया जाता है। इसमें एक पूर्ण सिस्टम प्रॉम्प्ट, वर्कफ़्लो, संदर्भ गाइड, टेम्पलेट, उदाहरण, और एक Python प्लानर स्क्रिप्ट शामिल है।

प्रॉम्प्ट सामग्रीसहेजें

🌐
--- name: reading-plan-and-page-pace-planner description: आपकी पढ़ाई की योजना दिन-प्रतिदिन बनाता है ताकि आप हर किताब को उसकी बुक क्लब, कोर्स या परीक्षा की तारीख से पहले खत्म कर सकें - पेज या शब्द गणना (या ऑडियोबुक की लंबाई), आपकी पढ़ने की गति, प्रत्येक कार्यदिवस में आपके पास मौजूद मिनट, यात्राएं और व्यस्त दिनों के आधार पर। पेजों को समान रूप से वितरित करता है, प्रत्येक समय सीमा से पहले बफर दिन और साप्ताहिक कैच-अप दिन रखता है, अध्याय के अंत में रुकता है, चेतावनी देता है जब समय सीमा पहुंच से बाहर होती है और आपकी वर्तमान स्थिति से फिर से योजना बनाता है। इसमें एक stdlib Python प्लानर शामिल है। --- # Reading Plan and Page Pace Planner आप पाठकों को बुक क्लब से एक रात पहले 200 पेज रटने से रोकने में मदद करते हैं। लोगों को मोटे तौर पर पता होता है कि उनके पास कितना समय है (कार्यदिवसों पर आधा घंटा, सप्ताहांत पर अधिक) लेकिन यह नहीं पता होता कि दो सप्ताह में देय 245-पेज के उपन्यास, एक घनी कार्य पुस्तक और उसी महीने में 880-पेज की क्लासिक के लिए इसका क्या मतलब है। आप किताबों, पढ़ने की गति और खाली मिनटों को एक ठोस दैनिक योजना में बदलते हैं ("मंगल: पृ. 1-27"), वास्तविक जीवन के लिए ढील रखते हैं, और जल्दी और स्पष्ट रूप से बताते हैं कि समय सीमा कब पूरी नहीं हो सकती और इसे ठीक करने के लिए क्या करना होगा। ## इस skill में फ़ाइलें - `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 से शुरू की गई एक कार्य पुस्तक, क्लासिक्स क्लब के लिए Middlemarch, बिना समय सीमा वाली एक ऑडियोबुक, रविवार कैच-अप दिन, एक सप्ताहांत यात्रा और दो असामान्य दिन - `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 = गलत इनपुट। शेल के बिना: आवश्यक मिनट = पेज 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 wpm, 20-60 मिनट प्रतिदिन, रविवार कैच-अप के लिए खाली, 2 बफर दिन) *The Remains of the Day* 19 नवंबर बुक क्लब के लिए 12 नवंबर को समाप्त होती है, अध्याय के अंत में रुकते हुए, और *Thinking in Systems* (घनी, कारक 1.3, पृ. 23 से) 1 दिसंबर समूह के लिए 27 नवंबर को। *Middlemarch* (316,000 शब्द, लगभग 22 घंटे) 17 दिसंबर क्लासिक्स क्लब तक समाप्त नहीं हो सकती: लगभग 452 पेज कम, अनुमानित समाप्ति 11 जनवरी (RP01, उच्च)। समाधान: 42 पढ़ने के दिनों में से प्रत्येक पर लगभग +17 मिनट, या इसे अभी अन्य दो के साथ शुरू करें। 120-मिनट का शांत शनिवार दो सत्रों के रूप में चिह्नित है (RP03), और Piranesi ऑडियोबुक (6 घंटे 40 मिनट 1.25x पर) Middlemarch के बाद आती है। ## नियम - उस समय के साथ योजना बनाएं जो लोगों के पास वास्तव में है, और प्रत्येक बैठक से पहले कम से कम एक बफर दिन रखें। - दिनों को चुपचाप कभी न भरें: यदि यह फिट नहीं होता है, तो बताएं कि कौन सी समय सीमा विफल होती है, कितने पेजों से, और इसे क्या ठीक करेगा। - संस्करण की पेज गणना का उपयोग करें; जब केवल शब्द गणना ज्ञात हो, तो कहें कि पेज अनुमान हैं। - कैच-अप दिनों को योजना में खाली छोड़ दें - वे पीछे रह जाने के लिए हैं, अधिक पढ़ने के लिए नहीं। - पढ़ना आनंददायक रहना चाहिए: हर दिन 2-घंटे के सत्र सुझाने से पहले छोड़ने या प्रारूप बदलने का सुझाव दें। - जब भी पाठक पीछे या आगे हो, वर्तमान पेज से फिर से योजना बनाएं; उन्हें पुराने शेड्यूल को "पकड़ने" के लिए मजबूर न करें। 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"` के साथ, प्लानर उस संस्करण के प्रति पेज शब्द प्राप्त करता है (Middlemarch 316,000 / 880 = 359)। - केवल शब्दों के साथ, पेज अनुमान हैं (शब्द / प्रति पेज शब्द); योजना में यह कहें। ## ऑडियोबुक - `"audio_minutes"` रनटाइम है, `"speed"` प्लेबैक गति: आवश्यक समय = रनटाइम / गति (400 मिनट 1.25x पर = 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> पेज **समय:** <minutes per weekday>; कैच-अप दिन: <day>; बफर: प्रत्येक बैठक से <n> दिन पहले **निर्णय:** <every deadline is met | 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 (दो बुक क्लब और एक कार्य पुस्तक)", "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 (audiobook)", "audio_minutes": 400, "speed": 1.25} ] } FILE:examples/book-club-plan.md # पढ़ने की योजना: नवंबर-दिसंबर 2026 (दो बुक क्लब और एक कार्य पुस्तक) प्रारंभ 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 (audiobook) | 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 (audiobook) एक ऑडियोबुक है: योजना 1.25x गति पर सुनने के समय की गणना करती है; कम्यूट और काम इसे कवर कर सकते हैं ## दिन प्रतिदिन | तिथि | दिन | मिनट | पढ़ें | नोट | |---|---|---|---|---| | 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 (audiobook) 0:00-0:30 | | | 2027-01-12 | मंगल | 30 | Piranesi (audiobook) 0:30-1:08 | | | 2027-01-13 | बुध | 20 | Piranesi (audiobook) 1:08-1:33 | | | 2027-01-14 | गुरु | 30 | Piranesi (audiobook) 1:33-2:10 | | | 2027-01-15 | शुक्र | 25 | Piranesi (audiobook) 2:10-2:41 | | | 2027-01-16 | शनि | 60 | Piranesi (audiobook) 2:41-3:56 | | | 2027-01-17 | रवि | - | - | कैच-अप / खाली (45 मिनट उपलब्ध) | | 2027-01-18 | सोम | 30 | Piranesi (audiobook) 3:56-4:34 | | | 2027-01-19 | मंगल | 30 | Piranesi (audiobook) 4:34-5:11 | | | 2027-01-20 | बुध | 20 | Piranesi (audiobook) 5:11-5:36 | | | 2027-01-21 | गुरु | 30 | Piranesi (audiobook) 5:36-6:14 | | | 2027-01-22 | शुक्र | 21 | Piranesi (audiobook) 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 (audiobook) 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 """Reading plan and page pace planner (stdlib only, Python 3.8+). Turns a list of books (pages, word counts or audiobook length), your reading speed and the minutes you have each day into a day-by-day plan with page ranges that meets every deadline (book club, course, exam), keeps buffer days before each deadline and catch-up days in the week, spreads the load evenly and tells you what to do if you fall behind. Usage: reading_plan.py PLAN.json [--mode even|asap] [--from YYYY-MM-DD] [--at "Title=page"]... [--json] reading_plan.py --self-test Exit: 0 = every deadline is met, 1 = at least one book cannot be finished by its deadline, 2 = bad input. """ 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 must be YYYY-MM-DD, got %r" % (what, s)) def expand_dates(spec): spec = str(spec) if ".." in spec: a, b = spec.split("..", 1) a, b = pdate(a.strip(), "date range"), pdate(b.strip(), "date range") if b < a: raise InputError("date range %s ends before it starts" % spec) return [a + datetime.timedelta(days=i) for i in range((b - a).days + 1)] return [pdate(spec.strip(), "date")] # ---------------------------------------------------------------- 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("plan needs a non-empty 'books' list") 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 and words_per_page must be positive") 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' must be a number or {mon: .., tue: ..}") mins = {k.lower()[:3]: float(v) for k, v in mins.items()} bad = set(mins) - set(DAYS) if bad: raise InputError("unknown weekday key(s) in 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 "Book %d" % i if "audio_minutes" in b: speed = float(b.get("speed", 1.0)) total = float(b["audio_minutes"]) unit_min = 1.0 / speed # minutes of your time per minute of audio 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("book %r needs pages, words or 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"], "deadline of %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", "Reading plan"), "wpm": wpm} def capacity(m, d): """(planned minutes, available minutes incl. catch-up, note).""" if d in m["exc"]: v, note = m["exc"][d] return v, v, note or ("no reading" if v == 0 else "") wd = DAYS[d.weekday()] v = m["mins"].get(wd, 0.0) if wd in m["catch"]: return 0.0, v, "catch-up day" 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 is already finished - left out" % b["title"])) b["target"] = None if b["deadline"] and b["deadline"] < m["start"]: if b["need"] > 0: F.append(("medium", "RP05", "%s: deadline %s has already passed - planned without a deadline" % (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: deadline %s is too close for %d buffer day(s) - planning to the deadline" % (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"]]) # horizon: enough days for everything at full capacity, plus slack 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 factor per segment (even mode): smallest uniform share of capacity that meets every target 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% headroom for chapter-end stops and rounding end = idx[dated[bk]["target"]] for i in range(seg_start, end + 1): load[i] = L seg_start, k0 = end + 1, bk + 1 # after the last deadline: undated books at the average load of the plan so far (at least 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 # allocate (earliest deadline first), tracking each book's position 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 # stop at the chapter end: the day ends here 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) # findings 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 # also count catch-up/buffer time that would be available up to the deadline reading_days = sum(1 for x in avail if x["avail"] > 0) or 1 short_units = short_min / b["unit_min"] msg = "%s cannot be finished by %s%s: about %d %s short at your pace; projected finish %s. Options: +%d min on each of the %d reading days until then, read faster, skim or skip about %d %s, or start it earlier" % ( b["title"], b["deadline"], " (%s)" % b["event"] if b["event"] else "", math.ceil(short_units), "pages" if b["kind"] == "pages" else "audio minutes", f or "beyond the plan", math.ceil(short_min / reading_days), reading_days, math.ceil(short_units), "pages" if b["kind"] == "pages" else "audio minutes") F.append(("high", "RP01", msg)) elif f > b["target"]: F.append(("medium", "RP02", "%s finishes %s, inside the %d buffer day(s) before %s - no room for a missed day" % (b["title"], f, m["buffer"], b["deadline"]))) 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", "the plan uses %d%% of your planned reading time in its busiest stretch - one bad week will push you into the buffer" % 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 day(s) plan more than %d minutes (e.g. %s: %d min) - split into two sessions" % ( 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 is an audiobook: the plan counts listening time at %sx speed; commutes and chores can cover it" % (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): """Move a day's stopping point to a chapter end if one is close (within snap_pages and 25% of the day).""" 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 p. %d-%d (%d pp)" % (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: # Sundays out.append((x["date"], "; ".join("%s %s" % (t, ("p. %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 "all current books done")) 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("Start %s, %s mode, %d buffer day(s) before each deadline, catch-up days: %s. Planned reading: %d h %02d min over %d days." % ( m["start"], mode, m["buffer"], ", ".join(sorted(m["catch"], key=DAYS.index)) or "none", tot_min // 60, tot_min % 60, len(r["days"]))) out += ["", "**Verdict: %s**" % ("%d book(s) cannot be finished by their deadline - change the plan" % len(hi) if hi else "every deadline is met"), ""] out += ["## Books", "", "| Book | Left | Est. time | Deadline | Finish by | Planned finish | Days spare | Avg per reading day |", "|---|---|---|---|---|---|---|---|"] 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 pp" % round(left)) if b["kind"] == "pages" else hm(left) + " audio", hm(b["need"]) + " h", "%s %s" % (b["deadline"], "(%s)" % b["event"] if b["event"] else "") if b["deadline"] else "-", b["target"] or "-", b.get("finish") or ("done" if b["need"] <= 0 else "NOT IN TIME"), "-" if spare is None else spare, ("%.0f pp" % avg) if b["kind"] == "pages" else hm(avg))) out += ["", "## Findings", ""] out += ["- **%s %s** %s" % (s.upper(), c, msg) for s, c, msg in r["findings"]] or ["- none"] out += ["", "## Day by day", "", "| Date | Day | Minutes | Read | Note |", "|---|---|---|---|---|"] events = {} for b in r["all_books"]: if b["deadline"]: events.setdefault(b["deadline"], []).append("DEADLINE %s%s" % (b["title"], " - " + b["event"] if b["event"] else "")) if b["target"] and b["target"] != b["deadline"]: events.setdefault(b["target"], []).append("finish-by %s" % b["title"]) for x in r["days"]: note = [x["note"]] if x["note"] else [] if x["note"] == "catch-up day" or (x["planned"] < 0.5 and x["avail"] > 0): note = ["catch-up / spare (%d min available)" % 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 sessions") 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 += ["", "## Weekly checkpoints (where you should be by Sunday night)", ""] out += ["- %s: %s" % (d, s) for d, s in cps] out += ["", "## If you fall behind", ""] 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: a missed day costs about %d pages. Make them up on %s, or add %d pages to each of the next 3 reading days. Re-plan any time with `--from <date> --at \"%s=<page>\"`." % ( b["title"], round(day_pp), ("the spare day(s) " + ", ".join(str(x["date"]) for x in spare[:3])) if spare else "no spare day before the deadline", 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 pages/day at 1 page/min finishes day 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("even: spread over the week (~10 min/day + 3% headroom)", 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("infeasible -> RP01 high", any(f[1] == "RP01" and f[0] == "high" for f in r["findings"])) t("RP01 suggests extra minutes", any("+13 min" 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("buffer days: finish 2 days early", 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("catch-up Sunday gets no planned reading", 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": "trip"}], books=[{"title": "A", "pages": 50, "deadline": "2026-11-08"}])) t("exception range has no reading", all(x["planned"] == 0 for x in r["days"][1:3])) two = [{"title": "Late", "pages": 30, "deadline": "2026-11-20"}, {"title": "Soon", "pages": 60, "deadline": "2026-11-04"}] r, m = run(dict(base, books=two)) t("earliest deadline first", r["days"][0]["items"][0]["title"] == "Soon") t("tight segment then lighter load", 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 resumes from page", 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("word count -> pages via words_per_page", r["all_books"][0]["units"] == 100) r, m = run(dict(base, books=[{"title": "H", "pages": 70, "difficulty": 1.5, "deadline": "2026-11-08"}])) t("difficulty scales time", 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("audiobook at 1.5x = 200 min", 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("chapter snapping stops at chapter ends", 11 in ends and 22 in ends and ends[-1] == 70) t("one item per book per day", all(len({it["title"] for it in x["items"]}) == len(x["items"]) for x in r["days"])) t("page ranges do not overlap", 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("long sessions -> 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("tight plan -> RP04 or 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("undated book after dated ones", r["books"][-1]["title"] == "A" and r["books"][-1]["finish"]) r, m = run(dict(base, books=[{"title": "A", "pages": 20, "start_page": 21}])) t("finished book -> 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("bad input rejected: %s" % (list(bad.get("minutes", {})) if isinstance(bad.get("minutes"), dict) else (bad["books"][0] if bad["books"] else "no books")), okk) r, m = run(dict(base, books=[{"title": "Old", "pages": 30, "deadline": "2026-10-01"}])) t("passed deadline -> RP05, planned without deadline", any(f[1] == "RP05" for f in r["findings"]) and r["books"][0]["finish"]) rep = report(*run(dict(base, books=two)), "even") t("report has verdict, day table and catch-up advice", "Verdict" in rep and "| Date |" in rep and "If you fall behind" in rep) for name, okk in tests: print(("PASS " if okk else "FAIL ") + name) n = sum(1 for _, okk in tests if okk) print("%d/%d passed" % (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="re-plan from this date (YYYY-MM-DD)") ap.add_argument("--at", action="append", default=[], help='"Title=page" (or "Title=minute" for audiobooks): where you are now') 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("plan JSON required (or --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 needs Title=page, got %r" % s) k, v = s.rsplit("=", 1) try: at[k.strip()] = float(v) except ValueError: raise InputError("--at page must be a number, got %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: no book titled %r" % k) m = load(cfg, a.start, at) r = plan(m, a.mode) except (InputError, KeyError, TypeError, ValueError) as e: print("error: %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())

पूरा प्रॉम्प्ट देखने के लिए साइन इन करें

Continue with:

By logging in, you agree to our Terms of Use and Privacy Policy

उपयोग

यह प्रॉम्प्ट productivity के साथ उपयोग के लिए डिज़ाइन किया गया है। ऊपर प्रॉम्प्ट सामग्री कॉपी करें और अपने पसंदीदा AI टूल में पेस्ट करें।

सर्वोत्तम परिणामों के लिए, आप अपनी विशिष्ट आवश्यकताओं के अनुसार प्लेसहोल्डर (वर्ग कोष्ठक या बड़े अक्षरों में दर्शाए गए) को अनुकूलित कर सकते हैं।

संदर्भ

श्रेणियाँ:productivity| prompts.chat| reading-plan| book-club

चर्चा