stats.sh Ordentlich aufgemotzt.
This commit is contained in:
@@ -1,119 +1,298 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
DB="$HOME/.local/share/mindwtr/mindwtr.db"
|
||||
DB="${HOME}/.local/share/mindwtr/mindwtr.db"
|
||||
[[ -f "$DB" ]] || { echo "Fehler: DB nicht gefunden: $DB" >&2; exit 1; }
|
||||
command -v bc >/dev/null || { echo "bc fehlt" >&2; exit 1; }
|
||||
command -v sqlite3 >/dev/null || { echo "sqlite3 fehlt" >&2; exit 1; }
|
||||
|
||||
if [ ! -f "$DB" ]; then
|
||||
echo "Fehler: Datenbank nicht gefunden: $DB" >&2
|
||||
exit 1
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'; MAGENTA='\033[0;35m'; CYAN='\033[0;36m'
|
||||
WHITE='\033[1;37m'; GRAY='\033[0;90m'; BOLD='\033[1m'; NC='\033[0m'
|
||||
|
||||
TMP="/tmp/mindwtr_stats_$$.tmp"
|
||||
trap 'rm -f "$TMP"' EXIT
|
||||
|
||||
bar() {
|
||||
local p=${1:-0} w=${2:-30}
|
||||
[[ -z "$p" ]] && p=0; [[ -z "$w" ]] && w=30
|
||||
[[ ! "$p" =~ ^[0-9]+$ ]] && p=0; [[ ! "$w" =~ ^[0-9]+$ ]] && w=30
|
||||
local f=0 e=$w
|
||||
(( w > 0 && p > 0 )) && f=$((w * p / 100)) && e=$((w - f))
|
||||
local c=$GREEN; [[ $p -lt 30 ]] && c=$RED; [[ $p -ge 30 && $p -lt 70 ]] && c=$YELLOW
|
||||
if [[ $p -eq 0 ]]; then
|
||||
printf "${GRAY}%${w}s${NC}" '' | sed 's/ /░/g'
|
||||
else
|
||||
printf "${c}%${f}s${NC}${GRAY}%${e}s${NC}" '' '' | sed 's/ /█/g; s/ /░/g'
|
||||
fi
|
||||
}
|
||||
|
||||
sparkline() {
|
||||
local -a v=("$@") max=0; for n in "${v[@]}"; do ((n>max)) && max=$n; done
|
||||
[[ $max -eq 0 ]] && max=1
|
||||
local chars=('▁' '▂' '▃' '▄' '▅' '▆' '▇' '█')
|
||||
for n in "${v[@]}"; do printf "%s" "${chars[n*7/max]}"; done
|
||||
}
|
||||
|
||||
hr() { printf "${GRAY}──────────────────────────────────────────────────────────────────────────────${NC}\n"; }
|
||||
hr2() { printf "${GRAY}┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈${NC}\n"; }
|
||||
hdr() { printf "\n${BOLD}${CYAN}%s${NC}\n" "$1"; hr; }
|
||||
|
||||
header() {
|
||||
clear
|
||||
printf "\n${BOLD}${WHITE}%s${NC}\n" "M I N D W T R D A S H B O A R D"
|
||||
printf "${GRAY}%s${NC}\n\n" "$(date '+%A, %d. %B %Y')"
|
||||
hr
|
||||
}
|
||||
|
||||
sqlite3 "$DB" -batch <<'SQL' > "$TMP"
|
||||
.headers off
|
||||
.mode list
|
||||
.separator |
|
||||
SELECT 'open' AS k, COUNT(*) AS v FROM tasks WHERE deletedAt IS NULL AND status!='done'
|
||||
UNION ALL SELECT 'done', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='done'
|
||||
UNION ALL SELECT 'total', COUNT(*) FROM tasks WHERE deletedAt IS NULL
|
||||
UNION ALL SELECT 'inbox', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='inbox'
|
||||
UNION ALL SELECT 'next', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='next'
|
||||
UNION ALL SELECT 'someday', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='someday'
|
||||
UNION ALL SELECT 'overdue', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='next' AND dueDate IS NOT NULL AND date(dueDate)<date('now')
|
||||
UNION ALL SELECT 'due_today', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='next' AND dueDate IS NOT NULL AND date(dueDate)=date('now')
|
||||
UNION ALL SELECT 'due_week', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='next' AND dueDate IS NOT NULL AND date(dueDate) BETWEEN date('now') AND date('now','+7 days')
|
||||
UNION ALL SELECT 'due_next_week', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='next' AND dueDate IS NOT NULL AND date(dueDate) BETWEEN date('now','+1 day') AND date('now','+7 days')
|
||||
UNION ALL SELECT 'active_projects', COUNT(*) FROM projects WHERE deletedAt IS NULL AND status='active'
|
||||
UNION ALL SELECT 'list_tasks', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND taskMode='list'
|
||||
UNION ALL SELECT 'single_tasks', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND taskMode='task'
|
||||
UNION ALL SELECT 'done_week', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='done' AND date(completedAt)>=date('now','-7 days')
|
||||
UNION ALL SELECT 'done_month', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status='done' AND date(completedAt)>=date('now','-30 days');
|
||||
|
||||
SELECT 'vel_'||date(completedAt) AS k, COUNT(*) AS v FROM tasks
|
||||
WHERE deletedAt IS NULL AND status='done' AND completedAt IS NOT NULL
|
||||
AND date(completedAt)>=date('now','-21 days')
|
||||
GROUP BY date(completedAt) ORDER BY date(completedAt);
|
||||
|
||||
SELECT p.id, p.title, p.dueDate, COUNT(t.id), SUM(CASE WHEN t.status='done' THEN 1 ELSE 0 END)
|
||||
FROM projects p LEFT JOIN tasks t ON t.projectId=p.id
|
||||
WHERE p.deletedAt IS NULL AND p.status='active'
|
||||
GROUP BY p.id, p.title, p.dueDate ORDER BY p.dueDate IS NULL, p.dueDate;
|
||||
|
||||
SELECT date(dueDate), COUNT(*), GROUP_CONCAT(title,' | ') FROM tasks
|
||||
WHERE deletedAt IS NULL AND status='next' AND dueDate IS NOT NULL
|
||||
AND date(dueDate) BETWEEN date('now') AND date('now','+30 days')
|
||||
GROUP BY date(dueDate) ORDER BY date(dueDate);
|
||||
|
||||
SELECT t.title, COALESCE(p.title,'(kein Projekt)'), t.dueDate FROM tasks t
|
||||
LEFT JOIN projects p ON t.projectId=p.id
|
||||
WHERE t.deletedAt IS NULL AND t.status='next' AND t.dueDate IS NOT NULL AND date(t.dueDate)<date('now')
|
||||
ORDER BY t.dueDate;
|
||||
|
||||
SELECT taskMode, COUNT(*), SUM(CASE WHEN status='done' THEN 1 ELSE 0 END), SUM(CASE WHEN status='next' THEN 1 ELSE 0 END), SUM(CASE WHEN status='someday' THEN 1 ELSE 0 END)
|
||||
FROM tasks WHERE deletedAt IS NULL GROUP BY taskMode;
|
||||
SQL
|
||||
|
||||
open=0; done_tasks=0; total=0; inbox=0; next_tasks=0; someday=0
|
||||
overdue=0; due_today=0; due_week=0; due_next_week=0
|
||||
active_projects=0; list_tasks=0; single_tasks=0
|
||||
done_week=0; done_month=0
|
||||
|
||||
mapfile -t stats < <(grep -E '^(open|done|total|inbox|next|someday|overdue|due_today|due_week|due_next_week|active_projects|list_tasks|single_tasks|done_week|done_month)\|' "$TMP")
|
||||
for line in "${stats[@]}"; do
|
||||
IFS='|' read -r k v <<< "$line"
|
||||
case "$k" in
|
||||
open) open=$v;; done) done_tasks=$v;; total) total=$v;;
|
||||
inbox) inbox=$v;; next) next_tasks=$v;; someday) someday=$v;;
|
||||
overdue) overdue=$v;; due_today) due_today=$v;; due_week) due_week=$v;;
|
||||
due_next_week) due_next_week=$v;;
|
||||
active_projects) active_projects=$v;;
|
||||
list_tasks) list_tasks=$v;; single_tasks) single_tasks=$v;;
|
||||
done_week) done_week=$v;; done_month) done_month=$v;;
|
||||
esac
|
||||
done
|
||||
|
||||
vel_data=(); vel_labels=()
|
||||
while IFS='|' read -r k v; do
|
||||
[[ $k == vel_* ]] && vel_data+=("$v") && vel_labels+=("$(date -d "${k#vel_}" '+%d.%m.' 2>/dev/null || echo "${k#vel_}")")
|
||||
done < <(grep '^vel_' "$TMP")
|
||||
|
||||
projects=()
|
||||
while IFS='|' read -r pid ptitle pdue ptotal pdone; do
|
||||
[[ -n $pid ]] && projects+=("$pid|$ptitle|$pdue|$ptotal|$pdone")
|
||||
done < <(grep -E '^[a-f0-9-]{36}\|' "$TMP")
|
||||
|
||||
due_timeline=()
|
||||
while IFS='|' read -r date count tasks; do
|
||||
[[ -n $date ]] && due_timeline+=("$date|$count|$tasks")
|
||||
done < <(grep -E '^[0-9]{4}-[0-9]{2}-[0-9]{2}\|' "$TMP")
|
||||
|
||||
overdue_tasks=()
|
||||
while IFS='|' read -r title project due; do
|
||||
[[ -n $title ]] && overdue_tasks+=("$title|$project|$due")
|
||||
done < <(grep -E '^[^|]*\|[^|]*\|[0-9]{4}-[0-9]{2}-[0-9]{2}$' "$TMP")
|
||||
|
||||
mode_data=()
|
||||
while IFS='|' read -r mode mtotal mdone_tasks mnext msomeday; do
|
||||
[[ -n $mode ]] && mode_data+=("$mode|$mtotal|$mdone_tasks|$mnext|$msomeday")
|
||||
done < <(grep -E '^(task|list)\|' "$TMP")
|
||||
|
||||
header
|
||||
|
||||
hdr "ÜBERSICHT"
|
||||
pct_total=0; [[ $total -gt 0 ]] && pct_total=$((done_tasks*100/total))
|
||||
pct_week=0; [[ $((done_week+open)) -gt 0 ]] && pct_week=$((done_week*100/(done_week+open)))
|
||||
pct_month=0; [[ $((done_month+open)) -gt 0 ]] && pct_month=$((done_month*100/(done_month+open)))
|
||||
|
||||
b1=$(bar $pct_total 25)
|
||||
b2=$(bar $pct_week 25)
|
||||
b3=$(bar $pct_month 25)
|
||||
printf " %s\n" "$(printf " ${BOLD}%-18s${NC} ${WHITE}%3d%%${NC} %s ${GRAY}(%d/%d)${NC}" "Gesamt" "$pct_total" "$b1" "$done_tasks" "$total")"
|
||||
printf " %s\n" "$(printf " ${BOLD}%-18s${NC} ${WHITE}%3d%%${NC} %s ${GRAY}(%d/%d)${NC}" "Diese Woche" "$pct_week" "$b2" "$done_week" "$((done_week+open))")"
|
||||
printf " %s\n" "$(printf " ${BOLD}%-18s${NC} ${WHITE}%3d%%${NC} %s ${GRAY}(%d/%d)${NC}" "Diesen Monat" "$pct_month" "$b3" "$done_month" "$((done_month+open))")"
|
||||
printf "\n"
|
||||
printf " %s\n" "$(printf " ${BOLD}Offen:${NC} ${WHITE}%d${NC} ${YELLOW}Inbox:${NC} %d ${BLUE}Next:${NC} %d ${GRAY}Someday:${NC} %d" "$open" "$inbox" "$next_tasks" "$someday")"
|
||||
printf " %s\n" "$(printf " ${RED}Überfällig:${NC} %d ${YELLOW}Heute:${NC} %d ${BLUE}Diese Woche:${NC} %d ${CYAN}Nächste Woche:${NC} %d" "$overdue" "$due_today" "$due_week" "$due_next_week")"
|
||||
printf " %s\n" "$(printf " ${GREEN}Aktive Projekte:${NC} %d ${CYAN}Listen:${NC} %d ${BLUE}Einzel:${NC} %d" "$active_projects" "$list_tasks" "$single_tasks")"
|
||||
|
||||
hdr "PROJEKT-GESUNDHEIT"
|
||||
printf " %s\n" "$(printf " ${BOLD}%-30s %6s %s${NC}" "Projekt" "Fertig" "Fortschritt")"
|
||||
hr2
|
||||
for p in "${projects[@]}"; do
|
||||
IFS='|' read -r id title due ptotal pdone <<< "$p"
|
||||
pct=0; [[ $ptotal -gt 0 ]] && pct=$((pdone*100/ptotal))
|
||||
due_str=""
|
||||
if [[ -n "$due" && "$due" != "" ]]; then
|
||||
days=$(( ($(date -d "$due" +%s) - $(date +%s)) / 86400 ))
|
||||
if [[ $days -lt 0 ]]; then due_str="${RED}⚠ ${days#-}d überfällig${NC}"
|
||||
elif [[ $days -eq 0 ]]; then due_str="${YELLOW}⏰ heute${NC}"
|
||||
elif [[ $days -le 3 ]]; then due_str="${YELLOW}📅 in ${days}d${NC}"
|
||||
elif [[ $days -le 7 ]]; then due_str="${BLUE}📅 in ${days}d${NC}"
|
||||
else due_str="${GREEN}📅 in ${days}d${NC}"; fi
|
||||
fi
|
||||
bp=$(bar $pct 18)
|
||||
printf " %s\n" "$(printf " ${BOLD}%-30.30s${NC} ${WHITE}%3d%%${NC} %s ${GRAY}(%d/%d)${NC} %s" "$title" "$pct" "$bp" "$pdone" "$ptotal" "$due_str")"
|
||||
done
|
||||
[[ ${#projects[@]} -eq 0 ]] && printf " ${GRAY}(keine aktiven Projekte)${NC}\n"
|
||||
|
||||
hdr "ÜBERFÄLLIGE AUFGABEN"
|
||||
if [[ ${#overdue_tasks[@]} -eq 0 ]]; then
|
||||
printf " ${GREEN}✓ Keine überfälligen Aufgaben${NC}\n"
|
||||
else
|
||||
printf " ${RED}⚠ ${#overdue_tasks[@]} überfällige Aufgaben:${NC}\n"
|
||||
for t in "${overdue_tasks[@]}"; do
|
||||
IFS='|' read -r title project due <<< "$t"
|
||||
days=$(( ($(date +%s) - $(date -d "$due" +%s)) / 86400 ))
|
||||
printf " %s\n" "$(printf " ${RED}•${NC} ${WHITE}%-42.42s${NC} ${GRAY}[%s]${NC} ${RED}(%d Tage)${NC}" "$title" "$project" "$days")"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "=== Mindwtr-Statistik ==="
|
||||
echo
|
||||
hdr "AUFGABEN NACH MODUS"
|
||||
for m in "${mode_data[@]}"; do
|
||||
IFS='|' read -r mode mtotal mdone_tasks mnext msomeday <<< "$m"
|
||||
[[ $mtotal -eq 0 ]] && continue
|
||||
pct=0; [[ $mtotal -gt 0 ]] && pct=$((mdone_tasks*100/mtotal))
|
||||
label="${mode^}"; [[ $mode == "list" ]] && label="Liste"
|
||||
bp=$(bar $pct 22)
|
||||
printf " %s\n" "$(printf " ${BOLD}%-12s${NC} ${WHITE}%3d%%${NC} %s ${GRAY}(%d/%d)${NC}" "$label:" "$pct" "$bp" "$mdone_tasks" "$mtotal")"
|
||||
printf " %s\n" "$(printf " ${BLUE}Next:${NC} %-4d ${GRAY}Someday:${NC} %-4d" "$mnext" "$msomeday")"
|
||||
done
|
||||
|
||||
# ── 1. Aufgaben-Übersicht ──
|
||||
echo "── Aufgaben (aktiv) ──────────────────"
|
||||
sqlite3 "$DB" "
|
||||
SELECT status, COUNT(*) AS count
|
||||
FROM tasks WHERE deletedAt IS NULL
|
||||
GROUP BY status
|
||||
ORDER BY CASE status
|
||||
WHEN 'inbox' THEN 1 WHEN 'next' THEN 2
|
||||
WHEN 'someday' THEN 3 WHEN 'done' THEN 4
|
||||
END;" | awk -F'|' '{ printf " %-12s %5s\n", $1, $2 }'
|
||||
hdr "NÄCHSTE 30 TAGE – FÄLLIGKEITEN"
|
||||
printf " %s\n" "$(printf " ${BOLD}%-12s %4s %s${NC}" "Datum" "Anz" "Aufgaben")"
|
||||
hr2
|
||||
today_ts=$(date +%s)
|
||||
for dt in "${due_timeline[@]}"; do
|
||||
IFS='|' read -r due_date count tasks <<< "$dt"
|
||||
due_ts=$(date -d "$due_date" +%s 2>/dev/null || echo 0)
|
||||
day_name=$(date -d "$due_date" '+%a %d.%m.' 2>/dev/null || echo "$due_date")
|
||||
if [[ $due_ts -lt $today_ts ]]; then color=$RED; marker="⚠"
|
||||
elif [[ $due_ts -eq $today_ts ]]; then color=$YELLOW; marker="●"
|
||||
elif [[ $due_ts -lt $((today_ts + 259200)) ]]; then color=$YELLOW; marker="◐"
|
||||
else color=$BLUE; marker="○"; fi
|
||||
first_task=$(echo "$tasks" | cut -d'|' -f1 | sed 's/^ *//; s/ *$//')
|
||||
[[ ${#first_task} -gt 50 ]] && first_task="${first_task:0:47}..."
|
||||
printf " %s\n" "$(printf " ${color}%s %-12s${NC} ${WHITE}%3d${NC} ${GRAY}%s${NC}" "$marker" "$day_name" "$count" "$first_task")"
|
||||
if [[ "$tasks" == *"|"* ]]; then
|
||||
echo "$tasks" | cut -d'|' -f2- | tr '|' '\n' | while read -r t; do
|
||||
t=$(echo "$t" | sed 's/^ *//; s/ *$//')
|
||||
[[ ${#t} -gt 50 ]] && t="${t:0:47}..."
|
||||
printf " %s\n" "$(printf " ${GRAY} └─ %s${NC}" "$t")"
|
||||
done
|
||||
fi
|
||||
done
|
||||
[[ ${#due_timeline[@]} -eq 0 ]] && printf " ${GREEN}✓ Keine anstehenden Fälligkeiten${NC}\n"
|
||||
|
||||
active=$(sqlite3 "$DB" "SELECT COUNT(*) FROM tasks WHERE deletedAt IS NULL AND status != 'done';")
|
||||
total=$(sqlite3 "$DB" "SELECT COUNT(*) FROM tasks WHERE deletedAt IS NULL;")
|
||||
echo " ─────────────────"
|
||||
printf " %-12s %5s\n" "Aktiv (o. done)" "$active"
|
||||
printf " %-12s %5s\n" "Gesamt" "$total"
|
||||
echo
|
||||
hdr "VELOCITY – LETZTE 21 TAGE"
|
||||
if [[ ${#vel_data[@]} -eq 0 ]]; then
|
||||
printf " ${GRAY}Keine Velocity-Daten in den letzten 21 Tagen${NC}\n"
|
||||
else
|
||||
for i in "${!vel_data[@]}"; do
|
||||
count=${vel_data[i]}; label=${vel_labels[i]}
|
||||
bar_len=$((count * 3)); [[ $bar_len -gt 40 ]] && bar_len=40
|
||||
bar_str=$(printf "${GREEN}%${bar_len}s${NC}" "" | sed 's/ /█/g')
|
||||
printf " %s\n" "$(printf " ${GRAY}%s${NC} ${WHITE}%2d${NC} %s" "$label" "$count" "$bar_str")"
|
||||
done
|
||||
total_week1=0; total_week2=0; total_week3=0
|
||||
for i in "${!vel_data[@]}"; do
|
||||
day_offset=$(( ${#vel_data[@]} - 1 - i ))
|
||||
if [[ $day_offset -lt 7 ]]; then total_week1=$((total_week1 + vel_data[i]))
|
||||
elif [[ $day_offset -lt 14 ]]; then total_week2=$((total_week2 + vel_data[i]))
|
||||
else total_week3=$((total_week3 + vel_data[i])); fi
|
||||
done
|
||||
printf "\n"
|
||||
printf " %s\n" "$(printf " ${BOLD}Wochen-Velocity:${NC} ${CYAN}W1:${WHITE}%2d${NC} ${CYAN}W2:${WHITE}%2d${NC} ${CYAN}W3:${WHITE}%2d${NC}" "$total_week1" "$total_week2" "$total_week3")"
|
||||
trend="→"; [[ $total_week1 -gt $total_week2 ]] && trend="↑"; [[ $total_week1 -lt $total_week2 ]] && trend="↓"
|
||||
avg=$(echo "scale=1; ($total_week1+$total_week2+$total_week3)/21" | bc -l 2>/dev/null || echo "?")
|
||||
[[ "$avg" == .* ]] && avg="0$avg"
|
||||
printf " %s\n" "$(printf " ${BOLD}Trend:${NC} ${WHITE}%s${NC} (%s/Tag Ø)" "$trend" "$avg")"
|
||||
fi
|
||||
|
||||
# ── 2. Fälligkeiten ──
|
||||
echo "── Fälligkeiten ──────────────────────"
|
||||
due_overdue=$(sqlite3 "$DB" "
|
||||
SELECT COUNT(*) FROM tasks
|
||||
WHERE deletedAt IS NULL AND status != 'done'
|
||||
AND dueDate IS NOT NULL AND dueDate != '' AND dueDate < datetime('now');")
|
||||
due_week=$(sqlite3 "$DB" "
|
||||
SELECT COUNT(*) FROM tasks
|
||||
WHERE deletedAt IS NULL AND status != 'done'
|
||||
AND dueDate IS NOT NULL AND dueDate != ''
|
||||
AND dueDate >= datetime('now') AND dueDate < datetime('now', '+7 days');")
|
||||
due_today=$(sqlite3 "$DB" "
|
||||
SELECT COUNT(*) FROM tasks
|
||||
WHERE deletedAt IS NULL AND status != 'done'
|
||||
AND dueDate IS NOT NULL AND dueDate != ''
|
||||
AND date(dueDate) = date('now');")
|
||||
printf " %-20s %5s\n" "Überfällig" "$due_overdue"
|
||||
printf " %-20s %5s\n" "Diese Woche" "$due_week"
|
||||
printf " %-20s %5s\n" "Heute" "$due_today"
|
||||
echo
|
||||
hdr "KALENDERANSICHT – NÄCHSTE 4 WOCHEN"
|
||||
weeks=4
|
||||
for w in $(seq 0 $((weeks-1))); do
|
||||
week_start=$(date -d "$(date +%F) +$((w*7)) days -$(($(date -d "$(date +%F) +$((w*7)) days" +%u)-1)) days" +%F)
|
||||
week_label=$(date -d "$week_start" '+%V. KW (%d.%m.)')
|
||||
printf "\n ${BOLD}${CYAN}▶ %s${NC}\n" "$week_label"
|
||||
for d in $(seq 0 6); do
|
||||
day=$(date -d "$week_start +$d days" +%F)
|
||||
day_name=$(date -d "$day" '+%a %d.')
|
||||
day_ts=$(date -d "$day" +%s)
|
||||
tasks_today=""; count=0
|
||||
for dt in "${due_timeline[@]}"; do
|
||||
IFS='|' read -r due_date c t <<< "$dt"
|
||||
[[ "$due_date" == "$day" ]] && tasks_today="$t" && count=$c && break
|
||||
done
|
||||
if [[ $day_ts -lt $today_ts ]]; then color=$RED; marker="✗"
|
||||
elif [[ $day_ts -eq $today_ts ]]; then color=$YELLOW; marker="●"
|
||||
elif [[ $count -gt 0 ]]; then color=$BLUE; marker="◆"
|
||||
else color=$GRAY; marker=" "; fi
|
||||
if [[ $count -gt 0 ]]; then
|
||||
first=$(echo "$tasks_today" | cut -d'|' -f1 | sed 's/^ *//; s/ *$//')
|
||||
[[ ${#first} -gt 48 ]] && first="${first:0:45}..."
|
||||
printf " %s\n" "$(printf " ${color}%s${NC} ${BOLD}%s${NC} ${WHITE}(%d)${NC} ${GRAY}%s${NC}" "$marker" "$day_name" "$count" "$first")"
|
||||
else
|
||||
printf " %s\n" "$(printf " ${GRAY}%s %s${NC}" "$marker" "$day_name")"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# ── 3. Heutige Aktivität ──
|
||||
echo "── Heute & diese Woche ───────────────"
|
||||
created_today=$(sqlite3 "$DB" "SELECT COUNT(*) FROM tasks WHERE date(createdAt) = date('now');")
|
||||
updated_today=$(sqlite3 "$DB" "SELECT COUNT(*) FROM tasks WHERE date(updatedAt) = date('now');")
|
||||
done_today=$(sqlite3 "$DB" "SELECT COUNT(*) FROM tasks WHERE date(completedAt) = date('now') AND deletedAt IS NULL;")
|
||||
done_week=$(sqlite3 "$DB" "SELECT COUNT(*) FROM tasks WHERE completedAt >= datetime('now', '-7 days') AND deletedAt IS NULL;")
|
||||
printf " %-20s %5s\n" "Heute erstellt" "$created_today"
|
||||
printf " %-20s %5s\n" "Heute aktualisiert" "$updated_today"
|
||||
printf " %-20s %5s\n" "Heute erledigt" "$done_today"
|
||||
printf " %-20s %5s\n" "Diese Woche erledigt" "$done_week"
|
||||
echo
|
||||
hdr "EMPFEHLUNGEN"
|
||||
recs=()
|
||||
[[ $inbox -gt 5 ]] && recs+=("${YELLOW}📥 Inbox verarbeiten ($inbox Items)${NC}")
|
||||
[[ $overdue -gt 0 ]] && recs+=("${RED}⚠ $overdue überfällige Aufgaben dringend prüfen${NC}")
|
||||
[[ $due_today -gt 0 ]] && recs+=("${YELLOW}⏰ $due_today Aufgaben sind heute fällig${NC}")
|
||||
[[ $due_week -gt 10 ]] && recs+=("${BLUE}📅 Diese Woche $due_week fällige Aufgaben – planen${NC}")
|
||||
[[ $someday -gt 20 ]] && recs+=("${GRAY}💭 $someday 'Irgendwann'-Aufgaben – aufräumen?${NC}")
|
||||
[[ $active_projects -gt 5 ]] && recs+=("${MAGENTA}📦 $active_projects aktive Projekte – Fokus setzen${NC}")
|
||||
[[ ${#vel_data[@]} -gt 0 && $total_week1 -eq 0 ]] && recs+=("${RED}📉 Keine Aufgaben diese Woche erledigt${NC}")
|
||||
for p in "${projects[@]}"; do
|
||||
IFS='|' read -r id title due ptotal pdone <<< "$p"
|
||||
pct=0; [[ $ptotal -gt 0 ]] && pct=$((pdone*100/ptotal))
|
||||
[[ $ptotal -gt 3 && $pct -eq 0 ]] && recs+=("${RED}🛑 Projekt '$title': 0%% Fortschritt ($ptotal Tasks)${NC}") && break
|
||||
done
|
||||
if [[ ${#recs[@]} -eq 0 ]]; then
|
||||
printf " ${GREEN}✓ Alles im grünen Bereich!${NC}\n"
|
||||
else
|
||||
for r in "${recs[@]}"; do printf " $r\n"; done
|
||||
fi
|
||||
|
||||
# ── 4. Aufgaben-Merkmale ──
|
||||
echo "── Aufgaben mit ──────────────────────"
|
||||
sqlite3 "$DB" "
|
||||
SELECT 'Priorität', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND priority IS NOT NULL AND priority != ''
|
||||
UNION ALL
|
||||
SELECT 'Energielevel', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND energyLevel IS NOT NULL AND energyLevel != ''
|
||||
UNION ALL
|
||||
SELECT 'Fälligkeitsdatum', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND dueDate IS NOT NULL AND dueDate != ''
|
||||
UNION ALL
|
||||
SELECT 'Checkliste', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND checklist IS NOT NULL AND checklist != '[]'
|
||||
UNION ALL
|
||||
SELECT 'Wiederkehrend', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND recurrence IS NOT NULL AND recurrence != ''
|
||||
UNION ALL
|
||||
SELECT 'Notizen', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND description IS NOT NULL AND description != ''
|
||||
UNION ALL
|
||||
SELECT 'Zeitschätzung', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND timeEstimate IS NOT NULL AND timeEstimate != ''
|
||||
UNION ALL
|
||||
SELECT 'Heute fokussiert', COUNT(*) FROM tasks WHERE deletedAt IS NULL AND isFocusedToday = 1;" | awk -F'|' '{ printf " %-20s %5s\n", $1, $2 }'
|
||||
echo
|
||||
|
||||
# ── 5. Top-Kontexte ──
|
||||
echo "── Top-Kontexte ──────────────────────"
|
||||
sqlite3 "$DB" "
|
||||
SELECT j.value AS context, COUNT(*) AS count
|
||||
FROM tasks t, json_each(t.contexts) j
|
||||
WHERE t.deletedAt IS NULL
|
||||
GROUP BY j.value ORDER BY count DESC;" | awk -F'|' '{ printf " %-20s %5s\n", $1, $2 }'
|
||||
echo
|
||||
|
||||
# ── 6. Top-Schlagwörter ──
|
||||
echo "── Top-Schlagwörter ──────────────────"
|
||||
sqlite3 "$DB" "
|
||||
SELECT j.value AS tag, COUNT(*) AS count
|
||||
FROM tasks t, json_each(t.tags) j
|
||||
WHERE t.deletedAt IS NULL
|
||||
GROUP BY j.value ORDER BY count DESC LIMIT 15;" | awk -F'|' '{ printf " %-20s %5s\n", $1, $2 }'
|
||||
echo
|
||||
|
||||
# ── 7. Projekte ──
|
||||
echo "── Projekte ──────────────────────────"
|
||||
sqlite3 "$DB" "
|
||||
SELECT COALESCE(p.title, '(kein Projekt)') AS project, COUNT(*) AS tasks
|
||||
FROM tasks t LEFT JOIN projects p ON t.projectId = p.id
|
||||
WHERE t.deletedAt IS NULL AND (p.deletedAt IS NULL OR p.id IS NULL)
|
||||
GROUP BY project ORDER BY tasks DESC;" | awk -F'|' '{ printf " %-30s %5s\n", $1, $2 }'
|
||||
echo
|
||||
|
||||
# ── 8. Unvollständige Aufgaben ──
|
||||
echo "── Unvollständige Aufgaben ───────────"
|
||||
incomplete=$(sqlite3 "$DB" "
|
||||
SELECT COUNT(*) FROM tasks t
|
||||
WHERE deletedAt IS NULL
|
||||
AND ((contexts IS NULL OR contexts = '[]') OR (tags IS NULL OR tags = '[]'))
|
||||
AND status != 'done';")
|
||||
echo " $incomplete Aufgaben ohne Kontext und/oder Schlagwort"
|
||||
echo " (Details: ./incomplete.sh)"
|
||||
hr
|
||||
printf "${GRAY}Datenbank: %s${NC}\n" "$DB"
|
||||
printf "${GRAY}Aktualisiert: %s${NC}\n" "$(date '+%H:%M:%S')"
|
||||
Reference in New Issue
Block a user