diff --git a/src/main/java/com/example/catchTheLetters/constant/CommonConstant.java b/src/main/java/com/example/catchTheLetters/constant/CommonConstant.java index 14a42be..bb46a1e 100644 --- a/src/main/java/com/example/catchTheLetters/constant/CommonConstant.java +++ b/src/main/java/com/example/catchTheLetters/constant/CommonConstant.java @@ -26,4 +26,8 @@ public interface CommonConstant { String STATUS = "status"; String BUCKET = "catchtheletters"; + + Integer WORDS_NUM = 10; + + String HEAL = "10"; } diff --git a/src/main/java/com/example/catchTheLetters/controller/AuthController.java b/src/main/java/com/example/catchTheLetters/controller/AuthController.java index 9469a5b..d032d3d 100644 --- a/src/main/java/com/example/catchTheLetters/controller/AuthController.java +++ b/src/main/java/com/example/catchTheLetters/controller/AuthController.java @@ -75,14 +75,14 @@ public class AuthController { @ApiOperation(value = "发送邮件") @PostMapping("/email") - public R emailSend(@RequestHeader("token") String token, String email) { + public R emailSend(String email) { return emailService.sendEmail(email); } @ApiOperation(value = "验证邮箱") @PostMapping("/verify-email") - public R emailVerify(@RequestHeader("token") String token, String email, String code) { + public R emailVerify(String email, String code) { return emailService.verifyEmail(email, code); } } diff --git a/src/main/java/com/example/catchTheLetters/entity/LetterAction.java b/src/main/java/com/example/catchTheLetters/entity/LetterAction.java index 87f20ad..b4c7641 100644 --- a/src/main/java/com/example/catchTheLetters/entity/LetterAction.java +++ b/src/main/java/com/example/catchTheLetters/entity/LetterAction.java @@ -5,6 +5,7 @@ import com.example.catchTheLetters.model.vo.Letter; import lombok.Data; import java.io.Serializable; +import java.util.Map; /** * 字母操作 @@ -17,6 +18,7 @@ public class LetterAction implements Serializable { private Letter letter; private String userId; private long letterId; + private Map words; public LetterAction() { } @@ -40,4 +42,9 @@ public class LetterAction implements Serializable { public LetterAction(LetterActionType type) { this.type = type; } + + public LetterAction(LetterActionType type, Map words) { + this.type = type; + this.words = words; + } } diff --git a/src/main/java/com/example/catchTheLetters/entity/Word.java b/src/main/java/com/example/catchTheLetters/entity/Word.java new file mode 100644 index 0000000..bcf5a14 --- /dev/null +++ b/src/main/java/com/example/catchTheLetters/entity/Word.java @@ -0,0 +1,13 @@ +package com.example.catchTheLetters.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Word { + private String id; + private String word; +} diff --git a/src/main/java/com/example/catchTheLetters/service/impl/LevelServiceImpl.java b/src/main/java/com/example/catchTheLetters/service/impl/LevelServiceImpl.java index 1417ce5..3c1eb58 100644 --- a/src/main/java/com/example/catchTheLetters/service/impl/LevelServiceImpl.java +++ b/src/main/java/com/example/catchTheLetters/service/impl/LevelServiceImpl.java @@ -6,6 +6,7 @@ import com.example.catchTheLetters.entity.ScoreInfoPage; import com.example.catchTheLetters.model.vo.RankVo; import com.example.catchTheLetters.service.AuthService; import com.example.catchTheLetters.service.LevelService; +import com.example.catchTheLetters.service.RoomService; import com.example.catchTheLetters.utils.JwtUtil; import com.example.catchTheLetters.utils.R; import jakarta.annotation.Resource; diff --git a/src/main/java/com/example/catchTheLetters/service/impl/RoomServiceImpl.java b/src/main/java/com/example/catchTheLetters/service/impl/RoomServiceImpl.java index 0c36cfa..307ebb8 100644 --- a/src/main/java/com/example/catchTheLetters/service/impl/RoomServiceImpl.java +++ b/src/main/java/com/example/catchTheLetters/service/impl/RoomServiceImpl.java @@ -1,5 +1,6 @@ package com.example.catchTheLetters.service.impl; +import com.example.catchTheLetters.constant.CommonConstant; import com.example.catchTheLetters.entity.*; import com.example.catchTheLetters.enums.*; import com.example.catchTheLetters.model.vo.Letter; @@ -7,15 +8,18 @@ import com.example.catchTheLetters.service.AuthService; import com.example.catchTheLetters.service.RoomService; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.Resource; +import lombok.Data; +import org.apache.poi.ss.formula.functions.T; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.stereotype.Service; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import java.io.IOException; -import java.util.Map; -import java.util.Random; -import java.util.UUID; +import java.sql.Time; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** @@ -36,6 +40,8 @@ public class RoomServiceImpl implements RoomService { private final Random random = new Random(); + private int remainTime = 300; + @Resource private MongoTemplate mongoTemplate; @@ -249,8 +255,35 @@ public class RoomServiceImpl implements RoomService { for (var playerEntry : players.entrySet()) sendMessage(playerEntry.getKey(), message); // TODO 字母校验和加分、改变血量逻辑 - // 玩家接取字母时,向玩家当前答案中添加字母,如果单词拼完,给玩家加5*word.length的分和10滴血,如果单词拼错,每秒扣5滴血,如果玩家血量为0,则死亡 + // 如果接取的是回血爱心,给玩家加10滴血 + if (letter.getLetterVal().equals(CommonConstant.HEAL)){ + player.setHealth(player.getHealth() + 10); + } + //判断单词是否拼完 + player.setCurrentAnswer(player.getCurrentAnswer() + letter.getLetterVal()); + if (player.getCurrentAnswer().length() != player.getCurrentWord().length()){ + return; + } + //如果单词拼完,给玩家加5*word.length的分和10滴血 + if (player.getCurrentAnswer().equals(player.getCurrentWord())){ + player.setScore(player.getScore() + 5 * letter.getLetterVal().length()); + player.setHealth(player.getHealth() + 10); + } else { + //每秒扣5滴血,如果玩家血量为0,则死亡 + Timer timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + if (player.getHealth() > 0){ + player.setHealth(player.getHealth() - 5); + } else { + //TODO + // 玩家死亡逻辑 + } + } + },0,1000); + } } private void generateLetter(GameRoom room) { @@ -258,7 +291,7 @@ public class RoomServiceImpl implements RoomService { var words = room.getWords(); // 如果words长度<=5,从数据库中再获取一批随机单词 - if (words.size() <= 5) getWords(words); + if (words.size() <= 5) getWords(words,room); Letter letter; var id = UUID.randomUUID().getLeastSignificantBits(); @@ -282,16 +315,41 @@ public class RoomServiceImpl implements RoomService { sendMessage(player, new GameMessage<>(MessageType.LETTER, new LetterAction(LetterActionType.CREATE, letter))); } - private void getWords(Map words) { + private void getWords(Map words,GameRoom room) { // TODO 从数据库中获取一批随机单词,然后放入words中,并把单词数组推送给所有玩家 + Aggregation aggregation = Aggregation.newAggregation(Aggregation.sample(10)); + AggregationResults results = mongoTemplate.aggregate(aggregation,Word.class,Word.class); + List mappedResults = results.getMappedResults(); + int num = CommonConstant.WORDS_NUM; + num += words.size(); + for (Word word : mappedResults) { + words.put(word.getWord(),num--); + } + for (var player : room.getPlayers().keySet()) { + sendMessage(player, new GameMessage<>(MessageType.LETTER, new LetterAction(LetterActionType.CREATE, words))); + } } private void gameLogic(GameRoom room) { - getWords(room.getWords()); + getWords(room.getWords(),room); // TODO 从300秒开始倒计时,每秒调用一次generateLetter方法,如果时间到了,调用endGame方法 // 如果当前单词被某玩家拼完,Map对应单词的value++,如果value>=玩家数(有可能中途有人退出),目前单词出队列,继续下一个单词 // 游戏结束后需要向玩家发送排行榜数据(用户ID、分数、排名) // 最大的问题:丢包后如何处理?比如其他玩家按下按键后,自己没有接收到松开消息,导致其他玩家在画面中一直持续运动,网络连接稳定后,不同C端的玩家位置不一致 + + //用timer进行异步执行任务,保证倒计时正常进行 + Timer timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + remainTime--; + generateLetter(room); + if (remainTime == 0) { + endGame(room.getRoomId()); + timer.cancel(); + } + } + },0,1000); } public void endGame(long roomId) { diff --git a/src/test/java/com/example/catchTheLetters/TestInsertLevel.java b/src/test/java/com/example/catchTheLetters/TestInsertLevel.java index 12766cb..159fe0f 100644 --- a/src/test/java/com/example/catchTheLetters/TestInsertLevel.java +++ b/src/test/java/com/example/catchTheLetters/TestInsertLevel.java @@ -4,8 +4,8 @@ import com.example.catchTheLetters.controller.LevelController; import com.example.catchTheLetters.entity.Level; import com.example.catchTheLetters.entity.ScoreInfo; import com.example.catchTheLetters.entity.VersionDownload; +import com.example.catchTheLetters.entity.Word; import com.example.catchTheLetters.service.VersionService; -import com.example.catchTheLetters.utils.R; import jakarta.annotation.Resource; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -14,8 +14,10 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.aggregation.Aggregation; import java.util.ArrayList; import java.util.List; @@ -122,5 +124,8 @@ class TestInsertLevel { @Test @Disabled void minIOTest(){ + Aggregation aggregation = Aggregation.newAggregation(Aggregation.sample(5)); + AggregationResults results = mongoTemplate.aggregate(aggregation,Word.class,Word.class); + System.out.println(results.getMappedResults()); } }