diff --git a/src/components/Rankings.jsx b/src/components/Rankings.jsx index 0ccb1fe..99598fd 100644 --- a/src/components/Rankings.jsx +++ b/src/components/Rankings.jsx @@ -5,18 +5,23 @@ /* eslint-disable max-len */ import React, { useState } from 'react'; -import { useSelector } from 'react-redux'; +import { shallowEqual, useSelector } from 'react-redux'; import { t } from 'ttag'; +import { selectStats } from '../store/selectors/ranks'; + const Rankings = () => { - const [orderDaily, setOrderDaily] = useState(false); - const totalRanking = useSelector( - (state) => state.ranks.totalRanking, - ); - const totalDailyRanking = useSelector( - (state) => state.ranks.totalDailyRanking, - ); + const [area, setArea] = useState('total'); + const [ + totalRanking, + totalDailyRanking, + dailyCRanking, + prevTop, + onlineStats, + cHistStats, + histStats, + ] = useSelector(selectStats, shallowEqual); return ( <> @@ -25,65 +30,124 @@ const Rankings = () => { role="button" tabIndex={-1} className={ - (!orderDaily) ? 'modallink selected' : 'modallink' + (area === 'total') ? 'modallink selected' : 'modallink' } - onClick={() => setOrderDaily(false)} + onClick={() => setArea('total')} >{t`Total`} setOrderDaily(true)} - >{t`Daily`} + onClick={() => setArea('today')} + >{t`Today`} + + setArea('yesterday')} + >{t`Yesterday`} + + setArea('countries')} + >{t`Countries Today`} - - - {(orderDaily) ? ( - - - - - - - - ) : ( - - - - - - - - )} - - - {(orderDaily) - ? totalDailyRanking.map((rank) => ( - - - - - - - - )) - : totalRanking.map((rank) => ( - - - - - - - - ))} - -
#userPixels# TotalTotal Pixels
#userPixels# TodayPixels Today
{rank.dr}{rank.name}{rank.dt}{rank.r}{rank.t}
{rank.r}{rank.name}{rank.t}{rank.dr}{rank.dt}
+ {(['total', 'today', 'yesterday', 'countries'].includes(area)) && ( + + + {{ + total: ( + + + + + + + + ), + today: ( + + + + + + + + ), + yesterday: ( + + + + + + ), + countries: ( + + + + + + ), + }[area]} + + + {{ + total: totalRanking.map((rank) => ( + + + + + + + + )), + today: totalDailyRanking.map((rank) => ( + + + + + + + + )), + yesterday: prevTop.map((rank, ind) => ( + + + + + + )), + countries: prevTop.map((rank, ind) => ( + + + + + + )), + }[area]} + +
#{t`User`}Pixels# TodayPixels Today
#{t`User`}Pixels# TotalTotal Pixels
#{t`User`}Pixels
#{t`Country`}Pixels
{rank.r}{rank.name}{rank.t}{rank.dr}{rank.dt}
{rank.dr}{rank.name}{rank.dt}{rank.r}{rank.t}
{ind + 1}{rank.name}{rank.px}
{ind + 1}{rank.cc}{rank.px}
+ )}

{t`Ranking updates every 5 min. Daily rankings get reset at midnight UTC.`}

diff --git a/src/core/Ranks.js b/src/core/Ranks.js index af9fed0..7f78d5a 100644 --- a/src/core/Ranks.js +++ b/src/core/Ranks.js @@ -10,6 +10,7 @@ import { getOnlineUserStats, storeOnlinUserAmount, getCountryDailyHistory, + getCountryRanks, getTopDailyHistory, } from '../data/redis/ranks'; import socketEvents from '../socket/socketEvents'; @@ -23,6 +24,7 @@ class Ranks { this.ranks = { dailyRanking: [], ranking: [], + dailyCRanking: [], prevTop: [], onlineStats: [], cHistStats: [], @@ -78,9 +80,11 @@ class Ranks { 1, 100, )); + const dailyCRanking = await getCountryRanks(1, 100); const ret = { ranking, dailyRanking, + dailyCRanking, }; socketEvents.rankingListUpdate(ret); return ret; diff --git a/src/data/redis/ranks.js b/src/data/redis/ranks.js index d3b7d57..8b4355f 100644 --- a/src/data/redis/ranks.js +++ b/src/data/redis/ranks.js @@ -80,6 +80,21 @@ export async function getRanks(daily, start, amount) { return ret; } +/* + * get daily country ranking + */ +export async function getCountryRanks(start, amount) { + let ranks = await client.zRangeWithScores( + DAILY_CRANKED_KEY, start, start + amount, { + REV: true, + }); + ranks = ranks.map((r) => ({ + cc: r.value, + px: Number(r.score), + })); + return ranks; +} + /* * get top 10 from previous day */ diff --git a/src/store/actions/index.js b/src/store/actions/index.js index 7976fbd..1b87f58 100644 --- a/src/store/actions/index.js +++ b/src/store/actions/index.js @@ -271,11 +271,24 @@ export function receiveMe( export function receiveStats( rankings, ) { - const { ranking: totalRanking, dailyRanking: totalDailyRanking } = rankings; + const { + ranking: totalRanking, + dailyRanking: totalDailyRanking, + dailyCRanking, + prevTop, + onlineStats, + cHistStats, + histStats, + } = rankings; return { type: 'REC_STATS', totalRanking, totalDailyRanking, + dailyCRanking, + prevTop, + onlineStats, + cHistStats, + histStats, }; } diff --git a/src/store/reducers/ranks.js b/src/store/reducers/ranks.js index 5b523bc..c09d6a4 100644 --- a/src/store/reducers/ranks.js +++ b/src/store/reducers/ranks.js @@ -17,6 +17,11 @@ const initialState = { }, totalRanking: [], totalDailyRanking: [], + dailyCRanking: [], + prevTop: [], + onlineStats: [], + cHistStats: [], + histStats: [], }; export default function ranks( @@ -70,13 +75,26 @@ export default function ranks( } case 'REC_STATS': { - const { totalRanking, totalDailyRanking } = action; + const { + totalRanking, + totalDailyRanking, + dailyCRanking, + prevTop, + onlineStats, + cHistStats, + histStats, + } = action; const lastFetch = Date.now(); return { ...state, lastFetch, totalRanking, totalDailyRanking, + dailyCRanking, + prevTop, + onlineStats, + cHistStats, + histStats, }; } diff --git a/src/store/selectors/ranks.js b/src/store/selectors/ranks.js new file mode 100644 index 0000000..ad09e9d --- /dev/null +++ b/src/store/selectors/ranks.js @@ -0,0 +1,15 @@ +/* + * selectors for ranks + */ + +/* eslint-disable import/prefer-default-export */ + +export const selectStats = (state) => [ + state.ranks.totalRanking, + state.ranks.totalDailyRanking, + state.ranks.dailyCRanking, + state.ranks.prevTop, + state.ranks.onlineStats, + state.ranks.cHistStats, + state.ranks.histStats, +]; diff --git a/src/store/sharedReducers.js b/src/store/sharedReducers.js index cdfc9a7..0027cc9 100644 --- a/src/store/sharedReducers.js +++ b/src/store/sharedReducers.js @@ -15,7 +15,7 @@ import canvas from './reducers/canvas'; import chat from './reducers/chat'; import fetching from './reducers/fetching'; -export const CURRENT_VERSION = 11; +export const CURRENT_VERSION = 12; export const migrate = (state, version) => { // eslint-disable-next-line no-underscore-dangle