From 99e08108f1dff51082d8616cb8915c4036d2e11d Mon Sep 17 00:00:00 2001 From: Timothee Groleau Date: Tue, 5 Sep 2023 21:55:35 +0800 Subject: [PATCH] feat: support elo rank and rating for players --- daos/UserDAO.js | 6 ++-- domains/User.js | 3 ++ routes/routes.js | 9 ++++-- setup/20230905.sql | 3 ++ setup/db.sql | 3 ++ views/profile_card.ejs | 73 +++++++++++++++++++++--------------------- 6 files changed, 56 insertions(+), 41 deletions(-) create mode 100644 setup/20230905.sql diff --git a/daos/UserDAO.js b/daos/UserDAO.js index 78ea759f..307a9844 100644 --- a/daos/UserDAO.js +++ b/daos/UserDAO.js @@ -116,10 +116,10 @@ class UserDAO { return user; } - async getUserByLogin(login) { + async getUserByLogin(login, force_fetch = false) { let user = this.users_by_login.get(login); - if (!user) { + if (!user || force_fetch) { const result = await dbPool.query( 'SELECT * FROM twitch_users WHERE login=$1', [login] @@ -131,6 +131,8 @@ class UserDAO { if (!user) { user = this.addUserFromData(result.rows[0]); + } else { + user.updateUserFields(result.rows[0]); } } } diff --git a/domains/User.js b/domains/User.js index 3fe8c27b..e5fdba62 100644 --- a/domains/User.js +++ b/domains/User.js @@ -71,6 +71,9 @@ class User extends EventEmitter { this.profile_image_url = user_object.profile_image_url; this.dob = user_object.dob; + this.elo_rank = user_object.elo_rank || 0; + this.elo_rating = user_object.elo_rating || 0; + this.country_code = user_object.country_code || this.country_code || 'US'; this.city = user_object.city || this.city || ''; this.timezone = user_object.timezone || this.timezone || 'UTC'; diff --git a/routes/routes.js b/routes/routes.js index 153a981f..857e7f43 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -7,6 +7,8 @@ import layouts from '../modules/layouts.js'; import UserDAO from '../daos/UserDAO.js'; import ScoreDAO from '../daos/ScoreDAO.js'; +import { readableScoreFomatter } from '../public/views/utils.js'; + const router = express.Router(); router.get('/debug/session', (req, res) => { @@ -140,7 +142,7 @@ function getAge(dob) { } router.get('/view/profile_card/:login', async (req, res) => { - const user = await UserDAO.getUserByLogin(req.params.login); + const user = await UserDAO.getUserByLogin(req.params.login, true); if (!user) { res.status(404).send('Not found'); @@ -149,8 +151,9 @@ router.get('/view/profile_card/:login', async (req, res) => { res.render('profile_card', { user, - age: user.dob ? getAge(user.dob) : 9, - pb: await ScoreDAO.getPB(user), + age: user.dob ? getAge(user.dob) : 9, // 😅 + pb: readableScoreFomatter(await ScoreDAO.getPB(user)), + elo_rating: readableScoreFomatter(Math.floor(user.elo_rating)), }); }); diff --git a/setup/20230905.sql b/setup/20230905.sql new file mode 100644 index 00000000..e974dd09 --- /dev/null +++ b/setup/20230905.sql @@ -0,0 +1,3 @@ +ALTER TABLE twitch_users + ADD COLUMN elo_rank INTEGER NOT NULL DEFAULT 0, + ADD COLUMN elo_rating DOUBLE PRECISION NOT NULL DEFAULT 0; diff --git a/setup/db.sql b/setup/db.sql index b047ea57..ee1bfd3c 100644 --- a/setup/db.sql +++ b/setup/db.sql @@ -19,6 +19,9 @@ CREATE TABLE twitch_users ( style play_style default 'das', timezone TEXT NOT NULL CHECK (now() AT TIME ZONE timezone IS NOT NULL) DEFAULT 'UTC', + elo_rank INTEGER NOT NULL DEFAULT 0, + elo_rating DOUBLE PRECISION NOT NULL DEFAULT 0, + created_on timestamptz NOT NULL, last_login timestamptz NOT NULL ); diff --git a/views/profile_card.ejs b/views/profile_card.ejs index 30888f20..7e17a781 100644 --- a/views/profile_card.ejs +++ b/views/profile_card.ejs @@ -19,21 +19,26 @@ html, body { line-height: 24px; font-size: var(--fsize); color: var(--beige); + height: 100%; } .frame { - background: black; + height: 100%; + min-height: 100%; + background: black; overflow: hidden; text-align: center; -} - -.container { - padding: 6px 3px; + padding: 0 3px; + display: flex; + flex-direction: column; } #name { border-bottom: 3px solid var(--beige); margin-bottom: 0.5em; + padding-top: 6px; + flex-shrink: 0; + flex-grow: 0; } h1 { @@ -50,7 +55,14 @@ h1 { line-height: 48px; } +.container { + display: flex; + flex-direction: column; + flex: 1; +} + section { + flex: 1; margin-top: 0.65em; } @@ -65,9 +77,11 @@ p { } #twitch { - position: absolute; + flex-grow: 0; + flex-shrink: 0; + position: relative; bottom: 0; - margin-bottom: 20px; + margin: 20px 0; color: white; width: 100%; } @@ -100,49 +114,36 @@ p { vertical-align: middle; } -#play_style span { - margin-right: 0.2em; -} - -#play_style span:last-of-type { - margin-right: 0; -} -
-
-
-

<%= (user.display_name || '').replace(/^\d+\.\s+/, '') %>

-
+
+

<%= (user.display_name || '').replace(/^\d+\.\s+/, '') %>

+
+

<%= [age, user.city].filter(v => v).join(' - ') %>

+
+

Player bio

+

<%= user.description %>

+
+

Play info

-

Style: <%= user.style %>

-

PB: <% - - let remainder = pb || 0; - let parts = []; - - while (remainder) { - parts.unshift(remainder % 1000); - remainder = Math.floor(remainder / 1000); - } - - if (!parts.length) parts.push(0); - - parts = parts - .map((part, idx) => idx > 0 ? `${part}`.padStart(3, '0') : part) - .map(part => `${part}`); +

Style: <%= (user.style || '').toUpperCase() %>

+

PB: <%= pb %>

+
- %><%- parts.join('') %>

+
+

ELO

+

Rank: <%= user.elo_rank %>

+

Rating: <%= elo_rating %>