# Stats overview page rendering. Split out of stats.source.sh (task cn0) so the # HTML/layout concern lives apart from the EXIF aggregation/bucketing (now in # stats-aggregate.source.sh) and the per-filter mini-albums (now in # stats-filter-album.source.sh). This module reads the aggregated stats filled by # collect_photo_exif_stats -- through the stats-aggregate.source.sh accessor # functions (stats_total_photos, stats_filter_pagebase, stats_category_*), never # by indexing the aggregator's private STATS_* maps directly -- and turns them # into the static stats overview page (bar charts, sections, camera leaderboard). # It still reads the shared registry constants it owns a stake in (STATS_CATEGORIES, # STATS_CATEGORY_BUCKETS) and the STATS_*_DIR layout constants from the sibling # modules. All libs are sourced before run, so the accessors and constants are # available here at runtime. # ---------------------------------------------------------------------------- # Rendering (task pm0) # ---------------------------------------------------------------------------- # render_stats_page turns the STATS_* globals filled by the aggregation above # into a static stats.html. The page is variable-length (each category may be # empty, sparse, or large) which does not fit the fixed field-spec template # engine cleanly, so we follow the same approach view/details pages use for # their dynamic EXIF table: build the whole body as an HTML string here, hand it # to stats.tmpl through the raw context field stats_body, and let the engine wrap # it with the shared header/footer chrome. Bars are plain CSS (width as a percent # of the section's top bucket) so the output stays JavaScript-free. # Print the integer percentage count/total (0 when total is 0). awk keeps the # rounding off bash integer math; the denominator is the photo total the caller # obtained from the stats_total_photos accessor. _stats_percent() { local -ri count="$1"; shift local -ri total="$1"; shift if (( total <= 0 )); then printf '0' return fi awk -v c="$count" -v t="$total" 'BEGIN { printf "%.0f", 100 * c / t }' } # Emit one bar-chart
  • : an already-escaped label, a CSS-width bar scaled to # the section maximum, and the count plus its share of all photos. Callers escape # labels themselves because some come from EXIF (camera/lens) and some are # trusted bucket names we build internally. _stats_bar_row() { local -r label_html="$1"; shift local -ri count="$1"; shift local -ri total="$1"; shift local -ri max="$1"; shift local -i width=0 if (( max > 0 )); then width=$(( 100 * count / max )) fi printf '
  • ' printf '%s' "$label_html" printf '' printf '' \ "$width" printf '%d (%s%%)' \ "$count" "$(_stats_percent "$count" "$total")" printf '
  • \n' } # Open a
    with an escaped heading and the