You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

223 lines
5.9 KiB

const express = require('express');
const bodyParser = require('body-parser');
const jwt = require('jsonwebtoken');
const cors = require('cors');
const { Document, Schema, connect } = require('camo');
// Define the Racers schema
class Racer extends Document {
constructor() {
super();
this.name = String;
this.gameHandle = String;
}
}
// Define the Seasons schema
class Season extends Document {
constructor() {
super();
this.title = String;
this.subTitle = String;
this.seasonStartDate = String;
}
}
// Define the Races schema
class Race extends Document {
constructor() {
super();
this.weekNumber = Number;
this.startDate = Date;
this.endDate = Date;
this.mapName = String;
this.mapLink = String;
this.season = Season;
}
}
// Define the RaceResults schema
class RaceResult extends Document {
constructor() {
super();
this.race = Race;
this.racer = Racer;
this.timeInSeconds = Number;
this.replayPath = String;
}
}
connect('nedb://./nedb-database');
const fs = require('fs');
const app = express();
const upload = require('./backend/routes/upload-replay');
const AdvancableBuffer = require('./backend/utilities/AdvancableBuffer.js');
const gbxHeader = require('./backend/trackmania-replays/gbx-header.js');
const gbxReplay = require('./backend/trackmania-replays/gbx-replay');
// handling CORS
app.use(cors());
app.use(bodyParser.json());
//const RSA_PRIVATE_KEY = fs.readFileSync('./private.key');
const RSA_PRIVATE_KEY = "Secret_KeY";
const RSA_PUBLIC_KEY = fs.readFileSync('./public.key');
const users = [
{ id: 1, username: 'user1', password: 'password1' },
{ id: 2, username: 'user2', password: 'password2' }
];
function verifyToken(req, res, next) {
const token = req.headers['authorization'];
console.log(token);
if (!token || !token.startsWith('Bearer ')) {
return res.status(401).json({ message: 'Unauthorized' });
}
const tokenWithoutBearer = token.slice(7); // Remove 'Bearer ' prefix
jwt.verify(tokenWithoutBearer, RSA_PRIVATE_KEY, (err, decoded) => {
if (err) {
console.error(err);
return res.status(401).json({ message: 'Invalid token' });
}
req.user = decoded.user;
next();
});
}
app.post('/api/login', (req, res) => {
const { username, password } = req.body;
// Check if the user exists and the password is correct
const user = users.find(u => u.username === username && u.password === password);
if (!user) {
return res.status(401).json({ message: 'Invalid username or password' });
}
// Generate and return a JWT token
const token = jwt.sign({ userId: user.id }, RSA_PRIVATE_KEY, { expiresIn: '1h', algorithm: 'HS256' });
console.log(token);
res.json({ token });
});
app.get('/api/seasons', async (req, res) => {
const seasons = await Season.find();
res.json({seasons: seasons});
});
function remapRaceInfo(raceRecord) {
modableRaceObject = {
weekNumber: raceRecord.weekNumber,
startDate: raceRecord.startDate,
endDate: raceRecord.endDate,
mapName: raceRecord.mapName,
mapLink: raceRecord.mapLink,
season: raceRecord.season,
results: []
}
return modableRaceObject;
}
app.get('/api/seasons/:id', async (req, res) => {
const { id } = req.params;
try {
let races = []
let racersInSeason = [];
const seasonDetails = await Season.findOne({_id: id});
const seasonRaceDetails = await Race.find({season: id});
for (let i = 0; i < seasonRaceDetails.length; i++) {
let raceRecord = seasonRaceDetails[i];
let modableRace = remapRaceInfo(raceRecord);
const fastestTimesMap = new Map();
const raceResults = await RaceResult.find('racer', { 'race._id': raceRecord._id });
raceResults.forEach(result => {
const racerId = result.racer._id;
const timeInSeconds = result.timeInSeconds;
if (!fastestTimesMap.has(racerId) || timeInSeconds < fastestTimesMap.get(racerId)) {
fastestTimesMap.set(racerId, timeInSeconds);
}
});
modableRace.results = Array.from(fastestTimesMap.entries()).map(([racerId, timeInSeconds]) => ({
racerId,
timeInSeconds
}));
// This is wrong it will get only the racers the in last race it processes.
racersInSeason = Array.from(new Set(raceResults.map(result => result.racer)));
races.push(modableRace);
}
let i = 1;
let standings = []
racersInSeason.forEach((racer) => {
let entry = {}
entry._id = i;
entry.position = i;
entry.points = 100-i;
entry.user = racer;
standings.push(entry);
});
res.json({season: seasonDetails, races: races, standings: standings});
}
catch( error ) {
console.error(error)
res.status(500).send('Internal Server Error');
}
});
app.post('/api/seasons/add', verifyToken, async (req, res) => {
const { name, subtitle, seasonStartDate } = req.body;
const season = await Season.create({ name, subtitle, seasonStartDate }).save();
console.log(season);
res.json(season);
});
app.post('/api/race/add', verifyToken, async (req, res) => {
const { seasonId, startDate, endDate, mapName, mapLink, weekNumber } = req.body;
const season = await Season.findOne({_id: seasonId});
const race = await Race.create({ weekNumber, startDate, endDate, mapName, mapLink, season })
console.log(race);
race.save();
res.json(race);
});
// route for handling requests from the Angular client
app.post('/api/upload-replay', upload.single('file'), (req, res) => {
let file = req.file;
console.log(req.body);
const { seasonId } = req.body;
console.log("File uploaded: ", req.file);
fs.readFile(file.path, function(err, buffer)
{
buff = new AdvancableBuffer(buffer);
header = new gbxHeader()
header.parse(buff);
console.log(header);
replay = new gbxReplay();
replay.parse(buff);
})
res.status(200);
});
app.listen(3000, () => {
console.log('Server listening on port 3000');
});