Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ Base URL: http://stats.filspark.com/

http://stats.filspark.com/participants/monthly

- `GET /participants/accumulative/daily?from=<day>&to=<day>`

http://stats.filspark.com/participants/accumulative/daily

- `GET /participants/change-rates?from=<day>&to=<day>`

http://stats.filspark.com/participants/change-rates
Expand Down
5 changes: 4 additions & 1 deletion stats/lib/platform-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
fetchTopEarningParticipants,
fetchParticipantsWithTopMeasurements,
fetchDailyStationMeasurementCounts,
fetchParticipantsSummary
fetchParticipantsSummary,
fetchAccumulativeDailyParticipantCount
} from './platform-stats-fetchers.js'

const createRespondWithFetchFn = (pathname, searchParams, res) => (pgPool, fetchFn) => {
Expand Down Expand Up @@ -40,6 +41,8 @@ export const handlePlatformRoutes = async (req, res, pgPools) => {
await respond(pgPools.stats, fetchTopEarningParticipants)
} else if (req.method === 'GET' && url === '/participants/summary') {
await respondWithParticipantsSummary(res, pgPools)
} else if (req.method === 'GET' && url === '/participants/accumulative/daily') {
await respond(pgPools.evaluate, fetchAccumulativeDailyParticipantCount)
} else if (req.method === 'GET' && url === '/transfers/daily') {
await respond(pgPools.stats, fetchDailyRewardTransfers)
} else {
Expand Down
34 changes: 34 additions & 0 deletions stats/lib/platform-stats-fetchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,40 @@ export const fetchDailyRewardTransfers = async (pgPool, filter) => {
return rows
}

/**
* @param {Queryable} pgPool
* @param {import('./typings.js').DateRangeFilter} filter
*/
export const fetchAccumulativeDailyParticipantCount = async (pgPool, filter) => {
const { rows } = await pgPool.query(`
WITH daily_participants_count AS (
SELECT
day,
participant_id,
ROW_NUMBER() OVER (PARTITION BY participant_id ORDER BY day) AS rn
FROM daily_participants
),
first_appearance AS (
SELECT day, participant_id
FROM daily_participants_count
WHERE rn = 1
),
cumulative_participants AS (
SELECT
day,
COUNT(participant_id) OVER (ORDER BY day) AS cumulative_participants
FROM first_appearance
)
SELECT
DISTINCT(day::TEXT),
cumulative_participants::INT as participants
FROM cumulative_participants
WHERE day >= $1 AND day <= $2
ORDER BY day
`, [filter.from, filter.to])
return rows
}

/**
* @param {Queryable} pgPool
* @param {import('./typings.js').DateRangeFilter} filter
Expand Down
51 changes: 51 additions & 0 deletions stats/test/platform-routes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,57 @@ describe('Platform Routes HTTP request handler', () => {
)
})
})

describe('GET /participants/accumulative/daily', () => {
it('counts accumulative daily participants', async () => {
// 3 new participants, out of range
await givenDailyParticipants(
pgPools.evaluate,
'1999-01-01',
['0x10', '0x20', '0x30']
)
// 3 new participants, 1 old participant -> 6
await givenDailyParticipants(
pgPools.evaluate,
'2000-01-01',
['0x1', '0x2', '0x3', '0x10']
)
// 0 new participants, 2 old participants
await givenDailyParticipants(
pgPools.evaluate,
'2000-01-02',
['0x1', '0x2']
)
// 1 new participant, 1 old participant -> 7
await givenDailyParticipants(
pgPools.evaluate,
'2000-01-03',
['0x1', '0x4']
)
// 1 new participant, out of range
await givenDailyParticipants(
pgPools.evaluate,
'2000-01-04',
['0x5']
)

const res = await fetch(
new URL('/participants/accumulative/daily?from=2000-01-01&to=2000-01-03', baseUrl), {
redirect: 'manual'
}
)
await assertResponseStatus(res, 200)
const daily = await res.json()
assert.deepStrictEqual(daily, [
{ day: '2000-01-01', participants: 6 },
{ day: '2000-01-03', participants: 7 }
])
assert.strictEqual(
res.headers.get('cache-control'),
'public, max-age=31536000, immutable'
)
})
})
})

const givenDailyMeasurementsSummary = async (pgPoolEvaluate, summaryData) => {
Expand Down
Loading