baby-tracker/src/routes/stats/+page.svelte

187 lines
5.8 KiB
Svelte

<script lang="ts">
import { onMount } from 'svelte';
import { pb } from '$lib/pocketbase';
type Action = {
type: string;
created: string;
};
let stats = {
avgSleepPerNap: 0,
avgNapsPerDay: 0,
avgSleepPerDay: 0,
avgDiaperChanges: 0,
avgPoops: 0,
avgEatingTimes: 0
};
onMount(async () => {
const actions = await fetchAllActions();
calculateStats(actions);
});
async function fetchAllActions() {
// Fetch all actions. Adjust as needed for date range or pagination
const result = await pb.collection('actions').getList(1, 1000);
return result.items;
}
function calculateStats(actions: Action[]) {
// Implement the logic to calculate each statistic
// This is a placeholder and should be replaced with actual calculation logic
stats.avgSleepPerNap = calculateAvgSleepPerNap(actions);
stats.avgNapsPerDay = calculateAvgNapsPerDay(actions);
stats.avgSleepPerDay = calculateAvgSleepPerDay(actions);
stats.avgDiaperChanges = calculateAvgDiaperChanges(actions);
stats.avgPoops = calculateAvgDaysBetweenPoops(actions);
stats.avgEatingTimes = calculateAvgMealsPerDay(actions);
}
function calculateAvgSleepPerNap(actions: Action[]): number {
const sleepActions = actions.filter((a) => a.type === 'asleep' || a.type === 'awake');
sleepActions.sort((a, b) => new Date(a.created).getTime() - new Date(b.created).getTime());
let totalSleepTime = 0;
let napCount = 0;
for (let i = 0; i < sleepActions.length - 1; i++) {
if (sleepActions[i].type === 'asleep' && sleepActions[i + 1].type === 'awake') {
totalSleepTime +=
new Date(sleepActions[i + 1].created).getTime() -
new Date(sleepActions[i].created).getTime();
napCount++;
}
}
console.log('Total Sleep Time:', totalSleepTime);
console.log('Nap Count:', napCount);
return Math.round(napCount > 0 ? totalSleepTime / napCount / 1000 / 60 : 0); // returns average time in minutes
}
function calculateAvgNapsPerDay(actions: Action[]): number {
const sortedActions = actions.sort(
(a, b) => new Date(a.created).getTime() - new Date(b.created).getTime()
);
const daysMap = new Map<string, number>();
for (let i = 0; i < sortedActions.length - 1; i++) {
if (sortedActions[i].type === 'asleep' && sortedActions[i + 1].type === 'awake') {
const asleepDate = new Date(sortedActions[i].created);
const awakeDate = new Date(sortedActions[i + 1].created);
if (asleepDate.toDateString() === awakeDate.toDateString()) {
const dayKey = asleepDate.toDateString();
daysMap.set(dayKey, (daysMap.get(dayKey) || 0) + 1);
}
}
}
const totalNaps = Array.from(daysMap.values()).reduce((acc, naps) => acc + naps, 0);
return daysMap.size > 0 ? totalNaps / daysMap.size : 0;
}
function calculateAvgSleepPerDay(actions: Action[]): number {
const sortedActions = actions.sort(
(a, b) => new Date(a.created).getTime() - new Date(b.created).getTime()
);
const sleepDurations: number[] = [];
for (let i = 0; i < sortedActions.length - 1; i++) {
if (sortedActions[i].type === 'asleep' && sortedActions[i + 1].type === 'awake') {
const asleepDate = new Date(sortedActions[i].created);
const awakeDate = new Date(sortedActions[i + 1].created);
if (asleepDate.toDateString() === awakeDate.toDateString()) {
const sleepDuration = (awakeDate.getTime() - asleepDate.getTime()) / 1000 / 60; // Sleep duration in minutes
sleepDurations.push(sleepDuration);
}
}
}
if (sleepDurations.length === 0) return 0;
const totalSleepDuration = sleepDurations.reduce((a, b) => a + b, 0);
return Math.round(totalSleepDuration / sleepDurations.length);
}
function calculateAvgDiaperChanges(actions: Action[]): number {
let diaperChangesPerDay = new Map<string, number>();
for (const action of actions) {
if (action.type === 'diaper') {
const actionDate = action.created.split('T')[0]; // Extract the date part
diaperChangesPerDay.set(actionDate, (diaperChangesPerDay.get(actionDate) || 0) + 1);
}
}
if (diaperChangesPerDay.size === 0) {
return 0;
}
const totalDiaperChanges = Array.from(diaperChangesPerDay.values()).reduce(
(total, count) => total + count,
0
);
return totalDiaperChanges / diaperChangesPerDay.size;
}
function calculateAvgDaysBetweenPoops(actions: Action[]): number {
let poopDates = [];
// Extract dates of 'poop' actions
for (const action of actions) {
if (action.type === 'poop') {
const actionDate = new Date(action.created.split('T')[0]); // Extract the date part
poopDates.push(actionDate);
}
}
// Sort dates
poopDates.sort((a, b) => a.getTime() - b.getTime());
if (poopDates.length < 2) {
return 0; // Not enough data to calculate intervals
}
let totalDays = 0;
for (let i = 1; i < poopDates.length; i++) {
const interval =
(poopDates[i].getTime() - poopDates[i - 1].getTime()) / (1000 * 60 * 60 * 24); // Convert to days
totalDays += interval;
}
return parseFloat((totalDays / (poopDates.length - 1)).toFixed(2));
}
function calculateAvgMealsPerDay(actions: Action[]): number {
let mealsPerDay = new Map<string, number>();
for (const action of actions) {
if (action.type === 'food') {
const actionDate = action.created.split('T')[0]; // Extract the date part
mealsPerDay.set(actionDate, (mealsPerDay.get(actionDate) || 0) + 1);
}
}
if (mealsPerDay.size === 0) {
return 0;
}
const totalMeals = Array.from(mealsPerDay.values()).reduce((total, count) => total + count, 0);
return totalMeals / mealsPerDay.size;
}
</script>
<section>
<h2>Stats</h2>
<ul>
<li>{stats.avgSleepPerNap} min / nap</li>
<li>{stats.avgNapsPerDay} naps / day</li>
<li>{stats.avgSleepPerDay} min of sleep / day</li>
<li>{stats.avgDiaperChanges} diapers / day</li>
<li>{stats.avgPoops} days between poops</li>
<li>{stats.avgEatingTimes} meals / day</li>
</ul>
</section>