From 6d03e450c98874b1269b41d8a405e852384f8227 Mon Sep 17 00:00:00 2001 From: "jmosrael@gmail.com" Date: Fri, 12 Jul 2024 00:46:53 -0700 Subject: [PATCH 1/4] setup the dm apis --- backend/src/app.ts | 3 +- backend/src/characterservice.ts | 10 +++--- backend/src/dmservice.ts | 58 +++++++++++++++++++++++++++++++++ backend/src/gameservice.ts | 8 ++--- backend/src/tokenizer.ts | 1 - frontend/src/vues/DmList.vue | 10 ++++++ 6 files changed, 77 insertions(+), 13 deletions(-) create mode 100644 backend/src/dmservice.ts create mode 100644 frontend/src/vues/DmList.vue diff --git a/backend/src/app.ts b/backend/src/app.ts index 5f50c87..13ebca8 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -6,6 +6,7 @@ import { OrderByParser, FilterParser } from './tokenizer' import { addGameApis } from './gameservice' import { addCharacterApis } from './characterservice' import { addRushStatsApis } from './rushstatsservice' +import { addDmApis } from './dmservice' const app = express() const jsonParser = json() @@ -14,7 +15,7 @@ const port = 3001 addGameApis(app, jsonParser) addCharacterApis(app, jsonParser) addRushStatsApis(app, jsonParser) - +addDmApis(app, jsonParser) app.use(express.static(__dirname + '/frontend')) app.use('/', (req, res) => { diff --git a/backend/src/characterservice.ts b/backend/src/characterservice.ts index 7cce42c..1750d46 100644 --- a/backend/src/characterservice.ts +++ b/backend/src/characterservice.ts @@ -5,7 +5,7 @@ export function addCharacterApis(app, jsonParser) { app.get('/api/character/:characterId', async (req, res) => { try { const character = await Character.findOne({ - attributes: ["id", "characterName", "playerName", "role", "creationDate", "status"], + attributes: ['id', 'characterName', 'playerName', 'role', 'creationDate', 'status'], where: { id: req.params['characterId'] } }) if (character) { @@ -35,11 +35,9 @@ export function addCharacterApis(app, jsonParser) { where: filter }) const totalCount = await Character.count({ - where: filter - }) - const pageCount = Math.ceil( - totalCount / count - ) + where: filter + }) + const pageCount = Math.ceil(totalCount / count) res.setHeader('Content-Type', 'application/json') res.send({ characterData, pageCount, totalCount }) diff --git a/backend/src/dmservice.ts b/backend/src/dmservice.ts new file mode 100644 index 0000000..3bb3dad --- /dev/null +++ b/backend/src/dmservice.ts @@ -0,0 +1,58 @@ +import { database, Character, Game, Pick, App } from './db' +import { OrderByParser, FilterParser, ParsingError } from './tokenizer' +import { fn, col } from 'sequelize' + +export function addDmApis(app, jsonParser) { + app.get('/api/dm/:dmName', async (req, res) => { + const dmName = req.params.dmName + + let games = await Game.findAll({ + where: { gamemaster: dmName } + }) + + res.send(games) + }) + + app.post('/api/dm', jsonParser, async (req, res) => { + try { + const fp = new FilterParser() + const obp = new OrderByParser() + + const page = req.body.page || 0 + const orderBy = req.body.orderBy ? obp.parse(req.body.orderBy) : ['id'] + const count = req.body.count || 10 + const filter = req.body.filter ? fp.parse(req.body.filter) : {} + + const dms = await Game.findAll({ + offset: page * count, + limit: count, + attributes: ['gamemaster', [fn('count', col('id')), 'gamecount']], + group: ['gamemaster'], + order: orderBy, + where: filter + }) + + const totalCount = ( + await Game.count({ + group: ['gamemaster'], + where: filter + }) + ).length + + const pageCount = Math.ceil(totalCount / count) + + res.setHeader('Content-Type', 'application/json') + res.send({ + dms, + pageCount, + totalCount + }) + } catch (e) { + if (e instanceof ParsingError) { + res.status(400).send('Could not parse filter.') + } else { + res.status(500).send(e) + } + } + }) +} diff --git a/backend/src/gameservice.ts b/backend/src/gameservice.ts index 96140f7..24d6738 100644 --- a/backend/src/gameservice.ts +++ b/backend/src/gameservice.ts @@ -33,11 +33,9 @@ export function addGameApis(app, jsonParser) { where: filter }) const totalCount = await Game.count({ - where: filter - }) - const pageCount = Math.ceil( - totalCount / count - ) + where: filter + }) + const pageCount = Math.ceil(totalCount / count) res.setHeader('Content-Type', 'application/json') res.send({ gameData, pageCount, totalCount }) diff --git a/backend/src/tokenizer.ts b/backend/src/tokenizer.ts index 5a4fe83..fde9ee2 100644 --- a/backend/src/tokenizer.ts +++ b/backend/src/tokenizer.ts @@ -98,7 +98,6 @@ export class FilterParser { ctx.accept('value', m[3]) }) - this.lexer.rule(spacerRegex, (ctx, m) => { ctx.ignore() }) diff --git a/frontend/src/vues/DmList.vue b/frontend/src/vues/DmList.vue new file mode 100644 index 0000000..7401387 --- /dev/null +++ b/frontend/src/vues/DmList.vue @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file From bc3455f5d0b38bc18a3e4e8a3f442cc138278099 Mon Sep 17 00:00:00 2001 From: "jmosrael@gmail.com" Date: Wed, 17 Jul 2024 22:50:25 -0700 Subject: [PATCH 2/4] Chron script for loading database --- frontend/src/App.vue | 1 + frontend/src/router/index.ts | 9 ++++++++- frontend/src/types.ts | 7 +++++++ frontend/src/vues/DmList.vue | 19 +++++++++++++------ frontend/src/vues/ServerStats.vue | 4 +--- loader/chron-script.sh | 16 ++++++++++++++++ loader/databasesync.py | 5 +++++ loader/requirements.txt | 5 +++++ 8 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 loader/chron-script.sh create mode 100644 loader/requirements.txt diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 1daed69..8a9be1c 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -5,6 +5,7 @@ Server Stats Games Characters + diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index f5d159d..a41d190 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -5,6 +5,7 @@ import GameDetails from '../vues/GameDetails.vue' import CharacterList from '../vues/CharacterList.vue' import CharacterDetails from '../vues/CharacterDetails.vue' import ServerStats from '../vues/ServerStats.vue' +import DmList from '../vues/DmList.vue' const root = { path: '/', @@ -36,13 +37,19 @@ const serverStatsRoute = { component: ServerStats } +const gameMasterListRoute = { + path: '/gamemasters', + component: DmList +} + const routes = [ root, gameListRoute, gameDetailsRoute, characterListRoute, characterDetailsRoute, - serverStatsRoute + serverStatsRoute, + gameMasterListRoute ] export default createRouter({ diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 814c40f..c13d050 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -21,6 +21,13 @@ export interface Character { creationDate: number } +export interface DmStats { + name: string + gameCount: string + lastGame: number + games: Game +} + export interface GameStats { Complete: number Postponed: number diff --git a/frontend/src/vues/DmList.vue b/frontend/src/vues/DmList.vue index 7401387..6a92ea0 100644 --- a/frontend/src/vues/DmList.vue +++ b/frontend/src/vues/DmList.vue @@ -1,10 +1,17 @@ - + - + \ No newline at end of file +type ReadonlyHeaders = VDataTable['$props']['headers'] + +const headers: ReadonlyHeaders = [ + { title: 'Game Master', align: 'start', sortable: true, key: 'id' }, + { title: 'Game Count', align: 'start', sortable: true, key: 'characterName' }, + { title: 'Last Game', align: 'start', sortable: true, key: 'role' } +] + diff --git a/frontend/src/vues/ServerStats.vue b/frontend/src/vues/ServerStats.vue index 3d46b68..cc4d007 100644 --- a/frontend/src/vues/ServerStats.vue +++ b/frontend/src/vues/ServerStats.vue @@ -33,9 +33,7 @@ Role - - Characters - + Characters App Count Games Played Pick Rate % diff --git a/loader/chron-script.sh b/loader/chron-script.sh new file mode 100644 index 0000000..2a88206 --- /dev/null +++ b/loader/chron-script.sh @@ -0,0 +1,16 @@ +#!/bin/bash +parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) + + +PYTHON_VEN="$parent_path"/venv/bin/python +if [ ! -f $PYTHON_VEN ]; then + echo "Setting up new VENV" + python -m venv venv + echo "Installing requirements." + source ./venv/bin/activate + pip install -r requirements.txt + deactivate +fi + +echo "Start DB Creation" +$parent_path/venv/bin/python createrushdatabase.py \ No newline at end of file diff --git a/loader/databasesync.py b/loader/databasesync.py index 41cb9a6..f5f2f61 100644 --- a/loader/databasesync.py +++ b/loader/databasesync.py @@ -12,6 +12,10 @@ Game = namedtuple('Game', Link = namedtuple('Link', ['gameId', 'gameTitle', 'characterId', 'characterName']) +SET_WAL_PRAGMA = """ +PRAGMA journal_mode=WAL; +""" + APPS_TABLE_CREATE = """ CREATE TABLE IF NOT EXISTS "Apps" ( "gameId" INTEGER, @@ -170,6 +174,7 @@ def loadAppsAndPicks(characterNameToId, gameTitleToId, gameFileName): def createTables(dbName): with sqlite3.connect(dbName) as connection: cursor = connection.cursor() + cursor.execute(SET_WAL_PRAGMA) cursor.execute(CHARACTER_TABLE_CREATE) cursor.execute(GAMES_TABLE_CREATE) cursor.execute(APPS_TABLE_CREATE) diff --git a/loader/requirements.txt b/loader/requirements.txt new file mode 100644 index 0000000..fd8654b --- /dev/null +++ b/loader/requirements.txt @@ -0,0 +1,5 @@ +certifi==2024.6.2 +charset-normalizer==3.3.2 +idna==3.7 +requests==2.32.3 +urllib3==2.2.1 From d6de4e55e84d316e145123a18bbdae4d81de7f52 Mon Sep 17 00:00:00 2001 From: "jmosrael@gmail.com" Date: Thu, 18 Jul 2024 21:07:20 -0700 Subject: [PATCH 3/4] install scripts --- install.sh | 35 +++++++++++++++++++++++++++++------ setup.sh | 2 +- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/install.sh b/install.sh index 9ed0858..067c39a 100755 --- a/install.sh +++ b/install.sh @@ -1,11 +1,30 @@ #!/bin/bash parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) +echo "" +echo "---" +echo "Creating user rushstats" +echo "---" +if [id rushstats >/dev/null 2>&1]; then + echo "rushstats user already exists, skipping." +else + useradd -s /sbin/nologin rushstats + echo "User rushstats created with /sbin/nologin" +fi + echo "" echo "---" echo "Moving the distributable folder into /srv/gamestats" echo "---" -cp -r "$parent_path"/dist /srv/gamestats +if [ -d /srv/gamestats ]; then + echo "/srv/gamestats already exists; removing" + rm -r /srv/rushstats +fi +mkdir /srv/gamestats +cp -r "$parent_path"/dist /srv/gamestats +cp -r "$parent_path"/loader /srv/gamestats +chown -r /srv/gamestats rushstats rushstats + echo "" echo "---" @@ -31,14 +50,18 @@ echo "[Install]" >> $SYSTEMD_SERVICE_FILE echo "WantedBy=multi-user.target" >> $SYSTEMD_SERVICE_FILE echo "" >> $SYSTEMD_SERVICE_FILE -echo "" -echo "---" -echo "Creating the cron job to refresh the database." -echo "---" +echo "Created new service." +echo cat $SYSTEMD_SERVICE_FILE echo "" echo "---" echo "Reloading daemons and starting service" echo "---" systemctl daeomon-reload -systemctl start rushstats.service \ No newline at end of file +systemctl enable rushstats.service +systemctl start rushstats.service + +echo "" +echo "---" +echo "Creating the cron job to refresh the database." +echo "---" \ No newline at end of file diff --git a/setup.sh b/setup.sh index 1eaf546..c8ca604 100755 --- a/setup.sh +++ b/setup.sh @@ -22,7 +22,7 @@ cp -f ./backend/dist/* ./dist cd "$parent_path"/loader python3 createrushdatabase.py cd ../ -cp -r ./loader/testdb.db ./dist/testdb.db +cp -r ./loader/* ./dist # Move the package into the dist folder and install the needed modules cd "$parent_path" From 3d4e4636f7e3d2863b586134a642059a9ea263e4 Mon Sep 17 00:00:00 2001 From: youdontneedthis Date: Sun, 21 Jul 2024 02:08:25 +0000 Subject: [PATCH 4/4] update scripts --- install.sh | 10 +++++----- loader/chron-script.sh | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index 067c39a..517a3eb 100755 --- a/install.sh +++ b/install.sh @@ -21,9 +21,9 @@ if [ -d /srv/gamestats ]; then rm -r /srv/rushstats fi mkdir /srv/gamestats -cp -r "$parent_path"/dist /srv/gamestats -cp -r "$parent_path"/loader /srv/gamestats -chown -r /srv/gamestats rushstats rushstats +cp -r "$parent_path"/dist/* /srv/gamestats +cp -r "$parent_path"/loader/* /srv/gamestats +chown -R rushstats:rushstats /srv/gamestats echo "" @@ -57,11 +57,11 @@ echo "" echo "---" echo "Reloading daemons and starting service" echo "---" -systemctl daeomon-reload +systemctl daemon-reload systemctl enable rushstats.service systemctl start rushstats.service echo "" echo "---" echo "Creating the cron job to refresh the database." -echo "---" \ No newline at end of file +echo "---" diff --git a/loader/chron-script.sh b/loader/chron-script.sh index 2a88206..f0c7e2a 100644 --- a/loader/chron-script.sh +++ b/loader/chron-script.sh @@ -1,11 +1,10 @@ #!/bin/bash parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) - PYTHON_VEN="$parent_path"/venv/bin/python if [ ! -f $PYTHON_VEN ]; then echo "Setting up new VENV" - python -m venv venv + python3 -m venv venv echo "Installing requirements." source ./venv/bin/activate pip install -r requirements.txt @@ -13,4 +12,4 @@ if [ ! -f $PYTHON_VEN ]; then fi echo "Start DB Creation" -$parent_path/venv/bin/python createrushdatabase.py \ No newline at end of file +$parent_path/venv/bin/python createrushdatabase.py