issues/completed/8-045-timeline-based-progress-bar-calculation.md
Issue 8-045: Timeline-Based Progress Bar Calculation
Priority
Medium
Current Behavior
Progress bars are calculated based on poem position in the chronological list:
local progress_pct = (chrono_info.position / chrono_info.total_poems) * 100
This means:
- Poem #1 of 7844 = 0% progress
- Poem #3922 of 7844 = 50% progress
- Poem #7844 of 7844 = 100% progress
The bar fills uniformly regardless of when poems were actually written. A burst of 100 poems in one week takes up the same visual space as 100 poems spread across a year.
Intended Behavior
Progress bars should be calculated based on actual timestamps:
local progress_pct = (poem_timestamp - first_timestamp) / (last_timestamp - first_timestamp) * 100
This means:
- First poem ever written = 0% progress
- Poem from the midpoint in time = ~50% progress (regardless of poem count)
- Most recent poem = 100% progress
Visual Impact
Before (position-based):
Poem from Jan 2020: ═══════════════────────────────────────────────────────────
Poem from Jun 2020: ═════════════════════════════════────────────────────────── (even spacing)
Poem from Dec 2020: ═══════════════════════════════════════════════────────────
After (timeline-based):
Poem from Jan 2020: ═══════════────────────────────────────────────────────────
Poem from Jun 2022: ═══════════════════════════════════════════════════════════ (2.5 years later = big jump)
Poem from Jul 2022: ═══════════════════════════════════════════════════════════ (1 month later = tiny increment)
Semantic Meaning
The progress bar becomes a visual timeline that:
- Shows periods of prolific writing as dense clusters
- Shows periods of silence as empty gaps
- Directly correlates with chronological.html's structure
- Gives viewers intuition about when in the author's life a poem was written
Technical Design
Data Requirements
Each poem needs a parseable timestamp. Current sources:
| Source | Timestamp Field | Format |
|---|---|---|
| Fediverse | metadata.creation_date | ISO 8601 (2024-01-15T14:30:00Z) |
| Notes | metadata.creation_date or file mtime | ISO 8601 or Unix |
| Messages | metadata.creation_date | ISO 8601 |
| Bluesky | metadata.creation_date | ISO 8601 |
Calculation Changes
1. Pre-compute timeline bounds (once per generation):
local first_timestamp = poems_data.poems[1].timestamp_unix
local last_timestamp = poems_data.poems[#poems_data.poems].timestamp_unix
local timeline_span = last_timestamp - first_timestamp
2. Calculate progress for each poem:
local poem_timestamp = poem.timestamp_unix or parse_timestamp(poem.metadata.creation_date)
local progress_pct = ((poem_timestamp - first_timestamp) / timeline_span) * 100
3. Pass to chrono_map:
chrono_map[poem_idx] = {
position = i, -- Still useful for "poem N of M"
page_number = page_num,
total_poems = total_poems,
total_pages = total_pages,
timeline_progress = progress_pct -- NEW: time-based progress
}
Affected Files
src/flat-html-generator.lua:
build_chronological_position_map()- add timeline calculationformat_single_poem_with_progress_and_color()- use timeline_progress- Effil worker
format_poem_entry()- use timeline_progress
src/poem-extractor.lua(possibly):
- Ensure all poems have parseable timestamps
- Add
timestamp_unixfield during extraction for efficiency
Edge Cases
- Missing timestamps: Fall back to position-based for poems without dates
- Same-day poems: Will cluster together (intended behavior)
- Single poem: 0% or 100%? (suggest: 50% to center it)
- Future timestamps: Clamp to 100%
Suggested Implementation Steps
- Audit timestamp availability:
- Count poems with valid
metadata.creation_date - Identify any sources missing timestamps
- Add timestamp parsing utility:
```lua
local function parse_iso_timestamp(iso_string)
-- Convert "2024-01-15T14:30:00Z" to Unix timestamp
local pattern = "(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)"
local y, m, d, h, min, s = iso_string:match(pattern)
return os.time({year=y, month=m, day=d, hour=h, min=min, sec=s})
end
```
- Modify
build_chronological_position_map():
- Calculate first/last timestamps
- Add
timeline_progressto each entry
- Update progress bar generation:
- Use
chrono_info.timeline_progressinstead of position calculation - Keep position-based as fallback
- Update effil worker:
- Same changes as main scope
- Test with known timeline gaps:
- Find poems with large time gaps between them
- Verify progress bar jumps appropriately
Configuration Options
Consider making this configurable in config/input-sources.json:
"progress_bar": {
"mode": "timeline", // "timeline" or "position"
"fallback_to_position": true // If timestamp missing
}
Visual Verification
After implementation, check a known gap period:
- If no poems exist between Jan 2021 and Jun 2021, poems from Dec 2020 and Jul 2021 should have a visible gap in their progress bars
Related Documents
src/flat-html-generator.lua- Progress bar generationsrc/poem-extractor.lua- Timestamp extractionissues/8-030-add-chronological-anchor-links.md- Chronological navigation
Metadata
- Status: Complete
- Created: 2026-01-21
- Completed: 2026-01-30
- Phase: 8 (Website Completion)
- Estimated Complexity: Medium
- Dependencies: All poems need parseable timestamps
- Affects: Progress bar display on all pages
Implementation Notes
Audit Results:
- All 7,844 poems have
creation_datefield (100% coverage) - Timeline spans: April 2021 → January 2026 (~4.7 years)
- Timestamp format: ISO 8601 with optional milliseconds
Files Modified:
src/flat-html-generator.lua:
compute_chronological_mapping(): Now calculatestimeline_progressfor each poem- Chronological page generation: Uses timeline-based progress instead of position
- Effil worker: Uses
timeline_progressfrom chrono_map
src/generate-word-pages.lua:
- Uses
timeline_progressfrom chrono_map with position fallback
Key Changes:
- Progress bars now show actual temporal position in the author's timeline
- Periods of prolific writing appear as dense clusters
- Periods of silence appear as visible gaps in progression
- Falls back to position-based calculation if timeline_progress missing