172928. 공원 산책
42840. 모의고사
12939. 최댓값과 최솟값
12951. JadenCase 문자열 만들기
어제 필수 기능 API를 구현했는데, 에러처리 부분과 데이터 가져오는데에 있어 몇가지 부분을 수정하였다.
[Node.js] CH3 개인과제 - 필수 API 구현
또 수정하다보니까 중복된 인증들이 눈에 밟힌다..
미들웨어를 뭘 쓸지 고민하고 코딩할 걸 그랬다. 완벽히 구현 끝나면 제출전까지 미들웨어 추가 구현해서
리팩토링 해봐야겠다.😎
밑에의 내용은 오늘 구현한 도전 기능 관련 API이다.
POST /shop/buy/:characterId
Authorization: Bearer <your_token>
[
{
"itemNo": 1,
"count": 2
},
{
"itemNo": 2,
"count": 1
}
]
{
"data": {
"changedMoney": your_changed_money,
"changedInventory": "{your_changed_inventory}"
}
}
{ errorMessage: `금액 부족. ${character.money} 원 보유중` }
{ errorMessage: "본인 캐릭터만 구매 가능합니다." }
{ errorMessage: "존재하지 않는 캐릭터입니다." }
{ errorMessage: "아이템이 없습니다." }
{ errorMessage: "서버 오류" }
router.post(
"/shop/buy/:characterNo",
authMiddleware,
async (req, res, next) => {
const {
params: { characterNo },
user: { userNo },
body: shoppingCart,
} = req;
try {
const [character, inventory] = await Promise.all([
prisma.characters.findFirst({ where: { characterNo: +characterNo } }),
prisma.inventories.findFirst({ where: { inventoryNo: +characterNo } }),
]);
if (!character)
return res
.status(404)
.json({ errorMessage: "존재하지 않는 캐릭터입니다." });
if (character.userNo !== userNo)
return res
.status(401)
.json({ errorMessage: "본인 캐릭터만 구매 가능합니다." });
const inventoryItems = JSON.parse(inventory.items);
let price = 0;
// 쇼핑카트 가격 계산
for (const { itemNo, count } of shoppingCart) {
const item = await prisma.items.findFirst({ where: { itemNo } });
if (!item)
return res.status(404).json({ errorMessage: "아이템이 없습니다." });
price += item.itemPrice * count;
}
// 결제 처리
if (character.money < price)
return res
.status(400)
.json({ errorMessage: `금액 부족. ${character.money} 원 보유중` });
// 인벤토리 및 캐릭터 업데이트
for (const { itemNo, count } of shoppingCart) {
inventoryItems[itemNo] = (inventoryItems[itemNo] || 0) + count;
}
const [updatedCharacter, updatedInventory] = await Promise.all([
prisma.characters.update({
where: { characterNo: +characterNo },
data: { money: character.money - price },
}),
prisma.inventories.update({
where: { inventoryNo: +characterNo },
data: { items: JSON.stringify(inventoryItems) },
}),
]);
res.status(200).json({
data: {
changedMoney: updatedCharacter.money,
changedInventory: JSON.parse(updatedInventory.items),
},
});
} catch (err) {
res.status(500).json({ errorMessage: "서버 오류" });
}
}
);
POST /shop/sell/:characterNo
Authorization: Bearer <your_token>
[
{
"itemNo": 1,
"count": 2
}
]
{
"data": {
"changedMoney": your_changed_money,
"changedInventory": {
your_changed_inventory
}
}
}
{errorMessage: "판매할 아이템보다 보유한 아이템이 적습니다."}
{ errorMessage: "본인 캐릭터만 판매 가능합니다." }
{ errorMessage: "존재하지 않는 캐릭터입니다." }
{ errorMessage: "아이템이 없습니다." }
{ errorMessage: "서버 오류" }
router.post(
"/shop/sell/:characterNo",
authMiddleware,
async (req, res, next) => {
const {
params: { characterNo },
user: { userNo },
body: sellingCart,
} = req;
try {
const [character, inventory] = await Promise.all([
prisma.characters.findFirst({ where: { characterNo: +characterNo } }),
prisma.inventories.findFirst({ where: { inventoryNo: +characterNo } }),
]);
if (!character)
return res
.status(404)
.json({ errorMessage: "존재하지 않는 캐릭터입니다." });
if (character.userNo !== userNo)
return res
.status(401)
.json({ errorMessage: "본인 캐릭터만 판매 가능합니다." });
const inventoryItems = JSON.parse(inventory.items);
let price = 0;
// 판매카트 가격 계산
for (const { itemNo, count } of sellingCart) {
const item = await prisma.items.findFirst({ where: { itemNo } });
if (!item)
return res.status(404).json({ errorMessage: "아이템이 없습니다." });
if (!inventoryItems[itemNo] || inventoryItems[itemNo] < count)
return res.status(400).json({
errorMessage: "판매할 아이템보다 보유한 아이템이 적습니다.",
});
price += Math.ceil(item.itemPrice * count * 0.6);
}
// 인벤토리 업데이트
for (const { itemNo, count } of sellingCart) {
if (inventoryItems[itemNo] - count === 0) {
delete inventoryItems[itemNo];
} else {
inventoryItems[itemNo] -= count;
}
}
const [updatedCharacter, updatedInventory] = await Promise.all([
prisma.characters.update({
where: { characterNo: +characterNo },
data: { money: character.money + price },
}),
prisma.inventories.update({
where: { inventoryNo: +characterNo },
data: { items: JSON.stringify(inventoryItems) },
}),
]);
res.status(200).json({
data: {
changedMoney: updatedCharacter.money,
changedInventory: JSON.parse(updatedInventory.items),
},
});
} catch (err) {
res.status(500).json({ errorMessage: "서버 오류" });
}
}
);
GET /inventory/:characterNo
Authorization: Bearer <your_token>
{
"data": {
your_inventory
}
}
{ errorMessage: "본인의 캐릭터만 조회 가능합니다." }
{ errorMessage: "조회하려는 캐릭터가 없습니다." }
{ errorMessage: "서버 오류" }
router.get(
"/inventory/:characterNo",
authMiddleware,
async (req, res, next) => {
const {
params: { characterNo },
user: { userNo },
} = req;
try {
const [inventory, character] = await Promise.all([
prisma.inventories.findFirst({ where: { inventoryNo: +characterNo } }),
prisma.characters.findFirst({ where: { characterNo: +characterNo } }),
]);
if (!inventory || !character)
return res
.status(404)
.json({ errorMessage: "조회하려는 캐릭터가 없습니다." });
if (userNo !== character.userNo)
return res
.status(401)
.json({ errorMessage: "본인의 캐릭터만 조회 가능합니다." });
return res.status(200).json({
data: JSON.parse(inventory.items),
});
} catch (err) {
res.status(500).json({ errorMessage: "서버오류" });
}
}
);
GET /equip/:characterNo
{
"data": {your_equip}
}
{ errorMessage: "조회하려는 장비창이 없습니다." }
{ errorMessage: "서버 오류" }
router.get("/equip/:characterNo", async (req, res, next) => {
const { characterNo } = req.params;
try {
const equip = await prisma.equips.findFirst({
where: { equipNo: +characterNo },
});
if (!equip)
return res
.status(404)
.json({ errorMessage: "조회하려는 장비창이 없습니다." });
if (Object.keys(equip.items).length === 0)
return res.status(200).json({ data: [] });
return res.status(200).json({
data: JSON.parse(equip.items),
});
} catch (err) {
res.status(500).json({ errorMessage: "서버오류" });
}
});
POST /equipItem/:characterNo
Authorization: Bearer <your_token>
{
"doEquipItem" : input_equip_item_number
}
{
"data": {
"character_health": 560,
"character_power": 109,
"updatedInventory": {
"1": 3,
"2": 1
},
"updatedEquip": {
"1": 1,
"2": 1
}
}
}
{ errorMessage: " 장비 착용 권한이 없습니다. " }
{errorMessage: " 장비를 착용할 캐릭터가 존재하지 않습니다. "}
{ errorMessage: "보유하지 않은 아이템입니다." }
{ errorMessage: "이미 장착하신 아이템입니다." }
{ errorMessage: "서버 오류" }
router.post(
"/equipItem/:characterNo",
authMiddleware,
async (req, res, next) => {
const {
params: { characterNo },
body: { doEquipItem },
user: { userNo },
} = req;
try {
const [character, inventory, equip, item] = await Promise.all([
prisma.characters.findFirst({ where: { characterNo: +characterNo } }),
prisma.inventories.findFirst({ where: { inventoryNo: +characterNo } }),
prisma.equips.findFirst({ where: { equipNo: +characterNo } }),
prisma.items.findFirst({ where: { itemNo: +doEquipItem } }),
]);
if (!character)
return res.status(404).json({
errorMessage: " 장비를 착용할 캐릭터가 존재하지 않습니다. ",
});
if (character.userNo !== userNo)
return res
.status(401)
.json({ errorMessage: " 장비 착용 권한이 없습니다. " });
const inventoryItems = JSON.parse(inventory.items);
const equipItems = JSON.parse(equip.items);
if (equipItems[doEquipItem])
return res
.status(409)
.json({ errorMessage: "이미 장착하신 아이템입니다." });
if (!inventoryItems[doEquipItem])
return res
.status(404)
.json({ errorMessage: "보유하지 않은 아이템입니다." });
// 장착할 아이템 인벤토리 제거
if (inventoryItems[doEquipItem] === 1) delete inventoryItems[doEquipItem];
else inventoryItems[doEquipItem] -= 1;
// 장착한 아이템 장비창에 등록
equipItems[doEquipItem] = 1;
// 캐릭터 스탯 조정
for (const [key, value] of Object.entries(item.itemStat)) {
character[key] += value;
}
const [updatedCharacter, updatedInventory, updatedEquip] =
await Promise.all([
prisma.characters.update({
where: { characterNo: +characterNo },
data: { health: character.health, power: character.power },
}),
prisma.inventories.update({
where: { inventoryNo: +characterNo },
data: { items: JSON.stringify(inventoryItems) },
}),
prisma.equips.update({
where: { equipNo: +characterNo },
data: { items: JSON.stringify(equipItems) },
}),
]);
return res.status(200).json({
data: {
character_health: updatedCharacter.health,
character_power: updatedCharacter.power,
updatedInventory: JSON.parse(updatedInventory.items),
updatedEquip: JSON.parse(updatedEquip.items),
},
});
} catch (err) {
console.error(err);
res.status(500).json({ errorMessage: "서버 오류" });
}
}
);
POST /unEquipItem/:characterNo
Authorization: Bearer <your_token>
{
"unEquipItem" : input_equip_item_number
}
{
"data": {
"character_health": 500,
"character_power": 100,
"updatedInventory": {
"1": 4,
"2": 2
},
"updatedEquip": {}
}
}
{ errorMessage: " 장비 탈착 권한이 없습니다. " }
{errorMessage: " 장비를 착용할 캐릭터가 존재하지 않습니다. "}
{ errorMessage: "장착하신 아이템이 아닙니다." }
{ errorMessage: "서버 오류" }
router.post(
"/unEquipItem/:characterNo",
authMiddleware,
async (req, res, next) => {
const {
params: { characterNo },
body: { unEquipItem },
user: { userNo },
} = req;
try {
const [character, inventory, equip, item] = await Promise.all([
prisma.characters.findFirst({ where: { characterNo: +characterNo } }),
prisma.inventories.findFirst({ where: { inventoryNo: +characterNo } }),
prisma.equips.findFirst({ where: { equipNo: +characterNo } }),
prisma.items.findFirst({ where: { itemNo: +unEquipItem } }),
]);
if (!character)
return res.status(404).json({
errorMessage: " 장비를 착용할 캐릭터가 존재하지 않습니다. ",
});
if (character.userNo !== userNo)
return res
.status(401)
.json({ errorMessage: " 장비 탈착 권한이 없습니다. " });
const inventoryItems = JSON.parse(inventory.items);
const equipItems = JSON.parse(equip.items);
if (!equipItems[unEquipItem])
return res
.status(404)
.json({ errorMessage: "장착하신 아이템이 아닙니다." });
// 장착한 아이템 장비창에서 제거
delete equipItems[unEquipItem];
// 탈착한 아이템 인벤토리 추가
if (!inventoryItems[unEquipItem]) inventoryItems[unEquipItem] = 1;
else inventoryItems[unEquipItem] += 1;
// 캐릭터 스탯 조정
for (const [key, value] of Object.entries(item.itemStat)) {
character[key] -= value;
}
const [updatedCharacter, updatedInventory, updatedEquip] =
await Promise.all([
prisma.characters.update({
where: { characterNo: +characterNo },
data: { health: character.health, power: character.power },
}),
prisma.inventories.update({
where: { inventoryNo: +characterNo },
data: { items: JSON.stringify(inventoryItems) },
}),
prisma.equips.update({
where: { equipNo: +characterNo },
data: { items: JSON.stringify(equipItems) },
}),
]);
return res.status(200).json({
data: {
character_health: updatedCharacter.health,
character_power: updatedCharacter.power,
updatedInventory: JSON.parse(updatedInventory.items),
updatedEquip: JSON.parse(updatedEquip.items),
},
});
} catch (err) {
console.error(err);
res.status(500).json({ errorMessage: "서버 오류" });
}
}
);
GET /showMeTheMoney/:characterNo
Authorization: Bearer <your_token>
{
"message": "100원이 추가되어 잔액이 6200 원이 되었습니다."
}
{ errorMessage: "남 캐릭터 돈벌어줘서 뭐합니까" }
{ errorMessage: "캐릭터가 존재하지 않습니다." }
{ errorMessage: "서버 오류" }
router.get(
"/showMeTheMoney/:characterNo",
authMiddleware,
async (req, res, next) => {
const {
params: { characterNo },
user: { userNo },
} = req;
try {
const character = await prisma.characters.findFirst({
where: { characterNo: +characterNo },
});
if (!character)
return res
.status(404)
.json({ errorMessage: "캐릭터가 존재하지 않습니다." });
if (character.userNo !== userNo)
return res
.status(401)
.json({ errorMessage: "남 캐릭터 돈벌어줘서 뭐합니까" });
character.money += 100;
const changedCharacter = await prisma.characters.update({
where: { characterNo: +characterNo },
data: { money: character.money },
});
return res.status(200).json({
message: `100원이 추가되어 잔액이 ${changedCharacter.money} 원이 되었습니다.`,
});
} catch (err) {
console.error(err);
}
}
);