Enhance smoke-tracker API to include statistics for active users only; update documentation to reflect changes in user activity criteria and statistics calculations.
This commit is contained in:
@@ -508,13 +508,17 @@ curl -X GET http://localhost:8044/smoke-tracker/stats/summary \
|
|||||||
- `total` — общее количество сигарет за период
|
- `total` — общее количество сигарет за период
|
||||||
- `daysWithData` — количество дней, в которые были записи
|
- `daysWithData` — количество дней, в которые были записи
|
||||||
|
|
||||||
**`global`** — общая статистика по всем пользователям:
|
**`global`** — общая статистика по всем **активным** пользователям:
|
||||||
- `daily` — массив с суммарным количеством сигарет всех пользователей по дням
|
- `daily` — массив с суммарным количеством сигарет всех активных пользователей по дням
|
||||||
- `averagePerDay` — среднее количество сигарет в день (все пользователи)
|
- `averagePerDay` — среднее количество сигарет в день (активные пользователи)
|
||||||
- `weekday` — статистика по дням недели (все пользователи)
|
- `weekday` — статистика по дням недели (активные пользователи)
|
||||||
- `total` — общее количество сигарет всех пользователей за период
|
- `total` — общее количество сигарет всех активных пользователей за период
|
||||||
- `daysWithData` — количество дней с записями
|
- `daysWithData` — количество дней с записями
|
||||||
- `activeUsers` — количество уникальных пользователей, записывавших сигареты в период
|
- `activeUsers` — количество активных пользователей в период
|
||||||
|
|
||||||
|
> **Примечание**: Активными считаются только пользователи, которые в среднем выкуривают **от 2 до 40 сигарет в день**. Это позволяет исключить из статистики:
|
||||||
|
> - Тестовые аккаунты и неактивных пользователей (< 2 сигарет/день)
|
||||||
|
> - Ошибочные или накликанные данные (> 40 сигарет/день)
|
||||||
|
|
||||||
**`period`** — информация о запрошенном периоде:
|
**`period`** — информация о запрошенном периоде:
|
||||||
- `from` — начало периода (ISO 8601)
|
- `from` — начало периода (ISO 8601)
|
||||||
|
|||||||
@@ -150,9 +150,47 @@ router.get('/summary', async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 4. Общая статистика по всем пользователям
|
// 4. Определяем активных пользователей (от 2 до 40 сигарет в день в среднем)
|
||||||
const globalDailyStats = await CigaretteModel.aggregate([
|
const MIN_CIGARETTES_PER_DAY = 2
|
||||||
|
const MAX_CIGARETTES_PER_DAY = 40
|
||||||
|
const periodDays = Math.ceil((toDate.getTime() - fromDate.getTime()) / (1000 * 60 * 60 * 24))
|
||||||
|
|
||||||
|
// Получаем статистику по каждому пользователю
|
||||||
|
const userStats = await CigaretteModel.aggregate([
|
||||||
{ $match: globalMatch },
|
{ $match: globalMatch },
|
||||||
|
{
|
||||||
|
$group: {
|
||||||
|
_id: '$userId',
|
||||||
|
total: { $sum: 1 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// Фильтруем активных пользователей (исключаем слишком низкие и слишком высокие значения)
|
||||||
|
const activeUserIds = userStats
|
||||||
|
.filter((stat) => {
|
||||||
|
const avgPerDay = stat.total / periodDays
|
||||||
|
return avgPerDay > MIN_CIGARETTES_PER_DAY && avgPerDay <= MAX_CIGARETTES_PER_DAY
|
||||||
|
})
|
||||||
|
.map((stat) => stat._id)
|
||||||
|
|
||||||
|
const filteredLow = userStats.filter((stat) => stat.total / periodDays <= MIN_CIGARETTES_PER_DAY).length
|
||||||
|
const filteredHigh = userStats.filter((stat) => stat.total / periodDays > MAX_CIGARETTES_PER_DAY).length
|
||||||
|
|
||||||
|
console.log('[STATS] Total users:', userStats.length)
|
||||||
|
console.log('[STATS] Active users (2-40 cigs/day):', activeUserIds.length)
|
||||||
|
console.log('[STATS] Filtered out (too low):', filteredLow)
|
||||||
|
console.log('[STATS] Filtered out (too high):', filteredHigh)
|
||||||
|
|
||||||
|
// Фильтр только для активных пользователей
|
||||||
|
const activeGlobalMatch = {
|
||||||
|
...globalMatch,
|
||||||
|
userId: { $in: activeUserIds },
|
||||||
|
}
|
||||||
|
|
||||||
|
// Общая статистика по активным пользователям
|
||||||
|
const globalDailyStats = await CigaretteModel.aggregate([
|
||||||
|
{ $match: activeGlobalMatch },
|
||||||
{
|
{
|
||||||
$group: {
|
$group: {
|
||||||
_id: {
|
_id: {
|
||||||
@@ -174,9 +212,9 @@ router.get('/summary', async (req, res, next) => {
|
|||||||
const globalAveragePerDay =
|
const globalAveragePerDay =
|
||||||
globalDaysWithData > 0 ? (globalTotalCigarettes / globalDaysWithData).toFixed(2) : 0
|
globalDaysWithData > 0 ? (globalTotalCigarettes / globalDaysWithData).toFixed(2) : 0
|
||||||
|
|
||||||
// Общая статистика по дням недели (все пользователи)
|
// Общая статистика по дням недели (активные пользователи)
|
||||||
const globalWeekdayStats = await CigaretteModel.aggregate([
|
const globalWeekdayStats = await CigaretteModel.aggregate([
|
||||||
{ $match: globalMatch },
|
{ $match: activeGlobalMatch },
|
||||||
{
|
{
|
||||||
$group: {
|
$group: {
|
||||||
_id: { $dayOfWeek: '$smokedAt' },
|
_id: { $dayOfWeek: '$smokedAt' },
|
||||||
@@ -205,8 +243,8 @@ router.get('/summary', async (req, res, next) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Количество активных пользователей в периоде
|
// Количество активных пользователей
|
||||||
const activeUsers = await CigaretteModel.distinct('userId', globalMatch)
|
const activeUsers = activeUserIds
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
user: {
|
user: {
|
||||||
|
|||||||
Reference in New Issue
Block a user