var express = require('express'); var router = express.Router(); var bcrypt = require('bcrypt'); const {ObjectId} = require("mongodb"); var saltRounds = 10; var ResponseType = { INVALID_EMAIL: 0, INVALID_PASSWORD: 1, SUCCESS: 2 } /* GET users listing. */ router.get('/', function(req, res, next) { res.send('respond with a resource'); }); // 회원 가입 router.post('/signup', async function (req, res, next) { try { var email = req.body.email; var password = req.body.password; var nickname = req.body.nickname; var profileImageIndex = req.body.imageIndex ?? 0; // 입력값 검증 if( !email || !password || !nickname ){ return res.status(400).send("모든 필드를 입력하세요.") } // 이메일 형식 검증 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(email)) { return res.status(400).send("유효한 이메일 주소를 입력하세요."); } var database = req.app.get('database'); var users = database.collection('users'); const existingUser = await users.findOne({email: email}) if(existingUser){ return res.status(409).send("이미 존재하는 사용자입니다.") } // 비밀번호 암호화 var salt = bcrypt.genSaltSync(saltRounds); var hash = bcrypt.hashSync(password, salt); // 신규 유저를 DB에 저장 await users.insertOne({ email: email, password: hash, nickname: nickname, profileImageIndex: profileImageIndex, rating: 18, score:0, win:0, lose:0, coins: 1000 }); res.status(201).send("사용자가 성공적으로 생성되었습니다."); } catch (err){ console.log("사용자 추가중 오류 발생 : " + err); res.status(500).send("서버 오류가 발생했습니다."); } }) // 로그인 router.post("/signin", async function (req, res, next) { try { var email = req.body.email; var password = req.body.password; var database = req.app.get('database'); var users = database.collection('users'); // 입력값 검증 if (!email || !password) { return res.status(400).send("모든 필드를 입력해주세요."); } const existingUser = await users.findOne({email: email}); if(existingUser){ var compareResult = bcrypt.compareSync(password, existingUser.password); if(compareResult){ req.session.isAuthenticated = true; req.session.userId = existingUser._id.toString(); req.session.email = existingUser.email; req.session.nickname = existingUser.nickname; req.session.profileImageIndex = existingUser.profileImageIndex || 0; req.session.rating = existingUser.rating; req.session.score = existingUser.score; req.session.coins = existingUser.coins; res.json({ result: ResponseType.SUCCESS, nickname: existingUser.nickname, imageIndex: existingUser.profileImageIndex, rating: existingUser.rating, score: existingUser.score, coins: existingUser.coins, }); } else { res.json({result : ResponseType.INVALID_PASSWORD}); } } else { res.json({result : ResponseType.INVALID_EMAIL}); } }catch (err){ console.log("로그인 중 오류 발생 : ", err); res.status(500).send("서버 오류가 발생했습니다."); } }) // 로그 아웃 router.post("/signout", async function (req, res, next) { req.session.destroy((err) => { if(err) { console.log("로그아웃 중 오류 발생"); return res.status(500).send("서버 오류가 발생했습니다."); } res.status(200).send("로그아웃 되었습니다.") }); }); // 점수 추가 router.post("/score-update", async function (req, res, next) { try { if(!req.session.isAuthenticated) { return res.status(400).send("로그인이 필요합니다."); } var userId = req.session.userId; var isWin = req.body.isWin; // 점수 유효성 검사 if(!isWin || isNaN(isWin) || isWin > 1 || isWin < -1) { return res.status(400).send("유효한 점수를 입력해주세요."); } var database = req.app.get('database'); var users = database.collection('users'); var findUser = await users.findOne({_id: ObjectId.createFromHexString(userId) }); var userRating = findUser.rating; var userScore = findUser.score + isWin; var winCount = findUser.win; var loseCount = findUser.lose; if (isWin > 0) { winCount += 1; } else { loseCount += 1; } // 급수에 따른 필요 승급 포인트 결정 let requiredPoints; if (userRating >= 10 && userRating <= 18) { requiredPoints = 3; // 10~18급은 3점 필요 } else if (userRating >= 5 && userRating <= 9) { requiredPoints = 5; // 5~9급은 5점 필요 } else if (userRating >= 1 && userRating <= 4) { requiredPoints = 10; // 1~4급은 10점 필요 } // 승급 확인 if (userScore >= requiredPoints) { if (userRating > 1) { // 1급보다 높은 급수인 경우만 승급 가능 userRating -= 1; // 급수 상승 (숫자는 작을수록 높은 급수) userScore = 0; // 승급 후 포인트 초기화 } else { // 1급인 경우 더 이상 승급 불가능, 최대 포인트로 유지 userScore = requiredPoints; } } // 강등 확인 if (userScore <= -requiredPoints) { if (userRating < 18) { // 18급보다 낮은 급수인 경우만 강등 가능 userRating += 1; // 급수 하락 (숫자가 커짐) userScore = 0; // 강등 후 포인트 초기화 } else { // 18급인 경우 더 이상 강등 불가능, 최소 포인트로 유지 userScore = -requiredPoints + 1; } } const result = await users.updateOne( {_id: ObjectId.createFromHexString(userId) }, { $set: { rating: Number(userRating), score: Number(userScore), win: winCount, lose: loseCount, updatedAt: new Date() } } ); if(result.matchedCount === 0 ) { return res.status(400).send("사용자를 찾을 수 없습니다."); } res.status(200).json({ message: "점수가 성공적으로 업데이트되었습니다.", rating: Number(userRating), score: Number(userScore), win: Number(winCount), lose: Number(loseCount), // TODO : 승급, 강등 여부 추가 -1 :강등, 0: 변화 없음 , 1: 승급 }); } catch(err) { console.log("점수 추가 중 오류 발생 : ",err); res.status(500).send("서버 오류가 발생했습니다."); } }) // 점수 조회 router.get("/get-info", async function (req, res, next) { try { if(!req.session.isAuthenticated) { return res.status(403).send("로그인이 필요합니다."); } var userId = req.session.userId; var database = req.app.get('database'); var users = database.collection('users'); const user = await users.findOne({_id: ObjectId.createFromHexString(userId) }); if(!user){ return res.status(404).send("사용자를 찾을 수 없습니다."); } res.json({ id: user._id.toString(), nickname: user.nickname, rating: user.rating, score: Number(user.score) || 0, imageIndex: Number(user.profileImageIndex), coins: Number(user.coins), }) } catch (err) { console.error("점수 조회 중 오류 발생 : ", err); res.status(500).send("서버 오류가 발생했습니다.") } }) module.exports = router;