diff --git a/src/core/Ranks.js b/src/core/Ranks.js index ee65962..70afa7a 100644 --- a/src/core/Ranks.js +++ b/src/core/Ranks.js @@ -44,7 +44,6 @@ class Ranks { // pixels placed by day pDailyStats: [], }; - this.prevTopIds = []; /* * we go through socketEvents for sharding */ @@ -71,11 +70,6 @@ class Ranks { if (!newRanks) { return; } - const { prevTopIds } = newRanks; - if (prevTopIds) { - this.prevTopIds = prevTopIds; - delete newRanks.prevTopIds; - } this.ranks = { ...this.ranks, ...newRanks, @@ -126,9 +120,9 @@ class Ranks { } static async dailyUpdateRanking() { - const prevTopData = await getPrevTop(); - const prevTopIds = prevTopData.map((d) => d.id); - const prevTop = await populateRanking(prevTopData); + const prevTop = await populateRanking( + await getPrevTop(), + ); const pDailyStats = await getDailyPixelStats(); const histStats = await getTopDailyHistory(); histStats.users = await populateRanking(histStats.users); @@ -139,7 +133,6 @@ class Ranks { prevTop, pDailyStats, histStats, - prevTopIds, }; if (socketEvents.amIImportant()) { // only main shard sends to others diff --git a/src/core/draw.js b/src/core/draw.js index f082c8d..dc5dbe5 100644 --- a/src/core/draw.js +++ b/src/core/draw.js @@ -10,7 +10,6 @@ import allowPlace from '../data/redis/cooldown'; import socketEvents from '../socket/socketEvents'; import { setPixelByOffset } from './setPixel'; import isIPAllowed from './isAllowed'; -import rankings from './Ranks'; import canvases from './canvases'; import { THREE_CANVAS_HEIGHT, THREE_TILE_SIZE, TILE_SIZE } from './constants'; @@ -112,27 +111,7 @@ export default async function drawByOffsets( * 2: mod */ const isAdmin = (user.userlvl === 1); - - if (canvas.req !== undefined && !isAdmin) { - if (user.id === null) { - // not logged in - throw new Error(6); - } - if (canvas.req > 0) { - const totalPixels = await user.getTotalPixels(); - if (totalPixels < canvas.req) { - // not enough pixels placed yet - throw new Error(7); - } - } - if (canvas.req === 'top' - && !rankings.prevTopIds.includes(user.id) - ) { - // not in top ten - throw new Error(12); - } - } - + const req = (isAdmin) ? null : canvas.req; const clrIgnore = canvas.cli || 0; const factor = (isAdmin || (user.userlvl > 0 && pixels[0][1] < clrIgnore)) ? 0.0 : coolDownFactor; @@ -187,6 +166,7 @@ export default async function drawByOffsets( } } + let needProxycheck; [retCode, pxlCnt, wait, coolDown, needProxycheck] = await allowPlace( ip, @@ -196,6 +176,7 @@ export default async function drawByOffsets( canvasId, i, j, clrIgnore, + req, bcd, pcd, canvas.cds, pxlOffsets, diff --git a/src/data/User.js b/src/data/User.js index 0acc086..7286a37 100644 --- a/src/data/User.js +++ b/src/data/User.js @@ -186,6 +186,7 @@ class User { return this.regUser.totalPixels; } try { + // TODO does not work anymore const userq = await sequelize.query( 'SELECT totalPixels FROM Users WHERE id = $1', { diff --git a/src/data/redis/client.js b/src/data/redis/client.js index ae65d30..fff6e61 100644 --- a/src/data/redis/client.js +++ b/src/data/redis/client.js @@ -10,7 +10,7 @@ import { REDIS_URL, SHARD_NAME } from '../../core/config'; const scripts = { placePxl: defineScript({ - NUMBER_OF_KEYS: 8, + NUMBER_OF_KEYS: 9, SCRIPT: fs.readFileSync('./workers/lua/placePixel.lua'), transformArguments(...args) { return args.map((a) => ((typeof a === 'string') ? a : a.toString())); diff --git a/src/data/redis/cooldown.js b/src/data/redis/cooldown.js index 6bfd743..7df65ba 100644 --- a/src/data/redis/cooldown.js +++ b/src/data/redis/cooldown.js @@ -5,7 +5,12 @@ import client from './client'; import { PREFIX as CAPTCHA_PREFIX } from './captcha'; import { PREFIX as ALLOWED_PREFIX } from './isAllowedCache'; -import { RANKED_KEY, DAILY_RANKED_KEY, DAILY_CRANKED_KEY } from './ranks'; +import { + RANKED_KEY, + DAILY_RANKED_KEY, + DAILY_CRANKED_KEY, + PREV_DAY_TOP_KEY, +} from './ranks'; import { CAPTCHA_TIME } from '../../core/config'; const PREFIX = 'cd'; @@ -30,6 +35,7 @@ export default function allowPlace( canvasId, i, j, clrIgnore, + req, bcd, pcd, cds, @@ -51,14 +57,17 @@ export default function allowPlace( } else { idCdKey = 'nope'; } + if (!req && req !== 0) { + req = 'nope'; + } const chunkKey = `ch:${canvasId}:${i}:${j}`; const cc = country || 'xx'; - const rankset = (ranked) ? RANKED_KEY : 'nope'; + const rankset = RANKED_KEY; const dailyset = (ranked) ? DAILY_RANKED_KEY : 'nope'; return client.placePxl( // eslint-disable-next-line max-len - isalKey, captKey, ipCdKey, idCdKey, chunkKey, rankset, dailyset, DAILY_CRANKED_KEY, - clrIgnore, bcd, pcd, cds, id, cc, + isalKey, captKey, ipCdKey, idCdKey, chunkKey, rankset, dailyset, DAILY_CRANKED_KEY, PREV_DAY_TOP_KEY, + clrIgnore, bcd, pcd, cds, id, cc, req, ...pxls, ); } diff --git a/src/data/redis/lua/placePixel.lua b/src/data/redis/lua/placePixel.lua index 5e08e15..43b16a8 100644 --- a/src/data/redis/lua/placePixel.lua +++ b/src/data/redis/lua/placePixel.lua @@ -11,9 +11,10 @@ -- 'nope' if not logged in -- chunk: 'ch:canvasId:i:j' -- rankset: 'rank' sorted set of pixelcount --- 'nope' if not increasing ranks -- dailyset: 'rankd' sorted set of daily pixelcount +-- 'nope' if not increasing ranks -- countryset: sorted set for country stats +-- prevTop: sorted set of yesterdays top 10 -- Args: -- clrIgnore: integer number of what colors are considered unset -- bcd: number baseColldown (fixed to cdFactor and 0 if admin) @@ -21,6 +22,8 @@ -- cds: max cooldown of canvas -- userId: '0' if not logged in -- cc country code +-- req: requirements of canvas +-- 'nope', unsigned integer or 'top' -- off1, chonk offset of first pixel -- off2, chonk offset of second pixel -- ..., infinie pixels possible @@ -59,6 +62,32 @@ else return ret end end +-- check if requirements for canvas met +if ARGV[7] ~= "nope" then + if ARGV[5] == "0" then + -- not logged in + ret[1] = 6 + return ret; + end + if ARGV[7] == "top" then + local pr = redis.call('zrank', KEYS[9], ARGV[5]) + if not pr or pr > 9 then + -- not in yesterdays top 10 + ret[1] = 12; + return ret; + end + else + local req = tonumber(ARGV[7]) + if req > 0 then + local sc = tonumber(redis.call('zscore', KEYS[6], ARGV[5])) + if not sc or sc < req then + -- not enough pxls placed + ret[1] = 7; + return ret + end + end + end +end -- get cooldown of user local cd = redis.call('pttl', KEYS[3]) if cd < 0 then @@ -77,7 +106,7 @@ local cli = tonumber(ARGV[1]) local bcd = tonumber(ARGV[2]) local pcd = tonumber(ARGV[3]) local cds = tonumber(ARGV[4]) -for c = 7,#ARGV do +for c = 8,#ARGV do local off = tonumber(ARGV[c]) * 8 -- get color of pixel on canvas local sclr = redis.call('bitfield', KEYS[5], 'get', 'u8', off) @@ -114,7 +143,7 @@ if pxlcnt > 0 then end end -- increment pixelcount - if KEYS[6] ~= 'nope' then + if KEYS[7] ~= 'nope' then redis.call('zincrby', KEYS[6], pxlcnt, ARGV[5]) redis.call('zincrby', KEYS[7], pxlcnt, ARGV[5]) if ARGV[6] ~= 'xx' then diff --git a/src/data/redis/ranks.js b/src/data/redis/ranks.js index b245a7a..406ff58 100644 --- a/src/data/redis/ranks.js +++ b/src/data/redis/ranks.js @@ -7,7 +7,7 @@ import { getDateKeyOfTs } from '../../core/utils'; export const RANKED_KEY = 'rank'; export const DAILY_RANKED_KEY = 'rankd'; export const DAILY_CRANKED_KEY = 'crankd'; -const PREV_DAY_TOP_KEY = 'prankd'; +export const PREV_DAY_TOP_KEY = 'prankd'; const DAY_STATS_RANKS_KEY = 'ds'; const CDAY_STATS_RANKS_KEY = 'cds'; const ONLINE_CNTR_KEY = 'tonl';