Browse Source

redis

master
6 years ago
parent
commit
a9ac650475
  1. 23
      game/src/main/java/com/ccsens/game/bean/dto/ClientDto.java
  2. 27
      game/src/main/java/com/ccsens/game/bean/dto/message/ChangeStatusMessageDto.java
  3. 4
      game/src/main/java/com/ccsens/game/bean/dto/message/GameMessageWithChangeStatusOut.java
  4. 12
      game/src/main/java/com/ccsens/game/persist/dao/GameUserJoinDao.java
  5. 119
      game/src/main/java/com/ccsens/game/service/ClientService.java
  6. 201
      game/src/main/java/com/ccsens/game/service/ScreenService.java
  7. 14
      game/src/main/java/com/ccsens/game/util/GameConstant.java
  8. 80
      game/src/main/java/com/ccsens/game/util/SendMsg.java
  9. 4
      game/src/main/resources/application.yml
  10. 14
      game/src/main/resources/mapper_dao/GameUserJoinDao.xml
  11. 83
      util/src/main/java/com/ccsens/util/RedisUtil.java

23
game/src/main/java/com/ccsens/game/bean/dto/ClientDto.java

@ -1,5 +1,6 @@
package com.ccsens.game.bean.dto;
import com.ccsens.game.bean.po.GameUserJoin;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -31,8 +32,28 @@ public class ClientDto {
@Data
public static class RedisUser{
private Long id;
private String avatarurl;
private String avatarUrl;
private String nickname;
private Long userId;
private Integer times;
private Integer score;
private Integer sort;
private Integer over;
private Integer timeDifference;
private Long localStartTime;
private Long localEndTime;
public static RedisUser getInstance(GameUserJoin userJoin){
ClientDto.RedisUser user = new ClientDto.RedisUser();
user.setId(userJoin.getId());
user.setAvatarUrl(userJoin.getAvatarUrl());
user.setNickname(userJoin.getNickname());
user.setUserId(userJoin.getUserId());
user.setTimeDifference(userJoin.getTimeDifference());
user.setLocalStartTime(userJoin.getLocalStartTime());
user.setLocalEndTime(userJoin.getLocalEndTime());
return user;
}
}
@Data

27
game/src/main/java/com/ccsens/game/bean/dto/message/ChangeStatusMessageDto.java

@ -10,6 +10,9 @@ import java.util.List;
public class ChangeStatusMessageDto {
private Long userId;
private PendingData pendingData;
@ApiModelProperty("准备中")
private PreparingData preparingData;
private CompletedData completedData;
@Data
@ -20,19 +23,25 @@ public class ChangeStatusMessageDto {
@ApiModelProperty("活动奖品")
private Long endLocalTime;
}
@Data
@ApiModel("准备中")
public static class PreparingData{
@ApiModelProperty("活动规则")
private Long startLocalTime ;
@ApiModelProperty("活动奖品")
private Long endLocalTime;
}
@Data
@ApiModel("结束")
public static class CompletedData{
@ApiModelProperty("总人数")
private Integer totalMembers ;
@ApiModelProperty("总次数")
private Integer totalTimes;
@ApiModelProperty("总分数")
private Integer totalScore;
@ApiModelProperty("平均每人多少分")
private Integer averageTimes;
@ApiModelProperty("平均次数超过百分之多少人")
@ApiModelProperty("次数")
private Integer times;
@ApiModelProperty("分数")
private Integer score;
@ApiModelProperty("排名次序")
private Integer sort;
@ApiModelProperty("超过百分之多少人")
private Integer over;
}
}

4
game/src/main/java/com/ccsens/game/bean/dto/message/GameMessageWithChangeStatusOut.java

@ -15,7 +15,7 @@ public class GameMessageWithChangeStatusOut extends BaseMessageDto{
public static class Data{
private Long recordId;
private int gameStatus;
private List<ChangeStatusMessageDto> changeStatusMessageDto;
private ChangeStatusMessageDto changeStatusMessageDto;
}
private Data data;
@ -25,7 +25,7 @@ public class GameMessageWithChangeStatusOut extends BaseMessageDto{
setTime(System.currentTimeMillis());
}
public GameMessageWithChangeStatusOut(Long recordId,int gameStatus,List<ChangeStatusMessageDto> changeStatusMessageDto){
public GameMessageWithChangeStatusOut(Long recordId,int gameStatus,ChangeStatusMessageDto changeStatusMessageDto){
this();
Data d = new Data();
d.setRecordId(recordId);

12
game/src/main/java/com/ccsens/game/persist/dao/GameUserJoinDao.java

@ -17,7 +17,7 @@ public interface GameUserJoinDao extends GameUserJoinMapper {
* @param recordId
* @return
*/
List<ClientVo.Ranking> getAllRanking( @Param("recordId") Long recordId);
List<ClientVo.MemberInfo> getAllRanking( @Param("recordId") Long recordId, @Param("start") int start, @Param("pageSize") int pageSize);
/**
* 获取排名
@ -42,8 +42,16 @@ public interface GameUserJoinDao extends GameUserJoinMapper {
* @param score
* @return
*/
int overNum(@Param("recordId") Long recordId, @Param("score") Integer score);
Integer overNum(@Param("recordId") Long recordId, @Param("score") Integer score);
List<ScreenVo.TopUsers> selectTopTen(@Param("recordId") Long recordId);
/**
* 修改参加游戏的用户的开始和结束时间
* @param recordId
* @param startTime
* @param endTime
*/
void updateTimeBatch(@Param("recordId") Long recordId, @Param("startTime") Long startTime, @Param("endTime") Long endTime);
}

119
game/src/main/java/com/ccsens/game/service/ClientService.java

@ -26,15 +26,13 @@ import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.ccsens.util.bean.dto.QueryDto;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ -122,14 +120,12 @@ public class ClientService implements IClientService {
}
gameUserJoinDao.insertSelective(userJoin);
// 3.更新redis(sort set key:分数 value:头像,姓名)
ClientDto.RedisUser user = new ClientDto.RedisUser();
user.setId(userJoin.getId());
user.setAvatarurl(userJoin.getAvatarUrl());
user.setNickname(userJoin.getNickname());
ClientDto.RedisUser user = ClientDto.RedisUser.getInstance(userJoin);
redisUtil.zsSet(GameConstant.generateGameKey(gameRecord.getId()), JSON.toJSONString(user), 0, GameConstant.REDIS_TIME);
//定时发送状态
ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
List<GameUserJoin> joins = new ArrayList<>();
joins.add(userJoin);
List<ClientDto.RedisUser> joins = new ArrayList<>();
joins.add(ClientDto.RedisUser.getInstance(userJoin));
//4.根据状态延时发送消息
if (prepare) {
//延时发送开始
@ -155,8 +151,6 @@ public class ClientService implements IClientService {
});
}
//5.返回状态
return joinResult(userJoin, gameRecord);
}
@ -224,6 +218,44 @@ public class ClientService implements IClientService {
return joinVo;
}
// /**
// * 查询总排名表
// * @param params
// * @return
// */
// @Override
// public ClientVo.RankingAll getRankingAll(QueryDto<ClientDto.GatRanking> params) {
// ClientDto.GatRanking gatRanking = params.getParam();
// ClientVo.RankingAll rankingAll = new ClientVo.RankingAll();
//
// GameUserJoinExample userJoinExample = new GameUserJoinExample();
// userJoinExample.createCriteria().andRecordIdEqualTo(gatRanking.getRecordId());
// List<GameUserJoin> userJoinList = gameUserJoinDao.selectByExample(userJoinExample);
// if(CollectionUtil.isNotEmpty(userJoinList)){
// rankingAll.setTotalMembers(userJoinList.size());
// }else {
// rankingAll.setTotalMembers(0);
// }
//
// PageHelper.startPage(gatRanking.getPageNum(), gatRanking.getPageSize());
// List<ClientVo.MemberInfo> memberInfo = gameUserJoinDao.selectByRecordId(gatRanking.getRecordId());
// List<ClientVo.Ranking> rankingAllList = gameUserJoinDao.getAllRanking(gatRanking.getRecordId());
// Map<String, Integer> map = new HashMap<>();
// rankingAllList.forEach(ranking -> {
// map.put(String.valueOf(ranking.getUserId()), ranking.getRank());
// });
// memberInfo.forEach(member -> {
// member.setSort(map.get(String.valueOf(member.getId())));
// });
// log.info("查询成员信息");
// PageInfo pageInfo =new PageInfo<>(memberInfo);
//
// rankingAll.setMemberInfoList(memberInfo);
// rankingAll.setFirstPage(pageInfo.isIsFirstPage());
// rankingAll.setLastPage(pageInfo.isIsLastPage());
//
// return rankingAll;
// }
/**
* 查询总排名表
* @param params
@ -233,32 +265,46 @@ public class ClientService implements IClientService {
public ClientVo.RankingAll getRankingAll(QueryDto<ClientDto.GatRanking> params) {
ClientDto.GatRanking gatRanking = params.getParam();
ClientVo.RankingAll rankingAll = new ClientVo.RankingAll();
boolean redisExist = true;
String userKey = GameConstant.generateGameKey(gatRanking.getRecordId());
Long totalMembers = redisUtil.zsGetSize(userKey);
if (totalMembers == null) {
redisExist = false;
GameUserJoinExample userJoinExample = new GameUserJoinExample();
userJoinExample.createCriteria().andRecordIdEqualTo(gatRanking.getRecordId());
List<GameUserJoin> userJoinList = gameUserJoinDao.selectByExample(userJoinExample);
totalMembers = userJoinList == null ? 0 : (long)userJoinList.size();
}
rankingAll.setTotalMembers(totalMembers.intValue());
GameUserJoinExample userJoinExample = new GameUserJoinExample();
userJoinExample.createCriteria().andRecordIdEqualTo(gatRanking.getRecordId());
List<GameUserJoin> userJoinList = gameUserJoinDao.selectByExample(userJoinExample);
if(CollectionUtil.isNotEmpty(userJoinList)){
rankingAll.setTotalMembers(userJoinList.size());
}else {
rankingAll.setTotalMembers(0);
int start = (gatRanking.getPageNum() - 1) * gatRanking.getPageSize();
int end = start + gatRanking.getPageSize();
List<ClientVo.MemberInfo> memberInfo = new ArrayList<>();
if (redisExist) {
Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisUtil.zsRevGetWithScore(userKey, start, end);
if (CollectionUtil.isNotEmpty(typedTuples)) {
List<ClientVo.MemberInfo> finalMemberInfo = memberInfo;
typedTuples.forEach(type -> {
ClientDto.RedisUser user = JSON.parseObject((String)type.getValue(), ClientDto.RedisUser.class);
ClientVo.MemberInfo info = new ClientVo.MemberInfo();
info.setId(user.getId());
info.setHeadImgUrl(user.getAvatarUrl());
info.setNickname(user.getNickname());
info.setScore(type.getScore().intValue());
info.setTimes(type.getScore().intValue()/100);
Long sort = redisUtil.zsReverseRank(userKey, type.getValue());
info.setSort(sort == null ? 1 : sort.intValue());
finalMemberInfo.add(info);
});
} else {
memberInfo = gameUserJoinDao.getAllRanking(gatRanking.getRecordId(), start, gatRanking.getPageSize());
}
}
PageHelper.startPage(gatRanking.getPageNum(), gatRanking.getPageSize());
List<ClientVo.MemberInfo> memberInfo = gameUserJoinDao.selectByRecordId(gatRanking.getRecordId());
List<ClientVo.Ranking> rankingAllList = gameUserJoinDao.getAllRanking(gatRanking.getRecordId());
Map<String, Integer> map = new HashMap<>();
rankingAllList.forEach(ranking -> {
map.put(String.valueOf(ranking.getUserId()), ranking.getRank());
});
memberInfo.forEach(member -> {
member.setSort(map.get(String.valueOf(member.getId())));
});
log.info("查询成员信息");
PageInfo pageInfo =new PageInfo<>(memberInfo);
rankingAll.setMemberInfoList(memberInfo);
rankingAll.setFirstPage(pageInfo.isIsFirstPage());
rankingAll.setLastPage(pageInfo.isIsLastPage());
rankingAll.setFirstPage(gatRanking.getPageNum() == 1 ? true : false);
rankingAll.setLastPage(end >= totalMembers ? true : false);
return rankingAll;
}
@ -274,13 +320,10 @@ public class ClientService implements IClientService {
if(CollectionUtil.isNotEmpty(userJoinList)){
GameUserJoin userJoin = userJoinList.get(0);
userJoin.setTimes(userJoin.getTimes() + 1);
userJoin.setScore(userJoin.getScore() + 1);
userJoin.setScore((userJoin.getScore() + 1) * 100);
gameUserJoinDao.updateByPrimaryKeySelective(userJoin);
//更新redis
ClientDto.RedisUser user = new ClientDto.RedisUser();
user.setId(userJoin.getId());
user.setAvatarurl(userJoin.getAvatarUrl());
user.setNickname(userJoin.getNickname());
ClientDto.RedisUser user = ClientDto.RedisUser.getInstance(userJoin);
redisUtil.zsSet(GameConstant.generateGameKey(Long.parseLong(recordId)), JSON.toJSONString(user), userJoin.getScore(), GameConstant.REDIS_TIME);
gameMessageCountOut = new GameMessageCountOut(userJoin.getTimes(),userJoin.getScore());
}

201
game/src/main/java/com/ccsens/game/service/ScreenService.java

@ -3,11 +3,15 @@ package com.ccsens.game.service;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.ccsens.cloudutil.feign.TallFeignClient;
import com.ccsens.game.bean.dto.ClientDto;
import com.ccsens.game.bean.dto.ScreenDto;
import com.ccsens.game.bean.dto.message.BaseMessageDto;
import com.ccsens.game.bean.dto.message.ChromeMessageDto;
import com.ccsens.game.bean.po.*;
import com.ccsens.game.bean.vo.ClientVo;
import com.ccsens.game.bean.vo.ScreenVo;
import com.ccsens.game.persist.dao.*;
import com.ccsens.game.util.GameConstant;
@ -21,7 +25,9 @@ import com.ccsens.util.exception.BaseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@ -224,56 +230,80 @@ public class ScreenService implements IScreenService{
ScreenDto.MemberRecord memberRecord = params.getParam();
ScreenVo.GameStatusVo gameStatusVo = new ScreenVo.GameStatusVo();
GameRecord gameRecord = gameRecordDao.selectByPrimaryKey(memberRecord.getMemberRecord());
if(ObjectUtil.isNull(gameRecord)){
throw new BaseException(CodeEnum.NOT_GAME_RECORD);
String gameRecordStr = (String)redisUtil.get(GameConstant.generateGameStatusKey(memberRecord.getMemberRecord()));
GameRecord gameRecord = null;
if (StrUtil.isBlank(gameRecordStr)) {
gameRecord = gameRecordDao.selectByPrimaryKey(memberRecord.getMemberRecord());
if(ObjectUtil.isNull(gameRecord)){
throw new BaseException(CodeEnum.NOT_GAME_RECORD);
}
} else {
gameRecord = JSON.parseObject(gameRecordStr, GameRecord.class);
}
GameUserJoinExample gameuserJoinExample = new GameUserJoinExample();
gameuserJoinExample.createCriteria().andRecordIdEqualTo(memberRecord.getMemberRecord());
List<GameUserJoin> userJoinList = gameUserJoinDao.selectByExample(gameuserJoinExample);
gameStatusVo.setGameStatus(gameRecord.getGameStatus());
switch (gameStatusVo.getGameStatus()){
case 0:
break;
case 1:
ScreenVo.PreparingData preparingData = new ScreenVo.PreparingData();
if(ObjectUtil.isNull(params.getUserId())){
// 无userId,默认大屏,获取大屏的游戏开始时间
preparingData.setStartLocalTime(gameRecord.getStartTime() + gameRecord.getTimeDifference());
}else {
if(CollectionUtil.isNotEmpty(userJoinList)){
for(GameUserJoin gameUserJoin : userJoinList){
if(gameUserJoin.getId().longValue() == params.getUserId().longValue()){
preparingData.setStartLocalTime(gameRecord.getStartTime() + gameUserJoin.getTimeDifference());
}
}
if(ObjectUtil.isNull(preparingData.getStartLocalTime())){
throw new BaseException(CodeEnum.NOT_JOIN_GAME);
}
}else {
throw new BaseException(CodeEnum.NOT_JOIN_GAME);
// 获取用户的开始时间
GameUserJoinExample joinExample = new GameUserJoinExample();
joinExample.createCriteria().andRecordIdEqualTo(gameRecord.getId()).andUserIdEqualTo(params.getUserId());
List<GameUserJoin> gameUserJoins = gameUserJoinDao.selectByExample(joinExample);
if (CollectionUtil.isEmpty(gameUserJoins)) {
log.info("用户{}未参加游戏{}", params.getUserId(), gameRecord.getId());
throw new BaseException(CodeEnum.PARAM_ERROR);
}
preparingData.setStartLocalTime(gameRecord.getStartTime() + gameUserJoins.get(0).getTimeDifference());
}
gameStatusVo.setPreparingData(preparingData);
break;
case 2:
// TODO
List<ScreenVo.TopUsers> tops = gameUserJoinDao.selectTopTen(gameRecord.getId());
ScreenVo.ProcessingData processingData = new ScreenVo.ProcessingData();
processingData.setTopMembers(tops);
gameStatusVo.setProcessingData(processingData);
// 查询前十名
String userKey = GameConstant.generateGameKey(gameRecord.getId());
Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisUtil.zsRevGetWithScore(userKey, 0, 10);
if (CollectionUtil.isNotEmpty(typedTuples)) {
List<ScreenVo.TopUsers> tops = new ArrayList<>();
typedTuples.forEach(type -> {
ClientDto.RedisUser user = JSON.parseObject((String) type.getValue(), ClientDto.RedisUser.class);
ScreenVo.TopUsers topUser = new ScreenVo.TopUsers();
topUser.setHeadImgUrl(user.getAvatarUrl());
topUser.setNickname(user.getNickname());
topUser.setScore(type.getScore().intValue());
topUser.setTimes(type.getScore().intValue()/100);
Long sort = redisUtil.zsReverseRank(userKey, type.getValue());
topUser.setSort(sort == null ? 1 : sort.intValue());
// TODO 微晚待续
tops.add(topUser);
processingData.setTopMembers(tops);
gameStatusVo.setProcessingData(processingData);
});
} else {
List<ScreenVo.TopUsers> tops = gameUserJoinDao.selectTopTen(gameRecord.getId());
processingData.setTopMembers(tops);
gameStatusVo.setProcessingData(processingData);
}
break;
case 3:
// List<ClientDto.RedisUser> userJoins = sendMsg.getAllScore(gameRecord);
GameUserJoinExample gameuserJoinExample = new GameUserJoinExample();
gameuserJoinExample.createCriteria().andRecordIdEqualTo(memberRecord.getMemberRecord());
List<GameUserJoin> userJoins = gameUserJoinDao.selectByExample(gameuserJoinExample);
ScreenVo.CompletedData completedData = new ScreenVo.CompletedData();
if(CollectionUtil.isNotEmpty(userJoinList)){
completedData = getCompletedData(userJoinList);
if(CollectionUtil.isNotEmpty(userJoins)){
completedData = getCompletedData(userJoins);
}
List<ScreenVo.TopUsers> top2 = gameUserJoinDao.selectTopTen(gameRecord.getId());
completedData.setMembers(top2);
gameStatusVo.setCompletedData(completedData);
break;
default:
break;
@ -376,6 +406,7 @@ public class ScreenService implements IScreenService{
}
return instructionsList;
}
/**
* 已结束时的返回值
*/
@ -407,6 +438,32 @@ public class ScreenService implements IScreenService{
}
/**
* 已结束时的返回值
*/
private ScreenVo.CompletedData getCompletedDataByRedis(List<ClientDto.RedisUser> userJoinList){
//TODO
ScreenVo.CompletedData completedData = new ScreenVo.CompletedData();
int totalTimes = 0;
int totalScore = 0;
int averageTimes = 0;
int over = 0;
if(CollectionUtil.isNotEmpty(userJoinList)){
for (ClientDto.RedisUser redisUser: userJoinList) {
totalScore += (redisUser.getScore() == null ? 0 : redisUser.getScore());
totalTimes += (redisUser.getTimes() == null ? 0 : redisUser.getTimes());
}
}
completedData.setTotalTimes(totalTimes);
completedData.setTotalScore(totalScore);
completedData.setAverageTimes(averageTimes);
completedData.setOver(over);
return completedData;
}
@Override
public ScreenVo.StartGame startGame(ScreenDto.Start start) {
@ -431,61 +488,35 @@ public class ScreenService implements IScreenService{
gameRecord.setEndTime(gameRecord.getStartTime() + GameConstant.GAME_TIME);
gameRecord.setTimeDifference((int)moreTime);
gameRecordDao.updateByPrimaryKeySelective(gameRecord);
//设置redis 游戏状态 准备中
redisUtil.set(GameConstant.generateGameStatusKey(gameRecord.getId()), JSON.toJSONString(gameRecord), GameConstant.REDIS_TIME);
//延时通知
long startSend = gameRecord.getStartTime() - System.currentTimeMillis();
long endSend = gameRecord.getEndTime() - System.currentTimeMillis();
System.out.println("开始延时:" + startSend + ",结束延时:" + endSend);
System.out.println("发送开始时间" + new Date());
log.info("发送开始时间" + new Date());
ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);
//更新开始状态
sendMsg.sendMsg(executor, startSend, () -> {
System.out.println(GameConstant.GAME_PREPARATION + "start: "+new Date());
gameRecord.setGameStatus(GameConstant.GAME_PROCESSING);
gameRecordDao.updateByPrimaryKeySelective(gameRecord);
//设置 游戏状态 进行中
gameRecord.setGameStatus(GameConstant.GAME_PROCESSING);
gameRecordDao.updateByPrimaryKeySelective(gameRecord);
redisUtil.set(GameConstant.generateGameStatusKey(gameRecord.getId()), JSON.toJSONString(gameRecord), GameConstant.REDIS_TIME);
});
//更新结束状态
sendMsg.sendMsg(executor, endSend, () -> {
System.out.println(GameConstant.GAME_COMPLETED + "end: "+new Date());
//设置 游戏状态 已结束
gameRecord.setGameStatus(GameConstant.GAME_COMPLETED);
gameRecordDao.updateByPrimaryKeySelective(gameRecord);
redisUtil.set(GameConstant.generateGameStatusKey(gameRecord.getId()), JSON.toJSONString(gameRecord), GameConstant.REDIS_TIME);
});
//更新用户游戏开始时间和结束时间
gameUserJoinDao.updateTimeBatch(gameRecord.getId(), gameRecord.getStartTime(), gameRecord.getEndTime());
//查询游戏用户,通知游戏开始和结束
GameUserJoinExample joinExample = new GameUserJoinExample();
joinExample.createCriteria().andRecordIdEqualTo(gameRecord.getId());
List<GameUserJoin> userJoins = gameUserJoinDao.selectByExample(joinExample);
if (CollectionUtil.isNotEmpty(userJoins)) {
new Thread(()->{
long startTime = gameRecord.getStartTime() - System.currentTimeMillis();
sendMsg.sendMsg(executor, startTime > 0 ? startTime : 0, ()->{
try {
sendMsg.sendStatus(gameRecord, userJoins, GameConstant.GAME_PROCESSING);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
});
long endTime = gameRecord.getEndTime() - System.currentTimeMillis();
sendMsg.sendMsg(executor, endTime > 0 ? endTime : 0, ()->{
try {
sendMsg.sendStatus(gameRecord, userJoins, GameConstant.GAME_COMPLETED);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
});
}).start();
}
List<ClientDto.RedisUser> userJoins = sendMsg.getAllScore(gameRecord);
//推送客户端
pushClient(gameRecord, executor, userJoins);
//返回大屏开始时间
ScreenVo.StartGame startGame = new ScreenVo.StartGame();
startGame.setStartLocalTime(gameRecord.getStartTime() + moreTime);
@ -493,4 +524,42 @@ public class ScreenService implements IScreenService{
}
/**
* 推送客户端状态
* @param gameRecord
* @param executor
* @param userJoins
*/
private void pushClient(GameRecord gameRecord, ScheduledExecutorService executor, List<ClientDto.RedisUser> userJoins) {
new Thread(()->{
sendMsg.sendMsg(executor, 0, ()->{
try {
sendMsg.sendStatus(gameRecord, userJoins, GameConstant.GAME_PREPARATION);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
});
long startTime = gameRecord.getStartTime() - System.currentTimeMillis();
sendMsg.sendMsg(executor, startTime > 0 ? startTime : 0, ()->{
try {
sendMsg.sendStatus(gameRecord, userJoins, GameConstant.GAME_PROCESSING);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
});
long endTime = gameRecord.getEndTime() - System.currentTimeMillis();
sendMsg.sendMsg(executor, endTime > 0 ? endTime : 0, ()->{
try {
sendMsg.sendStatus(gameRecord, userJoins, GameConstant.GAME_COMPLETED);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
});
}).start();
}
}

14
game/src/main/java/com/ccsens/game/util/GameConstant.java

@ -16,7 +16,8 @@ public class GameConstant {
/**游戏状态:已结束*/
public static final byte GAME_COMPLETED = 3;
/**游戏key*/
public static final String GAME_KEY = "_game";
public static final String GAME_SCORE_KEY = "_scores";
public static final String GAME_STATUS_KEY = "_status";
/**数据默认保存 10分钟*/
public static final long REDIS_TIME = 600 ;
/**倒计时:10s ms值*/
@ -31,7 +32,16 @@ public class GameConstant {
* @return
*/
public static String generateGameKey(Long recordId) {
return recordId + GAME_KEY;
return recordId + GAME_SCORE_KEY;
}
/**
* 游戏状态key
* @param recordId
* @return
*/
public static String generateGameStatusKey(Long recordId) {
return recordId + GAME_STATUS_KEY;
}

80
game/src/main/java/com/ccsens/game/util/SendMsg.java

@ -1,22 +1,25 @@
package com.ccsens.game.util;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.ccsens.game.bean.dto.ClientDto;
import com.ccsens.game.bean.dto.message.ChangeStatusMessageDto;
import com.ccsens.game.bean.dto.message.GameMessageWithChangeStatusOut;
import com.ccsens.game.bean.po.GameRecord;
import com.ccsens.game.bean.po.GameUserJoin;
import com.ccsens.game.persist.dao.GameUserJoinDao;
import com.ccsens.util.JacksonUtil;
import com.ccsens.util.RedisUtil;
import com.ccsens.util.config.RabbitMQConfig;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ -32,20 +35,22 @@ public class SendMsg {
private GameUserJoinDao gameUserJoinDao;
@Autowired
private AmqpTemplate rabbitTemplate;
@Autowired
private RedisUtil redisUtil;
public void sendStatus(GameRecord gameRecord, List<GameUserJoin> userJoins, byte status) throws JsonProcessingException {
public void sendStatus(GameRecord gameRecord, List<ClientDto.RedisUser> userJoins, byte status) throws JsonProcessingException {
List<GameMessageWithChangeStatusOut> outs = new ArrayList<>();
userJoins.forEach(join -> {
outs.add(getMsg(gameRecord, join, status));
});
if (CollectionUtil.isNotEmpty(outs)) {
System.out.println("==================="+outs);
log.info("==================="+outs);
rabbitTemplate.convertAndSend(RabbitMQConfig.GAME_STATUS, JacksonUtil.beanToJson(outs));
}
}
public GameMessageWithChangeStatusOut getMsg(GameRecord gameRecord, GameUserJoin join, byte gameStatus) {
public GameMessageWithChangeStatusOut getMsg(GameRecord gameRecord, ClientDto.RedisUser join, byte gameStatus) {
GameMessageWithChangeStatusOut out = new GameMessageWithChangeStatusOut();
GameMessageWithChangeStatusOut.Data data = new GameMessageWithChangeStatusOut.Data();
@ -53,24 +58,31 @@ public class SendMsg {
data.setGameStatus(gameStatus);
out.setUserId(join.getUserId());
ChangeStatusMessageDto dtos = new ChangeStatusMessageDto();
//游戏结束返回值
ChangeStatusMessageDto.CompletedData completedData = null;
if (gameStatus == GameConstant.GAME_COMPLETED) {
completedData = gameUserJoinDao.gameCount(gameRecord.getId());
completedData.setTotalTimes(completedData.getTotalScore());
if (completedData.getAverageTimes() == null) {
completedData.setOver(0);
} else {
int num = gameUserJoinDao.overNum(gameRecord.getId(), completedData.getAverageTimes());
completedData.setOver(completedData.getTotalMembers() == null || completedData.getTotalMembers().longValue() == 0 ? 100 : num / completedData.getTotalMembers() * 100);
}
dtos.setCompletedData(completedData);
} else {
ChangeStatusMessageDto.PendingData pendingData = new ChangeStatusMessageDto.PendingData();
pendingData.setStartLocalTime(join.getLocalStartTime());
pendingData.setEndLocalTime(join.getLocalEndTime());
dtos.setPendingData(pendingData);
switch (gameStatus) {
case GameConstant.GAME_COMPLETED:
ChangeStatusMessageDto.CompletedData completedData = gameUserJoinDao.gameCount(gameRecord.getId());
completedData.setTimes(join.getTimes());
completedData.setScore(join.getScore());
completedData.setSort(join.getSort());
completedData.setOver(join.getOver());
dtos.setCompletedData(completedData);
break;
case GameConstant.GAME_PREPARATION:
//preparingData
ChangeStatusMessageDto.PreparingData preparingData = new ChangeStatusMessageDto.PreparingData();
preparingData.setStartLocalTime(join.getLocalStartTime());
preparingData.setEndLocalTime(join.getLocalEndTime());
dtos.setPreparingData(preparingData);
break;
case GameConstant.GAME_PROCESSING:
ChangeStatusMessageDto.PendingData pendingData = new ChangeStatusMessageDto.PendingData();
pendingData.setStartLocalTime(join.getLocalStartTime());
pendingData.setEndLocalTime(join.getLocalEndTime());
dtos.setPendingData(pendingData);
break;
}
data.setChangeStatusMessageDto(dtos);
out.setData(data);
return out;
}
@ -85,4 +97,28 @@ public class SendMsg {
public void sendMsg(ScheduledExecutorService executor, long delayTime, Runnable runnable) {
executor.schedule(new Thread(runnable), delayTime, TimeUnit.MILLISECONDS);
}
public List<ClientDto.RedisUser> getAllScore(GameRecord gameRecord) {
String userKey = GameConstant.generateGameKey(gameRecord.getId());
Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisUtil.zsRevGetWithScore(userKey, 0, -1);
if (CollectionUtil.isNotEmpty(typedTuples)) {
List<ClientDto.RedisUser> userJoins = new ArrayList<>();
typedTuples.forEach( type -> {
ClientDto.RedisUser user = JSON.parseObject((String)type.getValue(), ClientDto.RedisUser.class);
user.setTimes(type.getScore().intValue()/100);
user.setScore(type.getScore().intValue());
Long sort = redisUtil.zsReverseRank(userKey, type.getValue());
user.setSort(sort == null ? 1 : sort.intValue());
//超过
Set<Object> overs = redisUtil.zsGet(userKey, 0, user.getScore() - 1);
Long total = redisUtil.zsGetSize(userKey);
user.setOver(overs == null || total == null || total.intValue() == 0 ? 0 : overs.size()*100/total.intValue());
userJoins.add(user);
});
return userJoins;
}
return null;
}
}

4
game/src/main/resources/application.yml

@ -1,4 +1,4 @@
spring:
profiles:
active: test
include: common, util-test
active: dev
include: common, util-dev

14
game/src/main/resources/mapper_dao/GameUserJoinDao.xml

@ -9,6 +9,12 @@
<result column="uScore" property="score"/>
</resultMap>
<update id="updateTimeBatch">
update `t_game_user_join` t
set t.local_start_time = #{startTime,jdbcType=BIGINT} + t.time_difference, t.local_end_time = #{endTime,jdbcType=BIGINT} + t.time_difference
where t.record_id = #{recordId,jdbcType=BIGINT}
</update>
<select id="selectTopTen" resultType="com.ccsens.game.bean.vo.ScreenVo$TopUsers">
select user_id, avatar_url as headImgUrl, nickname, score, score as times
from t_game_user_join
@ -49,11 +55,11 @@ WHERE c.user_id= #{userId,jdbcType=BIGINT} limit 1
<select id="overNum" resultType="Integer">
select count(*) from t_game_user_join where record_id = #{recordId,jdbcType=BIGINT} and score &lt; #{score,jdbcType=INTEGER}
</select>
<select id="getAllRanking" resultType="com.ccsens.game.bean.vo.ClientVo$Ranking">
SELECT user_id as userId,(@rowNum:=@rowNum+1) AS rank
<select id="getAllRanking" resultType="com.ccsens.game.bean.vo.ClientVo$MemberInfo">
SELECT a.*,(@rowNum:=@rowNum+1) AS sort
FROM
(select user_id,score from t_game_user_join where rec_status = 0 and record_id = #{recordId,jdbcType=BIGINT}) a,
(select id,score, avatar_url as headImgUrl,nickname, times from t_game_user_join where rec_status = 0 and record_id = #{recordId,jdbcType=BIGINT}) a,
(SELECT(@rowNum:=0)) b
ORDER BY a.score DESC
ORDER BY a.score DESC limit #{start}, #{pageSize}
</select>
</mapper>

83
util/src/main/java/com/ccsens/util/RedisUtil.java

@ -2,6 +2,7 @@ package com.ccsens.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@ -110,7 +111,7 @@ public class RedisUtil {
*
* @param key
* @param value
* @param time 时间() time要大于0 如果time小于等于0 将设置无限期
* @param seconds 时间() time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long seconds) {
@ -559,7 +560,7 @@ public class RedisUtil {
return 0;
}
}
//===============================zset=================================
/**
* 获取sort set缓存的内容
* @author whj
@ -573,6 +574,45 @@ public class RedisUtil {
return redisTemplate.opsForZSet().range(key, start, end);
}
/**
* 获取sort set缓存的内容(包含分数)
* @author whj
* @date 2019/8/1
* @param key
* @param start 开始 0:第一个元素
* @param end 结束 -1代表所有
* @return java.util.Set<ZSetOperations.TypedTuple<Object>>
*/
public Set<ZSetOperations.TypedTuple<Object>> zsGetWithScore(String key, long start, long end) {
return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
}
/**
* 分数由高到低 获取sort set缓存的内容
* @author whj
* @date 2019/8/1
* @param key
* @param start 开始 0:第一个元素
* @param end 结束 -1代表所有
* @return java.util.Set<java.lang.Object>
*/
public Set<Object> zsRevGet(String key, long start, long end) {
return redisTemplate.opsForZSet().reverseRange(key, start, end);
}
/**
* 分数由高到低 获取sort set缓存的内容(包含分数)
* @author whj
* @date 2019/8/1
* @param key
* @param start 开始 0:第一个元素
* @param end 结束 -1代表所有
* @return java.util.Set<ZSetOperations.TypedTuple<Object>>
*/
public Set<ZSetOperations.TypedTuple<Object>> zsRevGetWithScore(String key, long start, long end) {
return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
}
/**
* 添加zset
* @author whj
@ -599,10 +639,7 @@ public class RedisUtil {
redisTemplate.opsForZSet().add(key, value, score);
if (time > 0) {
expire(key, time);
} else {
zsDel(key, value);
}
return true;
}
@ -613,16 +650,48 @@ public class RedisUtil {
* @param key
* @return
*/
public long zsGetSize(String key) {
public Long zsGetSize(String key) {
return redisTemplate.opsForZSet().size(key);
}
public long zsDel(String key, Object... values) {
/**
* 删除元素
* @param key
* @param values
* @return
*/
public Long zsDel(String key, Object... values) {
return redisTemplate.opsForZSet().remove(key, values);
}
/**
* 获取对应分数
* @param key
* @param value
* @return
*/
public Object zsGetScore(String key, Object value) {
return redisTemplate.opsForZSet().score(key, value);
}
/**
* 查询排第几
* @param key
* @param value
* @return
*/
public Long zsRank(String key, Object value) {
return redisTemplate.opsForZSet().rank(key, value);
}
/**
* 查询倒叙排第几
* @param key
* @param value
* @return
*/
public Long zsReverseRank(String key, Object value) {
return redisTemplate.opsForZSet().reverseRank(key, value);
}
}

Loading…
Cancel
Save