@@ -111,3 +111,49 @@ export const countTeeByDate = (
111111 . map ( ( [ dateLabel , count ] ) => ( { dateLabel, count } ) )
112112 . sort ( ( a , b ) => a . dateLabel . localeCompare ( b . dateLabel ) ) ;
113113} ;
114+
115+ export const countTeeMovingAverage = (
116+ dailyTeeCount : {
117+ dateLabel : string ;
118+ count : number ;
119+ } [ ]
120+ ) => {
121+ const DURATION = 30 ;
122+ if ( ! Array . isArray ( dailyTeeCount ) || dailyTeeCount . length === 0 ) {
123+ return [ ] ;
124+ }
125+
126+ const minDateLabel = dailyTeeCount [ 0 ] . dateLabel ;
127+ const maxDateLabel = dailyTeeCount [ dailyTeeCount . length - 1 ] . dateLabel ;
128+ const dateDelta =
129+ 1 +
130+ ( new Date ( maxDateLabel ) . getTime ( ) - new Date ( minDateLabel ) . getTime ( ) ) /
131+ 1000 /
132+ 86400 ;
133+
134+ const differentiatedTees = Array . from ( Array ( dateDelta ) ) . map ( ( __ , i ) => {
135+ const nextDate = new Date ( minDateLabel ) ;
136+ nextDate . setDate ( nextDate . getDate ( ) + i ) ;
137+ const nextDateLabel = nextDate . toISOString ( ) . substring ( 0 , 10 ) ;
138+ const found = dailyTeeCount . find ( ( tee ) => tee . dateLabel === nextDateLabel ) ;
139+ if ( found ) {
140+ return found ;
141+ } else {
142+ return { dateLabel : nextDateLabel , count : 0 } ;
143+ }
144+ } ) ;
145+
146+ return differentiatedTees
147+ . map ( ( { dateLabel } , i ) => {
148+ const dateSecond = parseDateLabel ( dateLabel ) . unix ( ) ;
149+ const begin = Math . max ( i - ( DURATION - 1 ) , 0 ) ;
150+ const total = differentiatedTees
151+ . slice ( begin , i + 1 )
152+ . reduce ( ( tot , data ) => data . count + tot , 0 ) ;
153+ if ( ! total ) {
154+ return null ;
155+ }
156+ return { dateSecond, count : total / DURATION } ;
157+ } )
158+ . filter ( ( data ) : data is { dateSecond : number ; count : number } => ! ! data ) ;
159+ } ;
0 commit comments