1+ var moment = require ( 'moment' ) ;
12var sprintf = require ( 'sprintf-js' ) . sprintf ;
23var _ = require ( 'underscore' ) ;
34
@@ -14,6 +15,12 @@ var cmd = {
1415 aliases : [ 'stats' , 'progress' , 'report' ] ,
1516 builder : function ( yargs ) {
1617 return yargs
18+ . option ( 'c' , {
19+ alias : 'cal' ,
20+ type : 'boolean' ,
21+ default : false ,
22+ describe : 'Show calendar statistics'
23+ } )
1724 . option ( 'g' , {
1825 alias : 'graph' ,
1926 type : 'boolean' ,
@@ -42,9 +49,7 @@ var cmd = {
4249
4350function bar ( c , n ) {
4451 return _ . range ( n )
45- . map ( function ( i ) {
46- return c ;
47- } )
52+ . map ( function ( i ) { return c ; } )
4853 . join ( '' ) ;
4954}
5055
@@ -81,11 +86,17 @@ function showProgress(problems) {
8186 printLine ( 'Hard' , stats . hard . ac , stats . hard . all ) ;
8287}
8388
89+ var CHARS = {
90+ ac : h . isWindows ( ) ? 'O ' : '▣ ' ,
91+ notac : h . isWindows ( ) ? 'X ' : '▤ ' ,
92+ none : h . isWindows ( ) ? 'o ' : '⬚ ' ,
93+ } ;
94+
8495function showGraph ( problems ) {
85- var icons = {
86- ac : chalk . green ( h . isWindows ( ) ? 'O ' : '▣ ' ) ,
87- notac : chalk . red ( h . isWindows ( ) ? 'X ' : '▤ ' ) ,
88- none : chalk . gray ( h . isWindows ( ) ? 'o ' : '⬚ ' ) ,
96+ var ICONS = {
97+ ac : chalk . green ( CHARS . ac ) ,
98+ notac : chalk . red ( CHARS . notac ) ,
99+ none : chalk . gray ( CHARS . none ) ,
89100 empty : ' '
90101 } ;
91102
@@ -103,15 +114,15 @@ function showGraph(problems) {
103114
104115 var graph = [ ] ;
105116 _ . each ( problems , function ( problem ) {
106- graph [ problem . id ] = icons [ problem . state ] || icons . none ;
117+ graph [ problem . id ] = ICONS [ problem . state ] || ICONS . none ;
107118 } ) ;
108119
109120 var line = [ sprintf ( ' %03d' , 0 ) ] ;
110121 for ( var i = 1 , n = graph . length ; i <= n ; ++ i ) {
111122 // padding before group
112123 if ( i % 10 === 1 ) line . push ( ' ' ) ;
113124
114- line . push ( graph [ i ] || icons . empty ) ;
125+ line . push ( graph [ i ] || ICONS . empty ) ;
115126
116127 // time to start new row
117128 if ( i % ( 10 * groups ) === 0 || i === n ) {
@@ -122,10 +133,83 @@ function showGraph(problems) {
122133
123134 log . info ( ) ;
124135 log . printf ( '%7s%s%3s%s%3s%s' ,
125- ' ' , icons . ac + chalk . green ( ' Accepted' ) ,
126- ' ' , icons . notac + chalk . red ( ' Not Accepted' ) ,
127- ' ' , icons . none + ' Remaining' ) ;
136+ ' ' , ICONS . ac + chalk . green ( ' Accepted' ) ,
137+ ' ' , ICONS . notac + chalk . red ( ' Not Accepted' ) ,
138+ ' ' , ICONS . none + ' Remaining' ) ;
139+ }
140+
141+ function showCal ( ) {
142+ var MONTHS = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' , 'Oct' , 'Nov' , 'Dec' ] ;
143+ var WEEKDAYS = [ 'Sun' , 'Mon' , 'Tue' , 'Wed' , 'Thu' , 'Fri' , 'Sat' ] ;
144+ var ICONS = [
145+ CHARS . none ,
146+ chalk . sprint ( CHARS . ac , '#ffffcc' ) ,
147+ chalk . sprint ( CHARS . ac , '#ccff66' ) ,
148+ chalk . sprint ( CHARS . ac , '#66cc33' ) ,
149+ chalk . sprint ( CHARS . ac , '#00ff00' )
150+ ] ;
151+
152+ var N_MONTHS = 12 ;
153+ var N_WEEKS = 53 ;
154+ var N_WEEKDAYS = 7 ;
155+
156+ var now = moment ( ) ;
157+
158+ // load historical stats
159+ var graph = [ ] ;
160+ var stats = require ( '../cache' ) . get ( h . KEYS . stat ) || { } ;
161+ _ . keys ( stats ) . forEach ( function ( k ) {
162+ var v = stats [ k ] . ac || 0 ;
163+ if ( v === 0 ) return ;
164+
165+ var d = moment ( k , 'YYYY-MM-DD' ) ;
166+ graph [ now . diff ( d , 'days' ) ] = v ;
167+ } ) ;
168+
169+ // print header
170+ var buf = Buffer . alloc ( 120 , ' ' , 'ascii' ) ;
171+ for ( var i = 0 ; i <= N_MONTHS ; ++ i ) {
172+ // for day 1 in each month, calculate its column position in graph
173+ var d = now . clone ( ) . subtract ( i , 'months' ) . date ( 1 ) ;
174+ var idx = now . diff ( d , 'days' ) ;
175+
176+ var j = ( N_WEEKS - idx / N_WEEKDAYS + 1 ) * 2 ;
177+ if ( j >= 0 ) buf . write ( MONTHS [ d . month ( ) ] , j ) ;
178+ }
179+ log . printf ( '%7s%s' , ' ' , buf . toString ( ) ) ;
180+
181+ // print graph
182+ var idx ;
183+ for ( var i = 0 ; i < N_WEEKDAYS ; ++ i ) {
184+ var line = [ ] ;
185+ // print day in week
186+ idx = ( now . day ( ) + i + 1 ) % N_WEEKDAYS ;
187+ line . push ( sprintf ( '%4s ' , WEEKDAYS [ idx ] ) ) ;
188+
189+ for ( var j = 0 ; j < N_WEEKS ; ++ j ) {
190+ idx = ( N_WEEKS - j - 1 ) * N_WEEKDAYS + N_WEEKDAYS - i - 1 ;
191+ var d = now . clone ( ) . subtract ( idx , 'days' ) ;
192+
193+ // map count to icons index:
194+ // [0] => 0, [1,5] => 1, [6,10] => 2, [11,15] => 3, [16,) => 4
195+ var count = graph [ idx ] || 0 ;
196+ idx = Math . floor ( ( count - 1 ) / 5 ) + 1 ;
197+ if ( idx > 4 ) idx = 4 ;
198+
199+ var icon = ICONS [ idx ] ;
200+ // use different colors for adjacent months
201+ if ( idx === 0 && d . month ( ) % 2 ) icon = chalk . gray ( icon ) ;
202+ line . push ( icon ) ;
203+ }
204+ log . info ( line . join ( '' ) ) ;
205+ }
206+
128207 log . info ( ) ;
208+ log . printf ( '%7s%s%3s%s%3s%s%3s%s' ,
209+ ' ' , ICONS [ 1 ] + ' 1~5' ,
210+ ' ' , ICONS [ 2 ] + ' 6~10' ,
211+ ' ' , ICONS [ 3 ] + ' 11~15' ,
212+ ' ' , ICONS [ 4 ] + ' 16+' ) ;
129213}
130214
131215cmd . handler = function ( argv ) {
@@ -141,8 +225,11 @@ cmd.handler = function(argv) {
141225 problems = _ . filter ( problems , function ( x ) { return ! x . locked ; } ) ;
142226 }
143227
144- if ( argv . graph ) return showGraph ( problems ) ;
145- showProgress ( problems ) ;
228+ log . info ( ) ;
229+ if ( argv . graph ) showGraph ( problems ) ;
230+ else if ( argv . cal ) showCal ( ) ;
231+ else showProgress ( problems ) ;
232+ log . info ( ) ;
146233 } ) ;
147234} ;
148235
0 commit comments