diff --git a/README.md b/README.md index a6dff19..e3587ff 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,6 @@ a Page to view some global statistics about [Modrinth](https://modrinth.com/) -### Planned Features - -* data on specific projects - Same graphs as for mods but only showing a single project - ### .env ```dotenv @@ -16,4 +12,4 @@ MONGODB_DEV_DB=modrinth-statistics-dev MONGODB_DEV_CONNECTION=mongodb://:@:27017/ POSTHOG_API_KEY= POSTHOG_API_HOST=https://eu.posthog.com -``` \ No newline at end of file +``` diff --git a/server/api/stats/time/global.ts b/server/api/stats/time/global.ts index 9809a1c..99f41d9 100644 --- a/server/api/stats/time/global.ts +++ b/server/api/stats/time/global.ts @@ -53,9 +53,9 @@ export default defineCachedEventHandler( const data = await exportGlobalStatsOverTime(dateKey, typeFn); if (query.aggregate === "false") { - return fracture(data); + return summarize(fracture(data), 64, false); } - return data; + return summarize(data, 64, true); }, { maxAge: 60 * 60 /* 1 hour */, swr: false }, ); diff --git a/server/api/stats/time/projects.ts b/server/api/stats/time/projects.ts index 078de25..d4fc4aa 100644 --- a/server/api/stats/time/projects.ts +++ b/server/api/stats/time/projects.ts @@ -27,9 +27,9 @@ export default defineCachedEventHandler( ); if (query.aggregate === "false") { - return fracture(data); + return summarize(fracture(data), 64, false); } - return data; + return summarize(data, 64, true); }, { maxAge: 60 * 60 /* 1 hour */, swr: false }, ); diff --git a/server/utils/processing/aggregate.ts b/server/utils/processing/aggregate.ts index 08b1d43..ddd8fec 100644 --- a/server/utils/processing/aggregate.ts +++ b/server/utils/processing/aggregate.ts @@ -1,5 +1,6 @@ import type { StatExport } from "~~/shared/types/types"; +// get data containing absolute values and convert it to data containing absolute difference export function fracture(data: StatExport): StatExport { data.data.map((value) => { const data = []; @@ -12,5 +13,45 @@ export function fracture(data: StatExport): StatExport { return value; }); + data.labels.pop(); + + return data; +} + +// summarize data to values +export function summarize( + data: StatExport, + count: number, + should_avg: boolean, +): StatExport { + const per_group = data.labels.length / count; + + const indexes: number[] = []; + for (let i = 0; i < data.labels.length; i++) { + if (indexes.length * per_group <= i) { + // insert reversed values so most recent data is always present + indexes.push(data.labels.length - 1 - i); + } + } + + for (let i = 0; i < indexes.length; i++) { + const from = indexes[i + 1] + 1 || 0; + const to = indexes[i]; + + for (const values of data.data) { + const to_avg = values.data; + + let sum = 0; + for (let j = from; j <= to; j++) { + sum += to_avg[j]; + } + + const value = should_avg ? Math.round(sum / (to - from + 1)) : sum; + to_avg.splice(from, to - from + 1, value); + } + } + + data.labels = data.labels.filter((_value, index) => indexes.includes(index)); + return data; }