added Serializer & Manager classes
This commit is contained in:
parent
d76110d06b
commit
2219ea93bf
24 changed files with 254 additions and 111 deletions
|
|
@ -2,23 +2,11 @@ import pgPromise from "pg-promise";
|
|||
|
||||
|
||||
export abstract class Database {
|
||||
static db = null;
|
||||
get db() {
|
||||
if (Database.db == null) {
|
||||
Database.db = pgPromise({})('postgres://postgres:postgres@db:5432/rr')
|
||||
private static _db = null;
|
||||
static get db() {
|
||||
if (Database._db == null) {
|
||||
Database._db = pgPromise({})('postgres://postgres:postgres@db:5432/rr')
|
||||
}
|
||||
return Database.db;
|
||||
return Database._db;
|
||||
}
|
||||
|
||||
static async catcher(request): Promise<any> {
|
||||
let data;
|
||||
try {
|
||||
data = await request();
|
||||
} catch (e) {
|
||||
console.log((e as Error).message)
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,12 +1,8 @@
|
|||
import express from 'express';
|
||||
import {Database} from "./Database.js";
|
||||
|
||||
import helmet from "helmet";
|
||||
import bodyParser from "body-parser";
|
||||
import morgan from 'morgan';
|
||||
import {UserDataManager} from "./manager/UserDataManager.js";
|
||||
import {UserDataPgPromiseSerializer} from "./manager/UserDataPgPromiseSerializer.js";
|
||||
import {leaderboardRouter} from "./leaderboardRouter.js";
|
||||
import {leaderboardRoute} from "./leaderboardRoute.js";
|
||||
import {userRoute} from "./userRoute.js";
|
||||
|
||||
|
||||
const app = express()
|
||||
|
|
@ -18,31 +14,13 @@ app.use(helmet())
|
|||
let morganFormatted = morgan('[:date[iso]] :method :url - :status')
|
||||
app.use(morganFormatted);
|
||||
|
||||
app.use('/leaderboard', leaderboardRouter)
|
||||
app.use('/leaderboard', leaderboardRoute)
|
||||
app.use('/user', userRoute)
|
||||
|
||||
app.get('/helloworld', (req, res) => {
|
||||
res.json({message: "Hello World!"})
|
||||
})
|
||||
|
||||
app.get('/highscore', async (req, res) => {
|
||||
let data = await Database.db.manyOrNone('SELECT * FROM lb_highscore;')
|
||||
.catch((error) => console.log(error.message))
|
||||
res.json(data)
|
||||
})
|
||||
|
||||
app.get('/user/:username', async (req, res) => {
|
||||
let data = await Database.db.oneOrNone(
|
||||
'SELECT * FROM user_data WHERE username = $1;',
|
||||
[req.params.username])
|
||||
.catch((error) => console.log(error.message)
|
||||
)
|
||||
let userDataManager: UserDataManager = new UserDataManager(data, new UserDataPgPromiseSerializer);
|
||||
res.json(userDataManager.userData);
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Server started at http://localhost:3000`);
|
||||
|
|
|
|||
23
backend/api/src/leaderboardRoute.ts
Normal file
23
backend/api/src/leaderboardRoute.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import express from 'express';
|
||||
import {Database} from "./Database.js";
|
||||
import {TimeLeaderboardManager} from "./manager/TimeLeaderboardManager.js";
|
||||
import {HighscoreLeaderboardManager} from "./manager/HighscoreLeaderboardManager.js";
|
||||
import {
|
||||
HighscoreLeaderboardPgPromiseSerializer
|
||||
} from "./serializer/pgpromise/HighscoreLeaderboardPgPromiseSerializer.js";
|
||||
import {TimeLeaderboardPgPromiseSerializer} from "./serializer/pgpromise/TimeLeaderboardPgPromiseSerializer.js";
|
||||
|
||||
export const leaderboardRoute = express.Router()
|
||||
|
||||
|
||||
leaderboardRoute.get('/highscore', async (req, res) => {
|
||||
let data = await Database.db.manyOrNone('SELECT * FROM lb_highscore INNER JOIN "user" ON user_id = id ORDER BY RANK;')
|
||||
const leaderboardManager = new HighscoreLeaderboardManager(data, new HighscoreLeaderboardPgPromiseSerializer);
|
||||
res.send(leaderboardManager.content)
|
||||
})
|
||||
|
||||
leaderboardRoute.get('/totalplaytime', async (req, res) => {
|
||||
let data = await Database.db.manyOrNone('SELECT * FROM lb_total_playtime INNER JOIN "user" ON user_id = id ORDER BY RANK;')
|
||||
const leaderboardManager = new TimeLeaderboardManager(data, new TimeLeaderboardPgPromiseSerializer);
|
||||
res.send(leaderboardManager.content)
|
||||
})
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import express from 'express';
|
||||
export const leaderboardRouter = express.Router()
|
||||
|
||||
|
||||
leaderboardRouter.get('/highscore', (req, res) => {
|
||||
res.send('highscore')
|
||||
})
|
||||
|
||||
leaderboardRouter.get('/totalplaytime', (req, res) => {
|
||||
res.send('total play time')
|
||||
})
|
||||
32
backend/api/src/manager/HighscoreLeaderboardManager.ts
Normal file
32
backend/api/src/manager/HighscoreLeaderboardManager.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import {Leaderboard} from "../model/Leaderboard.js";
|
||||
import {Manager} from "./Manager.js";
|
||||
import {HighscoreLeaderboardSerializer} from "../serializer/HighscoreLeaderboardSerializer.js";
|
||||
|
||||
export class HighscoreLeaderboardManager implements Manager<Leaderboard<number>>{
|
||||
private _content: Leaderboard<number>;
|
||||
private _serializer: HighscoreLeaderboardSerializer;
|
||||
|
||||
constructor(rawData: any, serializer: HighscoreLeaderboardSerializer) {
|
||||
this.serializer = serializer;
|
||||
this._content = this.serializer.serialize(rawData);
|
||||
}
|
||||
|
||||
//region getter&setter
|
||||
get content() {
|
||||
return this._content;
|
||||
}
|
||||
|
||||
set content(value: Leaderboard<number>) {
|
||||
this._content = value;
|
||||
}
|
||||
|
||||
get serializer() {
|
||||
return this._serializer;
|
||||
}
|
||||
|
||||
set serializer(value: HighscoreLeaderboardSerializer) {
|
||||
this._serializer = value;
|
||||
}
|
||||
//endregion
|
||||
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
export interface LeaderBoardSerializer {
|
||||
|
||||
}
|
||||
8
backend/api/src/manager/Manager.ts
Normal file
8
backend/api/src/manager/Manager.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import {Serializer} from "../serializer/Serializer.js";
|
||||
|
||||
export interface Manager<T> {
|
||||
get content(),
|
||||
set content(value: T),
|
||||
get serializer(),
|
||||
set serializer(value: Serializer<T>),
|
||||
}
|
||||
34
backend/api/src/manager/TimeLeaderboardManager.ts
Normal file
34
backend/api/src/manager/TimeLeaderboardManager.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import {Manager} from "./Manager.js";
|
||||
import {Leaderboard} from "../model/Leaderboard.js";
|
||||
import {Time} from "../model/Time.js";
|
||||
import {TimeLeaderboardSerializer} from "../serializer/TimeLeaderboardSerializer.js";
|
||||
import {TimeLeaderboardPgPromiseSerializer} from "../serializer/pgpromise/TimeLeaderboardPgPromiseSerializer.js";
|
||||
|
||||
export class TimeLeaderboardManager implements Manager<Leaderboard<Time>> {
|
||||
private _content: Leaderboard<Time>;
|
||||
private _serializer: TimeLeaderboardPgPromiseSerializer
|
||||
|
||||
constructor(data: any, serializer: TimeLeaderboardSerializer) {
|
||||
this._serializer = serializer;
|
||||
this._content = this._serializer.serialize(data);
|
||||
}
|
||||
|
||||
//region getter&setter
|
||||
get content() {
|
||||
return this._content;
|
||||
}
|
||||
|
||||
set content(value: Leaderboard<Time>) {
|
||||
this._content = value;
|
||||
}
|
||||
|
||||
get serializer(): TimeLeaderboardPgPromiseSerializer {
|
||||
return this._serializer;
|
||||
}
|
||||
|
||||
set serializer(value: TimeLeaderboardPgPromiseSerializer) {
|
||||
this._serializer = value;
|
||||
}
|
||||
//endregion
|
||||
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
import {UserData} from "../model/UserData.js";
|
||||
import {UserDataSerializer} from "./UserDataSerializer.js";
|
||||
|
||||
export class UserDataManager {
|
||||
private _userData: UserData;
|
||||
private serializer: UserDataSerializer;
|
||||
|
||||
constructor(data: any, serializer: UserDataSerializer) {
|
||||
this.serializer = serializer;
|
||||
this._userData = this.serializer.serialize(data);
|
||||
}
|
||||
|
||||
get userData(): UserData {
|
||||
return this._userData;
|
||||
}
|
||||
|
||||
set userData(value: UserData) {
|
||||
this._userData = value;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import {UserData} from "../model/UserData.js";
|
||||
import {UserDataSerializer} from "./UserDataSerializer.js";
|
||||
|
||||
export class UserDataPgPromiseSerializer implements UserDataSerializer {
|
||||
deserialize(userData: UserData): any {
|
||||
throw new Error("Method not implemented")
|
||||
}
|
||||
|
||||
serialize(data: any): UserData {
|
||||
return {
|
||||
username: data.username,
|
||||
highscore: data.highscore,
|
||||
totalScore: data.total_score,
|
||||
totalPlaytime: data.total_playtime,
|
||||
averageScore: data.averageScore,
|
||||
gamesPlayed: data.games_played,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
import {UserData} from "../model/UserData.js";
|
||||
|
||||
export interface UserDataSerializer {
|
||||
serialize(data: any): UserData,
|
||||
deserialize(userData: UserData): any,
|
||||
}
|
||||
33
backend/api/src/manager/UserScoresManager.ts
Normal file
33
backend/api/src/manager/UserScoresManager.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import {UserScores} from "../model/UserScores.js";
|
||||
import { Serializer } from "../serializer/Serializer.js";
|
||||
import {UserScoresSerializer} from "../serializer/UserScoresSerializer.js";
|
||||
import {Manager} from "./Manager.js";
|
||||
|
||||
export class UserScoresManager implements Manager<UserScores> {
|
||||
private _content: UserScores;
|
||||
private _serializer: UserScoresSerializer;
|
||||
|
||||
constructor(rawData: any, serializer: UserScoresSerializer) {
|
||||
this.serializer = serializer;
|
||||
this._content = this.serializer.serialize(rawData);
|
||||
}
|
||||
|
||||
//region getter&setter
|
||||
get content() {
|
||||
return this._content;
|
||||
}
|
||||
|
||||
set content(value: UserScores) {
|
||||
this._content = value;
|
||||
}
|
||||
|
||||
get serializer() {
|
||||
return this._serializer
|
||||
}
|
||||
|
||||
set serializer(value: Serializer<UserScores>) {
|
||||
this._serializer = value
|
||||
}
|
||||
//endregion
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import {LeaderboardEntry} from "./LeaderboardEntry.js";
|
||||
export type Leaderboard<T> = LeaderboardEntry<T>[];
|
||||
|
||||
export class Leaderboard<T> {
|
||||
content: LeaderboardEntry<T>[];
|
||||
export interface LeaderboardEntry<T> {
|
||||
rank: number,
|
||||
username: string,
|
||||
score: T,
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
export interface LeaderboardEntry<T> {
|
||||
rank: number,
|
||||
username: string,
|
||||
score: T,
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
export interface UserData {
|
||||
export interface UserScores {
|
||||
username: string,
|
||||
highscore: number,
|
||||
totalScore: number,
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import {Serializer} from "./Serializer.js";
|
||||
import {Leaderboard} from "../model/Leaderboard.js";
|
||||
|
||||
export interface HighscoreLeaderboardSerializer extends Serializer<Leaderboard<number>> {}
|
||||
4
backend/api/src/serializer/Serializer.ts
Normal file
4
backend/api/src/serializer/Serializer.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export interface Serializer<T> {
|
||||
serialize(rawData: any): T,
|
||||
deserialize(parsedData: T): any,
|
||||
}
|
||||
5
backend/api/src/serializer/TimeLeaderboardSerializer.ts
Normal file
5
backend/api/src/serializer/TimeLeaderboardSerializer.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import {Serializer} from "./Serializer.js";
|
||||
import {Leaderboard} from "../model/Leaderboard.js";
|
||||
import {Time} from "../model/Time.js";
|
||||
|
||||
export interface TimeLeaderboardSerializer extends Serializer<Leaderboard<Time>> {}
|
||||
4
backend/api/src/serializer/UserScoresSerializer.ts
Normal file
4
backend/api/src/serializer/UserScoresSerializer.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import {UserScores} from "../model/UserScores.js";
|
||||
import {Serializer} from "./Serializer.js";
|
||||
|
||||
export interface UserScoresSerializer extends Serializer<UserScores>{}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import {HighscoreLeaderboardSerializer} from "../HighscoreLeaderboardSerializer.js";
|
||||
import {Leaderboard, LeaderboardEntry} from "../../model/Leaderboard.js";
|
||||
|
||||
export class HighscoreLeaderboardPgPromiseSerializer implements HighscoreLeaderboardSerializer {
|
||||
deserialize(parsedData: Leaderboard<number>): any {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
serialize(rawData: any): Leaderboard<number> {
|
||||
return rawData.map((item) => {
|
||||
let newItem: LeaderboardEntry<number> = {
|
||||
rank: item.rank,
|
||||
username: item.name,
|
||||
score: item.highscore,
|
||||
}
|
||||
return newItem
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import {TimeLeaderboardSerializer} from "../TimeLeaderboardSerializer.js";
|
||||
import {Leaderboard, LeaderboardEntry} from "../../model/Leaderboard.js";
|
||||
import {Time} from "../../model/Time.js";
|
||||
|
||||
export class TimeLeaderboardPgPromiseSerializer implements TimeLeaderboardSerializer {
|
||||
deserialize(parsedData: Leaderboard<Time>): any {
|
||||
throw new Error("Method not implemented.")
|
||||
}
|
||||
|
||||
serialize(rawData: any): Leaderboard<Time> {
|
||||
return rawData.map((item) => {
|
||||
let newItem: LeaderboardEntry<Time> = {
|
||||
rank: item.rank,
|
||||
username: item.name,
|
||||
score: item.total_playtime,
|
||||
}
|
||||
return newItem
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import {UserScores} from "../../model/UserScores.js";
|
||||
import {UserScoresSerializer} from "../UserScoresSerializer.js";
|
||||
|
||||
export class UserScoresPgPromiseSerializer implements UserScoresSerializer {
|
||||
deserialize(parsedData: UserScores): any {
|
||||
throw new Error("Method not implemented");
|
||||
}
|
||||
|
||||
serialize(rawData: any): UserScores {
|
||||
return {
|
||||
username: rawData.name,
|
||||
highscore: rawData.highscore,
|
||||
totalScore: rawData.total_score,
|
||||
totalPlaytime: rawData.total_playtime,
|
||||
averageScore: rawData.averageScore,
|
||||
gamesPlayed: rawData.games_played,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
30
backend/api/src/userRoute.ts
Normal file
30
backend/api/src/userRoute.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import express from "express";
|
||||
import {Database} from "./Database.js";
|
||||
import {UserScoresManager} from "./manager/UserScoresManager.js";
|
||||
import {UserScoresPgPromiseSerializer} from "./serializer/pgpromise/UserScoresPgPromiseSerializer.js";
|
||||
import bodyParser from "body-parser";
|
||||
|
||||
export const userRoute = express.Router()
|
||||
|
||||
userRoute.use(bodyParser.json)
|
||||
|
||||
userRoute.get('/:username/scores', async (req, res) => {
|
||||
let data = await Database.db.oneOrNone(
|
||||
'SELECT * FROM user_scores INNER JOIN "user" ON user_scores.user_id = "user".id WHERE "user".name = $1;',
|
||||
[req.params.username])
|
||||
.catch((error) => console.log(error.message)
|
||||
)
|
||||
let userDataManager: UserScoresManager = new UserScoresManager(data, new UserScoresPgPromiseSerializer);
|
||||
res.json(userDataManager.content);
|
||||
})
|
||||
|
||||
userRoute.post('/register', async (req, res) => {
|
||||
if (req.body.name == undefined) {
|
||||
res.status(400).send("'name' was not defined");
|
||||
return;
|
||||
}
|
||||
await Database.db.none(
|
||||
'INSERT INTO "user" (name) VALUES ($1);', [req.body.name]
|
||||
);
|
||||
res.status(200).send();
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue