본문 바로가기
내일배움 과제/CH3 풋살온라인게임

캐시 기능 추가시 기능 추가

by GREEN나무 2024. 12. 4.
728x90

  캐시 추가기능

1. 다른 유저에게 캐시 주기

    내꺼 줄어들고 받은사람 늘어나고

2. 돈 불리기 ( 행운의 룰렛)

    유저가 캐시를 걸면 n배로 돌려받기. 확률 설정하기

  0.5배: 20% |1배: 50%  |2배: 20%  |5배: 8% |10배: 1.8%  |50배: 0.2%

3. 게임 승패로 캐시 증감   <- 구현방법 찾아보자

    게임 결과로 캐시 주고 뺐기

    게임 이기면 캐시 랜덤 쿠폰 주기

   쿠폰 테이블 만들어야함(위에 끝나고 하기)

 



📚 cash API 명세서

url 생략 : localhost:3001/api

기능 Method URL Reqest  Respond
캐시선물 POST /cash/gift {
"senderNickname" :"내가 보냄", 
"receiverNickname" :"나는 받음", 
"amount":50, 
"password" :"sendcash123"
}
{
message: `${receiverNickname}님에게 ${newAmount}캐시를 선물했습니다.`,
        }
룰렛캐시 POST /cash/roulette {
"email":"reciverr@gmail.com", 
"betAmount":10, 
"password":"recivecash123"
}
{
 message: `${multiplyC}배에 당첨되셨습니다! ${Math.floor(multiplyC * betAmount)} 캐시를 획득하셨습니다.`,
}
승패캐시 호 POST /cash/game-result {
"winnerEmail":"reciverr@gmail.com", 
"loserEmail":"sender@gmail.com", 
"result":1,
"amount":20
}
{
message: '경기보상을 받으세요!',
                gameResult: `${winnerEmail} 승리`,
details: [
                    { email: winnerEmail, change: `+${winnerReward} 캐시` },
                    { email: loserEmail, change: `${loserPenalty} 캐시` },
                ],
            }
캐시쿠폰 POST /cash/coupon {
"email":"strobus@gmail.com",
"coponNumber":123456
}
{ "message": "쿠폰이 적용되었습니다. OOO캐시를 받으세요." }
랜덤캐시쿠폰 POST /cash/randomCoupon {
"email":"strobus@gmail.com",
"coponNumber":123456
}
{ "message": "랜덤 쿠폰으로 OOO캐시를 받으셨습니다." }

 


1. 다른 유저에게 캐시 주기

    내꺼 줄어들고 받은사람 늘어나고

 

이 기능을 선물캐시('/cash/gift')로 정하고 이전의 선물캐시는 "Lucky cash"('/cash/lucky')로 바꿈

 

코드

더보기
// 1. 다른 유저에게 캐시 선물

router.post('/cash/gift', async (req, res, next) => {
    const { senderNickname, receiverNickname, amount, password } = req.body;
    let newAmount = +amount;
    try {
        // 입력정보 확인
        if (!senderNickname || !receiverNickname || !newAmount || !password) {
            return res.status(404).json({
                message:
                    '보내는 닉네임, 받는 닉네임, 금액, 비밀번호를 모두 입력해주세요.',
            });
        }

        // 송신자 닉네임 확인
        const sender = await prisma.manager.findFirst({
            where: { nickname: senderNickname },
            select: {
                cash: true,
                account: {
                    select: {
                        password: true, // Account.password
                    },
                },
            },
        });
        if (!sender) {
            return res.status(404).json({
                message: '송신자 닉네임이 존재하지 않습니다.',
            });
        }

        // 송신자 비번확인
        if (sender.account.password !== password) {
            return res.status(404).json({
                message: '송신자의 비밀번호가 일치하지 않습니다.',
            });
        }

        // 수신자 닉네임 확인
        const receiver = await prisma.manager.findFirst({
            where: { nickname: receiverNickname },
            select: {
                cash: true,
            },
        });

        if (!receiver) {
            return res.status(404).json({
                message: '수신자 닉네임이 존재하지 않습니다.',
            });
        }

        // 캐시 1이상의 정수 확인
        if (!Number.isInteger(newAmount) || newAmount < 1) {
            return res.status(404).json({
                message: '선물하는 금액은 1 이상의 정수여야 합니다.',
            });
        }
        // 송신자 잔액 확인
        if (sender.cash < newAmount) {
            return res.status(400).json({
                message: '송신자의 잔액이 부족합니다.',
            });
        }

        // 캐시 수정하기  내꺼 줄어들고 받은사람 늘어나고
        await prisma.manager.update({
            where: { nickname: senderNickname },
            data: { cash: sender.cash - newAmount },
        });
        await prisma.manager.update({
            where: { nickname: receiverNickname },
            data: { cash: receiver.cash + newAmount },
        });

        // 수신 알림 저장 <- 알림용 테이블을 만들어야함
        // await prisma.notification.create({
        //     data: {
        //         receiverNickname,
        //         message: `${senderNickname}님이 ${newAmount}캐시를 선물하였습니다.`,
        //         createdAt: new Date(),
        //     },
        // });

        return res.status(200).json({
            message: `${receiverNickname}님에게 ${newAmount}캐시를 선물했습니다.`,
        });
    } catch (error) {
        console.error('Error gifting cash:', error);
        return res.status(500).json({ message: 'Internal server error' });
    }
});

 

 

오류

Unknown field `password` for select statement on model `Manager`. Available options are listed in green.
Error gifting cash: PrismaClientValidationError:
Invalid `prisma.manager.findFirst()` invocation:

또 같은 실수함. 계정테이블에 있는 password는 중첩 select써야함.

 

금액인증 코드 오류. 조건을 잘못 줌

// 캐시 1이상의 정수 확인
        // newAmount가 정수일 때도 작동해버림.
        if (Number.isInteger(newAmount) || newAmount < 1) {}
        // 이렇게 바꾸기
        if (!Number.isInteger(newAmount) || newAmount < 1) {}

 

메니저 테이블의 닉네임이 uniqe가 아니라 오류나서 수정함

Argument where of type ManagerWhereUniqueInput needs at least one of managerId, email or accountId arguments. Available options are listed in green.
Error gifting cash: PrismaClientValidationError:
Invalid prisma.manager.update() invocation:

성공!


2. 돈 불리기 ( 행운의 룰렛)

    유저가 캐시를 걸면 n배로 돌려받기. 확률 설정하기

  0.5배: 20% |1배: 50%  |2배: 20%  |5배: 8% |10배: 1.8%  |50배: 0.2%

더보기
// 2. 돈 불리기 ( 행운의 룰렛)

router.post('/cash/roulette', async (req, res, next) => {
    const { email, betAmount, password } = req.body;
    try {
        // 입력정보 유효성 확인
        const bet = await prisma.manager.findFirst({
            where: { email },
            select: {
                email: true,
                cash: true,
                account: { select: { password: true } },
            },
        });
        // 이메일
        if (!bet) {
            return res
                .status(404)
                .json({ message: '일치하는 이메일이 없습니다.' });
        }

        // 비번
        if (bet.account.password !== password) {
            return res
                .status(404)
                .json({ message: '비밀번호가 일치하지 않습니다.' });
        }

        // 캐시 보유금액
        if (!Number.isInteger(betAmount)) {
            return res
                .status(404)
                .json({ message: '캐시는 정수로 적어주세요.' });
        }
        if (bet.cash < betAmount && betAmount > 0) {
            return res.status(404).json({
                message: '0보다 크고 보유캐시보다 적은 캐시를 걸어주세요.',
            });
        }

        // 유저가 캐시를 걸면 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 multiplyCash = 0;

        if (roulette <= 20) {
            multiplyCash = Math.floor(betAmount * 0.5);
        } else if (roulette <= 70) {
            multiplyCash = Math.floor(betAmount * 1);
        } else if (roulette <= 90) {
            multiplyCash = Math.floor(betAmount * 2);
        } else if (roulette <= 98) {
            multiplyCash = Math.floor(betAmount * 5);
        } else if (roulette <= 99.8) {
            multiplyCash = Math.floor(betAmount * 10);
        } else {
            multiplyCash = Math.floor(betAmount * 50);
        }

        await prisma.manager.update({
            data: { cash: bet.cash - betAmount + multiplyCash },
            where: { email },
        });

        return res
            .status(200)
            .json({ message: `${multiplyCash} 캐시를 획득하셨습니다.` });
    } catch (error) {
        console.error('Error fetching cash data:', error);
        return res.status(500).json({ message: 'Internal server error' });
    }
});

성공

 


3 게임 승패로 캐시 증감 - 경기보상 구현중

더보기
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.manager.findFirst({
            where: { email: winnerEmail },
            select: { cash: true },
        });
        if (!winner) {
            return res
                .status(404)
                .json({ message: '승자 이메일이 존재하지 않습니다.' });
        }

        // 패자 데이터 확인
        const loser = await prisma.manager.findFirst({
            where: { email: loserEmail },
            select: { cash: 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.cash, -amount); // 최대 패널티는 가진 돈까지만
            /*
            if (loser.cash < amount) {
                loserPenalty = -loser.cash; // 돈 없으면 있는것만 뺏기
            } else {
                loserPenalty = -amount;
            }*/
        } else {
            // 무승부: 승자에게 배팅 금액의 절반만 지급, 패자는 그대로
            winnerReward = Math.floor(amount / 2);
            loserPenalty = Math.floor(amount / 2);
        }

        // 데이터 업데이트
        await prisma.manager.update({
            where: { email: winnerEmail },
            data: { cash: winner.cash + winnerReward },
        });
        // 데이터 업데이트
        await prisma.manager.update({
            where: { email: loserEmail },
            data: { cash: loser.cash + loserPenalty },
        });

        if (result) {
            return res.status(200).json({
                gameResult: `${winnerEmail} 승리`,
                details: [
                    { email: winnerEmail, change: `+${winnerReward} 캐시` },
                    { email: loserEmail, change: `${loserPenalty} 캐시` },
                ],
            });
        } else {
            return res.status(200).json({
                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' });
    }
});

 

무승부 추가

 

오류발생

// result의 값은 0 or 1
// result의 값이 0일때도 걸림.  '|| !result '지우고 따로 확인하기
if (!winnerEmail || !loserEmail || !result || !amount || amount <= 0) {}

// 수정
       if (!winnerEmail || !loserEmail || !amount || amount <= 0) {...}

        if (!result === 0 && !result === 1) {
            return res.status(400).json({
                message:
                    '승패는 무승부면 0을, 아니면 1을 정수 형태로 넣어주세요.',
            });
        }

 

서버오류발생

 

코드 내에 ' loserNickname'이 아직 남아있음. loseeEmail로 수정

이제 되기는 하는데 res 폼이 맘에 안듬.

// 수정함
        if (result) {
            return res.status(200).json({
                gameResult: `${winnerEmail} 승리`,
                details: [
                    { email: winnerEmail, change: `+${winnerReward} 캐시` },
                    { email: loserEmail, change: `${loserPenalty} 캐시` },
                ],
            });
        } else {
            return res.status(200).json({
                gameResult: '무승부',
                details: [
                    { email: winnerEmail, change: `+${winnerReward} 캐시` },
                    { email: loserEmail, change: `+${loserPenalty} 캐시` },
                ],
            });
        }



4.    게임 이기면 캐시 랜덤 쿠폰 주기

   쿠폰 테이블 만들어야함(위에 끝나고 하기)

 

 

 

 

 

 

'내일배움 과제 > CH3 풋살온라인게임' 카테고리의 다른 글

튜터님 코드리뷰  (1) 2024.12.06
1차 머지 후 오류 수정  (0) 2024.12.05
회의 24.12.04  (0) 2024.12.04
회의 241203  (2) 2024.12.03
cash API 만들기(조회, 선물, 구매)  (0) 2024.12.03