11import type { Db } from 'mongodb' ;
22
3- import type { StatsCollection } from '../db' ;
43import { getStatsCollection , initDb } from '../db' ;
54import type { Command } from '../types' ;
65import { getDateForWeekNumber , getWeekNumber } from '../utils' ;
@@ -20,59 +19,36 @@ const stats: Command = {
2019 async execute ( msg ) {
2120 const db = await initDb ( ) ;
2221
23- const { totalStats, statsChangeThisWeek, year1, year2, week1, week2 } =
24- await getStatsChangeThisWeek ( db ) ;
25-
26- const d1 = formatDate ( getDateForWeekNumber ( year2 , week2 + 1 ) ) ;
27- const d2 = formatDate ( getDateForWeekNumber ( year1 , week1 + 1 ) ) ;
28-
29- const ids = [
30- ...new Set ( [
31- ...totalStats . map ( ( { memberId } ) => memberId ) ,
32- ...statsChangeThisWeek . map ( ( { memberId } ) => memberId ) ,
33- ] ) ,
34- ] ;
22+ const { totalStats, statsThisWeek, year1, year2, week1, week2 } = await getStatsChangeThisWeek (
23+ db ,
24+ ) ;
3525
36- await Promise . allSettled ( ids . map ( ( memberId ) => msg . guild ?. members . fetch ( memberId ) ) ) ;
26+ const d1 = formatDate ( getDateForWeekNumber ( year2 , week2 ) ) ;
27+ const d2 = formatDate ( getDateForWeekNumber ( year1 , week1 ) ) ;
3728
3829 return msg . channel . send (
3930 [
40- format (
41- `Najbardziej aktywne w tym tygodniu (${ d1 } – ${ d2 } ):` ,
42- statsChangeThisWeek . map ( ( data ) => ( {
43- ...data ,
44- displayName : msg . guild ?. members . cache . get ( data . memberId ) ?. displayName ,
45- } ) ) ,
46- ) ,
31+ format ( `Najbardziej aktywne osoby w tym tygodniu (${ d1 } – ${ d2 } ):` , statsThisWeek ) ,
4732 '\n' ,
48- format (
49- 'Najbardziej aktywne osoby od początku istnienia serwera:' ,
50- totalStats . map ( ( data ) => ( {
51- ...data ,
52- displayName : msg . guild ?. members . cache . get ( data . memberId ) ?. displayName ,
53- } ) ) ,
54- ) ,
33+ format ( 'Najbardziej aktywne osoby od początku istnienia serwera:' , totalStats ) ,
5534 ] . join ( '\n' ) ,
5635 ) ;
5736 } ,
5837} ;
5938
6039export default stats ;
6140
62- type Stats = {
63- readonly memberId : string ;
64- readonly messagesCount : number ;
65- readonly displayName ?: string ;
66- } ;
67-
68- function format ( title : string , stats : readonly Stats [ ] ) {
41+ function format (
42+ title : string ,
43+ stats : readonly { messagesCount ?: number | null ; memberName ?: string | null } [ ] ,
44+ ) {
6945 const messages = [
7046 `**${ title } **` ,
7147 ...stats
72- . slice ( 0 , 10 )
48+ . filter ( ( d ) => d . messagesCount )
7349 . map (
74- ( { messagesCount, displayName } , index ) =>
75- `\`${ ( index + 1 ) . toString ( ) . padStart ( 2 , ' ' ) } \`. ${ displayName ?? '' } – ${
50+ ( { messagesCount, memberName } , index ) =>
51+ `\`${ ( index + 1 ) . toString ( ) . padStart ( 2 , ' ' ) } \`. ${ memberName ?? '' } – ${
7652 messagesCount ?? 0
7753 } `,
7854 ) ,
@@ -89,56 +65,50 @@ async function getStatsChangeThisWeek(db: Db) {
8965
9066 now . setDate ( now . getDate ( ) - 7 ) ;
9167 const [ year2 , week2 ] = getWeekNumber ( now ) ;
92- const previousWeek = `${ year2 } -${ week2 } ` ;
93-
94- const [ totalStats , statsThisWeek , statsPreviousWeek ] = await Promise . all ( [
95- statsCollection
96- . find (
97- {
98- yearWeek : null ,
99- } ,
100- { sort : { messagesCount : 'desc' } } ,
101- )
102- . toArray ( ) ,
103-
104- statsCollection . find ( { yearWeek : thisWeek } ) . toArray ( ) ,
105-
106- statsCollection . find ( { yearWeek : previousWeek } ) . toArray ( ) ,
107- ] ) ;
108-
109- const totalStatsById = resultToMessagesByMemberId ( totalStats ) ;
110- const statsPreviousWeekById = resultToMessagesByMemberId ( statsPreviousWeek ) ;
11168
112- const statsChangeThisWeek = statsThisWeek
113- . map ( ( { memberId , messagesCount } ) => {
114- if ( ! messagesCount ) {
115- return null ;
116- }
69+ const statsThisWeekPromise = statsCollection
70+ . find ( { yearWeek : thisWeek } )
71+ . sort ( { messagesCount : - 1 } )
72+ . limit ( 10 )
73+ . toArray ( ) ;
11774
118- const messagesCountDifference =
119- messagesCount - ( statsPreviousWeekById [ memberId ] ?? totalStatsById [ memberId ] ?? 0 ) ;
75+ // @todo should aggregate and sum
76+ const totalStatsPromise = getStats ( db ) ;
12077
121- return { memberId, messagesCount : messagesCountDifference } ;
122- } )
123- . filter ( ( obj ) : obj is Stats => ! ! obj )
124- . sort ( ( a , b ) => b . messagesCount - a . messagesCount ) ;
78+ const [ statsThisWeek , totalStats ] = await Promise . all ( [ statsThisWeekPromise , totalStatsPromise ] ) ;
12579
12680 return {
127- statsChangeThisWeek : statsChangeThisWeek . slice ( 0 , 10 ) ,
128- totalStats : totalStats . slice ( 0 , 10 ) as readonly Stats [ ] ,
81+ statsThisWeek ,
82+ totalStats,
12983 year1,
13084 year2,
13185 week1,
13286 week2,
13387 } ;
13488}
13589
136- function resultToMessagesByMemberId ( stats : readonly StatsCollection [ ] ) {
137- return stats . reduce < Record < StatsCollection [ 'memberId' ] , StatsCollection [ 'messagesCount' ] > > (
138- ( acc , { memberId, messagesCount } ) => {
139- acc [ memberId ] = messagesCount ;
140- return acc ;
90+ export type StatsAgg = {
91+ readonly _id : string ;
92+ readonly messagesCount : number ;
93+ readonly memberName : string ;
94+ } ;
95+
96+ const statsAggregation = [
97+ {
98+ $group : {
99+ _id : '$memberId' ,
100+ messagesCount : { $sum : '$messagesCount' } ,
101+ memberName : { $push : '$memberName' } ,
141102 } ,
142- { } ,
143- ) ;
144- }
103+ } ,
104+ { $sort : { messagesCount : - 1 } } ,
105+ { $limit : 10 } ,
106+ { $addFields : { memberName : { $arrayElemAt : [ { $reverseArray : '$memberName' } , 0 ] } } } ,
107+ ] ;
108+
109+ export const getStats = async ( db : Db ) => {
110+ const statsCollection = getStatsCollection ( db ) ;
111+
112+ const agg = await statsCollection . aggregate < StatsAgg > ( statsAggregation ) . toArray ( ) ;
113+ return agg ;
114+ } ;
0 commit comments