728x90
테이블 수정 후 코드 고치기
테이블 변화
이메일은 계정 테이블에만 존재
닉네임 @unique 사라짐 ->
manager에서 email 참고한 부분 모두 수정하기
const isEmail = await prisma.manager.findFirst({
where: { email: email },
select: {
email: true,
cash: true,
},
});
캐시결제 - 서버 오류 발생
where: {
account: {
email: email,
},
},
where를 고유한 값으로 바꿈. - 해결.
// Manager 업데이트
await prisma.manager.update({
where: { managerId: account.manager.managerId },
data: { cash: account.manager.cash + buyCash },
});
의문점 : email도 @유니크 였는데 왜 않됬지?
email이 Manager와 직접 연결되어 있지 않기 때문에 Manager의 where 조건으로 사용할 수 없는 것입니다.
/cash/gift 서버오류
위와 같은 방법으로 해결해보기
전부 서버오류 떴음.
경로 수정하니 잘 실행됨.
비번 bcrypt해서 인증하기
오류발생
// 비번
const bcryptPassword = await bcrypt.hash(password, 10);
if (account.password !== bcryptPassword) {
return res
.status(404)
.json({ message: '비밀번호가 일치하지 않습니다.' });
}
bcrypt.hash로 생성한 해시값은 항상 새로 생성되므로, 기존 저장된 해시와 직접 비교하면 비교가 실패합니다. 대신, bcrypt.compare를 사용해야 올바르게 해시값을 비교할 수 있습니다.
수정 완료
더보기
// routes/cash.router.js
import express from 'express';
import bcrypt from 'bcrypt';
import { prisma } from '../../utils/prisma/index.js';
const router = express.Router();
// const bcryptPassword = await bcrypt.hash(password, 10); // 생성
// const isPasswordMatch = await bcrypt.compare(password, account.password); // 비교
/** Lucky캐시API email **/
router.post('/cash/lucky', async (req, res, next) => {
const { email } = req.body;
try {
// email이 있는지 확인
const account = await prisma.account.findFirst({
where: { email },
select: {
email: true,
manager: {
select: {
// 수정: `select`로 변경
cash: true,
managerId: true,
},
},
},
});
// 있으면
if (!account) {
return res.status(404).json({ message: '존재하지 않는 Email 입니다.' });
}
const giftCash = Math.floor(Math.random() * 200) + 20;
// originalCache는 객체 형태. originalCache -> originalCache.cash
await prisma.manager.update({
where: { managerId: account.manager.managerId },
data: { cash: account.manager.cash + giftCash },
});
return res.status(200).json({ message: `LUCKY!!! ${giftCash}캐시를 받았습니다.` });
} catch (error) {
console.error('Error lucky cash:', error);
return res.status(500).json({ message: 'Internal server error' });
}
});
/**O 캐시 구매API email, 캐시, 비번! **/
router.post('/cash/payment', async (req, res, next) => {
const { email, buyCash, password } = req.body;
try {
// 구매할 캐시가 유효한지 확인
if (!buyCash || buyCash <= 0) {
return res.status(400).json({
message: '구매하려는 캐시는 0 이상의 정수를 입력해주세요.',
});
}
// 이메일과 비밀번호로 Account 조회
const account = await prisma.account.findUnique({
where: { email: email },
select: {
password: true,
manager: {
select: { managerId: true, cash: true },
},
},
});
// 없으면
if (!account) {
return res.status(404).json({ message: '존재하지 않는 Email 입니다.' });
}
// 비번확인
const isPasswordMatch = await bcrypt.compare(password, account.password); // (password, account.password);
if (!isPasswordMatch) {
return res.status(404).json({ message: '비밀번호가 일치하지 않습니다.' });
}
// Manager 업데이트
await prisma.manager.update({
where: { managerId: account.manager.managerId },
data: { cash: account.manager.cash + buyCash },
});
return res.status(200).json({ message: `${buyCash}캐시를 결제하셧습니다.` });
} catch (error) {
console.error('Error fetching cash data:', error);
return res.status(500).json({ message: '캐시 구매 Internal server error' });
}
});
/**O 캐시 조회API email, 비번 추가하기 **/
router.get('/cash/:email', async (req, res, next) => {
console.log('조회');
const { email } = req.params;
const { password } = req.body;
// 이메일 유효성 검사
if (!email || typeof email !== 'string') {
return res.status(400).json({ message: 'Invalid email parameter' });
}
try {
const account = await prisma.account.findFirst({
where: { email },
select: {
email: true,
password: true,
manager: {
select: {
cash: true,
managerId: true,
},
},
},
});
if (!account) {
return res.status(404).json({ message: 'User not found' });
}
// 비번
const isPasswordMatch = await bcrypt.compare(password, account.password); // (password, account.password);
if (!isPasswordMatch) {
return res.status(404).json({ message: '비밀번호가 일치하지 않습니다.' });
}
return res.status(200).json({
data: { email: account.email, cash: account.manager.cash },
});
} catch (error) {
console.error('Error fetching cash data:', error);
return res.status(500).json({ message: '캐시조회 Internal server error' });
}
});
/** 1. 다른 유저에게 캐시 선물API 비번!**/
router.post('/cash/gift', async (req, res, next) => {
const { senderEmail, receiverEmail, amount, password } = req.body;
try {
// 입력정보 확인
if (!senderEmail || !receiverEmail || !amount || !password) {
return res.status(404).json({
message: '송신자 이메일, 수신자 이메일, 금액, 비밀번호를 모두 입력해주세요.',
});
}
// 송신자 이메일 확인
const sender = await prisma.account.findFirst({
where: { email: senderEmail },
select: {
email: true,
password: true,
manager: { select: { cash: true, managerId: true } },
},
});
if (!sender) {
return res.status(404).json({
message: '송신자 이메일이 존재하지 않습니다.',
});
}
// 송신자 비번확인
const isPasswordMatch = await bcrypt.compare(password, sender.password); // (password, account.password);
if (!isPasswordMatch) {
return res.status(404).json({ message: '비밀번호가 일치하지 않습니다.' });
}
// 수신자 이메일 확인
const receiver = await prisma.account.findFirst({
where: { email: receiverEmail },
select: { manager: { select: { cash: true, managerId: true } } },
});
if (!receiver) {
return res.status(404).json({
message: '수신자 이메일이 존재하지 않습니다.',
});
}
// 캐시 1이상의 정수 확인
const parsedAmount = Number(amount);
if (!Number.isInteger(parsedAmount) || parsedAmount < 1) {
return res.status(404).json({
message: '선물하는 금액은 1 이상의 정수여야 합니다.',
});
}
// 송신자 잔액 확인
if (sender.manager.cash < amount) {
return res.status(400).json({
message: '송신자의 잔액이 부족합니다.',
});
}
// 캐시 수정하기 내꺼 줄어들고 받은사람 늘어나고
await prisma.manager.update({
where: { managerId: sender.manager.managerId },
data: { cash: sender.manager.cash - amount },
});
await prisma.manager.update({
where: { managerId: receiver.manager.managerId },
data: { cash: receiver.manager.cash + amount },
});
return res.status(200).json({
message: `${receiverEmail}님에게 ${amount}캐시를 선물했습니다.`,
});
} catch (error) {
console.error('Error gifting cash:', error);
return res.status(500).json({ message: 'Internal server error' });
}
});
/** 2. 돈 불리기 ( 행운의 룰렛)API 비번!**/
router.post('/cash/roulette', async (req, res, next) => {
const { email, betAmount, password } = req.body;
try {
// 입력정보 유효성 확인
const account = await prisma.account.findFirst({
where: { email },
select: {
email: true,
password: true,
manager: { select: { cash: true, managerId: true } },
},
});
// 이메일
if (!account) {
return res.status(404).json({ message: '일치하는 이메일이 없습니다.' });
}
// 비번
const isPasswordMatch = await bcrypt.compare(password, account.password);
if (!isPasswordMatch) {
return res.status(404).json({ message: '비밀번호가 일치하지 않습니다.' });
}
// 캐시 보유금액
if (!Number.isInteger(betAmount)) {
return res.status(404).json({ message: '캐시는 정수로 적어주세요.' });
}
// 캐시 보유금액 확인
if (!Number.isInteger(betAmount) || betAmount < 1) {
return res.status(404).json({
message: '캐시는 1 이상의 정수로 적어주세요.',
});
}
if (betAmount > account.manager.cash) {
return res.status(404).json({
message: '보유 캐시보다 적은 금액만 걸 수 있습니다.',
});
}
// 유저가 캐시를 걸면 n배로 돌려받기. 확률 설정하기
// 0.5배: 20% |1배: 50% |2배: 20% |5배: 8% |10배: 1.8% |50배: 0.2%
const roulette = Math.random() * 100; // 0 ~ 99.9999
let multiplyC = 0.0;
if (roulette <= 20) {
multiplyC = 0.5;
} else if (roulette <= 70) {
multiplyC = 1;
} else if (roulette <= 90) {
multiplyC = 2;
} else if (roulette <= 98) {
multiplyC = 5;
} else if (roulette <= 99.8) {
multiplyC = 10;
} else {
multiplyC = 50;
}
let batR = Math.floor(betAmount * multiplyC);
await prisma.manager.update({
where: { managerId: account.manager.managerId },
data: { cash: account.manager.cash - betAmount + batR },
});
return res.status(200).json({
message: `${multiplyC}배에 당첨되셨습니다! ${batR} 캐시를 획득하셨습니다.`,
});
} catch (error) {
console.error('Error fetching cash data:', error);
return res.status(500).json({ message: '캐시 룰렛 Internal server error' });
}
});
/**O 3. 게임 승패로 캐시 증감API **/
// 게임 결과로 캐시 주고 뺐기
router.post('/cash/game-result', async (req, res, next) => {
const { winnerEmail, loserEmail, result, amount } = req.body;
try {
if (!winnerEmail || !loserEmail || !amount || amount <= 0) {
return res.status(400).json({
message: '승자, 패자 이메일, 경기결과, 0 이상의 보상캐시을 입력해주세요.',
});
}
if (!result === 0 && !result === 1) {
return res.status(400).json({
message: '승패는 무승부면 0을, 아니면 1을 정수 형태로 넣어주세요.',
});
}
// 승자 데이터 확인
const winner = await prisma.account.findFirst({
where: { email: winnerEmail },
select: { manager: { select: { cash: true, managerId: true } } },
});
if (!winner) {
return res.status(404).json({ message: '승자 이메일이 존재하지 않습니다.' });
}
// 패자 데이터 확인
const loser = await prisma.account.findFirst({
where: { email: loserEmail },
select: { manager: { select: { cash: true, managerId: true } } },
});
if (!loser) {
return res.status(404).json({ message: '패자 이메일이 존재하지 않습니다.' });
}
// result 승패 있으면 1, 무승부면 0 을 넣기
let winnerReward = 0;
let loserPenalty = 0;
if (result) {
winnerReward = amount;
loserPenalty = Math.max(-loser.manager.cash, -amount); // 최대 패널티는 가진 돈까지만
} else {
// 무승부: 배팅 금액의 절반씩 지급
winnerReward = Math.floor(amount / 2);
loserPenalty = Math.floor(amount / 2);
}
if (isNaN(winnerReward) || isNaN(loserPenalty)) {
throw new Error('캐시 계산1 중 오류가 발생했습니다.');
}
const winnerCashUpdate = winner.manager.cash + winnerReward;
const loserCashUpdate = loser.manager.cash + loserPenalty;
if (isNaN(winnerCashUpdate) || isNaN(loserCashUpdate)) {
throw new Error('캐시 계산2 중 오류가 발생했습니다.');
}
// 데이터 업데이트
await prisma.manager.update({
where: { managerId: winner.manager.managerId },
data: { cash: winnerCashUpdate },
});
await prisma.manager.update({
where: { managerId: loser.manager.managerId },
data: { cash: loserCashUpdate },
});
if (result) {
return res.status(200).json({
message: '경기보상을 받으세요!',
gameResult: `${winnerEmail} 승리`,
details: [
{ email: winnerEmail, change: `+${winnerReward} 캐시` },
{ email: loserEmail, change: `${loserPenalty} 캐시` },
],
});
} else {
return res.status(200).json({
message: '경기보상을 받으세요!',
gameResult: '무승부',
details: [
{ email: winnerEmail, change: `+${winnerReward} 캐시` },
{ email: loserEmail, change: `+${loserPenalty} 캐시` },
],
});
}
} catch (error) {
console.error('Error processing game result:', error);
return res.status(500).json({ message: '캐시 승패 Internal server error' });
}
});
export default router;
팀프로젝트
리드 하고 당한 경험 - 면접에 좋음
'내일배움 과제 > CH3 풋살온라인게임' 카테고리의 다른 글
발표회 준비 (0) | 2024.12.06 |
---|---|
튜터님 코드리뷰 (1) | 2024.12.06 |
캐시 기능 추가시 기능 추가 (0) | 2024.12.04 |
회의 24.12.04 (0) | 2024.12.04 |
회의 241203 (2) | 2024.12.03 |