mirror of
https://github.com/KeyZox71/knl_meowscendence.git
synced 2025-12-31 21:56:41 +01:00
fixed single-player tetris games
This commit is contained in:
@ -22,9 +22,9 @@ Input needed :
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"game": "<pong/tetris>"
|
"game": "<pong/tetris>"
|
||||||
"opponent": "<the opponent's username>",
|
"opponent": "<the opponent's username>", <= item only present if the match involved 2 players
|
||||||
"myScore": <my score>,
|
"myScore": <my score>,
|
||||||
"opponentScore": <the opponent's score>,
|
"opponentScore": <the opponent's score>, <= item only present if the match involved 2 players
|
||||||
"date": <seconds since Epoch (Date.now() return)>
|
"date": <seconds since Epoch (Date.now() return)>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -36,7 +36,7 @@ Can return:
|
|||||||
"msg": "Match successfully saved to the blockchain"
|
"msg": "Match successfully saved to the blockchain"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- 400 with response (if no user is specified in header, or no opponent/p1Score/p2Score is specified in body, or opponent is the user specified in header, or a score is negative, or the game specified is invalid)
|
- 400 with response (if no user is specified in header, or no opponent/p1Score/p2Score is specified in body, or opponent is the user specified in header, or a score is negative, or the game specified is invalid, or the game should involve more players than was specified)
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"error": "<corresponding error>"
|
"error": "<corresponding error>"
|
||||||
@ -69,9 +69,9 @@ Can return:
|
|||||||
"score":
|
"score":
|
||||||
{
|
{
|
||||||
"p1": "<the name of the p1>",
|
"p1": "<the name of the p1>",
|
||||||
"p2": "<the name of the p2>",
|
"p2": "<the name of the p2>", <= item only present if the match involved 2 players
|
||||||
"p1Score": "<the score of the p1>",
|
"p1Score": "<the score of the p1>",
|
||||||
"p2Score": "<the score of the p2>",
|
"p2Score": "<the score of the p2>", <= item only present if the match involved 2 players
|
||||||
"date": <seconds since Epoch (Date.now() return)>
|
"date": <seconds since Epoch (Date.now() return)>
|
||||||
},
|
},
|
||||||
"tx": "<the transcaction hash>"
|
"tx": "<the transcaction hash>"
|
||||||
|
|||||||
21
src/api/TODO
21
src/api/TODO
@ -1,21 +0,0 @@
|
|||||||
Todo :
|
|
||||||
- view friend's activity status
|
|
||||||
- add a privacy setting so not anybody can GET friends, match history, etc. (what are the RGPD requirements ?) ?
|
|
||||||
- test updated score storing (delays)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
User API :
|
|
||||||
POST /users/:userId/avatar + {image} (calls POST /images, stores returned imageId in DB at :userId)
|
|
||||||
GET /users/:userId/avatar -> {image}
|
|
||||||
DELETE /users/:userId/avatar (calls DELETE /images/:imageId, clears imageId in DB at :userId)
|
|
||||||
PATCH /users/:userId/avatar + {image} (emulates a DELETE /users/:userId/avatar and a POST /users/:userId/avatar) -> use uMember instead ?
|
|
||||||
- provide a random kanel image from Adam's website ?
|
|
||||||
|
|
||||||
Image API :
|
|
||||||
- convert everything to webp (using @fastify/sharp)
|
|
||||||
- test size max
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Always update API docs
|
|
||||||
@ -20,7 +20,7 @@ export default async function(fastify, options) {
|
|||||||
required: ['p1', 'p2', 'p1Score', 'p2Score'],
|
required: ['p1', 'p2', 'p1Score', 'p2Score'],
|
||||||
properties: {
|
properties: {
|
||||||
p1: { type: 'string', minLength: 1 },
|
p1: { type: 'string', minLength: 1 },
|
||||||
p2: { type: 'string', minLength: 1 },
|
p2: { type: 'string', minLength: 0 },
|
||||||
p1Score: { type: 'integer', minimum: 0 },
|
p1Score: { type: 'integer', minimum: 0 },
|
||||||
p2Score: { type: 'integer', minimum: 0 },
|
p2Score: { type: 'integer', minimum: 0 },
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
export async function dAvatar(request, reply, fastify, deleteAvatarId) {
|
export async function dAvatar(request, reply, fastify, getUserInfo, deleteAvatarId) {
|
||||||
try {
|
try {
|
||||||
;
|
const userId = request.params.userId;
|
||||||
|
if (!getUserInfo.get(userId)) {
|
||||||
|
return reply.cose(404).send({ error: "User does not exist" });
|
||||||
|
}
|
||||||
|
deleteAvatarId.run(userId);
|
||||||
return reply.code(200).send({ msg: "Avatar deleted successfully" });
|
return reply.code(200).send({ msg: "Avatar deleted successfully" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
fastify.log.error(err);
|
fastify.log.error(err);
|
||||||
|
|||||||
@ -69,9 +69,9 @@ function prepareDB() {
|
|||||||
player1 TEXT,
|
player1 TEXT,
|
||||||
player2 TEXT,
|
player2 TEXT,
|
||||||
matchId INTEGER,
|
matchId INTEGER,
|
||||||
CHECK(player1 != player2),
|
|
||||||
CHECK(game = 'pong' OR game = 'tetris'),
|
CHECK(game = 'pong' OR game = 'tetris'),
|
||||||
CHECK(date >= 0)
|
CHECK(date >= 0),
|
||||||
|
CHECK(player1 != player2)
|
||||||
) STRICT
|
) STRICT
|
||||||
`);
|
`);
|
||||||
database.exec(`
|
database.exec(`
|
||||||
@ -125,9 +125,8 @@ const deleteStatsTetris = database.prepare('UPDATE userData SET tetrisWins = 0,
|
|||||||
const deleteAvatarId = database.prepare('UPDATE userData SET avatarId = -1 WHERE username = ?;');
|
const deleteAvatarId = database.prepare('UPDATE userData SET avatarId = -1 WHERE username = ?;');
|
||||||
|
|
||||||
const querySchema = { type: 'object', required: ['iStart', 'iEnd'], properties: { iStart: { type: 'integer', minimum: 0 }, iEnd: { type: 'integer', minimum: 0 } } }
|
const querySchema = { type: 'object', required: ['iStart', 'iEnd'], properties: { iStart: { type: 'integer', minimum: 0 }, iEnd: { type: 'integer', minimum: 0 } } }
|
||||||
const bodySchema = { type: 'object', required: ['opponent', 'myScore', 'opponentScore'], properties: { opponent: { type: 'string' }, myScore: { type: 'integer', minimum: 0 }, opponentScore: { type: 'integer', minimum: 0 } } }
|
|
||||||
const querySchemaMatchHistory = { type: 'object', required: ['game', 'iStart', 'iEnd'], properties: { game: { type: 'string' }, iStart: { type: 'integer', minimum: 0 }, iEnd: { type: 'integer', minimum: 0 } } }
|
const querySchemaMatchHistory = { type: 'object', required: ['game', 'iStart', 'iEnd'], properties: { game: { type: 'string' }, iStart: { type: 'integer', minimum: 0 }, iEnd: { type: 'integer', minimum: 0 } } }
|
||||||
const bodySchemaMatchHistory = { type: 'object', required: ['game', 'date', 'opponent', 'myScore', 'opponentScore'], properties: { game: { type: 'string' }, date: { type: 'integer', minimum: 0 }, opponent: { type: 'string' }, myScore: { type: 'integer', minimum: 0 }, opponentScore: { type: 'integer', minimum: 0 } } }
|
const bodySchemaMatchHistory = { type: 'object', required: ['game', 'date', 'myScore'], properties: { game: { type: 'string' }, date: { type: 'integer', minimum: 0 }, opponent: { type: 'string' }, myScore: { type: 'integer', minimum: 0 }, opponentScore: { type: 'integer', minimum: 0 } } }
|
||||||
const querySchemaMatchHistoryGame = { type: 'object', required: ['game'], properties: { game: { type: 'string' } } }
|
const querySchemaMatchHistoryGame = { type: 'object', required: ['game'], properties: { game: { type: 'string' } } }
|
||||||
|
|
||||||
export default async function(fastify, options) {
|
export default async function(fastify, options) {
|
||||||
@ -182,7 +181,7 @@ export default async function(fastify, options) {
|
|||||||
return gNumberMatches(request, reply, fastify, getUserInfo, getNumberMatches);
|
return gNumberMatches(request, reply, fastify, getUserInfo, getNumberMatches);
|
||||||
});
|
});
|
||||||
fastify.get('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
fastify.get('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||||
return gAvatar(request, reply, fastify, getAvatarId);
|
return gAvatar(request, reply, fastify, getUserInfo, getAvatarId);
|
||||||
});
|
});
|
||||||
fastify.get('/ping/:userId', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
fastify.get('/ping/:userId', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||||
return gPing(request, reply, fastify, getActivityTime);
|
return gPing(request, reply, fastify, getActivityTime);
|
||||||
@ -199,7 +198,7 @@ export default async function(fastify, options) {
|
|||||||
return pMatchHistory(request, reply, fastify, getUserInfo, addMatch, incWinsPong, incLossesPong, incWinsTetris, incLossesTetris);
|
return pMatchHistory(request, reply, fastify, getUserInfo, addMatch, incWinsPong, incLossesPong, incWinsTetris, incLossesTetris);
|
||||||
});
|
});
|
||||||
fastify.post('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
fastify.post('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||||
return pAvatar(request, reply, fastify, setAvatarId);
|
return pAvatar(request, reply, fastify, getUserInfo, setAvatarId);
|
||||||
});
|
});
|
||||||
fastify.post('/ping', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
fastify.post('/ping', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||||
return pPing(request, reply, fastify, setActivityTime);
|
return pPing(request, reply, fastify, setActivityTime);
|
||||||
@ -227,6 +226,6 @@ export default async function(fastify, options) {
|
|||||||
return dMatchHistory(request, reply, fastify, getUserInfo, deleteMatchHistory, deleteStatsPong, deleteStatsTetris);
|
return dMatchHistory(request, reply, fastify, getUserInfo, deleteMatchHistory, deleteStatsPong, deleteStatsTetris);
|
||||||
});
|
});
|
||||||
fastify.delete('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
fastify.delete('/users/:userId/avatar', { preHandler: [fastify.authenticate] }, async (request, reply) => {
|
||||||
return dAvatar(request, reply, fastify, deleteAvatarId);
|
return dAvatar(request, reply, fastify, getUserInfo, deleteAvatarId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,27 @@
|
|||||||
export async function gAvatar(request, reply, fastify, getAvatarId) {
|
export async function gAvatar(request, reply, fastify, getUserInfo, getAvatarId) {
|
||||||
try {
|
try {
|
||||||
;
|
const userId = request.params.userId;
|
||||||
return reply.code(200).send({ });
|
if (!getUserInfo.get(userId)) {
|
||||||
|
return reply.code(404).send({ error: "User does not exist" });
|
||||||
|
}
|
||||||
|
const imageId = 1;//getAvatarId.get(userId);
|
||||||
|
if (imageId === -1) {
|
||||||
|
;// return random kanel image
|
||||||
|
}
|
||||||
|
const res = await fetch(`http://localhost:3004/images/${imageId}`, { method: "GET" });
|
||||||
|
if (!res.ok) {
|
||||||
|
console.log("====================================\nAn error on the image API has occured");
|
||||||
|
return reply.code(500).send({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
for (const [key, value] of res.headers) {
|
||||||
|
reply.header(key, value);
|
||||||
|
}
|
||||||
|
if (res.body) {
|
||||||
|
reply.code(res.statusCode).send(res.body);
|
||||||
|
} else {
|
||||||
|
reply.code(res.statusCode).send();
|
||||||
|
}
|
||||||
|
//return reply.code(200).type(res.header).send(res.body);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
fastify.log.error(err);
|
fastify.log.error(err);
|
||||||
return reply.code(500).send({ error: "Internal server error" });
|
return reply.code(500).send({ error: "Internal server error" });
|
||||||
|
|||||||
@ -22,6 +22,10 @@ export async function gMatchHistory(request, reply, fastify, getUserInfo, getMat
|
|||||||
}
|
}
|
||||||
const resJson = await res.json();
|
const resJson = await res.json();
|
||||||
resJson.score.date = match.date;
|
resJson.score.date = match.date;
|
||||||
|
if (resJson.score.p2 === "" && resJson.score.p2Score === 0) {
|
||||||
|
delete resJson.score.p2;
|
||||||
|
delete resJson.score.p2Score;
|
||||||
|
}
|
||||||
return resJson;
|
return resJson;
|
||||||
});
|
});
|
||||||
const matchHistory = await Promise.all(promises);
|
const matchHistory = await Promise.all(promises);
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
export async function pAvatar(request, reply, fastify, setAvatarId) {
|
export async function pAvatar(request, reply, fastify, getUserInfo, setAvatarId) {
|
||||||
try {
|
try {
|
||||||
/* const res = await fetch('http://localhost:3004/images', { method: "POST", headers: { } });
|
const userId = request.params.userId;
|
||||||
|
if (!getUserInfo.get(userId)) {
|
||||||
|
return reply.cose(404).send({ error: "User does not exist" });
|
||||||
|
}
|
||||||
|
console.log("====================================\n", request.headers);//==========
|
||||||
|
const res = await fetch('http://localhost:3004/images', { method: "POST", headers: { "Content-Type": "image/webp" }, body: request.body ? JSON.stringify(request.body) : undefined });
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
return reply.code(500).send({ error: "Internal server error" });
|
return reply.code(500).send({ error: "Internal server error" });
|
||||||
}
|
}
|
||||||
const data = await res.json();*/
|
const data = await res.json();
|
||||||
|
setAvatarId.run(data.imageId, userId);
|
||||||
return reply.code(200).send({ msg: "Avatar uploaded successfully" });
|
return reply.code(200).send({ msg: "Avatar uploaded successfully" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
fastify.log.error(err);
|
fastify.log.error(err);
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
async function fetchSave(request, reply, userId, addMatch) {
|
async function fetchSave(request, reply, userId, addMatch) {
|
||||||
const res = await fetch('http://localhost:3003/', { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ p1: userId, p2: request.body.opponent, p1Score: request.body.myScore, p2Score: request.body.opponentScore }) });
|
let opponentName = '';
|
||||||
|
let opponentScore = 0;
|
||||||
|
if (request.body.opponent && request.body.opponentScore) {
|
||||||
|
opponentName = request.body.opponent;
|
||||||
|
opponentScore = request.body.opponentScore;
|
||||||
|
}
|
||||||
|
const res = await fetch('http://localhost:3003/', { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ p1: userId, p2: opponentName, p1Score: request.body.myScore, p2Score: opponentScore }) });
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
throw new Error('Internal server error');
|
throw new Error('Internal server error');
|
||||||
}
|
}
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
addMatch.run(request.body.game, request.body.date, userId, request.body.opponent, data.id);
|
addMatch.run(request.body.game, request.body.date, userId, opponentName, data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function pMatchHistory(request, reply, fastify, getUserInfo, addMatch, incWinsPong, incLossesPong, incWinsTetris, incLossesTetris) {
|
export async function pMatchHistory(request, reply, fastify, getUserInfo, addMatch, incWinsPong, incLossesPong, incWinsTetris, incLossesTetris) {
|
||||||
@ -19,14 +25,19 @@ export async function pMatchHistory(request, reply, fastify, getUserInfo, addMat
|
|||||||
if (request.body.game !== 'pong' && request.body.game !== 'tetris') {
|
if (request.body.game !== 'pong' && request.body.game !== 'tetris') {
|
||||||
return reply.code(400).send({ error: "Specified game does not exist" });
|
return reply.code(400).send({ error: "Specified game does not exist" });
|
||||||
}
|
}
|
||||||
|
if (request.body.game === 'pong' && (!request.body.opponent || !request.body.opponentScore)) {
|
||||||
|
return reply.code(400).send({ error: "Game requires two players" });
|
||||||
|
}
|
||||||
if (!getUserInfo.get(userId)) {
|
if (!getUserInfo.get(userId)) {
|
||||||
return reply.code(404).send({ error: "User does not exist" });
|
return reply.code(404).send({ error: "User does not exist" });
|
||||||
}
|
}
|
||||||
if (!getUserInfo.get(request.body.opponent)) {
|
if (request.body.opponent) {
|
||||||
return reply.code(404).send({ error: "Opponent does not exist" });
|
if (!getUserInfo.get(request.body.opponent)) {
|
||||||
}
|
return reply.code(404).send({ error: "Opponent does not exist" });
|
||||||
if (request.body.opponent === userId) {
|
}
|
||||||
return reply.code(400).send({ error: "Do you have dementia ? You cannot have played a match against yourself gramps" });
|
if (request.body.opponent === userId) {
|
||||||
|
return reply.code(400).send({ error: "Do you have dementia ? You cannot have played a match against yourself gramps" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await fetchSave(request, reply, userId, addMatch);
|
await fetchSave(request, reply, userId, addMatch);
|
||||||
if (request.body.game === 'pong') {
|
if (request.body.game === 'pong') {
|
||||||
@ -38,7 +49,7 @@ export async function pMatchHistory(request, reply, fastify, getUserInfo, addMat
|
|||||||
incLossesPong.run(userId);
|
incLossesPong.run(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (request.body.game === 'tetris') {
|
else if (request.body.game === 'tetris' && request.body.opponent && request.body.opponentScore) {
|
||||||
if (request.body.myScore > request.body.opponentScore) {
|
if (request.body.myScore > request.body.opponentScore) {
|
||||||
incWinsTetris.run(userId);
|
incWinsTetris.run(userId);
|
||||||
incLossesTetris.run(request.body.opponent);
|
incLossesTetris.run(request.body.opponent);
|
||||||
|
|||||||
Reference in New Issue
Block a user