@@ -29,6 +29,72 @@ function getFileName(daysAgo) {
2929 return `${ year } -${ month } -${ date } -${ day } .json` ;
3030}
3131
32+ async function getYesterdaySnapshot ( filePath ) {
33+ const owner = "codepvg" ;
34+ const repo = "leetcode-ranking-data" ;
35+ const d = new Date ( ) ;
36+ d . setDate ( d . getDate ( ) - 1 ) ;
37+ const targetDate = d . toISOString ( ) . split ( "T" ) [ 0 ] ;
38+ const until = `${ targetDate } T23:59:59Z` ;
39+ const commitsUrl = `https://api.github.com/repos/${ owner } /${ repo } /commits?path=${ filePath } &until=${ until } &per_page=1` ;
40+
41+ const headers = { "User-Agent" : "CodePVG-App" } ;
42+ if ( process . env . DATA_REPO_TOKEN ) {
43+ headers [ "Authorization" ] = `token ${ process . env . DATA_REPO_TOKEN } ` ;
44+ }
45+
46+ try {
47+ const commitResponse = await axios . get ( commitsUrl , { headers } ) ;
48+ const commits = commitResponse . data ;
49+
50+ if ( ! commits || commits . length === 0 ) {
51+ console . warn (
52+ `No commits found for ${ filePath } on or before ${ targetDate } .` ,
53+ ) ;
54+ return null ;
55+ }
56+
57+ const yesterdaySHA = commits [ 0 ] . sha ;
58+ console . log (
59+ `📌 Using Commit for ${ filePath } : "${ commits [ 0 ] . commit . message } " (SHA: ${ yesterdaySHA } )` ,
60+ ) ;
61+
62+ const rawFileUrl = `https://raw.githubusercontent.com/${ owner } /${ repo } /${ yesterdaySHA } /${ filePath } ` ;
63+ const fileResponse = await axios . get ( rawFileUrl ) ;
64+ return fileResponse . data ;
65+ } catch ( error ) {
66+ console . error (
67+ `Error fetching historical data for ${ filePath } :` ,
68+ error . message ,
69+ ) ;
70+ return null ;
71+ }
72+ }
73+
74+ async function computeRankChanges ( currentSorted , filename ) {
75+ let previousRanks = { } ;
76+ const previousData = await getYesterdaySnapshot ( filename ) ;
77+
78+ if ( previousData && Array . isArray ( previousData ) ) {
79+ previousData . forEach ( ( user , idx ) => {
80+ previousRanks [ user . id ] = idx + 1 ;
81+ } ) ;
82+ }
83+
84+ currentSorted . forEach ( ( user , idx ) => {
85+ const currentRank = idx + 1 ;
86+
87+ if ( previousRanks [ user . id ] === undefined ) {
88+ user . rankChange = "NEW" ;
89+ } else {
90+ const delta = previousRanks [ user . id ] - currentRank ;
91+ if ( delta > 0 ) user . rankChange = `+${ delta } ` ;
92+ else if ( delta < 0 ) user . rankChange = `${ delta } ` ;
93+ else user . rankChange = "=" ;
94+ }
95+ } ) ;
96+ }
97+
3298( async ( ) => {
3399 const DATA_DIR = process . env . DATA_DIR || path . join ( __dirname , ".." , "data" ) ;
34100 console . log ( `Using data directory: ${ DATA_DIR } ` ) ;
@@ -87,6 +153,7 @@ function getFileName(daysAgo) {
87153 overallData . sort ( ( a , b ) => b . score - a . score ) ;
88154 console . log ( "Writing sorted daily data to overall file..." ) ;
89155 const overallFilepath = path . join ( DATA_DIR , "overall.json" ) ;
156+ await computeRankChanges ( overallData , "overall.json" ) ;
90157 try {
91158 fs . writeFileSync (
92159 overallFilepath ,
@@ -144,6 +211,7 @@ function getFileName(daysAgo) {
144211
145212 console . log ( "Writing sorted daily data to daily.json..." ) ;
146213 const dailyFilepath = path . join ( DATA_DIR , "daily.json" ) ;
214+ await computeRankChanges ( dailyData , "daily.json" ) ;
147215 try {
148216 fs . writeFileSync ( dailyFilepath , JSON . stringify ( dailyData , null , 2 ) , "utf8" ) ;
149217 console . log ( "Daily data saved successfully" ) ;
@@ -199,6 +267,7 @@ function getFileName(daysAgo) {
199267
200268 console . log ( "Writing sorted weekly data to weekly.json..." ) ;
201269 const weeklyFilepath = path . join ( DATA_DIR , "weekly.json" ) ;
270+ await computeRankChanges ( weeklyData , "weekly.json" ) ;
202271 try {
203272 fs . writeFileSync (
204273 weeklyFilepath ,
@@ -258,6 +327,7 @@ function getFileName(daysAgo) {
258327
259328 console . log ( "Writing sorted monthly data to monthly.json..." ) ;
260329 const monthlyFilepath = path . join ( DATA_DIR , "monthly.json" ) ;
330+ await computeRankChanges ( monthlyData , "monthly.json" ) ;
261331 try {
262332 fs . writeFileSync (
263333 monthlyFilepath ,
0 commit comments