Bladeren bron

Add stats routes for distance by year/month/week

k4be 7 uur geleden
bovenliggende
commit
629f45eab0
1 gewijzigde bestanden met toevoegingen van 82 en 0 verwijderingen
  1. 82 0
      gpx-vis-backend/src/routes/stats.js

+ 82 - 0
gpx-vis-backend/src/routes/stats.js

@@ -0,0 +1,82 @@
+const router = require('express').Router();
+const { requireAuth } = require('../middleware/auth');
+const { Track } = require('../models');
+
+function getWeek(date) {
+  const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
+  const dayNum = d.getUTCDay() || 7;
+  d.setUTCDate(d.getUTCDate() + 4 - dayNum);
+  const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
+  return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
+}
+
+router.get('/', requireAuth, async (req, res) => {
+  try {
+    const tracks = await Track.findAll({
+      where: { userId: req.user.id },
+      attributes: ['totalDistance', 'trackDate', 'uploadDate'],
+    });
+
+    const byYear = {}, byMonth = {}, byWeek = {};
+
+    for (const t of tracks) {
+      const d = t.trackDate ? new Date(t.trackDate) : (t.uploadDate ? new Date(t.uploadDate) : null);
+      if (!d || isNaN(d.getTime())) continue;
+
+      const year = d.getFullYear();
+      const month = d.getMonth() + 1;
+      const week = getWeek(d);
+      const dist = t.totalDistance || 0;
+
+      byYear[year] = (byYear[year] || 0) + dist;
+      const mk = `${year}-${String(month).padStart(2,'0')}`;
+      byMonth[mk] = (byMonth[mk] || 0) + dist;
+      const wk = `${year}-W${String(week).padStart(2,'0')}`;
+      byWeek[wk] = (byWeek[wk] || 0) + dist;
+    }
+
+    res.json({
+      byYear: Object.entries(byYear).map(([year, distance]) => ({ year: parseInt(year), distance })).sort((a,b) => a.year - b.year),
+      byMonth: Object.entries(byMonth).map(([key, distance]) => {
+        const [year, month] = key.split('-');
+        return { year: parseInt(year), month: parseInt(month), distance };
+      }).sort((a,b) => a.year - b.year || a.month - b.month),
+      byWeek: Object.entries(byWeek).map(([key, distance]) => {
+        const [year, week] = key.split('-W');
+        return { year: parseInt(year), week: parseInt(week), distance };
+      }).sort((a,b) => a.year - b.year || a.week - b.week),
+    });
+  } catch (e) {
+    res.status(500).json({ error: 'Server error' });
+  }
+});
+
+// Overview stats for a directory (including subdirectories)
+router.get('/directory/:id', requireAuth, async (req, res) => {
+  try {
+    const { Directory, Track } = require('../models');
+    const { Op } = require('sequelize');
+
+    // Collect all subdir IDs
+    async function collectIds(dirId) {
+      const children = await Directory.findAll({ where: { parentId: dirId, userId: req.user.id } });
+      let ids = [dirId];
+      for (const c of children) ids = ids.concat(await collectIds(c.id));
+      return ids;
+    }
+
+    const allIds = await collectIds(parseInt(req.params.id));
+    const tracks = await Track.findAll({
+      where: { directoryId: { [Op.in]: allIds }, userId: req.user.id },
+      attributes: ['id', 'name', 'totalDistance', 'trackDate', 'uploadDate', 'pointCount', 'directoryId'],
+      order: [['trackDate', 'DESC'], ['uploadDate', 'DESC']],
+    });
+
+    const totalDistance = tracks.reduce((s, t) => s + (t.totalDistance || 0), 0);
+    res.json({ tracks, totalDistance, trackCount: tracks.length });
+  } catch (e) {
+    res.status(500).json({ error: 'Server error' });
+  }
+});
+
+module.exports = router;