diff --git a/backend/src/app.ts b/backend/src/app.ts index 31f890e..f7a8249 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -3,6 +3,8 @@ import { json } from 'body-parser' import { Sequelize, Op, QueryTypes } from 'sequelize' import { database, Character, Game, Pick, App } from './db' import { OrderByParser, FilterParser } from './tokenizer' +import { addGameApis } from './gameservice' +import { addCharacterApis } from './characterservice' const app = express() const jsonParser = json() @@ -14,6 +16,9 @@ app.get('/', (req, res) => { res.send('Hello World!') }) +addGameApis(app, jsonParser) +addCharacterApis(app, jsonParser) + app.post('/api/serverstats/gamestats', jsonParser, async (req, res) => { const monthId = req.body.monthId let startSeconds = 0 @@ -91,9 +96,7 @@ app.post('/api/serverstats/rolestats', jsonParser, async (req, res) => { picks.forEach((character, characterNum) => { const role = character.dataValues.role // Count role application - pickedCharacterCount.set( - role, (pickedCharacterCount.get(role) || 0) + 1 - ) + pickedCharacterCount.set(role, (pickedCharacterCount.get(role) || 0) + 1) }) appls.forEach((character, characterNum) => { @@ -105,9 +108,7 @@ app.post('/api/serverstats/rolestats', jsonParser, async (req, res) => { } activeCharacters.get(role).add(charId) // Count role application - appedCharacterCount.set( - role, (appedCharacterCount.get(role) || 0) + 1 - ) + appedCharacterCount.set(role, (appedCharacterCount.get(role) || 0) + 1) }) }) @@ -130,101 +131,13 @@ app.post('/api/serverstats/rolestats', jsonParser, async (req, res) => { result[roleName] = { apps: appedCharacterCount.get(roleName) || 0, picks: pickedCharacterCount.get(roleName) || 0, - active: activeCharacters.has(roleName) ?activeCharacters.get(roleName).size : 0 + active: activeCharacters.has(roleName) ? activeCharacters.get(roleName).size : 0 } }) res.send(result) }) -app.get('/api/character/:characterId', async (req, res) => { - res.send(await Character.findOne({ where: { id: req.params['characterId'] } })) -}) - -app.post('/api/character', jsonParser, async (req, res) => { - const page = req.body.page - const orderBy = req.body.orderBy ? obp.parse(req.body.orderBy) : ['id'] - const count = req.body.count - const filter = req.body.filter ? fp.parse(req.body.filter) : {} - - const characterData = await Character.findAll({ - offset: page * count, - limit: count, - order: orderBy, - where: filter - }) - const pageCount = Math.ceil( - (await Character.count({ - where: filter - })) / count - ) - - res.setHeader('Content-Type', 'application/json') - res.send({ characterData, pageCount }) -}) - -app.get('/api/game/:gameId', async (req, res) => { - res.send(await Game.findOne({ where: { id: req.params['gameId'] } })) -}) - -app.post('/api/game', jsonParser, async (req, res) => { - 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 gameData = await Game.findAll({ - offset: page * count, - limit: count, - order: orderBy, - where: filter - }) - const pageCount = Math.ceil( - (await Game.count({ - where: filter - })) / count - ) - - res.setHeader('Content-Type', 'application/json') - res.send({ gameData, pageCount }) -}) - -app.get('/api/game/:gameId', async (req, res) => { - const game = await Game.findOne({ where: { id: req.params['gameId'] } }) - res.send(game) -}) - -app.post('/api/game/:gameId/apps', async (req, res) => { - const apps = await App.findAll({ where: { gameId: req.params['gameId'] } }) - res.send(apps) -}) - -app.post('/api/character/:characterId/apps', async (req, res) => { - const apps = await App.findAll({ where: { characterId: req.params['characterId'] } }) - res.send(apps) -}) - -app.post('/api/game/:gameId/picks', async (req, res) => { - const picks = await Pick.findAll({ where: { gameId: req.params['gameId'] } }) - res.send(picks) -}) - -app.post('/api/character/:characterId/picks', async (req, res) => { - const picks = await Pick.findAll({ where: { characterId: req.params['characterId'] } }) - res.send(picks) -}) - -app.post('/api/character/:characterId/gameHistory', async (req, res) => { - const gameHistory = await Character.findOne({ - include: [ - { model: Game, as: 'characterPickedForGame' }, - { model: Game, as: 'characterAppliedForGame' } - ], - where: { id: req.params['characterId'] } - }) - res.send(gameHistory) -}) - app.listen(port, async () => { await database.authenticate() return console.log(`Express is listening at http://localhost:${port}`) diff --git a/backend/src/characterservice.ts b/backend/src/characterservice.ts new file mode 100644 index 0000000..ba8e33e --- /dev/null +++ b/backend/src/characterservice.ts @@ -0,0 +1,97 @@ +import { database, Character, Game, Pick, App } from './db' +import { OrderByParser, FilterParser, ParsingError } from './tokenizer' + +export function addCharacterApis(app, jsonParser) { + app.get('/api/character/:characterId', async (req, res) => { + try { + const character = await Character.findOne({ + where: { id: req.params['characterId'] } + }) + if (character) { + res.send(character) + } else { + res.status(404).send('Cannot find character.') + } + } catch (e) { + res.status(500).send(e) + } + }) + + app.post('/api/character', jsonParser, async (req, res) => { + try { + const fp = new FilterParser() + const obp = new OrderByParser() + + const page = req.body.page + const orderBy = req.body.orderBy ? obp.parse(req.body.orderBy) : ['id'] + const count = req.body.count + const filter = req.body.filter ? fp.parse(req.body.filter) : {} + + const characterData = await Character.findAll({ + offset: page * count, + limit: count, + order: orderBy, + where: filter + }) + const pageCount = Math.ceil( + (await Character.count({ + where: filter + })) / count + ) + + res.setHeader('Content-Type', 'application/json') + res.send({ characterData, pageCount }) + } catch (e) { + if (e instanceof ParsingError) { + res.status(400).send('Could not parse filter.') + } else { + res.status(500).send(e) + } + } + }) + + app.post('/api/character/:characterId/apps', async (req, res) => { + try { + const apps = await App.findAll({ where: { characterId: req.params['characterId'] } }) + if (apps) { + res.send(apps) + } else { + res.status(400).send('Could not find apps.') + } + } catch (e) { + res.status(500).send(e) + } + }) + + app.post('/api/character/:characterId/picks', async (req, res) => { + try { + const picks = await Pick.findAll({ where: { characterId: req.params['characterId'] } }) + if (picks) { + res.send(picks) + } else { + res.status(400).send('Could not find picks.') + } + } catch (e) { + res.status(500).send(e) + } + }) + + app.post('/api/character/:characterId/gameHistory', async (req, res) => { + try { + const gameHistory = await Character.findOne({ + include: [ + { model: Game, as: 'characterPickedForGame' }, + { model: Game, as: 'characterAppliedForGame' } + ], + where: { id: req.params['characterId'] } + }) + if (gameHistory) { + res.send(gameHistory) + } else { + res.status(404).send("Could nor find character.") + } + } catch (e) { + res.status(500).send(e) + } + }) +} diff --git a/backend/src/gameservice.ts b/backend/src/gameservice.ts new file mode 100644 index 0000000..745632e --- /dev/null +++ b/backend/src/gameservice.ts @@ -0,0 +1,76 @@ +import { database, Character, Game, Pick, App } from './db' +import { OrderByParser, FilterParser, ParsingError } from './tokenizer' + +export function addGameApis(app, jsonParser) { + app.get('/api/game/:gameId', async (req, res) => { + try { + const game = await Game.findOne({ where: { id: req.params['gameId'] } }) + if (!game) { + res.status(404).send('Game Not Found') + } else { + res.send(game) + } + } catch (e) { + console.log(e) + res.status(500).send(e) + } + }) + + app.post('/api/game', 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 gameData = await Game.findAll({ + offset: page * count, + limit: count, + order: orderBy, + where: filter + }) + const pageCount = Math.ceil( + (await Game.count({ + where: filter + })) / count + ) + + res.setHeader('Content-Type', 'application/json') + res.send({ gameData, pageCount }) + } catch (e) { + if (e instanceof ParsingError) { + res.status(400).send('Could not parse filter.') + } else { + res.status(500).send(e) + } + } + }) + + app.post('/api/game/:gameId/apps', async (req, res) => { + try { + const apps = await App.findAll({ where: { gameId: req.params['gameId'] } }) + if (!apps) { + res.status(404).send('Apps not found.') + } else { + res.send(apps) + } + } catch (e) { + res.status(500).send(e) + } + }) + + app.post('/api/game/:gameId/picks', async (req, res) => { + try { + const picks = await Pick.findAll({ where: { gameId: req.params['gameId'] } }) + if (!picks) { + res.status(404).send('Picks not found') + } else { + res.send(picks) + } + } catch (e) { + res.status(500).send(e) + } + }) +} diff --git a/backend/src/tokenizer.ts b/backend/src/tokenizer.ts index 95dac4e..e29817e 100644 --- a/backend/src/tokenizer.ts +++ b/backend/src/tokenizer.ts @@ -1,6 +1,8 @@ import Tokenizr from 'tokenizr' import { Op } from 'sequelize' +export { ParsingError } from 'tokenizr' + export class OrderByParser { lexer = new Tokenizr() @@ -50,8 +52,8 @@ export class OrderByParser { const openGroupRegex = /\(/ const closeGroupRegex = /\)/ const conjunctinoRegex = /AND|OR/ -const equalityRegex = /([a-zA-Z]+)\s?(=|!=|<|>|<=|>=|:)\s?([a-zA-Z\d]+)/ -const stringEqualityRegex = /([a-zA-Z]+)\s?(=|!=|<|>|<=|>=|:)\s?\"([a-zA-Z\d\s]*)\"/ +const equalityRegex = /([a-zA-Z]+)\s?(=|!=|<|>|<=|>=|:)\s?([a-zA-Z'"\d]+)/ +const stringEqualityRegex = /([a-zA-Z]+)\s?(=|!=|<|>|<=|>=|:)\s?\"([a-zA-Z'"\d\s]*)\"/ const spacerRegex = /\s/ const opperatorMap = {