fix minor dash
This commit is contained in:
@@ -171,30 +171,27 @@
|
|||||||
function todayPotentialFor(memberId: string) {
|
function todayPotentialFor(memberId: string) {
|
||||||
return assigned.filter((a: any) => a.memberId === memberId && a.frequency === 'daily').length;
|
return assigned.filter((a: any) => a.memberId === memberId && a.frequency === 'daily').length;
|
||||||
}
|
}
|
||||||
// Max points a full "all daily chores done" day is worth for a member.
|
// All-time completion rate for a member: all chores ever done ÷ (current
|
||||||
function dailyPointsPotential(memberId: string) {
|
// weekly potential × weeks active). Bounded and meaningful, unlike the old
|
||||||
return assigned
|
// points-per-day average (bonus points + weeklies done in one day could
|
||||||
.filter((a: any) => a.memberId === memberId && a.frequency === 'daily')
|
// push it past a "perfect day" — e.g. Jethro's 100%).
|
||||||
.reduce((sum: number, a: any) => sum + (a.type === 'points' ? Number(a.value) || 0 : 0), 0);
|
function overallRateFor(memberId: string): { done: number; total: number; pct: number } {
|
||||||
}
|
|
||||||
// All-time average daily points for a member, from the server-computed
|
|
||||||
// weekly series (all history, not just this week). Days active runs from
|
|
||||||
// their earliest recorded week through today (min 1).
|
|
||||||
function avgDailyPointsFor(memberId: string): number {
|
|
||||||
const line = trend.find((m: any) => m.memberId === memberId);
|
const line = trend.find((m: any) => m.memberId === memberId);
|
||||||
const weeks = line?.weeks || [];
|
const weeks = line?.weeks || [];
|
||||||
if (weeks.length === 0) return 0;
|
const done = weeks.reduce((sum: number, w: any) => sum + (Number(w.chores) || 0), 0);
|
||||||
const total = weeks.reduce((sum: number, w: any) => sum + (Number(w.points) || 0), 0);
|
const potential = weeklyPotentialFor(memberId);
|
||||||
|
if (weeks.length === 0 || potential <= 0) return { done, total: 0, pct: 0 };
|
||||||
const earliest = weeks.map((w: any) => w.weekStart).sort()[0];
|
const earliest = weeks.map((w: any) => w.weekStart).sort()[0];
|
||||||
const today = todayInTz(famTz);
|
const today = todayInTz(famTz);
|
||||||
const days = Math.max(
|
const weeksActive = Math.max(
|
||||||
1,
|
1,
|
||||||
Math.round(
|
Math.floor(
|
||||||
(new Date(today + 'T00:00:00').getTime() - new Date(earliest + 'T00:00:00').getTime()) /
|
(new Date(today + 'T00:00:00').getTime() - new Date(earliest + 'T00:00:00').getTime()) /
|
||||||
86400000
|
(7 * 86400000)
|
||||||
) + 1
|
) + 1
|
||||||
);
|
);
|
||||||
return total / days;
|
const total = potential * weeksActive;
|
||||||
|
return { done, total, pct: Math.min(100, Math.round((done / total) * 100)) };
|
||||||
}
|
}
|
||||||
// Today's completion count — tolerant of UTC vs fam-local date keys.
|
// Today's completion count — tolerant of UTC vs fam-local date keys.
|
||||||
function todayDone(s: any): number {
|
function todayDone(s: any): number {
|
||||||
@@ -277,10 +274,11 @@
|
|||||||
}
|
}
|
||||||
const scoreCanvas = donutCanvases[`${s.memberId}:score`];
|
const scoreCanvas = donutCanvases[`${s.memberId}:score`];
|
||||||
if (scoreCanvas) {
|
if (scoreCanvas) {
|
||||||
|
const overall = overallRateFor(s.memberId);
|
||||||
donutCharts[`${s.memberId}:score`] = makeDonut(
|
donutCharts[`${s.memberId}:score`] = makeDonut(
|
||||||
scoreCanvas,
|
scoreCanvas,
|
||||||
avgDailyPointsFor(s.memberId),
|
overall.done,
|
||||||
dailyPointsPotential(s.memberId),
|
overall.total,
|
||||||
s.memberColor
|
s.memberColor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -413,9 +411,7 @@
|
|||||||
{@const tdTotal = todayPotentialFor(s.memberId)}
|
{@const tdTotal = todayPotentialFor(s.memberId)}
|
||||||
{@const tdDone = todayDone(s)}
|
{@const tdDone = todayDone(s)}
|
||||||
{@const tdPct = tdTotal > 0 ? Math.min(100, Math.round((tdDone / tdTotal) * 100)) : 0}
|
{@const tdPct = tdTotal > 0 ? Math.min(100, Math.round((tdDone / tdTotal) * 100)) : 0}
|
||||||
{@const scPot = dailyPointsPotential(s.memberId)}
|
{@const sc = overallRateFor(s.memberId)}
|
||||||
{@const scVal = avgDailyPointsFor(s.memberId)}
|
|
||||||
{@const scPct = scPot > 0 ? Math.min(100, Math.round((scVal / scPot) * 100)) : 0}
|
|
||||||
{@const goals = goalsByMember.get(s.memberId)}
|
{@const goals = goalsByMember.get(s.memberId)}
|
||||||
<div class="column col-member" style="--mc: {s.memberColor}">
|
<div class="column col-member" style="--mc: {s.memberColor}">
|
||||||
<div class="member-head">
|
<div class="member-head">
|
||||||
@@ -438,8 +434,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="donut-wrap">
|
<div class="donut-wrap">
|
||||||
<canvas use:captureCanvas={`${s.memberId}:score`} height="100" width="100"></canvas>
|
<canvas use:captureCanvas={`${s.memberId}:score`} height="100" width="100"></canvas>
|
||||||
<div class="donut-center" style="color:{s.memberColor}">{scPct}%</div>
|
<div class="donut-center" style="color:{s.memberColor}">{sc.pct}%</div>
|
||||||
<span class="donut-label">Avg/day</span>
|
<span class="donut-label">Overall</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="member-stats">
|
<div class="member-stats">
|
||||||
|
|||||||
Reference in New Issue
Block a user