diff --git a/src/lib/db/users.ts b/src/lib/db/users.ts index 6c1677d..6bcd4a6 100644 --- a/src/lib/db/users.ts +++ b/src/lib/db/users.ts @@ -77,16 +77,16 @@ export const getUserResearch = async (user: User): Promise> => { return research; } -export const createOrUpgradeResearch = async (username: string, research: Research) => { +export const createOrUpgradeResearch = async (userId: ObjectId, research: Research) => { const users = await Users(); const result = await users.updateOne( - { username, "research.id": research.id }, + { _id: userId, "research.id": research.id }, { $set: { "research.$.level": research.level } } ); if (result.modifiedCount === 0) { - await users.updateOne({ username }, + await users.updateOne({ _id: userId }, { $push: { research } } ); } diff --git a/src/pages/api/research/getResearch.ts b/src/pages/api/research/getResearch.ts new file mode 100644 index 0000000..c8d580d --- /dev/null +++ b/src/pages/api/research/getResearch.ts @@ -0,0 +1,26 @@ +import { type APIRoute } from "astro"; +import validateAccessToken from "../../../lib/utils/validateAccessToken"; +import { getUserByAccessToken, getUserResearch } from "../../../lib/db/users"; + +export const GET: APIRoute = async({ request }) => { + const response = await validateAccessToken(request); + if(response instanceof Response) return response; + + const user = await getUserByAccessToken(response); + if(user === null) { + return new Response( + JSON.stringify({ + code: 401, + message: "Unauthorized" + }), { status: 401 } + ) + } + + return new Response( + JSON.stringify({ + code: 200, + message: "OK", + data: await getUserResearch(user) + }), { status: 200 } + ) +} \ No newline at end of file diff --git a/src/pages/api/research/performResearch.ts b/src/pages/api/research/performResearch.ts index b4216d4..b7fea54 100644 --- a/src/pages/api/research/performResearch.ts +++ b/src/pages/api/research/performResearch.ts @@ -1,12 +1,15 @@ import { type APIRoute } from "astro"; import validateAccessToken from "../../../lib/utils/validateAccessToken"; -import { getUserResources, updateUserResources } from "../../../lib/utils/resourceManager"; import research from '../../../lib/data/research.json'; import { createOrUpgradeResearch, getUserByAccessToken, getUserResearch } from "../../../lib/db/users"; -import type DBResource from "../../../types/DBResource"; +import { getPlanetById } from "../../../lib/db/planets"; +import Planet from "../../../types/Planet"; +import { ObjectId } from "mongodb"; +import { calculateCurrentAvailableResources, getResourcesFromPlanet, updatePlanetResources } from "../../../lib/utils/resourceManager"; +import DBResource from "../../../types/DBResource"; +import calculateAvailableResources from "../../../lib/utils/calculateAvailableResources"; export const POST: APIRoute = async({ request }) => { - // validate access token const response = await validateAccessToken(request); if(response instanceof Response) return response; @@ -20,8 +23,20 @@ export const POST: APIRoute = async({ request }) => { ) } - // check if research id is valid - const researchId = (await request.json()).research; + let body; + try { + body = await request.json() + } catch(e) { + return new Response( + JSON.stringify({ + code: 400, + message: "Bad Request", + error: "Invalid JSON body" + }), { status: 400 } + ) + } + + const researchId = body.research; const researchData = research.filter((element: any) => element.id === researchId)[0]; if(!researchId || !researchData) { return new Response( @@ -32,17 +47,38 @@ export const POST: APIRoute = async({ request }) => { }), { status: 400 } ) } + let userPlanet: Planet | null; + try { + userPlanet = await getPlanetById(new ObjectId(body.planetId)); + } catch(e) { + return new Response( + JSON.stringify({ + code: 400, + message: "Bad Request", + error: "Invalid planet id" + }), { status: 400 } + ) + } + if(!userPlanet) { + return new Response( + JSON.stringify({ + code: 404, + message: "Not Found", + error: "Planet not found" + }), { status: 404 } + ) + } // check requirements // buildings - const buildings = user.buildings; + const buildings = userPlanet.buildings; researchData.requirements.buildings.forEach((buildingReq) => { - if(buildings.filter((building) => building.id === buildingReq.id)[0].level < buildingReq.level) { + if(buildings.filter((building) => building.id === buildingReq.id)[0]?.level ?? 0 < buildingReq.level) { return new Response( JSON.stringify({ code: 400, message: "Bad Request", - error: `${buildingReq.id} level ${buildingReq.level} required` + error: `${buildingReq.id} level ${buildingReq.level} required, found ${buildings.filter((building) => building.id === buildingReq.id)[0]?.level ?? 0}` }), { status: 400 } ) } @@ -56,38 +92,54 @@ export const POST: APIRoute = async({ request }) => { JSON.stringify({ code: 400, message: "Bad Request", - error: `${researchReq.id} level ${researchReq.level} required` + error: `${researchReq.id} level ${researchReq.level} required, found ${playerResearch.filter((research) => research.id === researchReq.id)[0].level}` }), { status: 400 } ) } }); // resources - const resources = await getUserResources(user._id); + const resources = await calculateCurrentAvailableResources(userPlanet._id); + if(!resources) { + return new Response( + JSON.stringify({ + code: 500, + message: "Internal Server Error", + error: "Failed to get resources" + }), { status: 500 } + ) + } const playerCurrentResearch = playerResearch.filter((element: any) => element.id === researchId)[0]; const level = playerCurrentResearch ? playerCurrentResearch.level : 0; const newResources = structuredClone(resources); - let hasEnoughResources = true; + const missingResources: Array<{}> = []; Object.entries(researchData.requirements.resources).forEach(([key, value]) => { const res = resources.filter((element: DBResource) => element.name === key)[0]; const cost = playerCurrentResearch ? value * Math.pow(researchData.multiplier, level) : value; - if(res.amount < cost) hasEnoughResources = false; + if(res.amount < cost) { + missingResources.push({ + name: key, + required: cost, + available: res.amount + }); + return; + } else newResources.filter((element: DBResource) => element.name === key)[0].amount -= cost; }); - if(!hasEnoughResources) { + if(missingResources.length > 0) { return new Response( JSON.stringify({ code: 400, message: "Bad Request", - error: "Not enough resources" + data: missingResources }), { status: 400 } ) } - await updateUserResources(user._id, newResources); - await createOrUpgradeResearch(user.username, { id: researchId, level: level + 1 }); + await updatePlanetResources(userPlanet._id, newResources); + await createOrUpgradeResearch(user._id, { id: researchId, level: level + 1 }); return new Response( JSON.stringify({