commit e7bab0d002fd9a00c6774b69b4931beaf2d2eb72 Author: JiahengHe <1746647790@qq.com> Date: Thu Mar 20 22:05:58 2025 +0800 项目上传 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6995735 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.idea +admin/target +basics/target +challenge/target +common/target +logs +mainland/target diff --git a/admin/pom.xml b/admin/pom.xml new file mode 100644 index 0000000..1b45f04 --- /dev/null +++ b/admin/pom.xml @@ -0,0 +1,150 @@ + + + + mine_clearance + com.lightyears.mine_clearance + 1.0 + + 4.0.0 + admin + admin + + + 8 + 8 + UTF-8 + + + + org.springframework.boot + spring-boot-starter-web + + + com.baomidou + mybatis-plus-boot-starter + + + org.springframework.boot + spring-boot-starter-aop + + + mysql + mysql-connector-java + + + + com.alibaba + druid-spring-boot-starter + + + + com.alibaba + fastjson + + + com.baomidou + mybatis-plus-generator + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + org.apache.commons + commons-pool2 + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.freemarker + freemarker + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + + cn.hutool + hutool-all + + + commons-io + commons-io + + + org.apache.commons + commons-collections4 + + + com.lightyears.mine_clearance + common + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.springframework.boot + spring-boot-starter-test + test + + + + admin + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + utf-8 + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.lightyears.admin.AdminApp + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + \ No newline at end of file diff --git a/admin/src/main/java/com/lightyears/admin/AdminApp.java b/admin/src/main/java/com/lightyears/admin/AdminApp.java new file mode 100644 index 0000000..460af0e --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/AdminApp.java @@ -0,0 +1,19 @@ +package com.lightyears.admin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.util.TimeZone; + +@EnableScheduling +@SpringBootApplication +@EnableTransactionManagement +public class AdminApp { + public static void main(String[] args) { + // 设置时区 + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + SpringApplication.run(AdminApp.class, args); + } +} diff --git a/admin/src/main/java/com/lightyears/admin/configuration/RedisConfig.java b/admin/src/main/java/com/lightyears/admin/configuration/RedisConfig.java new file mode 100644 index 0000000..3cf72c0 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/configuration/RedisConfig.java @@ -0,0 +1,86 @@ +package com.lightyears.admin.configuration; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +// 开启redis缓存功能 +@EnableCaching +// 备注这是一个配置类 +@Configuration +public class RedisConfig extends CachingConfigurerSupport { + + /** + * 配置redis模板文件 + * @param redisConnectionFactory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisSerializer serializer = redisSerializer(); + // 创建RedisTemplate对象 + RedisTemplate redisTemplate = new RedisTemplate<>(); + // 配置连接工厂 + redisTemplate.setConnectionFactory(redisConnectionFactory); + // redis key 序列化方式使用stringSerial + redisTemplate.setKeySerializer(new StringRedisSerializer()); + // redis value 序列化方式使用jackson + redisTemplate.setValueSerializer(serializer); + // redis hash key 序列化方式使用stringSerial + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + // redis hash value 序列化方式使用jackson + redisTemplate.setHashValueSerializer(serializer); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + /** + * 配置序列化 + * @return + */ + @Bean + public RedisSerializer redisSerializer() { + // 定义Jackson2JsonRedisSerializer序列化对象 + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会报异常 + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + serializer.setObjectMapper(objectMapper); + return serializer; + } + + /** + * 自定义缓存管理器 + * @param redisConnectionFactory + * @return + */ + @Bean + public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) { + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory); + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration + .defaultCacheConfig() + // 设置value 为自动转json的Object + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())) + // 缓存有效期为一天 + .entryTtl(Duration.ofDays(1)); + return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); + } + +} diff --git a/admin/src/main/java/com/lightyears/admin/configuration/ScheduledConfig.java b/admin/src/main/java/com/lightyears/admin/configuration/ScheduledConfig.java new file mode 100644 index 0000000..3a291f4 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/configuration/ScheduledConfig.java @@ -0,0 +1,24 @@ +package com.lightyears.admin.configuration; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +import java.util.TimeZone; + +@Configuration +public class ScheduledConfig { + @Bean + public ThreadPoolTaskScheduler threadPoolTaskScheduler() { + ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); + threadPoolTaskScheduler.setPoolSize(3); + threadPoolTaskScheduler.setRemoveOnCancelPolicy(true); + return threadPoolTaskScheduler; + } + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() { + return jacksonObjectMapperBuilder -> + jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8")); + } +} \ No newline at end of file diff --git a/admin/src/main/java/com/lightyears/admin/controller/BaseController.java b/admin/src/main/java/com/lightyears/admin/controller/BaseController.java new file mode 100644 index 0000000..391336f --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/controller/BaseController.java @@ -0,0 +1,54 @@ +package com.lightyears.admin.controller; + +import com.lightyears.admin.util.RedisCache; +import com.lightyears.admin.util.StaticUtil; +import com.lightyears.common.domain.entity.Player; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class BaseController { + + @Autowired + private RedisCache redisCache; + + /** + * 得到request对象 + * + * @return + */ + public HttpServletRequest getRequest() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getRequest(); + return request; + } + + /** + * 得到respones对象 + * @return + */ + public HttpServletResponse getResponse() { + HttpServletResponse request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getResponse(); + return request; + } + + /** + * 得到当前登录用户信息 + * + * @return + */ + public String getUserInfo() { + // 获取请求头中的token数据 + String token = getRequest().getHeader("Tracecode"); + if(token == null) { + token = this.getRequest().getParameter("Tracecode"); + } + String key = StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY.concat(token); + + return redisCache.getCacheObject(key).toString(); + } +} diff --git a/admin/src/main/java/com/lightyears/admin/controller/SystemController.java b/admin/src/main/java/com/lightyears/admin/controller/SystemController.java new file mode 100644 index 0000000..3e55751 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/controller/SystemController.java @@ -0,0 +1,178 @@ +package com.lightyears.admin.controller; + +import com.lightyears.admin.dto.*; +import com.lightyears.admin.service.IClearanceLogService; +import com.lightyears.admin.service.ILogService; +import com.lightyears.admin.service.ISystemService; +import com.lightyears.admin.util.ResultUtil; +import com.lightyears.common.domain.dto.Params; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.common.domain.entity.Notice; +import com.lightyears.common.domain.enums.MessageEnum; +import io.swagger.annotations.Api; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/sys") +@Api("扫雷 管理端调用接口:") +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class SystemController extends BaseController { + private final ISystemService systemService; + private final ILogService logService; + private final IClearanceLogService clearanceLogService; + + /** + * 管理端登录 v + * @return + */ + @RequestMapping(value = "/login", method = RequestMethod.POST) + public ResModeBase login(@RequestBody UserLoginParams params) { + return systemService.login(params.getUserName(), params.getPassword()); + } + + /** + * 获取登录信息 v + * @return + */ + @PostMapping("/getInfo") + public ResModeBase getInfo(){ + return ResultUtil.success(this.getUserInfo()); + } + + /** + * 用户列表 v + * @param params + * @return + */ + @PostMapping("/queryUserList") + public ResModeBase queryUserList(@RequestBody Params params){ + return systemService.userList(params); + } + + /** + * 设置用户启用禁用 v + * @param params + * @return + */ + @PostMapping("/setPlayerStatus") + public ResModeBase setPlayerStatus(@RequestBody UserStatusParams params){ + systemService.updateUserStatus(params); + return ResultUtil.success(); + } + + /** + * 发布公告 v + * @param notice + * @return + */ + @RequestMapping(value = "/publishNotice", method = RequestMethod.POST) + public ResModeBase publishNotice(@RequestBody Notice notice) { + systemService.publishNotice(notice); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } + + /** + * 刷新排行榜和雷塔缓存 v + * @return + */ + @RequestMapping(value = "/refreshRankCache", method = RequestMethod.GET) + public ResModeBase refreshRankCache() { + // 排行榜缓存 + logService.cacheRankList(null); + // 雷神之塔缓存 + clearanceLogService.cachePlayerClearanceRank(); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } + + /** + * 删除玩家 v + * @return + */ + @RequestMapping(value = "/cancellationAccount", method = RequestMethod.POST) + public ResModeBase cancellationAccount(@RequestParam(value = "playerId") Integer playerId) { + systemService.cancellationAccount(playerId); + return ResultUtil.success(); + } + + /** + * 删除玩家排行榜数据 v + * @return + */ + @RequestMapping(value = "/deleteCacheByRankUserId", method = RequestMethod.POST) + public ResModeBase deleteCacheByRankUserId(@RequestBody DeletePlayerRankParams params) { + systemService.deleteCacheByRankUserId(params.getLevel(), params.getPlayerId()); + return ResultUtil.success(); + } + + /** + * 加/减用户资产 v + * @param params + * @return + */ + @RequestMapping(value = "/setPlayerAssets", method = RequestMethod.POST) + public ResModeBase setPlayerAssets(@RequestBody PlayerAssetsParams params) { + systemService.setPlayerAssets(params); + return ResultUtil.success(); + } + + /** + * 查询挑战榜模板列表 + * @param params + * @return + */ + @RequestMapping(value = "/challengeBaseList", method = RequestMethod.POST) + public ResModeBase challengeBaseList(@RequestBody Params params) { + return systemService.challengeBaseList(params); + } + + /** + * 添加挑战模板 + * @param params + * @return + */ + @RequestMapping(value = "/addBase", method = RequestMethod.POST) + public ResModeBase addBase(@RequestBody ListBase params) { + return systemService.addBase(params); + } + + /** + * 删除模板 + * @param id 模板id + * @return + */ + @RequestMapping(value = "/deleteBase", method = RequestMethod.GET) + public ResModeBase deleteBase(@RequestParam("id") Integer id) { + return systemService.deleteBase(id); + } + + /** + * 获取实例list + * @return + */ + @RequestMapping(value = "/challengeInstanceList", method = RequestMethod.POST) + public ResModeBase challengeInstanceList() { + return systemService.challengeInstanceList(); + } + + /** + * 清空指定挑战榜排名的玩家数据 + * @return + */ + @RequestMapping(value = "/removeChallengeRankInfo", method = RequestMethod.POST) + public ResModeBase removeChallengeRankInfo(@RequestBody RemoveChallengeRankParams params) { + systemService.removeChallengeRankInfo(params.getInstanceId(), params.getRankNum()); + return ResultUtil.success(); + } + + /** + * 登出 v + * @return + */ + @GetMapping("/logout") + public ResModeBase logout(){ + return systemService.logout(); + } +} diff --git a/admin/src/main/java/com/lightyears/admin/dto/DeletePlayerRankParams.java b/admin/src/main/java/com/lightyears/admin/dto/DeletePlayerRankParams.java new file mode 100644 index 0000000..893dfb2 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/dto/DeletePlayerRankParams.java @@ -0,0 +1,11 @@ +package com.lightyears.admin.dto; + +import lombok.Data; + +@Data +public class DeletePlayerRankParams { + // 用户id + private Integer playerId; + // 游戏难度:1 - 普通 2 困难 3 大师 4 超凡 + private Integer level; +} diff --git a/admin/src/main/java/com/lightyears/admin/dto/ListBaseListParams.java b/admin/src/main/java/com/lightyears/admin/dto/ListBaseListParams.java new file mode 100644 index 0000000..62600c5 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/dto/ListBaseListParams.java @@ -0,0 +1,9 @@ +package com.lightyears.admin.dto; + +import lombok.Data; + +@Data +public class ListBaseListParams { + // 关键字 + private String keyword; +} diff --git a/admin/src/main/java/com/lightyears/admin/dto/PlayerAssetsParams.java b/admin/src/main/java/com/lightyears/admin/dto/PlayerAssetsParams.java new file mode 100644 index 0000000..a7529af --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/dto/PlayerAssetsParams.java @@ -0,0 +1,15 @@ +package com.lightyears.admin.dto; + +import lombok.Data; + +@Data +public class PlayerAssetsParams { + // 用户id + private Integer userId; + // 操作数量 + private Integer gold; + // 资产类型 + private Integer type; + // 备注 + private String remark; +} diff --git a/admin/src/main/java/com/lightyears/admin/dto/RemoveChallengeRankParams.java b/admin/src/main/java/com/lightyears/admin/dto/RemoveChallengeRankParams.java new file mode 100644 index 0000000..9880457 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/dto/RemoveChallengeRankParams.java @@ -0,0 +1,11 @@ +package com.lightyears.admin.dto; + +import lombok.Data; + +@Data +public class RemoveChallengeRankParams { + // 实例榜单id + private Integer instanceId; + // 排名 + private Integer rankNum; +} diff --git a/admin/src/main/java/com/lightyears/admin/dto/UserListParams.java b/admin/src/main/java/com/lightyears/admin/dto/UserListParams.java new file mode 100644 index 0000000..bd4c57e --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/dto/UserListParams.java @@ -0,0 +1,9 @@ +package com.lightyears.admin.dto; + +import lombok.Data; + +@Data +public class UserListParams { + // 关键字 + private String keyword; +} diff --git a/admin/src/main/java/com/lightyears/admin/dto/UserLoginParams.java b/admin/src/main/java/com/lightyears/admin/dto/UserLoginParams.java new file mode 100644 index 0000000..7552457 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/dto/UserLoginParams.java @@ -0,0 +1,9 @@ +package com.lightyears.admin.dto; + +import lombok.Data; + +@Data +public class UserLoginParams { + private String userName; + private String password; +} diff --git a/admin/src/main/java/com/lightyears/admin/dto/UserStatusParams.java b/admin/src/main/java/com/lightyears/admin/dto/UserStatusParams.java new file mode 100644 index 0000000..3fe9eb4 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/dto/UserStatusParams.java @@ -0,0 +1,11 @@ +package com.lightyears.admin.dto; + +import lombok.Data; + +@Data +public class UserStatusParams { + // 玩家id + private Integer playerId; + // 状态(1.启用 0.禁用) + private Integer status; +} diff --git a/admin/src/main/java/com/lightyears/admin/exception/BussinessException.java b/admin/src/main/java/com/lightyears/admin/exception/BussinessException.java new file mode 100644 index 0000000..8f9d03b --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/exception/BussinessException.java @@ -0,0 +1,18 @@ +package com.lightyears.admin.exception; + + +import com.lightyears.common.domain.enums.MessageEnum; + +/** + * @author fengshuonan + * @Description 业务异常的封装 + */ +public class BussinessException extends GlobalException { + public BussinessException(MessageEnum messageEnum) { + super(messageEnum.getCode(), messageEnum.getMessage()); + } + + public BussinessException(Integer code, String message) { + super(code, message); + } +} diff --git a/admin/src/main/java/com/lightyears/admin/exception/GlobalException.java b/admin/src/main/java/com/lightyears/admin/exception/GlobalException.java new file mode 100644 index 0000000..6af0876 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/exception/GlobalException.java @@ -0,0 +1,46 @@ +package com.lightyears.admin.exception; + +import com.lightyears.common.domain.enums.MessageEnum; + +/*** + * 全局异常捕捉 统一返回 model + * */ +public class GlobalException extends RuntimeException { + + //友好提示的code码 + protected int friendlyCode; + + //友好提示 + protected String friendlyMsg; + + + protected GlobalException(int friendlyCode, String friendlyMsg) { + this.setValues(friendlyCode, friendlyMsg); + } + + public GlobalException(MessageEnum messageEnum) { + this.setValues(messageEnum.getCode(), messageEnum.getMessage()); + } + + private void setValues(int friendlyCode, String friendlyMsg) { + this.friendlyCode = friendlyCode; + this.friendlyMsg = friendlyMsg; + } + + public int getCode() { + return friendlyCode; + } + + public void setCode(int code) { + this.friendlyCode = code; + } + + public String getMessage() { + return friendlyMsg; + } + + public void setMessage(String message) { + this.friendlyMsg = message; + } + +} diff --git a/admin/src/main/java/com/lightyears/admin/exception/MyExceptionHandle.java b/admin/src/main/java/com/lightyears/admin/exception/MyExceptionHandle.java new file mode 100644 index 0000000..0e7d492 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/exception/MyExceptionHandle.java @@ -0,0 +1,26 @@ +package com.lightyears.admin.exception; + +import com.lightyears.admin.util.ResultUtil; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +@Slf4j +@ControllerAdvice +public class MyExceptionHandle { + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public ResModeBase handle(Exception e) { + if (e instanceof GlobalException) { + GlobalException myException = (GlobalException) e; + return ResultUtil.result(myException.getCode(), myException.getMessage()); + } else { + log.error("系统异常", e); + return ResultUtil.result(MessageEnum.UNKNOWN_ERROR.getCode(), MessageEnum.UNKNOWN_ERROR.getMessage()); + } + } +} diff --git a/admin/src/main/java/com/lightyears/admin/filter/TokenFilter.java b/admin/src/main/java/com/lightyears/admin/filter/TokenFilter.java new file mode 100644 index 0000000..c15bfa7 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/filter/TokenFilter.java @@ -0,0 +1,84 @@ +package com.lightyears.admin.filter; + +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.util.StringUtil; +import com.lightyears.admin.util.RedisCache; +import com.lightyears.admin.util.StaticUtil; +import com.lightyears.common.domain.entity.Player; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.annotation.Resource; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Component +public class TokenFilter implements Filter{ + @Resource + private RedisCache redisCache; + + @Override + public void init(FilterConfig filterConfig) { + ServletContext servletContext = filterConfig.getServletContext(); + ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); + redisCache = (RedisCache) ctx.getBean("redisCache"); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + + String tracecode = request.getHeader("Tracecode"); + Boolean flag = request.getRequestURI().indexOf("/login")<0; + + // 登录放行 + if(flag){ + // 判断身份码, 是否已登录 + if((StringUtil.isEmpty(tracecode) || !redisCache.hasKey(StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY.concat(tracecode)))){ + /** + * 不是登录 || 身份码不存在 || 未在登录列表 就拒绝访问 + */ + this.authcReq(response, MessageEnum.SYSTEM_ERROR.getCode(), MessageEnum.SYSTEM_ERROR.getMessage()); + return; + } + // 重置身份认证过期时间 + redisCache.expire(StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY.concat(tracecode), 1, TimeUnit.HOURS); + } + + //执行 + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + + } + + /** + * 响应访问 + * @param response + * @throws IOException + */ + private void authcReq(HttpServletResponse response, Integer code, String msg) throws IOException { +// response.setHeader("Access-Control-Allow-Origin", "*"); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentType("application/json; charset=utf-8"); + PrintWriter writer = response.getWriter(); + Map map = new HashMap<>(); + map.put("code", code); + map.put("msg", msg); + writer.print(JSONObject.toJSON(map)); + } + +} diff --git a/admin/src/main/java/com/lightyears/admin/init/AdminInit.java b/admin/src/main/java/com/lightyears/admin/init/AdminInit.java new file mode 100644 index 0000000..388ddf7 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/init/AdminInit.java @@ -0,0 +1,32 @@ +package com.lightyears.admin.init; + +import com.lightyears.admin.util.RedisCache; +import com.lightyears.admin.util.StaticUtil; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.annotation.Resource; + +; + +/** + * 挑战数据初始化 + */ +@Component +public class AdminInit { + @Resource + private RedisCache redisCache; + + @PostConstruct + public void init() { + // 管理端密码 + redisCache.setCacheObject(StaticUtil.ADMIN_PASSWORD, "admin1476346288ALsk"); + } + + @PreDestroy + public void destroy() { + // 写入持久层 + } + +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/AssertLogMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/AssertLogMapper.java new file mode 100644 index 0000000..cc146f4 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/AssertLogMapper.java @@ -0,0 +1,18 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.AssertLog; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface AssertLogMapper extends BaseMapper { + +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/ClearanceLogMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/ClearanceLogMapper.java new file mode 100644 index 0000000..686cdb4 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/ClearanceLogMapper.java @@ -0,0 +1,26 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.ClearanceRankDto; +import com.lightyears.common.domain.entity.ClearanceLog; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-06-02 + */ +@Mapper +public interface ClearanceLogMapper extends BaseMapper { + /** + * 获取玩家最高闯关 关卡数据 + * @return + */ + List getPlayerClearanceLogs(@Param("userId")Integer userId); +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/ListBaseMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/ListBaseMapper.java new file mode 100644 index 0000000..2183db4 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/ListBaseMapper.java @@ -0,0 +1,17 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.ListBase; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface ListBaseMapper extends BaseMapper { +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/ListInstanceMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/ListInstanceMapper.java new file mode 100644 index 0000000..5cbbca1 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/ListInstanceMapper.java @@ -0,0 +1,39 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.ListInstanceDto; +import com.lightyears.common.domain.entity.ListInstance; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface ListInstanceMapper extends BaseMapper { + + /** + * 奖池增加 + * @param instanceId 榜实例id + * @param awardSize 奖池要增加的数 + * @param assetsType 货币类型 + * @return + */ + int updateInstanceAwardSize(@Param("instanceId") Integer instanceId,@Param("awardSize") Integer awardSize,@Param("assetsType") Integer assetsType); + + /** + * 获取榜单列表 + * + * @return + */ + List getListInstances(); +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/ListRankMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/ListRankMapper.java new file mode 100644 index 0000000..12a4f1e --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/ListRankMapper.java @@ -0,0 +1,25 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.entity.ListRank; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface ListRankMapper extends BaseMapper { + int initRank(@Param("instanceId") Integer instanceId, @Param("rankNum") Integer rankNum); + List getRankList(@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId, @Param("state") Integer state); + List getNewRankList (@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId); + ListRankDto getRankByInsRank(@Param("instanceId") Integer instanceId,@Param("rank") Integer rank); +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/LogMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/LogMapper.java new file mode 100644 index 0000000..e33d46b --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/LogMapper.java @@ -0,0 +1,29 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.entity.Log; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface LogMapper extends BaseMapper { + List paging(@Param("level") Integer level, @Param("userId")Integer userId); + //综合查询 三种难度加起来 获取排名 + List syntheticalPaging(); + // 查询用户综合排名 + Map getComprehensiveRankByUserId(@Param("userId") Integer userId); + //根据User_id和 level 查询排名 + Map getRankByLevelUserId(@Param("level")int level, @Param("userId") Integer userId); +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/NoticeMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/NoticeMapper.java new file mode 100644 index 0000000..b956e62 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/NoticeMapper.java @@ -0,0 +1,23 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.NoticeDto; +import com.lightyears.common.domain.entity.Notice; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +@Mapper +public interface NoticeMapper extends BaseMapper { + List getList(@Param("type") Integer type, @Param("playerId") Integer playerId); + String getContent(@Param("id")Integer id); +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/PlayerAssetsMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/PlayerAssetsMapper.java new file mode 100644 index 0000000..5d83fb9 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/PlayerAssetsMapper.java @@ -0,0 +1,33 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface PlayerAssetsMapper extends BaseMapper { + // 货币存放服务器 + int addGold(@Param("id") int id, @Param("gold") int gold, @Param("version") Long version); + + // 从服务器取出货币 + int reduceGold(@Param("id") int id,@Param("gold") int gold, @Param("version") Long version); + + /** + * 获取用户资产 + * @param playerId + * @return + */ + List getPlayerAssets(@Param("playerId") int playerId); +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/PlayerMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/PlayerMapper.java new file mode 100644 index 0000000..f00bd00 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/PlayerMapper.java @@ -0,0 +1,26 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.admin.dto.UserListParams; +import com.lightyears.common.domain.entity.Player; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + *

+ * 扫雷玩家表 Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface PlayerMapper extends BaseMapper { + /** + * 玩家列表 + * @param params + * @return + */ + List getPlayerList(UserListParams params); +} diff --git a/admin/src/main/java/com/lightyears/admin/mapper/RecordMapper.java b/admin/src/main/java/com/lightyears/admin/mapper/RecordMapper.java new file mode 100644 index 0000000..783db8c --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/mapper/RecordMapper.java @@ -0,0 +1,18 @@ +package com.lightyears.admin.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.Record; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 游戏存档 Mapper 接口 + *

x + * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface RecordMapper extends BaseMapper { + +} diff --git a/admin/src/main/java/com/lightyears/admin/service/IClearanceLogService.java b/admin/src/main/java/com/lightyears/admin/service/IClearanceLogService.java new file mode 100644 index 0000000..96c8e1f --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/IClearanceLogService.java @@ -0,0 +1,26 @@ +package com.lightyears.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.PlayerClearanceLogInfoDto; +import com.lightyears.common.domain.entity.ClearanceLog; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-06-02 + */ +public interface IClearanceLogService extends IService { + + /** + * 缓存用户闯关记录 + */ + void cachePlayerClearanceRank(); + + /** + * 删除用户闯关记录缓存 + */ + void deletCacheByPlayerId(Integer playerId); +} diff --git a/admin/src/main/java/com/lightyears/admin/service/IGameSystemService.java b/admin/src/main/java/com/lightyears/admin/service/IGameSystemService.java new file mode 100644 index 0000000..5120080 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/IGameSystemService.java @@ -0,0 +1,16 @@ +package com.lightyears.admin.service; + +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Player; + +public interface IGameSystemService { + + ResModeBase pushGoldImpl(Integer userId, int gold, int type, String remark); + + ResModeBase pushGold(Integer userId, int gold, int type, String remark); + + ResModeBase pullGoldImpl(Integer userId, int gold, int type, String remark); + + ResModeBase pullGold(Integer userId, int gold, int type, String remark); + +} diff --git a/admin/src/main/java/com/lightyears/admin/service/ILogService.java b/admin/src/main/java/com/lightyears/admin/service/ILogService.java new file mode 100644 index 0000000..567e293 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/ILogService.java @@ -0,0 +1,42 @@ +package com.lightyears.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.entity.Log; + +import java.util.List; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface ILogService extends IService { + /** + * 查询排行榜 + * @param level 游戏难度:1 - 普通 2 困难 3 大师 + * @return + */ + List getRankList(Integer level); + + /** + * 排行榜数据写入缓存 + */ + void cacheRankList(Integer level); + + /** + * 删除缓存 + * @param userId + */ + void deleteCacheByUserId(Integer userId); + + /** + * 删除用户指定排行榜数据 + * @param level + * @param userId + */ + void deleteCacheByRankUserId(Integer level, Integer userId); +} diff --git a/admin/src/main/java/com/lightyears/admin/service/INoticeService.java b/admin/src/main/java/com/lightyears/admin/service/INoticeService.java new file mode 100644 index 0000000..cdc9f1b --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/INoticeService.java @@ -0,0 +1,20 @@ +package com.lightyears.admin.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Notice; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +public interface INoticeService extends IService { + ResModeBase getList(Integer playerId); + ResModeBase getContent(Integer id); + void deleteNoticeForTask(); +} diff --git a/admin/src/main/java/com/lightyears/admin/service/IPlayerAssetsService.java b/admin/src/main/java/com/lightyears/admin/service/IPlayerAssetsService.java new file mode 100644 index 0000000..1346a34 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/IPlayerAssetsService.java @@ -0,0 +1,38 @@ +package com.lightyears.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +public interface IPlayerAssetsService extends IService { + /** + * 添加金币 + * @param id id + * @param gold 增加后的金币 + */ + Integer addGold(int id, int gold); + + /** + * 扣除金币 + * @param id id + * @param gold 需要扣减的金币 + */ + Integer reduceGold(int id, int gold); + + /** + * 获取指定用户的资产 + * @param playerId 用户id + * @return + */ + List getPlayerAssets(int playerId); +} diff --git a/admin/src/main/java/com/lightyears/admin/service/IPlayerService.java b/admin/src/main/java/com/lightyears/admin/service/IPlayerService.java new file mode 100644 index 0000000..710af06 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/IPlayerService.java @@ -0,0 +1,15 @@ +package com.lightyears.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.Player; + +/** + *

+ * 扫雷玩家表 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface IPlayerService extends IService { +} diff --git a/admin/src/main/java/com/lightyears/admin/service/IRecordService.java b/admin/src/main/java/com/lightyears/admin/service/IRecordService.java new file mode 100644 index 0000000..2840b07 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/IRecordService.java @@ -0,0 +1,16 @@ +package com.lightyears.admin.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.Record; + +/** + *

+ * 游戏存档 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface IRecordService extends IService { + +} diff --git a/admin/src/main/java/com/lightyears/admin/service/ISystemService.java b/admin/src/main/java/com/lightyears/admin/service/ISystemService.java new file mode 100644 index 0000000..3caf031 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/ISystemService.java @@ -0,0 +1,98 @@ +package com.lightyears.admin.service; + +import com.lightyears.admin.dto.ListBaseListParams; +import com.lightyears.admin.dto.PlayerAssetsParams; +import com.lightyears.admin.dto.UserListParams; +import com.lightyears.admin.dto.UserStatusParams; +import com.lightyears.common.domain.dto.Params; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.common.domain.entity.Notice; + +public interface ISystemService { + /** + * 管理端登录 + * @param userName + * @param password + * @return + */ + ResModeBase login(String userName, String password); + + /** + * 注销登录 + * @return + */ + ResModeBase logout(); + + /** + * 用户列表 + * @param params + * @return + */ + ResModeBase userList(Params params); + /** + * 发布公告 + * @param notice + * @return + */ + void publishNotice(Notice notice); + + /** + * 删除玩家 + * @param userId 玩家id + */ + void cancellationAccount(Integer userId); + + /** + * 删除玩家排行数据 + * @param level + * @param userId + */ + void deleteCacheByRankUserId(Integer level, Integer userId); + + /** + * 修改用户状态 + * @param params + */ + void updateUserStatus(UserStatusParams params); + + /** + * 加/减用户资产 + * @param params + */ + void setPlayerAssets(PlayerAssetsParams params); + + /** + * 查询挑战榜模板列表 + * @param params + * @return + */ + ResModeBase challengeBaseList(Params params); + + /** + * 添加挑战模板 + * @param base + * @return + */ + ResModeBase addBase(ListBase base); + + /** + * 删除未实例化的模板 + * @param id 模板id + * @return + */ + ResModeBase deleteBase(Integer id); + + /** + * 获取实例list + * @return + */ + ResModeBase challengeInstanceList(); + + /** + * 清空指定挑战榜排名的玩家数据 + * @param instanceId 实例榜单id + * @param rankNum 排名 + */ + void removeChallengeRankInfo(Integer instanceId, Integer rankNum); +} diff --git a/admin/src/main/java/com/lightyears/admin/service/impl/ClearanceLogServiceImpl.java b/admin/src/main/java/com/lightyears/admin/service/impl/ClearanceLogServiceImpl.java new file mode 100644 index 0000000..666aa5c --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/impl/ClearanceLogServiceImpl.java @@ -0,0 +1,60 @@ +package com.lightyears.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.admin.exception.BussinessException; +import com.lightyears.admin.mapper.ClearanceLogMapper; +import com.lightyears.admin.service.IClearanceLogService; +import com.lightyears.admin.util.RedisCache; +import com.lightyears.admin.util.StaticUtil; +import com.lightyears.common.domain.dto.ClearanceRankDto; +import com.lightyears.common.domain.dto.PlayerClearanceLogInfoDto; +import com.lightyears.common.domain.entity.ClearanceLog; +import com.lightyears.common.domain.enums.MessageEnum; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-06-02 + */ +@Service +public class ClearanceLogServiceImpl extends ServiceImpl implements IClearanceLogService { + + @Resource + private RedisCache redisCache; + + @Override + public void cachePlayerClearanceRank(){ + List logs = this.getClearanceLogs(); + String key = StaticUtil.CLEARANCE_RANK_LIST; + BoundZSetOperations operations = redisCache.getRedisTemplate().boundZSetOps(key); + redisCache.deleteByPrefix(key); + for (ClearanceRankDto log: logs){ + operations.add(log.getPlayerId(), log.getLayersNum()); + } + } + + @Override + public void deletCacheByPlayerId(Integer playerId){ + String key = StaticUtil.CLEARANCE_RANK_LIST; + BoundZSetOperations operations = redisCache.getRedisTemplate().boundZSetOps(key); + operations.remove(playerId); + } + + public List getClearanceLogs(){ + List logs = baseMapper.getPlayerClearanceLogs(null); + return logs; + } + +} diff --git a/admin/src/main/java/com/lightyears/admin/service/impl/GameSystemServiceImpl.java b/admin/src/main/java/com/lightyears/admin/service/impl/GameSystemServiceImpl.java new file mode 100644 index 0000000..ea3a44b --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/impl/GameSystemServiceImpl.java @@ -0,0 +1,107 @@ +package com.lightyears.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.github.pagehelper.Page; +import com.github.pagehelper.PageInfo; +import com.github.pagehelper.util.StringUtil; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; +import com.lightyears.admin.mapper.*; +import com.lightyears.admin.exception.BussinessException; +import com.lightyears.admin.service.IClearanceLogService; +import com.lightyears.admin.service.IGameSystemService; +import com.lightyears.admin.service.ILogService; +import com.lightyears.admin.service.IPlayerAssetsService; +import com.lightyears.admin.util.RedisCache; +import com.lightyears.admin.util.ResultUtil; +import com.lightyears.admin.util.StaticUtil; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.*; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service("gameSystemServiceImpl") +public class GameSystemServiceImpl implements IGameSystemService { + @Resource + private IPlayerAssetsService playerAssetsService; + @Resource + private AssertLogMapper assertLogMapper; + @Resource + private IGameSystemService gameSystemService; + Interner pool = Interners.newWeakInterner(); + private static final int AssetLimit = 999999; + + @Override + public ResModeBase pushGoldImpl(Integer userId, int gold, int type, String remark){ + synchronized (pool.intern("gold-".concat(userId.toString()))) { + return gameSystemService.pushGold(userId, gold, type, remark); + } + } + + @Override + @Transactional + public ResModeBase pushGold(Integer userId, int gold, int type, String remark) { + //1. 查询金额, 设置资产上限 + PlayerAssets playerAssets = playerAssetsService.getOne(new QueryWrapper().eq("player_id", userId).eq("type", type).last("limit 1")); + Integer playerAssetsNumber = playerAssets == null? 0 : playerAssets.getNumber(); + int nowGold = Math.min(playerAssetsNumber +gold , AssetLimit); + // 2.写入改变数量 + if (ObjectUtils.isEmpty(playerAssets)) { + playerAssetsService.save(PlayerAssets.builder().playerId(userId).type(type).number(nowGold).version(0L).build()); + } else { + playerAssetsService.addGold(playerAssets.getId(), nowGold - playerAssetsNumber); + } + //3 写入变化记录 + assertLogMapper.insert(AssertLog.builder().playerId(userId).createDate(new Date()).assertChangeNum(nowGold - playerAssetsNumber).assertType(type).remark(remark).build()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), nowGold); + } + + @Override + public ResModeBase pullGoldImpl(Integer userId, int gold, int type, String remark){ + synchronized (pool.intern("gold-".concat(userId.toString()))) { + return gameSystemService.pullGold(userId, gold, type, remark); + } + } + + @Override + @Transactional + public ResModeBase pullGold(Integer userId, int gold, int type, String remark) { + //1 查询金额 + PlayerAssets playerAssets = playerAssetsService.getOne(new QueryWrapper().eq("player_id", userId).eq("type", type).last("limit 1")); + Integer num = 0; + // 不存在用户的钱包数据则新增初始化钱包数据 + if(ObjectUtils.isEmpty(playerAssets)){ + playerAssets = PlayerAssets.builder().playerId(userId).type(0).number(0).version(0L).build(); + playerAssetsService.save(playerAssets); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), 0); + } + if (playerAssets.getNumber() < gold) { + return ResultUtil.result(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getCode(), String.format(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getMessage(), playerAssets.getNumber())); + } + //2 取出金币 + num = playerAssetsService.reduceGold(playerAssets.getId(), gold); + if(num == -999){ + return ResultUtil.result(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getCode(), String.format(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getMessage(), playerAssets.getNumber())); + } + //3 写入变化记录 + assertLogMapper.insert(AssertLog.builder().playerId(userId).createDate(new Date()).assertChangeNum(-gold).assertType(type).remark(remark).build()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), num); + } + + +} diff --git a/admin/src/main/java/com/lightyears/admin/service/impl/LogServiceImpl.java b/admin/src/main/java/com/lightyears/admin/service/impl/LogServiceImpl.java new file mode 100644 index 0000000..6b6f783 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/impl/LogServiceImpl.java @@ -0,0 +1,101 @@ +package com.lightyears.admin.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.admin.mapper.LogMapper; +import com.lightyears.admin.service.ILogService; +import com.lightyears.admin.util.RedisCache; +import com.lightyears.admin.util.StaticUtil; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.entity.Log; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class LogServiceImpl extends ServiceImpl implements ILogService { + @Resource + private RedisCache redisCache; + + @Override + public List getRankList(Integer level){ + List reqData = new ArrayList<>(); + if (level == -1) {//查询综合 + reqData = baseMapper.syntheticalPaging(); + } else { + reqData = baseMapper.paging(level, -1); + } + return reqData; + } + + @Override + public void deleteCacheByUserId(Integer userId){ + deleteCacheByRankUserId(0, userId); + deleteCacheByRankUserId(1, userId); + deleteCacheByRankUserId(2, userId); + deleteCacheByRankUserId(3, userId); + deleteCacheByRankUserId(4, userId); + } + + @Override + public void cacheRankList(Integer level){ + if(level == null){ + // -1 - 综合 + List zh = getRankList(-1); + cacheRankListItem(zh, 0); + // 1 - 普通 + List zh1 = getRankList(1); + cacheRankListItem(zh1, 1); + // 2 困难 + List zh2 = getRankList(2); + cacheRankListItem(zh2, 2); + // 3 大师 + List zh3 = getRankList(3); + cacheRankListItem(zh3, 3); + // 4 超凡 + List zh4 = getRankList(4); + cacheRankListItem(zh4, 4); + } else if(level == -1) { // 刷新综合榜数据 + // -1 - 综合 + List zh = getRankList(-1); + cacheRankListItem(zh, 0); + } + } + + public void cacheRankListItem(List list, Integer level){ + String key = StaticUtil.RANK_LIST.concat(level.toString()); + redisCache.deleteByPrefix(key); + BoundZSetOperations operations = redisCache.getRedisTemplate().boundZSetOps(key); + for (OrdinaryRankDto item : list){ + operations.add(item, item.getGame_time()); + } + } + + + @Override + public void deleteCacheByRankUserId(Integer level, Integer userId){ + String key = StaticUtil.RANK_LIST.concat(level.toString()); + BoundZSetOperations operations = redisCache.getRedisTemplate().boundZSetOps(key); + if (operations != null && operations.size() > 0){ + Set sets = operations.range(0, -1); + if(sets != null && sets.size() > 0){ + Optional dto = sets.stream().filter(obj -> obj.getUser_id().equals(userId)).findFirst(); + if(dto != null && dto.isPresent()){ + operations.remove(dto.get()); + } + } + } + } +} diff --git a/admin/src/main/java/com/lightyears/admin/service/impl/NoticeServiceImpl.java b/admin/src/main/java/com/lightyears/admin/service/impl/NoticeServiceImpl.java new file mode 100644 index 0000000..8a34f9d --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/impl/NoticeServiceImpl.java @@ -0,0 +1,77 @@ +package com.lightyears.admin.service.impl; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.admin.mapper.NoticeMapper; +import com.lightyears.admin.service.INoticeService; +import com.lightyears.admin.util.ResultUtil; +import com.lightyears.common.domain.dto.NoticeDto; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Notice; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +@Service(value = "noticeServiceImpl") +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class NoticeServiceImpl extends ServiceImpl implements INoticeService { + + + @Override + public ResModeBase getList(Integer playerId){ +// List results = new ArrayList<>(); + List systemNotice = this.baseMapper.getList(null, playerId); +// List myNotice = this.baseMapper.getList(1, playerId); +// if (!CollectionUtils.isEmpty(systemNotice)){ +// results.add(systemNotice.get(0)); +// } +// if (!CollectionUtils.isEmpty(myNotice)){ +// results.addAll(myNotice); +// } + + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), systemNotice); + } + + @Override + public ResModeBase getContent(Integer id){ + String content = this.baseMapper.getContent(id); + // 设置已读 + this.baseMapper.updateById(Notice.builder().id(id).status(1).build()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), content); + } + + @Override + public void deleteNoticeForTask(){ + List notices = this.baseMapper.selectList(new LambdaQueryWrapper().select(Notice::getId, Notice::getExpirationDay, Notice::getCreateDate).isNotNull(Notice::getExpirationDay)); + if (CollectionUtils.isEmpty(notices)) + return; + Date now = new Date(); + List ids = new ArrayList<>(); + notices.forEach(notice -> { + Date date = DateUtil.offsetDay(notice.getCreateDate(), notice.getExpirationDay()); + if(DateUtil.compare(now, date) > -1){ + ids.add(notice.getId()); + } + }); + + if(ids.size() < 1) + return; + baseMapper.deleteBatchIds(ids); + } + +} diff --git a/admin/src/main/java/com/lightyears/admin/service/impl/PlayerAssetsServiceImpl.java b/admin/src/main/java/com/lightyears/admin/service/impl/PlayerAssetsServiceImpl.java new file mode 100644 index 0000000..0f3529d --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/impl/PlayerAssetsServiceImpl.java @@ -0,0 +1,76 @@ +package com.lightyears.admin.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.admin.exception.BussinessException; +import com.lightyears.admin.mapper.PlayerAssetsMapper; +import com.lightyears.admin.service.IPlayerAssetsService; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Slf4j +@Service +public class PlayerAssetsServiceImpl extends ServiceImpl implements IPlayerAssetsService { + + @Override + public Integer addGold(int id, int gold){ + PlayerAssets playerAssets = baseMapper.selectById(id); + if(ObjectUtils.isEmpty(playerAssets)){ + log.error("减少金币异常------------没有查到资产信息"); + throw new BussinessException(MessageEnum.ERROR.getCode(), "减少金币异常------------没有查到资产信息!"); + } + int result = 0; + try{ + result = baseMapper.addGold(playerAssets.getId(), gold, playerAssets.getVersion()); + }catch (Exception ex){ + log.error("写入金币异常", ex); + throw new BussinessException(MessageEnum.ERROR.getCode(), "写入金币异常!"); + } + + if(result < 1){ + this.addGold(id, gold); + } + return gold; + } + + @Override + public Integer reduceGold(int id, int gold){ + PlayerAssets playerAssets = baseMapper.selectById(id); + if(ObjectUtils.isEmpty(playerAssets)){ + log.error("减少金币异常------------没有查到资产信息"); + throw new BussinessException(MessageEnum.ERROR.getCode(), "减少金币异常------------没有查到资产信息!"); + } + int result = 0; + if(playerAssets.getNumber() < gold){ + return -999; + } + try { + result = baseMapper.reduceGold(playerAssets.getId(), gold, playerAssets.getVersion()); + } catch (Exception ex){ + log.error("写入金币异常", ex); + throw new BussinessException(MessageEnum.ERROR.getCode(), "写入金币异常!"); + } + if(result < 1){ + this.reduceGold(id, gold); + } + return playerAssets.getNumber() - gold; + } + + @Override + public List getPlayerAssets(int playerId){ + return baseMapper.getPlayerAssets(playerId); + } +} diff --git a/admin/src/main/java/com/lightyears/admin/service/impl/PlayerServiceImpl.java b/admin/src/main/java/com/lightyears/admin/service/impl/PlayerServiceImpl.java new file mode 100644 index 0000000..44913f0 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/impl/PlayerServiceImpl.java @@ -0,0 +1,20 @@ +package com.lightyears.admin.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.admin.mapper.PlayerMapper; +import com.lightyears.admin.service.IPlayerService; +import com.lightyears.common.domain.entity.Player; +import org.springframework.stereotype.Service; + +/** + *

+ * 扫雷玩家表 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class PlayerServiceImpl extends ServiceImpl implements IPlayerService { + +} diff --git a/admin/src/main/java/com/lightyears/admin/service/impl/RecordServiceImpl.java b/admin/src/main/java/com/lightyears/admin/service/impl/RecordServiceImpl.java new file mode 100644 index 0000000..9954a3d --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/impl/RecordServiceImpl.java @@ -0,0 +1,20 @@ +package com.lightyears.admin.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.admin.mapper.RecordMapper; +import com.lightyears.admin.service.IRecordService; +import com.lightyears.common.domain.entity.Record; +import org.springframework.stereotype.Service; + +/** + *

+ * 游戏存档 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class RecordServiceImpl extends ServiceImpl implements IRecordService { + +} diff --git a/admin/src/main/java/com/lightyears/admin/service/impl/SystemServiceImpl.java b/admin/src/main/java/com/lightyears/admin/service/impl/SystemServiceImpl.java new file mode 100644 index 0000000..603c3da --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/service/impl/SystemServiceImpl.java @@ -0,0 +1,280 @@ +package com.lightyears.admin.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.lightyears.admin.dto.ListBaseListParams; +import com.lightyears.admin.dto.PlayerAssetsParams; +import com.lightyears.admin.dto.UserListParams; +import com.lightyears.admin.dto.UserStatusParams; +import com.lightyears.admin.exception.BussinessException; +import com.lightyears.admin.mapper.*; +import com.lightyears.admin.service.*; +import com.lightyears.admin.util.*; +import com.lightyears.common.domain.dto.ListInstanceDto; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.dto.Params; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.*; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class SystemServiceImpl implements ISystemService { + private final INoticeService noticeService; + private final IPlayerAssetsService playerAssetsService; + private final PlayerMapper playerMapper; + private final RecordMapper recordMapper; + private final ILogService logService; + private final AssertLogMapper assertLogMapper; + private final NoticeMapper noticeMapper; + private final IClearanceLogService clearanceLogService; + private final RedisCache redisCache; + private final RedisLock redisLock; + private final IGameSystemService gameSystemService; + private final ListBaseMapper listBaseMapper; + private final ListRankMapper listRankMapper; + private final ListInstanceMapper listInstanceMapper; + + @Override + public ResModeBase login(String userName, String password){ + String checkStr = redisCache.getCacheObject(StaticUtil.ADMIN_PASSWORD).toString(); + log.info("登录来了:" + checkStr); + if(checkStr.equals(userName.trim().concat(password.trim()))){ + String token = StrUtil.uuid().replace("-", ""); + // 写入管理端用户在线缓存 + redisCache.setCacheObject(StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY.concat(token), "admin", 86400, TimeUnit.SECONDS); + // 返回token + return ResultUtil.success(token); + } else { + return ResultUtil.error("登录失败,账号或密码错误!"); + } + } + + @Override + public ResModeBase logout(){ + redisCache.deleteByPrefix(StaticUtil.ONLINE_ADMIN_USER_PUBLIC_KEY); + return ResultUtil.success(); + } + + @Override + public ResModeBase userList(Params params){ + PageHelperUtil.setPage(params.getPageNum(), params.getPageSize()); + return ResultUtil.success(PageHelperUtil.slicedQueryResult(playerMapper.getPlayerList(params.getRecord()))); + } + + @Override + @Transactional + public void updateUserStatus(UserStatusParams params){ + playerMapper.update(null, new LambdaUpdateWrapper().set(Player::getStatus, params.getStatus()).eq(Player::getUser_id, params.getPlayerId())); + // 如果是禁用 + if(params.getStatus() == 0){ + Object token = redisCache.getCacheObject(StaticUtil.ONLINE_USER_TOKEN.concat(params.getPlayerId().toString())); + if(token == null) + return; + redisCache.deleteByPrefix(StaticUtil.ONLINE_USER_TOKEN.concat(params.getPlayerId().toString())); + // 删除缓存 + redisCache.deleteByPrefix(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(token.toString())); + } + } + + @Override + public void publishNotice(Notice notice){ + //redis锁 + String lockKey=StaticUtil.NOTICE_LOCK; + try { + if(redisLock.tryLock(lockKey)){ + List players = playerAssetsService.list(new LambdaQueryWrapper().select(PlayerAssets::getPlayerId).eq(PlayerAssets::getType, 0)); + if(CollectionUtils.isEmpty(players)) + return; + Date now = new Date(); + + List notices = new ArrayList<>(); + players.stream().forEach(player -> { + Notice obj = new Notice(); + obj.setContent(notice.getContent()); + obj.setTitle(notice.getTitle()); + obj.setType(0); + obj.setPlayerId(player.getPlayerId()); + obj.setStatus(0); + obj.setCreateDate(now); + notices.add(obj); + }); + //一个线程处理10000条数据 + int count = 10000; + //数据集合大小 + int listSize = notices.size(); + //开启的线程数 + int runSize = (listSize / count) + 1; + //存放每个线程的执行数据 + List newlist = null; + + //创建一个线程池,数量和开启线程的数量一样 + //Executors 的写法 + // ExecutorService executor = Executors.newFixedThreadPool(runSize); + + //ThreadPoolExecutor的写法 + ThreadPoolExecutor executor = new ThreadPoolExecutor(runSize, runSize, 1, + TimeUnit.SECONDS, new ArrayBlockingQueue(3), + new ThreadPoolExecutor.DiscardOldestPolicy()); + + //创建两个个计数器 + CountDownLatch begin = new CountDownLatch(1); + CountDownLatch end = new CountDownLatch(runSize); + try { + //循环创建线程 + for (int i = 0; i < runSize; i++) { + //计算每个线程执行的数据 + if ((i + 1) == runSize) { + int startIndex = (i * count); + int endIndex = notices.size(); + newlist = notices.subList(startIndex, endIndex); + } else { + int startIndex = (i * count); + int endIndex = (i + 1) * count; + newlist = notices.subList(startIndex, endIndex); + } + //线程类 + BatchInsertThread mythead = new BatchInsertThread(newlist, begin, end, noticeService); + //这里执行线程的方式是调用线程池里的executor.execute(mythead)方法。 + executor.execute(mythead); + } + begin.countDown(); + end.await(); + } finally { + //执行完关闭线程池 + executor.shutdown(); + } + + }else{ + throw new BussinessException(MessageEnum.ERROR.getCode(), "公告正在发布中,请稍后!"); + } + }catch (BussinessException e){ + throw new BussinessException(MessageEnum.ERROR.getCode(), "公告正在发布中,请稍后!"); + }catch (Exception e){ + log.error("发布公告异常:", e); + throw new BussinessException(MessageEnum.ERROR.getCode(), "发布公告异常!"); + } finally { + redisLock.releaseLock(lockKey); + } + } + + + @Override + public void deleteCacheByRankUserId(Integer level, Integer userId){ + // 删除游戏日志 + logService.remove(new LambdaQueryWrapper().eq(Log::getUser_id, userId).eq(Log::getLevel, level)); + // 删除缓存 + logService.deleteCacheByRankUserId(level, userId); + } + + @Override + @Transactional + public void cancellationAccount(Integer userId) { + // 删除排行榜缓存数据. + logService.deleteCacheByUserId(userId); + // 删除雷神之塔缓存数据 + clearanceLogService.deletCacheByPlayerId(userId); + + // sl_assert_log 资产日志 + assertLogMapper.delete(new UpdateWrapper().eq("player_id", userId)); + // sl_log 游戏日志 + logService.remove(new UpdateWrapper().eq("user_id", userId)); + // sl_notic 公告 + noticeMapper.delete(new UpdateWrapper().eq("player_id", userId)); + // sl_player_assets 用户资产 + playerAssetsService.remove(new UpdateWrapper().eq("player_id", userId)); + // sl_record 用户游戏数据记录 + recordMapper.delete(new UpdateWrapper().eq("user_id", userId)); + // sl_player 用户 + playerMapper.deleteById(userId); + // sl_clearance_log 通关日志 + clearanceLogService.remove(new LambdaQueryWrapper().eq(ClearanceLog::getPlayerId, userId)); + } + + @Override + public void setPlayerAssets(PlayerAssetsParams params){ + if(params.getGold() == 0) + return; + if(params.getGold() > 0){ + gameSystemService.pushGold(params.getUserId(),params.getGold(),params.getType(), params.getRemark()); + } else { + gameSystemService.pullGold(params.getUserId(),0 - params.getGold(),params.getType(), params.getRemark()); + } + } + + @Override + public ResModeBase challengeBaseList(Params params){ + PageHelperUtil.setPage(params.getPageNum(), params.getPageSize()); + CustomLambdaQueryWrapper queryWrapper = new CustomLambdaQueryWrapper(); + if(params.getRecord() != null && !StrUtil.isBlankIfStr(params.getRecord().getKeyword())){ + queryWrapper.like(ListBase::getName, params.getRecord().getKeyword()); + } + return ResultUtil.success(PageHelperUtil.slicedQueryResult(listBaseMapper.selectList(queryWrapper))); + } + + @Override + public ResModeBase addBase(ListBase base){ + if(base.getId() == null){ + listBaseMapper.insert(base); + } else { + listBaseMapper.updateById(base); + } + return ResultUtil.success(); + } + + @Override + public ResModeBase deleteBase(Integer id){ + Long num = listInstanceMapper.selectCount(new LambdaQueryWrapper().eq(ListInstance:: getId, id).eq(ListInstance::getStatus, 0)); + if(num == 0L){ + listBaseMapper.deleteById(id); + } + return ResultUtil.success(); + } + + @Override + public ResModeBase challengeInstanceList(){ + List list = listInstanceMapper.getListInstances(); + return ResultUtil.success(list); + } + + @Override + public void removeChallengeRankInfo(Integer instanceId, Integer rankNum){ + int i = listRankMapper.initRank(instanceId, rankNum); + // 清空成功 更新缓存 + if(i > 0){ + ListRankDto rank; + // 获取指定榜单与名次的listRank + Object obj = redisCache.lGetIndex(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(instanceId.toString()), rankNum-1); + if(obj == null){ + return; + } else { + String json = JSONObject.toJSONString(obj) ; + rank = JSON.parseObject(json, ListRankDto.class); + } + rank.setChallengeTime(null); + rank.setPlayerId(null); + rank.setPlayerName(null); + rank.setGameData(null); + redisCache.lUpdateIndex(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(rank.getInstanceId().toString()), rank.getRankNum() - 1, rank); + } + } +} diff --git a/admin/src/main/java/com/lightyears/admin/util/BatchInsertThread.java b/admin/src/main/java/com/lightyears/admin/util/BatchInsertThread.java new file mode 100644 index 0000000..fe0100b --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/BatchInsertThread.java @@ -0,0 +1,46 @@ +package com.lightyears.admin.util; + +import com.lightyears.admin.service.INoticeService; +import com.lightyears.common.domain.entity.Notice; + +import java.util.List; +import java.util.concurrent.CountDownLatch; + +public class BatchInsertThread implements Runnable { + + public BatchInsertThread() { + } + + INoticeService noticeService; + private List list; + private CountDownLatch begin; + private CountDownLatch end; + + /** + * 方法名: ImportThread + * 方法描述: 创建个构造函数初始化 list,和其他用到的参数 + * @throws + */ + public BatchInsertThread(List list, CountDownLatch begin, CountDownLatch end,INoticeService noticeService) { + this.list = list; + this.begin = begin; + this.end = end; + this.noticeService=noticeService; + } + + @Override + public void run() { + try { + //执行完让线程直接进入等待 + noticeService.saveBatch(list); + begin.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //这里要注意了,当一个线程执行完 了计数要减一不然这个线程会被一直挂起 + //这个方法就是直接把计数器减一的 + end.countDown(); + } + } + +} \ No newline at end of file diff --git a/admin/src/main/java/com/lightyears/admin/util/CronUtils.java b/admin/src/main/java/com/lightyears/admin/util/CronUtils.java new file mode 100644 index 0000000..f2352f1 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/CronUtils.java @@ -0,0 +1,37 @@ +package com.lightyears.admin.util; + +import cn.hutool.core.date.DateTime; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Objects; + +/** + * 日期转换cron表达式 + */ +public class CronUtils { + + /*** + * 功能描述:日期转换cron表达式 + * @param dateStr + * @return + */ + public static String formatDateByPattern(String dateStr) { + String formatTimeStr = null; + if (Objects.nonNull(dateStr)) { + LocalDateTime time = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + formatTimeStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ?")); + } + return formatTimeStr; + } + + /*** + * @param dateTime : 时间点 + * @return + */ + public static String getCron(DateTime dateTime) { + return formatDateByPattern(dateTime.toString()); + } + +} + diff --git a/admin/src/main/java/com/lightyears/admin/util/CustomLambdaQueryWrapper.java b/admin/src/main/java/com/lightyears/admin/util/CustomLambdaQueryWrapper.java new file mode 100644 index 0000000..6484b41 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/CustomLambdaQueryWrapper.java @@ -0,0 +1,149 @@ +package com.lightyears.admin.util; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; + +import java.util.Collection; + +/** + * .自定义的查询wrapper. + * + * @author yangps + */ +public class CustomLambdaQueryWrapper extends LambdaQueryWrapper { + + public CustomLambdaQueryWrapper() { + } + + /** + * + */ + private static final long serialVersionUID = 7733721688976788787L; + + /** + * .软条件查询, 如果条件无值, 就不加入查询. + * + * @param R + * @param val + * @return + */ + public CustomLambdaQueryWrapper softEq(SFunction R, Object val) { + if (val != null && StringUtils.isNotBlank(val + "")) { + super.eq(R, val); + } + return this; + } + + /** + * .软条件查询, 如果条件无值, 就不加入查询. + * + * @param R + * @param val + * @return + */ + public CustomLambdaQueryWrapper softEqForInteger(SFunction R, Object val) { + if (val != null && StringUtils.isNotBlank(val + "") && Integer.valueOf(String.valueOf(val)).intValue() != -1) { + super.eq(R, val); + } + return this; + } + + /** + * .软条件查询, 如果条件无值, 就不加入查询. + * + * @param R + * @param val + * @return + */ + public CustomLambdaQueryWrapper softNe(SFunction R, Object val) { + if (val != null && StringUtils.isNotBlank(val + "")) { + super.ne(R, val); + } + return this; + } + + /** + * .软条件查询, 如果条件无值, 就不加入查询. + * + * @param R + * @param val + * @return + */ + public CustomLambdaQueryWrapper softLike(SFunction R, Object val) { + if (val != null && StringUtils.isNotBlank(val + "")) { + super.like(R, val); + } + return this; + } + + /** + * .软条件查询, 如果条件无值, 就不加入查询. + * + * @param R + * @param coll + * @return + */ + public CustomLambdaQueryWrapper softIn(SFunction R, Collection coll) { + if (coll.size() > 0) { + super.in(R, coll); + } + return this; + } + + /** + * .软条件查询, 如果条件无值, 就不加入查询. + * + * @param R + * @param coll + * @return + */ + public CustomLambdaQueryWrapper softNotIn(SFunction R, Collection coll) { + if (coll.size() > 0) { + super.notIn(R, coll); + } + return this; + } + + /** + * .软条件查询, 如果条件无值, 就不加入查询. + * + * @param R + * @param val1 + * @param val2 + * @return + */ + public CustomLambdaQueryWrapper softTimeBetween(SFunction R, Object val1, Object val2) { + + if (val1 != null && StringUtils.isNotBlank(val1 + "") && val2 != null && StringUtils.isNotBlank(val2 + "")) { + super.between(R, val1, val2); + return this; + } + + if (val1 != null && StringUtils.isNotBlank(val1 + "") && val2 == null) { + super.ge(R, val1); + return this; + } + + if (val1 == null && val2 != null && StringUtils.isNotBlank(val2 + "")) { + super.le(R, val2); + } + return this; + } + + /** + * .软条件查询, 如果条件为null, 查询就改为is null. + * + * @param R + * @param val + * @return + */ + public CustomLambdaQueryWrapper softEqOrIsNull(SFunction R, Object val) { + if (val != null && StringUtils.isNotBlank(val + "")) { + super.eq(R, val); + } else if (val == null) { + super.isNull(R); + } + return this; + } +} diff --git a/admin/src/main/java/com/lightyears/admin/util/GetBeanUtil.java b/admin/src/main/java/com/lightyears/admin/util/GetBeanUtil.java new file mode 100644 index 0000000..04cac51 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/GetBeanUtil.java @@ -0,0 +1,26 @@ +package com.lightyears.admin.util; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class GetBeanUtil implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + public void setApplicationContext(ApplicationContext context) { + GetBeanUtil.applicationContext = context; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static Object getBean(Class classObj) { + return applicationContext.getBean(classObj); + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } +} \ No newline at end of file diff --git a/admin/src/main/java/com/lightyears/admin/util/MD5Utils.java b/admin/src/main/java/com/lightyears/admin/util/MD5Utils.java new file mode 100644 index 0000000..cc3ef6e --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/MD5Utils.java @@ -0,0 +1,51 @@ +package com.lightyears.admin.util; + +import java.security.MessageDigest; + +/** + * Created by tanhao on 2019/3/18. + */ +public class MD5Utils { + private static final String hexDigIts[] = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"}; + + /** + * MD5加密 + * @param origin 字符 + * @param charsetname 编码 UTF-8 + * @return + */ + public static String MD5Encode(String origin, String charsetname){ + String resultString = null; + try{ + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if(null == charsetname || "".equals(charsetname)){ + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + }else{ + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + }catch (Exception e){ + } + return resultString; + } + + + public static String byteArrayToHexString(byte b[]){ + StringBuffer resultSb = new StringBuffer(); + for(int i = 0; i < b.length; i++){ + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + public static String byteToHexString(byte b){ + int n = b; + if(n < 0){ + n += 256; + } + int d1 = n / 16; + int d2 = n % 16; + return hexDigIts[d1] + hexDigIts[d2]; + } + +} diff --git a/admin/src/main/java/com/lightyears/admin/util/PageHelperUtil.java b/admin/src/main/java/com/lightyears/admin/util/PageHelperUtil.java new file mode 100644 index 0000000..01bcd17 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/PageHelperUtil.java @@ -0,0 +1,28 @@ +package com.lightyears.admin.util; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.lightyears.common.domain.dto.SlicedQueryResult; + +import java.util.List; + +public class PageHelperUtil { + + public static void setPage(Integer pageNo, Integer pageSize) { + PageHelper.startPage(pageNo, pageSize); + } + + /** + * 分页查询数据 + * + * @param data + * 数据集合 + * @return 分页对象 + */ + public static SlicedQueryResult slicedQueryResult(List data) { + PageInfo pageInfo = new PageInfo(data); + SlicedQueryResult slicedQueryResult = new SlicedQueryResult(pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), data); + PageHelper.clearPage(); + return slicedQueryResult; + } +} diff --git a/admin/src/main/java/com/lightyears/admin/util/RedisCache.java b/admin/src/main/java/com/lightyears/admin/util/RedisCache.java new file mode 100644 index 0000000..c958751 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/RedisCache.java @@ -0,0 +1,383 @@ +package com.lightyears.admin.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * spring redis 工具类 + **/ +@Component +public class RedisCache { + + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private StringRedisTemplate stringRedisTemplate; + + /** + * 判断key是否存在 + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + */ + public void setCacheObject(final String key, final T value) { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param timeout 时间 + * @param timeUnit 时间颗粒度 + */ + public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout) { + return expire(key, timeout, TimeUnit.SECONDS); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @param unit 时间单位 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout, final TimeUnit unit) { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return 缓存键值对应的数据 + */ + public T getCacheObject(final String key) { + ValueOperations operation = redisTemplate.opsForValue(); + return operation.get(key); + } + + /** + * 删除单个对象 + * + * @param key + */ + public boolean deleteObject(final String key) { + return redisTemplate.delete(key); + } + + /** + * 删除指定前缀的缓存 + * @param key + * @return + */ + public Long deleteByPrefix(final String key) { + Set keys = redisTemplate.keys(key.concat("*")); + return redisTemplate.delete(keys); + } + + /** + * 删除集合对象 + * + * @param collection 多个对象 + * @return + */ + public long deleteObject(final Collection collection) { + return redisTemplate.delete(collection); + } + + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSetAll(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public long setCacheSet(final String key, final Set dataSet) { + Long count = redisTemplate.opsForSet().add(key, dataSet); + return count == null ? 0 : count; + } + + /** + * 获得缓存的set + * + * @param key + * @return + */ + public Set getCacheSet(final String key) { + return redisTemplate.opsForSet().members(key); + } + + /** + * 缓存Map + * + * @param key + * @param dataMap + */ + public void setCacheMap(final String key, final Map dataMap) { + if (dataMap != null) { + redisTemplate.opsForHash().putAll(key, dataMap); + } + } + + /** + * 获得缓存的Map + * + * @param key + * @return + */ + public Map getCacheMap(final String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 往Hash中存入数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @param value 值 + */ + public void setCacheMapValue(final String key, final String hKey, final T value) { + redisTemplate.opsForHash().put(key, hKey, value); + } + + /** + * 获取Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public T getCacheMapValue(final String key, final String hKey) { + HashOperations opsForHash = redisTemplate.opsForHash(); + return opsForHash.get(key, hKey); + } + + /** + * 获取多个Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键集合 + * @return Hash对象集合 + */ + public List getMultiCacheMapValue(final String key, final Collection hKeys) { + return redisTemplate.opsForHash().multiGet(key, hKeys); + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public Collection keys(final String pattern) { + return redisTemplate.keys(pattern); + } + + public StringRedisTemplate getStringRedisTemplate() { + return stringRedisTemplate; + } + + public RedisTemplate getRedisTemplate() { + return redisTemplate; + } +} \ No newline at end of file diff --git a/admin/src/main/java/com/lightyears/admin/util/RedisLock.java b/admin/src/main/java/com/lightyears/admin/util/RedisLock.java new file mode 100644 index 0000000..62aa5b5 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/RedisLock.java @@ -0,0 +1,127 @@ +package com.lightyears.admin.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +/** + * 利用reids处理多线程问题 + */ +@Component +public class RedisLock { + + private static final String RELEASE_RESULT = "1"; + + @Autowired + private RedisCache redisCache; + + /** + * 获取redis锁 + * @param lockKey 锁标识 + * @param requestId 锁的持有者,加锁的请求,可以是线程ID + * @param expireTime 锁过期时间(秒) + * @return + */ + public boolean getLock(String lockKey, String requestId, long expireTime){ + String script = "if redis.call('EXISTS', KEYS[1]) == 0 then" + + " redis.call('set', KEYS[1] , ARGV[1] ,'EX',"+expireTime+"); " + + " return 1;" + + " else " + + " if redis.call('get', KEYS[1]) == ARGV[1] then" + + " return 1; " + + " else " + + " return 0; " + + " end " + + " end"; +// System.out.println(script); + Object releaseResult =redisCache.getRedisTemplate().execute(new DefaultRedisScript(script,Long.class), + Arrays.asList(lockKey), + requestId); + return RELEASE_RESULT.equals(releaseResult.toString()); + + } + + /** + * @功能 尝试获取锁,获取者未当前线程,锁持有时间20分钟,等待时间1秒 + * @Author 刘建 + * @创建时间 2022/1/16 22:18 + * @修改人 刘建 + * @修改时间 2022/1/16 22:18 + * @Param + * @param lockKey: + * @return + **/ + public boolean tryLock(String lockKey){ + return tryLock(lockKey,Thread.currentThread().getId()+"",1200,1); + } + /** + * @功能 尝试获取锁,获取时间不超过wait,每500毫秒获取一次 + * @Author 刘建 + * @创建时间 2022/1/16 20:52 + * @修改人 刘建 + * @修改时间 2022/1/16 20:52 + * @Param + * @param lockKey: 锁标识 + * @param requestId: 锁的持有者 + * @param expireTime: 过期时间,秒 + * @param wait: 等到时间秒 + * @return + **/ + public boolean tryLock(String lockKey, String requestId, long expireTime,long wait){ + long time=System.currentTimeMillis(); + wait=wait*1000; + while (System.currentTimeMillis()-wait(script,Long.class), + Arrays.asList(lockKey), + requestId);; + if (RELEASE_RESULT.equals(releaseResult.toString())) { + return true; + } + return false; + } +} diff --git a/admin/src/main/java/com/lightyears/admin/util/ResultUtil.java b/admin/src/main/java/com/lightyears/admin/util/ResultUtil.java new file mode 100644 index 0000000..7138a62 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/ResultUtil.java @@ -0,0 +1,56 @@ +package com.lightyears.admin.util; + +import cn.hutool.crypto.digest.MD5; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; + +/** + * 返回 数据 指定数据结构 + * + * @author Melody + */ +@Slf4j +public class ResultUtil { + public static final ObjectMapper mapper = new ObjectMapper(); + public static ResModeBase result(int code, String mes) { + return result(code, mes, null); + } + + public static ResModeBase result(int code, String mes, Object data) { + String key = ""; + String dataStr = ""; + if(data == null){ + key = MD5.create().digestHex(MD5.create().digestHex(StaticUtil.PRIVATE_KEY)); + } else { + try { + if (data instanceof String){ + dataStr = data.toString(); + } else { + dataStr = mapper.writeValueAsString(data); + } + key = MD5.create().digestHex(MD5.create().digestHex(dataStr.concat(StaticUtil.PRIVATE_KEY))); + }catch (JsonProcessingException ex){ + log.error("json解析错误", ex); + return new ResModeBase(MessageEnum.SERVER_ERROR.getCode(), MessageEnum.SERVER_ERROR.getMessage(), key, null); + } + + } + return new ResModeBase(code, mes, key, data); + } + + public static ResModeBase success(){ + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } + + public static ResModeBase success(Object data){ + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), data); + } + + public static ResModeBase error(String mes){ + return ResultUtil.result(MessageEnum.ERROR.getCode(), mes); + } + +} diff --git a/admin/src/main/java/com/lightyears/admin/util/ScheduledFutureHolder.java b/admin/src/main/java/com/lightyears/admin/util/ScheduledFutureHolder.java new file mode 100644 index 0000000..e12ff18 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/ScheduledFutureHolder.java @@ -0,0 +1,46 @@ +package com.lightyears.admin.util; +import java.util.concurrent.ScheduledFuture; + +/** + * 任务执行的包装类 + */ +public class ScheduledFutureHolder { + private ScheduledFuture scheduledFuture; + + private Class runnableClass; + + private String corn; + + public ScheduledFuture getScheduledFuture() { + return scheduledFuture; + } + + public void setScheduledFuture(ScheduledFuture scheduledFuture) { + this.scheduledFuture = scheduledFuture; + } + + public Class getRunnableClass() { + return runnableClass; + } + + public void setRunnableClass(Class runnableClass) { + this.runnableClass = runnableClass; + } + + public String getCorn() { + return corn; + } + + public void setCorn(String corn) { + this.corn = corn; + } + + @Override + public String toString() { + return "ScheduledFutureHolder{" + + "scheduledFuture=" + scheduledFuture + + ", runnableClass=" + runnableClass + + ", corn='" + corn + '\'' + + '}'; + } +} diff --git a/admin/src/main/java/com/lightyears/admin/util/SpecialTool.java b/admin/src/main/java/com/lightyears/admin/util/SpecialTool.java new file mode 100644 index 0000000..6946f78 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/SpecialTool.java @@ -0,0 +1,50 @@ +package com.lightyears.admin.util; + +import java.util.List; +import java.util.Map; + +/** + * 文 件 名 : 特殊处理工具 + * 创 建 人:HL + * 日 期:2019-8-12 + * 修 改 人:HL + * 日 期:2019-8-12 + * 描 述: 分页、 + * 版 本 号:2.0 + */ +public class SpecialTool { + public static SpecialTool specialTool = new SpecialTool(); + + //时间格式 + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + //集合判断是否为空 + + public boolean ifGather(Object o) { + if ((o instanceof List && null == o) || (o instanceof Map && null == o)) { + return true; + } + return false; + } + + //字符串判断是否为空 + public boolean isEmpty(String s) { + if (null == s || s.equals("")) { + return true; + } + return false; + } + + + /** + * 将字符串的首字母转大写 + * @param str 需要转换的字符串 + * @return + */ + private static String captureName(String str) { + // 进行字母的ascii编码前移,效率要高于截取字符串进行转换的操作 + char[] cs=str.toCharArray(); + cs[0]-=32; + return String.valueOf(cs); + } +} diff --git a/admin/src/main/java/com/lightyears/admin/util/StaticUtil.java b/admin/src/main/java/com/lightyears/admin/util/StaticUtil.java new file mode 100644 index 0000000..08ce752 --- /dev/null +++ b/admin/src/main/java/com/lightyears/admin/util/StaticUtil.java @@ -0,0 +1,46 @@ +package com.lightyears.admin.util; + + +import java.util.HashMap; +import java.util.Map; + +/** + * 静态工具栏 :目前数据较小 且又想减少服务器压力,特建此类 做静态缓存 + */ +public class StaticUtil { + // ------------------------系统类----------------------- + //金币极限操作 防范静态变量 + public static Map goldSyn = new HashMap(); + // 数据加解密盐 + public static final String PRIVATE_KEY = "123144123"; + // 发布公告 redis锁key + public static final String NOTICE_LOCK = "mineClearance:publicNotice:lock"; + + // ---------------------------------redis ----------------------------------------- + // 在线用户信息 + public static final String ONLINE_USER_PUBLIC_KEY="mineClearance:onlineUser:"; + // 在线用户TOKEN + public static final String ONLINE_USER_TOKEN="mineClearance:onlineToken:"; + // 排行榜 + public static final String RANK_LIST = "mineClearance:rankList:"; + // 闯关排行 + public static final String CLEARANCE_RANK_LIST = "mineClearance:clearanceList"; + + // admin 密码 + public static final String ADMIN_PASSWORD = "mineClearance:admin:password"; + // admin 在线key + public static final String ONLINE_ADMIN_USER_PUBLIC_KEY="mineClearance:admin:onlineUser:"; + + + //----------------------------挑战榜task-------------------------- + // 锁榜时间 + public static final String LOCKE_TIME = " 23:00:00"; + // 结算时间 + public static final String SETTLEMENT_TIME = " 23:45:00"; + // 挑战榜初始化时间 + public static final String CHALLENGE_INIT_TIME = " 1:00:00"; + // 挑战榜redis刷新时间 + public static final String CHALLENGE_REFRESH_TIME = " 1:05:00"; + + public static final String CHALLENGE_INSTANCE_RANK_DETAIL="mineClearance:challenge:rankDetail:"; +} diff --git a/admin/src/main/resources/application-dev.yml b/admin/src/main/resources/application-dev.yml new file mode 100644 index 0000000..4868b15 --- /dev/null +++ b/admin/src/main/resources/application-dev.yml @@ -0,0 +1,67 @@ +qbs-switch: + swagger-open: true #swagger开关(true:打开, false:关闭) +spring: + application: + name: mine-clearance-admin + main: + allow-bean-definition-overriding: true + allow-circular-references: true + # 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题 + jackson: + time-zone: GMT+8 + datasource: + username: root + password: 43626546 + url: jdbc:mysql://42.192.76.87:3306/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 20 + max-active: 80 + min-idle: 20 + max-wait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictabkeIdleTimeMillis: 1800000 + validationQuery: SELECT 1 + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + # 配置监控统计拦截的filters,去掉后监控界面sql无法统计。‘wall’用于防火墙 + filters: stat,wall + # cloud: + # nacos: + # discovery: + # server-addr: localhost:8848 + redis: + # Redis服务器地址 + host: localhost + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + password: 123456 + # 连接超时时间 + timeout: 1000ms + lettuce: + pool: + # 连接池最大连接数 + max-active: 8 + # 连接池最大空闲连接数 + max-idle: 8 + # 连接池最小空闲连接数 + min-idle: 0 + # 连接池最大阻塞等待时间,负值表示没有限制 + max-wait: -1ms +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + type-aliases-package: com.lightyears.common.domain + global-config: + banner: false + db-config: + id-type: input + configuration: + # 控制台SQL日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: false \ No newline at end of file diff --git a/admin/src/main/resources/application-prod.yml b/admin/src/main/resources/application-prod.yml new file mode 100644 index 0000000..6334e40 --- /dev/null +++ b/admin/src/main/resources/application-prod.yml @@ -0,0 +1,73 @@ +qbs-switch: + swagger-open: true #swagger开关(true:打开, false:关闭) +spring: + application: + name: mine-clearance-admin + main: + allow-bean-definition-overriding: true + allow-circular-references: true + # 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题 + jackson: + time-zone: GMT+8 + datasource: + username: root + password: 1476346288@mysql + # password: 1813547935mysql + # 基础 + url: jdbc:mysql://127.0.0.1:3986/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull + # 本地 + # url: jdbc:mysql://39.106.21.14:3986/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 20 + max-active: 80 + min-idle: 20 + max-wait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictabkeIdleTimeMillis: 1800000 + validationQuery: SELECT 1 + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + # 配置监控统计拦截的filters,去掉后监控界面sql无法统计。‘wall’用于防火墙 + filters: stat,wall + # cloud: + # nacos: + # discovery: + # server-addr: localhost:8848 + redis: + # Redis服务器地址 + host: localhost + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器连接端口 + port: 7963 + # Redis服务器连接密码(默认为空) + password: 1476346288@redis + # password: 123456 + # 连接超时时间 + timeout: 1000ms + lettuce: + pool: + # 连接池最大连接数 + max-active: 8 + # 连接池最大空闲连接数 + max-idle: 8 + # 连接池最小空闲连接数 + min-idle: 0 + # 连接池最大阻塞等待时间,负值表示没有限制 + # max-wait: -1ms + max-wait: 3 +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + type-aliases-package: com.lightyears.common.domain + global-config: + banner: false + db-config: + id-type: input + configuration: + # 控制台SQL日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: false \ No newline at end of file diff --git a/admin/src/main/resources/application.yml b/admin/src/main/resources/application.yml new file mode 100644 index 0000000..0199299 --- /dev/null +++ b/admin/src/main/resources/application.yml @@ -0,0 +1,11 @@ +server: + port: 18634 + tomcat: + uri-encoding: UTF-8 +logging: + config: classpath:log.xml +spring: + profiles: + active: dev +appconfig: + version: 197.0 \ No newline at end of file diff --git a/admin/src/main/resources/log.xml b/admin/src/main/resources/log.xml new file mode 100644 index 0000000..6e850e2 --- /dev/null +++ b/admin/src/main/resources/log.xml @@ -0,0 +1,51 @@ + + + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + logs/basics/sys.log + + + + + + logs/basics/sys.%d.%i.log + + 30 + + + 10MB + + + + + + %d %p (%file:%line\)- %m%n + + + UTF-8 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/admin/src/main/resources/mapper/AssertLogMapper.xml b/admin/src/main/resources/mapper/AssertLogMapper.xml new file mode 100644 index 0000000..f9aefdb --- /dev/null +++ b/admin/src/main/resources/mapper/AssertLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/admin/src/main/resources/mapper/ClearanceLogMapper.xml b/admin/src/main/resources/mapper/ClearanceLogMapper.xml new file mode 100644 index 0000000..0a4d620 --- /dev/null +++ b/admin/src/main/resources/mapper/ClearanceLogMapper.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/admin/src/main/resources/mapper/ListBaseMapper.xml b/admin/src/main/resources/mapper/ListBaseMapper.xml new file mode 100644 index 0000000..c66b5c0 --- /dev/null +++ b/admin/src/main/resources/mapper/ListBaseMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/admin/src/main/resources/mapper/ListInstanceMapper.xml b/admin/src/main/resources/mapper/ListInstanceMapper.xml new file mode 100644 index 0000000..e9c5678 --- /dev/null +++ b/admin/src/main/resources/mapper/ListInstanceMapper.xml @@ -0,0 +1,32 @@ + + + + + + UPDATE sl_list_instance + SET award_size = award_size + #{awardSize} + where id = #{instanceId} + and assets_type = #{assetsType} + + + + diff --git a/admin/src/main/resources/mapper/ListRankMapper.xml b/admin/src/main/resources/mapper/ListRankMapper.xml new file mode 100644 index 0000000..90e9d32 --- /dev/null +++ b/admin/src/main/resources/mapper/ListRankMapper.xml @@ -0,0 +1,79 @@ + + + + + UPDATE `sl_list_rank` + SET + `player_name` = NULL, + `player_id` = NULL, + `challenge_time` = NULL, + `game_data` = NULL + WHERE + `instance_id` = ${instanceId} + and `rank_num` = ${rankNum} + + + + + diff --git a/admin/src/main/resources/mapper/LogMapper.xml b/admin/src/main/resources/mapper/LogMapper.xml new file mode 100644 index 0000000..48b53f8 --- /dev/null +++ b/admin/src/main/resources/mapper/LogMapper.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + diff --git a/admin/src/main/resources/mapper/NoticeMapper.xml b/admin/src/main/resources/mapper/NoticeMapper.xml new file mode 100644 index 0000000..9c3b489 --- /dev/null +++ b/admin/src/main/resources/mapper/NoticeMapper.xml @@ -0,0 +1,31 @@ + + + + + + diff --git a/admin/src/main/resources/mapper/PlayerAssetsMapper.xml b/admin/src/main/resources/mapper/PlayerAssetsMapper.xml new file mode 100644 index 0000000..6e5b789 --- /dev/null +++ b/admin/src/main/resources/mapper/PlayerAssetsMapper.xml @@ -0,0 +1,14 @@ + + + + + update sl_player_assets set number = number + #{gold}, version = version +1 where id = #{id} and version = ${version} + + + update sl_player_assets set number = number - #{gold}, version = version +1 where id = #{id} and version = ${version} + + + + diff --git a/admin/src/main/resources/mapper/PlayerMapper.xml b/admin/src/main/resources/mapper/PlayerMapper.xml new file mode 100644 index 0000000..98b226b --- /dev/null +++ b/admin/src/main/resources/mapper/PlayerMapper.xml @@ -0,0 +1,22 @@ + + + + + diff --git a/admin/src/main/resources/mapper/RecordMapper.xml b/admin/src/main/resources/mapper/RecordMapper.xml new file mode 100644 index 0000000..92241c5 --- /dev/null +++ b/admin/src/main/resources/mapper/RecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/basics/pom.xml b/basics/pom.xml new file mode 100644 index 0000000..f13b9c8 --- /dev/null +++ b/basics/pom.xml @@ -0,0 +1,146 @@ + + + + + mine_clearance + com.lightyears.mine_clearance + 1.0 + + 4.0.0 + basics + basics + + + + org.springframework.boot + spring-boot-starter-web + + + com.baomidou + mybatis-plus-boot-starter + + + org.springframework.boot + spring-boot-starter-aop + + + mysql + mysql-connector-java + + + + com.alibaba + druid-spring-boot-starter + + + + com.alibaba + fastjson + + + com.baomidou + mybatis-plus-generator + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + org.apache.commons + commons-pool2 + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.freemarker + freemarker + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + + cn.hutool + hutool-all + + + commons-io + commons-io + + + org.apache.commons + commons-collections4 + + + com.lightyears.mine_clearance + common + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.springframework.boot + spring-boot-starter-test + test + + + + + basics + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + utf-8 + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.lightyears.basics.BasicsApp + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + diff --git a/basics/src/main/java/com/lightyears/basics/BasicsApp.java b/basics/src/main/java/com/lightyears/basics/BasicsApp.java new file mode 100644 index 0000000..b52a70b --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/BasicsApp.java @@ -0,0 +1,19 @@ +package com.lightyears.basics; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.util.TimeZone; + +@EnableScheduling +@SpringBootApplication +@EnableTransactionManagement +public class BasicsApp { + public static void main(String[] args) { + // 设置时区 + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + SpringApplication.run(BasicsApp.class, args); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/annotation/DataVerification.java b/basics/src/main/java/com/lightyears/basics/annotation/DataVerification.java new file mode 100644 index 0000000..7aca3aa --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/annotation/DataVerification.java @@ -0,0 +1,9 @@ +package com.lightyears.basics.annotation; + +import java.lang.annotation.*; + +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface DataVerification { +} diff --git a/basics/src/main/java/com/lightyears/basics/aspect/DataVerificationAspect.java b/basics/src/main/java/com/lightyears/basics/aspect/DataVerificationAspect.java new file mode 100644 index 0000000..c41c519 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/aspect/DataVerificationAspect.java @@ -0,0 +1,65 @@ +package com.lightyears.basics.aspect; + +import cn.hutool.crypto.digest.MD5; +import com.github.pagehelper.util.StringUtil; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.basics.exception.GlobalException; +import com.lightyears.basics.util.StaticUtil; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.util.Collection; +import java.util.Map; + +@Aspect +@Component +public class DataVerificationAspect { + /** + * 过滤类 + * 指定自定义注解为切入点 + **/ + @Pointcut("@annotation(com.lightyears.basics.annotation.DataVerification)") + public void checkPoint() { + } + + /** + * 前置 + */ + @Before("checkPoint()") + public void doAround(JoinPoint joinPoint) throws GlobalException { + RequestAttributes ra = RequestContextHolder.getRequestAttributes(); + ServletRequestAttributes sra = (ServletRequestAttributes) ra; + assert sra != null; + HttpServletRequest request = sra.getRequest(); + String checkKey = request.getHeader("checkKey"); + Map paramMap = request.getParameterMap(); + StringBuffer paramsStr = new StringBuffer(); + + if (StringUtil.isEmpty(checkKey)) { + throw new GlobalException(MessageEnum.CHECK_KEY_ERROR); + } + Object[] params = joinPoint.getArgs(); + if(paramMap.size() > 0) { + Collection values = paramMap.values(); + for (String[] value : values) { + paramsStr.append(value[0]); + } + } else { + if(params.length == 1) { + paramsStr.append(params[0].toString()); + } + } + String testKey = MD5.create().digestHex(MD5.create().digestHex(paramsStr.append(StaticUtil.PRIVATE_KEY).toString())); + if (!checkKey.equals(testKey)) { + throw new GlobalException(MessageEnum.CHECK_KEY_ERROR); + } + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/config/AppConfig.java b/basics/src/main/java/com/lightyears/basics/config/AppConfig.java new file mode 100644 index 0000000..740b0b1 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/config/AppConfig.java @@ -0,0 +1,16 @@ +package com.lightyears.basics.config; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@NoArgsConstructor +@AllArgsConstructor +@ConfigurationProperties(prefix = "appconfig") +public class AppConfig { + private Float version; +} diff --git a/basics/src/main/java/com/lightyears/basics/configuration/RedisConfig.java b/basics/src/main/java/com/lightyears/basics/configuration/RedisConfig.java new file mode 100644 index 0000000..02e33de --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/configuration/RedisConfig.java @@ -0,0 +1,86 @@ +package com.lightyears.basics.configuration; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +// 开启redis缓存功能 +@EnableCaching +// 备注这是一个配置类 +@Configuration +public class RedisConfig extends CachingConfigurerSupport { + + /** + * 配置redis模板文件 + * @param redisConnectionFactory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisSerializer serializer = redisSerializer(); + // 创建RedisTemplate对象 + RedisTemplate redisTemplate = new RedisTemplate<>(); + // 配置连接工厂 + redisTemplate.setConnectionFactory(redisConnectionFactory); + // redis key 序列化方式使用stringSerial + redisTemplate.setKeySerializer(new StringRedisSerializer()); + // redis value 序列化方式使用jackson + redisTemplate.setValueSerializer(serializer); + // redis hash key 序列化方式使用stringSerial + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + // redis hash value 序列化方式使用jackson + redisTemplate.setHashValueSerializer(serializer); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + /** + * 配置序列化 + * @return + */ + @Bean + public RedisSerializer redisSerializer() { + // 定义Jackson2JsonRedisSerializer序列化对象 + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会报异常 + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + serializer.setObjectMapper(objectMapper); + return serializer; + } + + /** + * 自定义缓存管理器 + * @param redisConnectionFactory + * @return + */ + @Bean + public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) { + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory); + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration + .defaultCacheConfig() + // 设置value 为自动转json的Object + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())) + // 缓存有效期为一天 + .entryTtl(Duration.ofDays(1)); + return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/configuration/ScheduledConfig.java b/basics/src/main/java/com/lightyears/basics/configuration/ScheduledConfig.java new file mode 100644 index 0000000..30a8f30 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/configuration/ScheduledConfig.java @@ -0,0 +1,24 @@ +package com.lightyears.basics.configuration; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +import java.util.TimeZone; + +@Configuration +public class ScheduledConfig { + @Bean + public ThreadPoolTaskScheduler threadPoolTaskScheduler() { + ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); + threadPoolTaskScheduler.setPoolSize(3); + threadPoolTaskScheduler.setRemoveOnCancelPolicy(true); + return threadPoolTaskScheduler; + } + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() { + return jacksonObjectMapperBuilder -> + jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8")); + } +} \ No newline at end of file diff --git a/basics/src/main/java/com/lightyears/basics/controller/BaseController.java b/basics/src/main/java/com/lightyears/basics/controller/BaseController.java new file mode 100644 index 0000000..c5a1c83 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/controller/BaseController.java @@ -0,0 +1,55 @@ +package com.lightyears.basics.controller; + +import com.lightyears.common.domain.entity.Player; +import com.lightyears.basics.util.RedisCache; +import com.lightyears.basics.util.StaticUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class BaseController { + + @Autowired + private RedisCache redisCache; + + /** + * 得到request对象 + * + * @return + */ + public HttpServletRequest getRequest() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getRequest(); + return request; + } + + /** + * 得到respones对象 + * @return + */ + public HttpServletResponse getResponse() { + HttpServletResponse request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getResponse(); + return request; + } + + /** + * 得到当前登录用户信息 + * + * @return + */ + public Player getUserInfo() { + // 获取请求头中的token数据 + String token = getRequest().getHeader("Tracecode"); + if(token == null) { + token = this.getRequest().getParameter("Tracecode"); + } + String key = StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(token); + // 获取登录用户信息 + Player user = redisCache.getCacheObject(key); + return user; + } +} diff --git a/basics/src/main/java/com/lightyears/basics/controller/ChallengeController.java b/basics/src/main/java/com/lightyears/basics/controller/ChallengeController.java new file mode 100644 index 0000000..5e35a4c --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/controller/ChallengeController.java @@ -0,0 +1,39 @@ +package com.lightyears.basics.controller; + +import com.lightyears.basics.annotation.DataVerification; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.basics.service.IPlayerAssetsService; +import com.lightyears.basics.util.ResultUtil; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +@CrossOrigin +@RestController +@RequestMapping("/challenge") +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class ChallengeController extends BaseController{ + private final IPlayerAssetsService playerAssetsService; + + // @DataVerification + @GetMapping("/list") + public ResModeBase list() { + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), new ArrayList<>()); + } + // @DataVerification + @GetMapping("/playerAssert") + @ApiOperation(value = "获取玩家资产信息", notes = "挑战榜") + public ResModeBase playerAssert(){ + List assets = playerAssetsService.getPlayerAssets(this.getUserInfo().getUser_id()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), assets); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/controller/ClientController.java b/basics/src/main/java/com/lightyears/basics/controller/ClientController.java new file mode 100644 index 0000000..ca62f6f --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/controller/ClientController.java @@ -0,0 +1,183 @@ +package com.lightyears.basics.controller; + +import cn.hutool.core.date.DateUtil; +import com.lightyears.basics.annotation.DataVerification; +import com.lightyears.basics.service.IClearanceLogService; +import com.lightyears.basics.service.IGameSystemService; +import com.lightyears.basics.service.ILogService; +import com.lightyears.basics.service.INoticeService; +import com.lightyears.basics.util.ResultUtil; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.Date; + +@CrossOrigin +@RestController +@RequestMapping("/saolei") +@Api("扫雷 客户端调用接口:") +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class ClientController extends BaseController{ + private final IGameSystemService gameSystemServiceImpl; + private final INoticeService noticeServiceImpl; + private final ILogService logService; + private final IClearanceLogService clearanceLogService; + + @RequestMapping(value = "/touristLogin/{id}", method = RequestMethod.GET) + @ApiImplicitParam(paramType="path", name = "id", value = "用户openId", example = "123", required = true, dataType = "Integer") + @ApiOperation(value = "三方登陆", notes = "参数 QQ/微信open_id(tokenId) 新建用户 isNewUser = true") + public ResModeBase touristLogin(@PathVariable String id) { + return this.gameSystemServiceImpl.touristlogin(id); + } + + @DataVerification + @RequestMapping(value = "/checkName", method = RequestMethod.POST) + @ApiOperation(value = "昵称验证", notes = "昵称是否重复,true 代表昵称可用") + public ResModeBase checkName(@RequestParam("userName") String userName) { + return this.gameSystemServiceImpl.checkName(userName); + } + + @DataVerification + @RequestMapping(value = "/updateName", method = RequestMethod.POST) + @ApiOperation(value = "修改昵称", notes = "更新指定ID玩家的名称(玩家第一次登录时,系统分配默认名称,并提供玩家一次改名的机会)") + public ResModeBase updateName(@RequestParam("userName") String userName) { + return this.gameSystemServiceImpl.updateName(this.getUserInfo().getUser_id(), userName); + } + + @DataVerification + @RequestMapping(value = "/add_Gold", method = RequestMethod.POST) + @ApiOperation(value = "金币存储", notes = "每次 用户主动向数据库 存储金币") + public ResModeBase add_Gold(@ApiParam(value = "货币数", example = "1") @RequestParam("gold") int gold, + @ApiParam(value = "货币类型(0.金币)", example = "0")@RequestParam("type") int type, + @ApiParam(value = "货币变化说明", example = "游戏增加货币") @RequestParam("remark")String remark) { + return this.gameSystemServiceImpl.pushGoldImpl(this.getUserInfo().getUser_id(), gold, type, remark); + } + + @DataVerification + @RequestMapping(value = "/sub_Gold", method = RequestMethod.POST) + @ApiOperation(value = "金币取出", notes = "与“金币存储”相反,从用户账号扣除指定金币,如果余额不够扣费") + public ResModeBase sub_Gold(@ApiParam(value = "货币数", example = "1") @RequestParam("gold") int gold, + @ApiParam(value = "货币类型(0.金币)", example = "0")@RequestParam("type") int type, + @ApiParam(value = "货币变化说明", example = "扣手续费") @RequestParam("remark")String remark) { + return this.gameSystemServiceImpl.pullGoldImpl(this.getUserInfo().getUser_id(), gold, type, remark); + } + + @DataVerification + @RequestMapping(value = "/saveFile", method = RequestMethod.POST) + @ApiOperation(value = "数据存档", notes = "本都游戏数据上传服务器保存") + public ResModeBase saveFile(@ApiParam(value = "存档数据") @RequestParam(value = "record", required = false) String record, + @ApiParam(value = "存档类型0 皮肤 1 记录 2游戏设置", example = "1") @RequestParam(value = "record_type") Integer record_type) { + return this.gameSystemServiceImpl.saveFileImpl(this.getUserInfo().getUser_id(), record, record_type); + } + + @DataVerification + @RequestMapping(value = "/readFile", method = RequestMethod.POST) + @ApiOperation(value = "读取存档", notes = "读取服务器存档") + public ResModeBase readFile(@ApiParam(value = "存档类型0 皮肤 1 记录 2游戏设置", example = "1") @RequestParam(value = "record_type") Integer record_type) { + return this.gameSystemServiceImpl.readFile(this.getUserInfo().getUser_id(), record_type); + } + + @DataVerification + @RequestMapping(value = "/saveLog", method = RequestMethod.POST) + @ApiOperation(value = "提交游戏记录", notes = "每次游戏完成 进行记录提交") + public ResModeBase saveLog(@ApiParam(value = " 游戏难度:1 - 普通 2 困难 3 大师 4 超凡", example = "1") @RequestParam(value = "level", required = false) Integer level, + @ApiParam(value = "本剧游戏所用时间", example = "1") @RequestParam(value = "game_time") int game_time, + @RequestParam(value = "bvs3") float bvs3, + @RequestParam(value = "bv3") float bv3, + @RequestParam(value = "video") String video, + @RequestParam(value = "gameinfo") String gameinfo, + @RequestParam(value = "nf") boolean nf) { + return this.gameSystemServiceImpl.saveLogImpl(this.getUserInfo(), level, game_time, bvs3, bv3, video, gameinfo,nf); + } + + @DataVerification + @RequestMapping(value = "/rankingLog", method = RequestMethod.POST) + @ApiOperation(value = "综合排行榜", notes = "所有玩家的排行榜信息") + public ResModeBase ranking( + @ApiParam(value = "当前页", example = "1") @RequestParam(value = "pageIndex") int pageIndex, + @ApiParam(value = "每页数量", example = "1") @RequestParam(value = "pageSize") int pageSize, + @ApiParam(value = "游戏难度:-1综合 1 - 普通 2 困难 3 大师 4 超凡", example = "1") @RequestParam(value = "level") int level) { + return this.gameSystemServiceImpl.ranking(pageIndex, pageSize, level); + } + + @DataVerification + @RequestMapping(value = "/userLog", method = RequestMethod.POST) + @ApiOperation(value = "玩家个人 排行名次以及信息", notes = "") + public ResModeBase log(@ApiParam(value = "游戏难度:-1综合 1 - 普通 2 困难 3 大师 4 超凡", example = "1") @RequestParam(value = "level") int level) { + return this.gameSystemServiceImpl.log(this.getUserInfo().getUser_id(), level); + } + + @DataVerification + @RequestMapping(value = "/getList", method = RequestMethod.GET) + @ApiOperation(value = "公告查询", notes = "1") + public ResModeBase getList() { + return this.noticeServiceImpl.getList(this.getUserInfo().getUser_id()); + } + + + @DataVerification + @RequestMapping(value = "/getContent", method = RequestMethod.GET) + @ApiOperation(value = "公告内容查询", notes = "1") + public ResModeBase getContent(@ApiParam(value = "公告id", example = "1") @RequestParam(value = "id") int id) { + return this.noticeServiceImpl.getContent(id); + } + + @DataVerification + @RequestMapping(value = "/getGameData", method = RequestMethod.POST) + @ApiOperation(value = "回放数据查询", notes = "1") + public ResModeBase getGameData(@ApiParam(value = "排行榜id", example = "1") @RequestParam(value = "id") Integer id,@ApiParam(value = "榜单类型:1.普通榜,2挑战榜", example = "1") Integer type) { + return this.gameSystemServiceImpl.getGameData(id, type); + } + + @DataVerification + @RequestMapping(value = "/getSystemTime", method = RequestMethod.GET) + @ApiOperation(value = "获取系统时间", notes = "1") + public ResModeBase getSystemTime() { + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), DateUtil.format(new Date(),"yyyy-MM-dd")); + } + + @DataVerification + @RequestMapping(value = "/cancellationAccount", method = RequestMethod.GET) + @ApiOperation(value = "注销账号", notes = "1") + public ResModeBase cancellationAccount(@ApiParam(value = "身份token", example = "1") @RequestParam(value = "checkToken")String checkToken, HttpServletRequest request) { + if(checkToken.equals(request.getHeader("Tracecode"))){ + gameSystemServiceImpl.cancellationAccount(this.getUserInfo().getUser_id()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } else { + return ResultUtil.result(MessageEnum.CHECK_LOGGING_ERROR.getCode(), MessageEnum.CHECK_LOGGING_ERROR.getMessage()); + } + } + + @RequestMapping(value = "/refreshRankCache", method = RequestMethod.GET) + @ApiOperation(value = "刷新排行榜缓存", notes = "1") + public ResModeBase refreshRankCache(@RequestParam(value = "key")Integer key) { + if(key == 43626546){ + // 排行榜缓存 + logService.cacheRankList(null); + // 雷神之塔缓存 + clearanceLogService.cachePlayerClearanceRank(); + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } + + @RequestMapping(value = "/saveClearanceLog", method = RequestMethod.POST) + @ApiOperation(value = "写入雷神之塔闯关记录", notes = "1") + public ResModeBase saveClearanceLog(@ApiParam(value = "游戏数据", example = "1") @RequestParam(value = "data")String data) { + clearanceLogService.saveClearanceLog(this.getUserInfo().getUser_id(), data); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } + + @RequestMapping(value = "/getPlayerClearanceLog", method = RequestMethod.GET) + @ApiOperation(value = "获取雷神之塔个人信息", notes = "1") + public ResModeBase getPlayerClearanceLog(@RequestParam(value = "type", required = false, defaultValue = "0")Integer type) { + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), clearanceLogService.getPlayer(this.getUserInfo().getUser_id(), this.getUserInfo().getUser_name(), type)); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/controller/SystemController.java b/basics/src/main/java/com/lightyears/basics/controller/SystemController.java new file mode 100644 index 0000000..d9e062b --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/controller/SystemController.java @@ -0,0 +1,23 @@ +package com.lightyears.basics.controller; + +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Notice; +import com.lightyears.basics.service.ISystemService; +import io.swagger.annotations.Api; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@CrossOrigin +@RestController +@RequestMapping("/sys") +@Api("扫雷 管理端调用接口:") +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class SystemController extends BaseController{ + private final ISystemService systemService; + + @RequestMapping(value = "/publishNotice", method = RequestMethod.POST) + public ResModeBase publishNotice(@RequestBody Notice notice) { + return systemService.publishNotice(notice); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/exception/BussinessException.java b/basics/src/main/java/com/lightyears/basics/exception/BussinessException.java new file mode 100644 index 0000000..205bda6 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/exception/BussinessException.java @@ -0,0 +1,18 @@ +package com.lightyears.basics.exception; + + +import com.lightyears.common.domain.enums.MessageEnum; + +/** + * @author fengshuonan + * @Description 业务异常的封装 + */ +public class BussinessException extends GlobalException { + public BussinessException(MessageEnum messageEnum) { + super(messageEnum.getCode(), messageEnum.getMessage()); + } + + public BussinessException(Integer code, String message) { + super(code, message); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/exception/GlobalException.java b/basics/src/main/java/com/lightyears/basics/exception/GlobalException.java new file mode 100644 index 0000000..1a04fe0 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/exception/GlobalException.java @@ -0,0 +1,46 @@ +package com.lightyears.basics.exception; + +import com.lightyears.common.domain.enums.MessageEnum; + +/*** + * 全局异常捕捉 统一返回 model + * */ +public class GlobalException extends RuntimeException { + + //友好提示的code码 + protected int friendlyCode; + + //友好提示 + protected String friendlyMsg; + + + protected GlobalException(int friendlyCode, String friendlyMsg) { + this.setValues(friendlyCode, friendlyMsg); + } + + public GlobalException(MessageEnum messageEnum) { + this.setValues(messageEnum.getCode(), messageEnum.getMessage()); + } + + private void setValues(int friendlyCode, String friendlyMsg) { + this.friendlyCode = friendlyCode; + this.friendlyMsg = friendlyMsg; + } + + public int getCode() { + return friendlyCode; + } + + public void setCode(int code) { + this.friendlyCode = code; + } + + public String getMessage() { + return friendlyMsg; + } + + public void setMessage(String message) { + this.friendlyMsg = message; + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/exception/MyExceptionHandle.java b/basics/src/main/java/com/lightyears/basics/exception/MyExceptionHandle.java new file mode 100644 index 0000000..8c02824 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/exception/MyExceptionHandle.java @@ -0,0 +1,26 @@ +package com.lightyears.basics.exception; + +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.basics.util.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +@Slf4j +@ControllerAdvice +public class MyExceptionHandle { + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public ResModeBase handle(Exception e) { + if (e instanceof GlobalException) { + GlobalException myException = (GlobalException) e; + return ResultUtil.result(myException.getCode(), myException.getMessage()); + } else { + log.error("系统异常", e); + return ResultUtil.result(MessageEnum.UNKNOWN_ERROR.getCode(), MessageEnum.UNKNOWN_ERROR.getMessage()); + } + } +} diff --git a/basics/src/main/java/com/lightyears/basics/filter/TokenFilter.java b/basics/src/main/java/com/lightyears/basics/filter/TokenFilter.java new file mode 100644 index 0000000..1afb80b --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/filter/TokenFilter.java @@ -0,0 +1,119 @@ +package com.lightyears.basics.filter; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.util.StringUtil; +import com.lightyears.basics.config.AppConfig; +import com.lightyears.common.domain.entity.Player; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.basics.util.RedisCache; +import com.lightyears.basics.util.StaticUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.annotation.Resource; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Component +public class TokenFilter implements Filter{ + @Resource + private RedisCache redisCache; + @Resource + private AppConfig appConfig; + + @Override + public void init(FilterConfig filterConfig) { + ServletContext servletContext = filterConfig.getServletContext(); + ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); + redisCache = (RedisCache) ctx.getBean("redisCache"); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + // 刷新缓存不验证 + if(request.getRequestURI().indexOf("refreshRankCache")<0){ + // 版本号验证 + String version = request.getHeader("version"); + if (StrUtil.isEmpty(version)) { + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + try{ + Float versionCode = Float.valueOf(version); +// log.info("version :" + appConfig.getVersion()); + if(versionCode < appConfig.getVersion()) { + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + }catch (Exception e) { + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + } + + String tracecode = request.getHeader("Tracecode"); + Boolean flag = request.getRequestURI().indexOf("touristLogin")<0 && request.getRequestURI().indexOf("getSystemTime") < 0 && request.getRequestURI().indexOf("swagger-ui")<0 && request.getRequestURI().indexOf("swagger-resources")<0 && request.getRequestURI().indexOf("v2") < 0 && request.getRequestURI().indexOf("refreshRankCache")<0; + + // 登录放行 + if(flag){ + // 判断身份码, 是否已登录 + if((StringUtil.isEmpty(tracecode) || !redisCache.hasKey(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode)))){ + /** + * 不是登录 || 身份码不存在 || 未在登录列表 就拒绝访问 + */ + this.authcReq(response, MessageEnum.SYSTEM_ERROR.getCode(), MessageEnum.SYSTEM_ERROR.getMessage()); + return; + } + Player player = redisCache.getCacheObject(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode)); + String token = redisCache.getCacheObject(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString())).toString(); + if(!tracecode.equals(token)) { + /** + * 登录失效,已被异地登录 + */ + this.authcReq(response, MessageEnum.LOCATION_ERROR.getCode(), MessageEnum.LOCATION_ERROR.getMessage()); + return; + } + // 重置身份缓存过期时间 + redisCache.expire(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString()), 1, TimeUnit.HOURS); + // 重置身份认证过期时间 + redisCache.expire(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode), 1, TimeUnit.HOURS); + } + + //执行 + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + + } + + /** + * 响应访问 + * @param response + * @throws IOException + */ + private void authcReq(HttpServletResponse response, Integer code, String msg) throws IOException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentType("application/json; charset=utf-8"); + PrintWriter writer = response.getWriter(); + Map map = new HashMap<>(); + map.put("code", code); + map.put("msg", msg); + writer.print(JSONObject.toJSON(map)); + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/init/ChallengeDataInit.java b/basics/src/main/java/com/lightyears/basics/init/ChallengeDataInit.java new file mode 100644 index 0000000..f51f38d --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/init/ChallengeDataInit.java @@ -0,0 +1,38 @@ +package com.lightyears.basics.init; + +import com.lightyears.basics.service.IClearanceLogService; +import com.lightyears.basics.service.ILogService; +import com.lightyears.basics.util.RedisCache; +import com.lightyears.basics.util.StaticUtil; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.annotation.Resource; + +; + +/** + * 挑战数据初始化 + */ +@Component +public class ChallengeDataInit { + @Resource + private ILogService logService; + @Resource + private IClearanceLogService clearanceLogService; + + @PostConstruct + public void init() { + // 缓存排行榜数据 + logService.cacheRankList(null); + // 缓存雷神之塔玩家关卡数据 + clearanceLogService.cachePlayerClearanceRank(); + } + + @PreDestroy + public void destroy() { + // 写入持久层 + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/mapper/AssertLogMapper.java b/basics/src/main/java/com/lightyears/basics/mapper/AssertLogMapper.java new file mode 100644 index 0000000..a76e932 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/mapper/AssertLogMapper.java @@ -0,0 +1,18 @@ +package com.lightyears.basics.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.AssertLog; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface AssertLogMapper extends BaseMapper { + +} diff --git a/basics/src/main/java/com/lightyears/basics/mapper/ClearanceLogMapper.java b/basics/src/main/java/com/lightyears/basics/mapper/ClearanceLogMapper.java new file mode 100644 index 0000000..6e6dd96 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/mapper/ClearanceLogMapper.java @@ -0,0 +1,26 @@ +package com.lightyears.basics.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.ClearanceRankDto; +import com.lightyears.common.domain.entity.ClearanceLog; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-06-02 + */ +@Mapper +public interface ClearanceLogMapper extends BaseMapper { + /** + * 获取玩家最高闯关 关卡数据 + * @return + */ + List getPlayerClearanceLogs(@Param("userId")Integer userId); +} diff --git a/basics/src/main/java/com/lightyears/basics/mapper/ListRankMapper.java b/basics/src/main/java/com/lightyears/basics/mapper/ListRankMapper.java new file mode 100644 index 0000000..1b373ff --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/mapper/ListRankMapper.java @@ -0,0 +1,25 @@ +package com.lightyears.basics.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.entity.ListRank; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface ListRankMapper extends BaseMapper { + int initRank(@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId); + List getRankList(@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId, @Param("state") Integer state); + List getNewRankList (@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId); + ListRankDto getRankByInsRank(@Param("instanceId") Integer instanceId,@Param("rank") Integer rank); +} diff --git a/basics/src/main/java/com/lightyears/basics/mapper/LogMapper.java b/basics/src/main/java/com/lightyears/basics/mapper/LogMapper.java new file mode 100644 index 0000000..07ca845 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/mapper/LogMapper.java @@ -0,0 +1,29 @@ +package com.lightyears.basics.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.entity.Log; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface LogMapper extends BaseMapper { + List paging(@Param("level") Integer level, @Param("userId")Integer userId); + //综合查询 三种难度加起来 获取排名 + List syntheticalPaging(); + // 查询用户综合排名 + Map getComprehensiveRankByUserId(@Param("userId") Integer userId); + //根据User_id和 level 查询排名 + Map getRankByLevelUserId(@Param("level")int level, @Param("userId") Integer userId); +} diff --git a/basics/src/main/java/com/lightyears/basics/mapper/NoticeMapper.java b/basics/src/main/java/com/lightyears/basics/mapper/NoticeMapper.java new file mode 100644 index 0000000..e33b81a --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/mapper/NoticeMapper.java @@ -0,0 +1,23 @@ +package com.lightyears.basics.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.NoticeDto; +import com.lightyears.common.domain.entity.Notice; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +@Mapper +public interface NoticeMapper extends BaseMapper { + List getList(@Param("type") Integer type, @Param("playerId") Integer playerId); + String getContent(@Param("id")Integer id); +} diff --git a/basics/src/main/java/com/lightyears/basics/mapper/PlayerAssetsMapper.java b/basics/src/main/java/com/lightyears/basics/mapper/PlayerAssetsMapper.java new file mode 100644 index 0000000..33ee9b4 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/mapper/PlayerAssetsMapper.java @@ -0,0 +1,33 @@ +package com.lightyears.basics.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface PlayerAssetsMapper extends BaseMapper { + // 货币存放服务器 + int addGold(@Param("id") int id, @Param("gold") int gold, @Param("version") Long version); + + // 从服务器取出货币 + int reduceGold(@Param("id") int id,@Param("gold") int gold, @Param("version") Long version); + + /** + * 获取用户资产 + * @param playerId + * @return + */ + List getPlayerAssets(@Param("playerId") int playerId); +} diff --git a/basics/src/main/java/com/lightyears/basics/mapper/PlayerMapper.java b/basics/src/main/java/com/lightyears/basics/mapper/PlayerMapper.java new file mode 100644 index 0000000..f125426 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/mapper/PlayerMapper.java @@ -0,0 +1,31 @@ +package com.lightyears.basics.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.Player; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

+ * 扫雷玩家表 Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface PlayerMapper extends BaseMapper { + /** + * 设置不活跃玩家标记 + * @param dateNum 秒数时间戳 + * @return + */ + int setInactivePlayer(@Param("dateNum") Long dateNum); + + /** + * 设置活跃玩家标记 + * @param dateNum 秒数时间戳 + * @return + */ + int setActivePlayer(@Param("dateNum") Long dateNum); +} diff --git a/basics/src/main/java/com/lightyears/basics/mapper/RecordMapper.java b/basics/src/main/java/com/lightyears/basics/mapper/RecordMapper.java new file mode 100644 index 0000000..02d2b21 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/mapper/RecordMapper.java @@ -0,0 +1,18 @@ +package com.lightyears.basics.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.Record; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 游戏存档 Mapper 接口 + *

x + * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface RecordMapper extends BaseMapper { + +} diff --git a/basics/src/main/java/com/lightyears/basics/schedule/BasicsTask.java b/basics/src/main/java/com/lightyears/basics/schedule/BasicsTask.java new file mode 100644 index 0000000..e5f6e95 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/schedule/BasicsTask.java @@ -0,0 +1,75 @@ +package com.lightyears.basics.schedule; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.lightyears.basics.mapper.AssertLogMapper; +import com.lightyears.basics.mapper.PlayerMapper; +import com.lightyears.basics.service.ILogService; +import com.lightyears.basics.service.INoticeService; +import com.lightyears.common.domain.entity.AssertLog; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Slf4j +@Component +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class BasicsTask { + private final ILogService logService; + private final AssertLogMapper assertLogMapper; + private final INoticeService noticeService; + private final PlayerMapper playerMapper; + + + /** + * 刷新综合榜数据 5分钟 + */ + @Scheduled(cron = "0 */1 * * * ?") + public void refreshComprehensiveRank() { + log.info("-----------刷新排行数据----------"); + // 重新计算、缓存综合榜数据 + logService.cacheRankList(-1); + } + + /** + * 每日 3点执行 删除用户资产log(保留最近7日记录) + */ + @Scheduled(cron = "0 0 3 * * ?") + public void deleteRecords(){ + Date date = DateUtil.offsetDay(new Date(), -7); + assertLogMapper.delete(new LambdaQueryWrapper().lt(AssertLog::getCreateDate, date)); + } + + /** + * 每日 0点执行 删除用户过期公告 + */ + @Scheduled(cron = "0 0 0 * * ?") + public void deleteNotices(){ + noticeService.deleteNoticeForTask(); + } + + /** + * 每月 1号 1点7分执行 标记上月不活跃用户 + */ + @Scheduled(cron = "0 7 1 1 * ?") + public void markPlayerActive(){ + // 30天前的时间戳 + Long time = System.currentTimeMillis() / 1000 - 2592000L; + // 标记上月活跃用户 + playerMapper.setActivePlayer(time); + // 标记上月不活跃用户 + playerMapper.setInactivePlayer(time); + } + + /** + * 每月 1号 1点13分执行 刷新基础排行榜(排除上月不活跃玩家) + */ + @Scheduled(cron = "0 13 1 1 * ?") + public void refreshRankList(){ + logService.cacheRankList(null); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/service/IClearanceLogService.java b/basics/src/main/java/com/lightyears/basics/service/IClearanceLogService.java new file mode 100644 index 0000000..98d2b8e --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/IClearanceLogService.java @@ -0,0 +1,42 @@ +package com.lightyears.basics.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.PlayerClearanceLogInfoDto; +import com.lightyears.common.domain.entity.ClearanceLog; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-06-02 + */ +public interface IClearanceLogService extends IService { + + /** + * 保存闯关记录 + * @param playerId + * @param layersNum + * @param gameData + */ + void saveClearanceLog(Integer playerId, String gameData); + + /** + * 获取用户闯关记录 + * @param playerId 用户id + * @param playerName 用户名 + * @return + */ + PlayerClearanceLogInfoDto getPlayer(Integer playerId, String playerName, Integer type); + + /** + * 缓存用户闯关记录 + */ + void cachePlayerClearanceRank(); + + /** + * 删除用户闯关记录缓存 + */ + void deletCacheByPlayerId(Integer playerId); +} diff --git a/basics/src/main/java/com/lightyears/basics/service/IGameSystemService.java b/basics/src/main/java/com/lightyears/basics/service/IGameSystemService.java new file mode 100644 index 0000000..6a1ee01 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/IGameSystemService.java @@ -0,0 +1,41 @@ +package com.lightyears.basics.service; + +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Player; + +public interface IGameSystemService { + + + ResModeBase touristlogin(String open_id); + + ResModeBase checkName(String userName); + + ResModeBase updateName(int userId, String userName); + + ResModeBase pushGoldImpl(Integer userId, int gold, int type, String remark); + + ResModeBase pushGold(Integer userId, int gold, int type, String remark); + + ResModeBase pullGoldImpl(Integer userId, int gold, int type, String remark); + + ResModeBase pullGold(Integer userId, int gold, int type, String remark); + + ResModeBase saveFileImpl(int userId, String record, Integer record_type); + + ResModeBase saveFile(int userId, String record, Integer record_type); + + ResModeBase readFile(int userId, int record_type); + + ResModeBase saveLogImpl(Player player, Integer level, int game_time, float bvs3, float bv3, String video, String gameinfo, boolean nf); + + ResModeBase saveLog(Player player, Integer level, int game_time, float bvs3, float bv3, String video, String gameinfo, boolean nf); + + ResModeBase ranking(int pageIndex, int pageSize, int level); + + ResModeBase log(int userId, int level); + + ResModeBase getGameData(Integer id, Integer type); + + void cancellationAccount(Integer userId); + +} diff --git a/basics/src/main/java/com/lightyears/basics/service/ILogService.java b/basics/src/main/java/com/lightyears/basics/service/ILogService.java new file mode 100644 index 0000000..a2a7b32 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/ILogService.java @@ -0,0 +1,35 @@ +package com.lightyears.basics.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.entity.Log; + +import java.util.List; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface ILogService extends IService { + /** + * 查询排行榜 + * @param level 游戏难度:1 - 普通 2 困难 3 大师 + * @return + */ + List getRankList(Integer level); + + /** + * 排行榜数据写入缓存 + */ + void cacheRankList(Integer level); + + /** + * 删除缓存 + * @param userId + */ + void deleteCacheByUserId(Integer userId); +} diff --git a/basics/src/main/java/com/lightyears/basics/service/INoticeService.java b/basics/src/main/java/com/lightyears/basics/service/INoticeService.java new file mode 100644 index 0000000..e673ad2 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/INoticeService.java @@ -0,0 +1,20 @@ +package com.lightyears.basics.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Notice; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +public interface INoticeService extends IService { + ResModeBase getList(Integer playerId); + ResModeBase getContent(Integer id); + void deleteNoticeForTask(); +} diff --git a/basics/src/main/java/com/lightyears/basics/service/IPlayerAssetsService.java b/basics/src/main/java/com/lightyears/basics/service/IPlayerAssetsService.java new file mode 100644 index 0000000..75484f2 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/IPlayerAssetsService.java @@ -0,0 +1,38 @@ +package com.lightyears.basics.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +public interface IPlayerAssetsService extends IService { + /** + * 添加金币 + * @param id id + * @param gold 增加后的金币 + */ + Integer addGold(int id, int gold); + + /** + * 扣除金币 + * @param id id + * @param gold 需要扣减的金币 + */ + Integer reduceGold(int id, int gold); + + /** + * 获取指定用户的资产 + * @param playerId 用户id + * @return + */ + List getPlayerAssets(int playerId); +} diff --git a/basics/src/main/java/com/lightyears/basics/service/IPlayerService.java b/basics/src/main/java/com/lightyears/basics/service/IPlayerService.java new file mode 100644 index 0000000..86198a3 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/IPlayerService.java @@ -0,0 +1,15 @@ +package com.lightyears.basics.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.Player; + +/** + *

+ * 扫雷玩家表 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface IPlayerService extends IService { +} diff --git a/basics/src/main/java/com/lightyears/basics/service/IRecordService.java b/basics/src/main/java/com/lightyears/basics/service/IRecordService.java new file mode 100644 index 0000000..e7fb8c8 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/IRecordService.java @@ -0,0 +1,16 @@ +package com.lightyears.basics.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.Record; + +/** + *

+ * 游戏存档 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface IRecordService extends IService { + +} diff --git a/basics/src/main/java/com/lightyears/basics/service/ISystemService.java b/basics/src/main/java/com/lightyears/basics/service/ISystemService.java new file mode 100644 index 0000000..616e868 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/ISystemService.java @@ -0,0 +1,8 @@ +package com.lightyears.basics.service; + +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Notice; + +public interface ISystemService { + ResModeBase publishNotice(Notice notice); +} diff --git a/basics/src/main/java/com/lightyears/basics/service/impl/ClearanceLogServiceImpl.java b/basics/src/main/java/com/lightyears/basics/service/impl/ClearanceLogServiceImpl.java new file mode 100644 index 0000000..9f0087b --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/impl/ClearanceLogServiceImpl.java @@ -0,0 +1,114 @@ +package com.lightyears.basics.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.basics.mapper.ClearanceLogMapper; +import com.lightyears.common.domain.dto.ClearanceRankDto; +import com.lightyears.common.domain.dto.PlayerClearanceLogInfoDto; +import com.lightyears.common.domain.entity.ClearanceLog; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.basics.exception.BussinessException; +import com.lightyears.basics.service.IClearanceLogService; +import com.lightyears.basics.util.RedisCache; +import com.lightyears.basics.util.StaticUtil; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-06-02 + */ +@Service +public class ClearanceLogServiceImpl extends ServiceImpl implements IClearanceLogService { + + @Resource + private RedisCache redisCache; + + @Override + public void saveClearanceLog(Integer playerId, String gameData){ + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(StaticUtil.CLEARANCE_RANK_LIST); + Integer layersNum = operations.score(playerId).intValue() + 1; + ClearanceLog clearanceLog = baseMapper.selectOne(new LambdaQueryWrapper().eq(ClearanceLog::getPlayerId, playerId).eq(ClearanceLog::getLayersNum, layersNum).last("limit 1")); + Date now = new Date(); + if(ObjectUtils.isEmpty(clearanceLog)){ + clearanceLog = new ClearanceLog(); + clearanceLog.setData(gameData); + clearanceLog.setLayersNum(layersNum); + clearanceLog.setPlayerId(playerId); + clearanceLog.setCreateTime(now); + clearanceLog.setLastUpdateTime(now); + baseMapper.insert(clearanceLog); + } else { + clearanceLog.setData(gameData); + clearanceLog.setLastUpdateTime(now); + baseMapper.updateById(clearanceLog); + } + operations.add(clearanceLog.getPlayerId(), clearanceLog.getLayersNum()); + } + + @Override + public PlayerClearanceLogInfoDto getPlayer(Integer playerId, String playerName, Integer type){ + PlayerClearanceLogInfoDto dto = new PlayerClearanceLogInfoDto(); + dto.setPlayerName(playerName); + BoundZSetOperations bzo = redisCache.redisTemplate.boundZSetOps(StaticUtil.CLEARANCE_RANK_LIST); + Set set = bzo.rangeByScore(1D, 99999999999999D); + // 从0开始 + Long rank = bzo.reverseRank(playerId); + Double score = bzo.score(playerId); + Set overSet = bzo.rangeByScore(score, 99999999999999D); + if (rank == null || score == null) { + throw new BussinessException(MessageEnum.ERROR.getCode(), "暂无玩家的排名信息"); + } + dto.setClearanceNum(score.intValue()); + dto.setPlayerId(playerId); + Float rage = 0f; + String text = StaticUtil.CLEARANCE_LOG_TEXT_HAVE; + if(score.equals(0D)){ + rage = 0.00F; + } else{ + if (type == 1) { + rage = (set.size() - overSet.size())*1f/set.size()*100F; + text = StaticUtil.CLEARANCE_LOG_TEXT_OVER; + } else { + rage = overSet.size()*1f/set.size()*100F; + } + } + dto.setRankRate(String.format("%.3f",rage).concat("%")); + dto.setRemark(String.format(text, dto.getRankRate())); + return dto; + } + + @Override + public void cachePlayerClearanceRank(){ + List logs = this.getClearanceLogs(); + String key = StaticUtil.CLEARANCE_RANK_LIST; + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(key); + redisCache.deleteByPrefix(key); + for (ClearanceRankDto log: logs){ + operations.add(log.getPlayerId(), log.getLayersNum()); + } + } + + @Override + public void deletCacheByPlayerId(Integer playerId){ + String key = StaticUtil.CLEARANCE_RANK_LIST; + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(key); + operations.remove(playerId); + } + + public List getClearanceLogs(){ + List logs = baseMapper.getPlayerClearanceLogs(null); + return logs; + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/service/impl/GameSystemServiceImpl.java b/basics/src/main/java/com/lightyears/basics/service/impl/GameSystemServiceImpl.java new file mode 100644 index 0000000..680db37 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/impl/GameSystemServiceImpl.java @@ -0,0 +1,462 @@ +package com.lightyears.basics.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.github.pagehelper.Page; +import com.github.pagehelper.PageInfo; +import com.github.pagehelper.util.StringUtil; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; +import com.lightyears.basics.exception.BussinessException; +import com.lightyears.basics.mapper.*; +import com.lightyears.basics.service.IClearanceLogService; +import com.lightyears.basics.service.IGameSystemService; +import com.lightyears.basics.service.ILogService; +import com.lightyears.basics.service.IPlayerAssetsService; +import com.lightyears.basics.util.RedisCache; +import com.lightyears.basics.util.ResultUtil; +import com.lightyears.basics.util.StaticUtil; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.*; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service("gameSystemServiceImpl") +public class GameSystemServiceImpl implements IGameSystemService { + + @Resource + private PlayerMapper playerMapper; + @Resource + private RecordMapper recordMapper; + @Resource + private ILogService logService; + @Resource + private RedisCache redisCache; + @Resource + private IPlayerAssetsService playerAssetsService; + @Resource + private AssertLogMapper assertLogMapper; + @Resource + private ListRankMapper listRankMapper; + @Resource + private NoticeMapper noticeMapper; + @Resource + private IClearanceLogService clearanceLogService; + @Resource + private IGameSystemService gameSystemService; + Interner pool = Interners.newWeakInterner(); + private static final int AssetLimit = 999999; + + @Override + @Transactional + public ResModeBase touristlogin(String open_id) { + //通过三方open_id 查询用户是否存在 + Player player = this.playerMapper.selectOne(new QueryWrapper().eq("open_id", open_id).last("limit 1")); + Long time = System.currentTimeMillis() / 1000; + //生成 该字段暂时启用 + String user_token = UUID.randomUUID().toString(); + if (null == player) { + //极限操作 检验 + if (StaticUtil.goldSyn.containsKey(open_id)) { + return ResultUtil.result(MessageEnum.MOTION_SAFEGUARD.getCode(), MessageEnum.MOTION_SAFEGUARD.getMessage()); + } else { + StaticUtil.goldSyn.put(open_id, true); + } + player = Player.builder() + //每次登陆刷新token + .token(user_token) + //账号密码暂不考虑,使用 + .user_name("saolei") + .sex("男") + .age(18) + .open_id(open_id) + .distric("") + .status(1) + .creation_time(time.intValue()) + .update_name_count(0) + .user_gold(0) + .user_rank(0) + .local_id(-1) + .build(); + int req = playerMapper.insert(player); + if (req < 1) { + return ResultUtil.result(MessageEnum.ADD_ERROR.getCode(), MessageEnum.ADD_ERROR.getMessage()); + } + // 写入雷神之塔排名缓存 + String key = StaticUtil.CLEARANCE_RANK_LIST; + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(key); + operations.add(player.getUser_id(), 0); + + // 初始化资产 + PlayerAssets playerAsset = PlayerAssets.builder().playerId(player.getUser_id()).type(0).number(0).version(0L).build(); + playerAssetsService.save(playerAsset); + + player.setNewUser(true); + } else { + if (player.getStatus() == 0){ + return ResultUtil.result(MessageEnum.LOGIN_USERNAME_ERROR.getCode(), MessageEnum.LOGIN_USERNAME_ERROR.getMessage()); + } + //存在 更新最后登录时间 + Player upObject = Player.builder() + //每次登陆刷新token + .token(user_token) + .user_id(player.getUser_id()) + .update_time(time.intValue()).build(); + int req = playerMapper.update(upObject, new QueryWrapper().eq("user_id", player.getUser_id())); + if (req < 1) { + return ResultUtil.result(MessageEnum.UPDATE_ERROR.getCode(), MessageEnum.UPDATE_ERROR.getMessage()); + } + player.setNewUser(player.getUpdate_name_count() == 0); + } + StaticUtil.goldSyn.remove(open_id); + player.setToken(user_token); + // 获取用户资产 + List playerAsserts = playerAssetsService.getPlayerAssets(player.getUser_id()); + player.setPlayerAssets(playerAsserts); + /** + * 写入用户信息缓存,token缓存 + */ + redisCache.setCacheObject(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(user_token), player, 1, TimeUnit.HOURS); + redisCache.setCacheObject(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString()),user_token,1, TimeUnit.HOURS); + player.setOpen_id(""); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), player); + } + + @Override + public ResModeBase checkName(String userName) { + Long num = playerMapper.selectCount(new QueryWrapper().eq("user_name", userName)); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), num.compareTo(0L) == 0); + } + + @Override + @Transactional + public ResModeBase updateName(int userId, String userName) { + //1 检查昵称修改次数 + int updaNameCount = playerMapper.selectById(userId).getUpdate_name_count(); + if (updaNameCount != 0) { + throw new BussinessException(MessageEnum.GAME_UPDATE_ERROR_COUNT); + } + //1 修改 + Player upObject = Player.builder() + .user_id(userId) + .update_name_count(updaNameCount + 1 + ).user_name(userName).build(); + int req = playerMapper.updateById(upObject); + if (req < 1) { + return ResultUtil.result(MessageEnum.UPDATE_ERROR.getCode(), MessageEnum.UPDATE_ERROR.getMessage()); + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + + } + + @Override + public ResModeBase pushGoldImpl(Integer userId, int gold, int type, String remark){ + synchronized (pool.intern("gold-".concat(userId.toString()))) { + return gameSystemService.pushGold(userId, gold, type, remark); + } + } + + @Override + @Transactional + public ResModeBase pushGold(Integer userId, int gold, int type, String remark) { + //1. 查询金额, 设置资产上限 + PlayerAssets playerAssets = playerAssetsService.getOne(new QueryWrapper().eq("player_id", userId).eq("type", type).last("limit 1")); + Integer playerAssetsNumber = playerAssets == null? 0 : playerAssets.getNumber(); + int nowGold = Math.min(playerAssetsNumber +gold , AssetLimit); + // 2.写入改变数量 + if (ObjectUtils.isEmpty(playerAssets)) { + playerAssetsService.save(PlayerAssets.builder().playerId(userId).type(type).number(nowGold).version(0L).build()); + } else { + playerAssetsService.addGold(playerAssets.getId(), nowGold - playerAssetsNumber); + } + //3 写入变化记录 + assertLogMapper.insert(AssertLog.builder().playerId(userId).createDate(new Date()).assertChangeNum(nowGold - playerAssetsNumber).assertType(type).remark(remark).build()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), nowGold); + } + + @Override + public ResModeBase pullGoldImpl(Integer userId, int gold, int type, String remark){ + synchronized (pool.intern("gold-".concat(userId.toString()))) { + return gameSystemService.pullGold(userId, gold, type, remark); + } + } + + @Override + @Transactional + public ResModeBase pullGold(Integer userId, int gold, int type, String remark) { + //1 查询金额 + PlayerAssets playerAssets = playerAssetsService.getOne(new QueryWrapper().eq("player_id", userId).eq("type", type).last("limit 1")); + Integer num = 0; + // 不存在用户的钱包数据则新增初始化钱包数据 + if(ObjectUtils.isEmpty(playerAssets)){ + playerAssets = PlayerAssets.builder().playerId(userId).type(0).number(0).version(0L).build(); + playerAssetsService.save(playerAssets); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), 0); + } + if (playerAssets.getNumber() < gold) { + return ResultUtil.result(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getCode(), String.format(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getMessage(), playerAssets.getNumber())); + } + //2 取出金币 + num = playerAssetsService.reduceGold(playerAssets.getId(), gold); + if(num == -999){ + return ResultUtil.result(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getCode(), String.format(MessageEnum.GAME_GOLD_PULL_MAX_ERROR.getMessage(), playerAssets.getNumber())); + } + //3 写入变化记录 + assertLogMapper.insert(AssertLog.builder().playerId(userId).createDate(new Date()).assertChangeNum(-gold).assertType(type).remark(remark).build()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), num); + } + + @Override + public ResModeBase saveFileImpl(int userId, String record, Integer record_type) { + if(StringUtil.isEmpty(record)){ + throw new BussinessException(MessageEnum.ERROR.getCode(), "数据存档异常:record is null! userId:".concat(String.valueOf(userId)).concat(",record_type: " + record_type)); + } + synchronized (pool.intern(String.valueOf(userId))){ + return gameSystemService.saveFile(userId, record, record_type); + } + } + + @Override + @Transactional + public ResModeBase saveFile(int userId, String record, Integer record_type) { + Record recordData = null; + Long time = System.currentTimeMillis() / 1000; + //1 检查 用户存档信息 + List records = recordMapper.selectList(new QueryWrapper().eq("user_id", userId).eq("record_type", record_type)); + if (CollectionUtils.isEmpty(records)) { //没有存档信息 + recordData = Record.builder() + .user_id(userId) + .record_name("第一次存档信息") + .record(record) + .creation_time(time.intValue()) + .updata_time(time.intValue()) + .record_type(record_type) + .build(); + int req = recordMapper.insert(recordData); + if (req < 1) { + throw new BussinessException(MessageEnum.ADD_ERROR); + } + } else { + recordData = records.get(0); + if (null != recordData) { + recordData.setUpdata_time(time.intValue()); + recordData.setRecord(record); + recordData.setRecord_name(recordData.getRecord_name()); + int req = recordMapper.updateById(recordData); + if (req < 1) { + throw new BussinessException(MessageEnum.UPDATE_ERROR); + } + } else { + throw new BussinessException(MessageEnum.GAME_RECORD_ID_IS_NULL); + } + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } + + @Override + public ResModeBase readFile(int userId, int record_type) { + QueryWrapper thisQueryWrapper = new QueryWrapper().eq("user_id", userId); + if (record_type != -1) { + thisQueryWrapper.eq("record_type", record_type); + } + + List records = recordMapper.selectList(thisQueryWrapper); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), records); + } + + @Override + public ResModeBase saveLogImpl(Player player, Integer level, int game_time, float bvs3, float bv3, String video, String gameinfo, boolean nf) { + if(level == null){ + throw new BussinessException(MessageEnum.ERROR.getCode(), "提交游戏记录异常:level is null! userId:".concat(String.valueOf(player.getUser_id())).concat(",record_type: ")); + } + synchronized (pool.intern(String.valueOf(player.getUser_id()).concat("saveLog"))){ + return gameSystemService.saveLog(player, level, game_time, bvs3, bv3, video, gameinfo, nf); + } + } + + @Override + @Transactional + public ResModeBase saveLog(Player player, Integer level, int game_time, float bvs3, float bv3, String video, String gameinfo, boolean nf) { + if(level == null){ + throw new BussinessException(MessageEnum.ERROR.getCode(), "提交游戏记录异常:level is null! userId:".concat(String.valueOf(player.getUser_id())).concat(",record_type: ")); + } + int req = -1; + //1 检验是否存在记录 + Log isTrue = logService.getOne(new QueryWrapper().eq("user_id", player.getUser_id()).eq("level", level).orderByDesc("creation_time").last("limit 1")); + String key = StaticUtil.RANK_LIST.concat(level.toString()); + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(key); + Log data = Log.builder() + .user_id(player.getUser_id()) + .creation_time(Integer.parseInt(System.currentTimeMillis() / 1000 + "")) + .game_time(game_time) + .bvs3(bvs3) + .bv3(bv3) + .video(video) + .game_info(gameinfo) + .level(level) + .nf(nf) + .build(); + + if (null != isTrue) { + if (game_time < isTrue.getGame_time()) { + data.setId(isTrue.getId()); + req = logService.updateById(data)?1:0; + } else { + req = 99; + } + } else { + //存储 + req = logService.save(data)?1:0; + } + // 排除成绩不计入排行的用户 + if(req != 99 && player.getUser_gold() == 0){ + OrdinaryRankDto rankDto; + // 正序 + Set sets = operations.range(0, -1); + // 更新缓存 + try{ + rankDto = sets.stream().filter(obj -> obj.getUser_id().equals(player.getUser_id())).findFirst().get(); + } catch (NoSuchElementException ex){ // 捕获缓存未找到玩家信息异常 + rankDto = new OrdinaryRankDto(); + rankDto.setUser_id(player.getUser_id()); + rankDto.setUser_name(player.getUser_name()); + rankDto.setId(data.getId()); + } + + BeanUtils.copyProperties(data, rankDto); + // 直接添加进缓存,userId相同自动覆盖 + operations.add(rankDto, rankDto.getGame_time()); + } + if (req < 1) { + throw new BussinessException(MessageEnum.GAME_SAVE_LOG_ADD_ERROR); + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } + + @Override + public ResModeBase ranking(int pageIndex, int pageSize, int level) { + Integer max = 999; + if(level == -1){ + level = 0; + max = 499; + } + BoundZSetOperations bzo = redisCache.redisTemplate.boundZSetOps(StaticUtil.RANK_LIST.concat(String.valueOf(level))); + //创建Page类 + Page page = new Page(pageIndex, pageSize); + List reuslts; + if(bzo == null || bzo.size() == 0){ + reuslts = new ArrayList(); + } else { + // 只取前1000名 + Set set = bzo.range(0, max); + List reqData = new ArrayList<>(); + reqData.addAll(set); + + //为Page类中的total属性赋值 + int total = reqData.size(); + page.setTotal(total); + //计算当前需要显示的数据下标起始值 + int startIndex = (pageIndex - 1) * pageSize; + int endIndex = Math.min(startIndex + pageSize,total); + reuslts = reqData.subList(startIndex,endIndex); + // 写排名 + for(OrdinaryRankDto map: reuslts){ + map.setRanking(startIndex); + startIndex ++; + } + } + + //从链表中截取需要显示的子链表,并加入到Page + page.addAll(reuslts); + + //以Page创建PageInfo + PageInfo pageInfo = new PageInfo<>(page); + + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), pageInfo); + } + + @Override + public ResModeBase log(int userId, int level) { + if(level == -1){ + level = 0; + } + String key = StaticUtil.RANK_LIST.concat(String.valueOf(level)); + BoundZSetOperations bzo = redisCache.redisTemplate.boundZSetOps(key); + OrdinaryRankDto dto = null; + if (bzo != null || bzo.size() > 0){ + // 正序 只取前1000 + Set sets = bzo.range(0, -1); + if(sets == null || sets.size() == 0){ + dto = null; + }else { + List reqData = new ArrayList<>(); + reqData.addAll(sets); + for(int i = 0; i < reqData.size(); i ++){ + OrdinaryRankDto obj = reqData.get(i); + if(obj.getUser_id().equals(userId)){ + dto = obj; + dto.setRanking(i +1); + break; + } + } + } + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), dto); + } + + @Override + public ResModeBase getGameData(Integer id, Integer type){ + String gameData = ""; + if(type == 1){ + Log log = logService.getById(id); + if(!ObjectUtils.isEmpty(log)){ + gameData = log.getVideo(); + } + } else if (type == 2){ + ListRank listRank =listRankMapper.selectById(id); + if(!ObjectUtils.isEmpty(listRank)){ + gameData = listRank.getGameData(); + } + } + + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), gameData); + } + + @Override + @Transactional + public void cancellationAccount(Integer userId) { + // 删除排行榜缓存数据. + logService.deleteCacheByUserId(userId); + // 删除雷神之塔缓存数据 + clearanceLogService.deletCacheByPlayerId(userId); + + // sl_assert_log 资产日志 + assertLogMapper.delete(new UpdateWrapper().eq("player_id", userId)); + // sl_log 游戏日志 + logService.remove(new UpdateWrapper().eq("user_id", userId)); + // sl_notic 公告 + noticeMapper.delete(new UpdateWrapper().eq("player_id", userId)); + // sl_player_assets 用户资产 + playerAssetsService.remove(new UpdateWrapper().eq("player_id", userId)); + // sl_record 用户游戏数据记录 + recordMapper.delete(new UpdateWrapper().eq("user_id", userId)); + // sl_player 用户 + playerMapper.deleteById(userId); + // sl_clearance_log 通关日志 + clearanceLogService.remove(new LambdaQueryWrapper().eq(ClearanceLog::getPlayerId, userId)); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/service/impl/LogServiceImpl.java b/basics/src/main/java/com/lightyears/basics/service/impl/LogServiceImpl.java new file mode 100644 index 0000000..740c497 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/impl/LogServiceImpl.java @@ -0,0 +1,100 @@ +package com.lightyears.basics.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.basics.mapper.LogMapper; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.entity.Log; +import com.lightyears.basics.service.ILogService; +import com.lightyears.basics.util.RedisCache; +import com.lightyears.basics.util.StaticUtil; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class LogServiceImpl extends ServiceImpl implements ILogService { + @Resource + private RedisCache redisCache; + + @Override + public List getRankList(Integer level){ + List reqData = new ArrayList<>(); + if (level == -1) {//查询综合 + reqData = baseMapper.syntheticalPaging(); + } else { + reqData = baseMapper.paging(level, -1); + } + return reqData; + } + + @Override + public void deleteCacheByUserId(Integer userId){ + deleteCacheByRankUserId(0, userId); + deleteCacheByRankUserId(1, userId); + deleteCacheByRankUserId(2, userId); + deleteCacheByRankUserId(3, userId); + deleteCacheByRankUserId(4, userId); + } + + @Override + public void cacheRankList(Integer level){ + if(level == null){ + // -1 - 综合 + List zh = getRankList(-1); + cacheRankListItem(zh, 0); + // 1 - 普通 + List zh1 = getRankList(1); + cacheRankListItem(zh1, 1); + // 2 困难 + List zh2 = getRankList(2); + cacheRankListItem(zh2, 2); + // 3 大师 + List zh3 = getRankList(3); + cacheRankListItem(zh3, 3); + // 4 超凡 + List zh4 = getRankList(4); + cacheRankListItem(zh4, 4); + } else if(level == -1) { // 刷新综合榜数据 + // -1 - 综合 + List zh = getRankList(-1); + cacheRankListItem(zh, 0); + } + } + + public void cacheRankListItem(List list, Integer level){ + String key = StaticUtil.RANK_LIST.concat(level.toString()); + redisCache.deleteByPrefix(key); + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(key); + for (OrdinaryRankDto item : list){ + operations.add(item, item.getGame_time()); + } + } + + + public void deleteCacheByRankUserId(Integer level, Integer userId){ + String key = StaticUtil.RANK_LIST.concat(level.toString()); + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(key); + if (operations != null && operations.size() > 0){ + Set sets = operations.range(0, -1); + if(sets != null && sets.size() > 0){ + Optional dto = sets.stream().filter(obj -> obj.getUser_id().equals(userId)).findFirst(); + if(dto != null && dto.isPresent()){ + operations.remove(dto.get()); + } + } + } + } +} diff --git a/basics/src/main/java/com/lightyears/basics/service/impl/NoticeServiceImpl.java b/basics/src/main/java/com/lightyears/basics/service/impl/NoticeServiceImpl.java new file mode 100644 index 0000000..89367ae --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/impl/NoticeServiceImpl.java @@ -0,0 +1,77 @@ +package com.lightyears.basics.service.impl; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.common.domain.dto.NoticeDto; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Notice; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.basics.mapper.NoticeMapper; +import com.lightyears.basics.service.INoticeService; +import com.lightyears.basics.util.ResultUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +@Service(value = "noticeServiceImpl") +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class NoticeServiceImpl extends ServiceImpl implements INoticeService { + + + @Override + public ResModeBase getList(Integer playerId){ +// List results = new ArrayList<>(); + List systemNotice = this.baseMapper.getList(null, playerId); +// List myNotice = this.baseMapper.getList(1, playerId); +// if (!CollectionUtils.isEmpty(systemNotice)){ +// results.add(systemNotice.get(0)); +// } +// if (!CollectionUtils.isEmpty(myNotice)){ +// results.addAll(myNotice); +// } + + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), systemNotice); + } + + @Override + public ResModeBase getContent(Integer id){ + String content = this.baseMapper.getContent(id); + // 设置已读 + this.baseMapper.updateById(Notice.builder().id(id).status(1).build()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), content); + } + + @Override + public void deleteNoticeForTask(){ + List notices = this.baseMapper.selectList(new LambdaQueryWrapper().select(Notice::getId, Notice::getExpirationDay, Notice::getCreateDate).isNotNull(Notice::getExpirationDay)); + if (CollectionUtils.isEmpty(notices)) + return; + Date now = new Date(); + List ids = new ArrayList<>(); + notices.forEach(notice -> { + Date date = DateUtil.offsetDay(notice.getCreateDate(), notice.getExpirationDay()); + if(DateUtil.compare(now, date) > -1){ + ids.add(notice.getId()); + } + }); + + if(ids.size() < 1) + return; + baseMapper.deleteBatchIds(ids); + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/service/impl/PlayerAssetsServiceImpl.java b/basics/src/main/java/com/lightyears/basics/service/impl/PlayerAssetsServiceImpl.java new file mode 100644 index 0000000..024ce27 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/impl/PlayerAssetsServiceImpl.java @@ -0,0 +1,76 @@ +package com.lightyears.basics.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.basics.mapper.PlayerAssetsMapper; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.basics.exception.BussinessException; +import com.lightyears.basics.service.IPlayerAssetsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Slf4j +@Service +public class PlayerAssetsServiceImpl extends ServiceImpl implements IPlayerAssetsService { + + @Override + public Integer addGold(int id, int gold){ + PlayerAssets playerAssets = baseMapper.selectById(id); + if(ObjectUtils.isEmpty(playerAssets)){ + log.error("减少金币异常------------没有查到资产信息"); + throw new BussinessException(MessageEnum.ERROR.getCode(), "减少金币异常------------没有查到资产信息!"); + } + int result = 0; + try{ + result = baseMapper.addGold(playerAssets.getId(), gold, playerAssets.getVersion()); + }catch (Exception ex){ + log.error("写入金币异常", ex); + throw new BussinessException(MessageEnum.ERROR.getCode(), "写入金币异常!"); + } + + if(result < 1){ + this.addGold(id, gold); + } + return gold; + } + + @Override + public Integer reduceGold(int id, int gold){ + PlayerAssets playerAssets = baseMapper.selectById(id); + if(ObjectUtils.isEmpty(playerAssets)){ + log.error("减少金币异常------------没有查到资产信息"); + throw new BussinessException(MessageEnum.ERROR.getCode(), "减少金币异常------------没有查到资产信息!"); + } + int result = 0; + if(playerAssets.getNumber() < gold){ + return -999; + } + try { + result = baseMapper.reduceGold(playerAssets.getId(), gold, playerAssets.getVersion()); + } catch (Exception ex){ + log.error("写入金币异常", ex); + throw new BussinessException(MessageEnum.ERROR.getCode(), "写入金币异常!"); + } + if(result < 1){ + this.reduceGold(id, gold); + } + return playerAssets.getNumber() - gold; + } + + @Override + public List getPlayerAssets(int playerId){ + return baseMapper.getPlayerAssets(playerId); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/service/impl/PlayerServiceImpl.java b/basics/src/main/java/com/lightyears/basics/service/impl/PlayerServiceImpl.java new file mode 100644 index 0000000..ab3f564 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/impl/PlayerServiceImpl.java @@ -0,0 +1,20 @@ +package com.lightyears.basics.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.basics.mapper.PlayerMapper; +import com.lightyears.common.domain.entity.Player; +import com.lightyears.basics.service.IPlayerService; +import org.springframework.stereotype.Service; + +/** + *

+ * 扫雷玩家表 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class PlayerServiceImpl extends ServiceImpl implements IPlayerService { + +} diff --git a/basics/src/main/java/com/lightyears/basics/service/impl/RecordServiceImpl.java b/basics/src/main/java/com/lightyears/basics/service/impl/RecordServiceImpl.java new file mode 100644 index 0000000..4db20ef --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/impl/RecordServiceImpl.java @@ -0,0 +1,20 @@ +package com.lightyears.basics.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.basics.mapper.RecordMapper; +import com.lightyears.common.domain.entity.Record; +import com.lightyears.basics.service.IRecordService; +import org.springframework.stereotype.Service; + +/** + *

+ * 游戏存档 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class RecordServiceImpl extends ServiceImpl implements IRecordService { + +} diff --git a/basics/src/main/java/com/lightyears/basics/service/impl/SystemServiceImpl.java b/basics/src/main/java/com/lightyears/basics/service/impl/SystemServiceImpl.java new file mode 100644 index 0000000..7619112 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/service/impl/SystemServiceImpl.java @@ -0,0 +1,101 @@ +package com.lightyears.basics.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Notice; +import com.lightyears.common.domain.entity.PlayerAssets; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.basics.service.INoticeService; +import com.lightyears.basics.service.IPlayerAssetsService; +import com.lightyears.basics.service.ISystemService; +import com.lightyears.basics.util.BatchInsertThread; +import com.lightyears.basics.util.ResultUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class SystemServiceImpl implements ISystemService { + private final INoticeService noticeService; + private final IPlayerAssetsService playerAssetsService; + + @Override + public ResModeBase publishNotice(Notice notice){ + List players = playerAssetsService.list(new LambdaQueryWrapper().select(PlayerAssets::getPlayerId).eq(PlayerAssets::getType, 0)); + if(CollectionUtils.isEmpty(players)) + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + Date now = new Date(); + + List notices = new ArrayList<>(); + players.stream().forEach(player -> { + Notice obj = new Notice(); + obj.setContent(notice.getContent()); + obj.setTitle(notice.getTitle()); + obj.setType(0); + obj.setPlayerId(player.getPlayerId()); + obj.setStatus(0); + obj.setCreateDate(now); + notices.add(obj); + }); + //一个线程处理200条数据 + int count = 2000; + //数据集合大小 + int listSize = notices.size(); + //开启的线程数 + int runSize = (listSize / count) + 1; + //存放每个线程的执行数据 + List newlist = null; + + //创建一个线程池,数量和开启线程的数量一样 + //Executors 的写法 + // ExecutorService executor = Executors.newFixedThreadPool(runSize); + + //ThreadPoolExecutor的写法 + ThreadPoolExecutor executor = new ThreadPoolExecutor(runSize, runSize, 1, + TimeUnit.SECONDS, new ArrayBlockingQueue(3), + new ThreadPoolExecutor.DiscardOldestPolicy()); + + //创建两个个计数器 + CountDownLatch begin = new CountDownLatch(1); + CountDownLatch end = new CountDownLatch(runSize); + try { + //循环创建线程 + for (int i = 0; i < runSize; i++) { + //计算每个线程执行的数据 + if ((i + 1) == runSize) { + int startIndex = (i * count); + int endIndex = notices.size(); + newlist = notices.subList(startIndex, endIndex); + } else { + int startIndex = (i * count); + int endIndex = (i + 1) * count; + newlist = notices.subList(startIndex, endIndex); + } + //线程类 + BatchInsertThread mythead = new BatchInsertThread(newlist, begin, end, noticeService); + //这里执行线程的方式是调用线程池里的executor.execute(mythead)方法。 + executor.execute(mythead); + } + begin.countDown(); + end.await(); + }catch (Exception e){ + log.error("发布公告异常:", e); + } finally { + //执行完关闭线程池 + executor.shutdown(); + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/util/BatchInsertThread.java b/basics/src/main/java/com/lightyears/basics/util/BatchInsertThread.java new file mode 100644 index 0000000..6ee0038 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/BatchInsertThread.java @@ -0,0 +1,46 @@ +package com.lightyears.basics.util; + +import com.lightyears.common.domain.entity.Notice; +import com.lightyears.basics.service.INoticeService; + +import java.util.List; +import java.util.concurrent.CountDownLatch; + +public class BatchInsertThread implements Runnable { + + public BatchInsertThread() { + } + + INoticeService noticeService; + private List list; + private CountDownLatch begin; + private CountDownLatch end; + + /** + * 方法名: ImportThread + * 方法描述: 创建个构造函数初始化 list,和其他用到的参数 + * @throws + */ + public BatchInsertThread(List list, CountDownLatch begin, CountDownLatch end,INoticeService noticeService) { + this.list = list; + this.begin = begin; + this.end = end; + this.noticeService=noticeService; + } + + @Override + public void run() { + try { + //执行完让线程直接进入等待 + noticeService.saveBatch(list); + begin.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //这里要主要了,当一个线程执行完 了计数要减一不然这个线程会被一直挂起 + //这个方法就是直接把计数器减一的 + end.countDown(); + } + } + +} \ No newline at end of file diff --git a/basics/src/main/java/com/lightyears/basics/util/CronUtils.java b/basics/src/main/java/com/lightyears/basics/util/CronUtils.java new file mode 100644 index 0000000..5d2e7e2 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/CronUtils.java @@ -0,0 +1,37 @@ +package com.lightyears.basics.util; + +import cn.hutool.core.date.DateTime; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Objects; + +/** + * 日期转换cron表达式 + */ +public class CronUtils { + + /*** + * 功能描述:日期转换cron表达式 + * @param dateStr + * @return + */ + public static String formatDateByPattern(String dateStr) { + String formatTimeStr = null; + if (Objects.nonNull(dateStr)) { + LocalDateTime time = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + formatTimeStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ?")); + } + return formatTimeStr; + } + + /*** + * @param dateTime : 时间点 + * @return + */ + public static String getCron(DateTime dateTime) { + return formatDateByPattern(dateTime.toString()); + } + +} + diff --git a/basics/src/main/java/com/lightyears/basics/util/GetBeanUtil.java b/basics/src/main/java/com/lightyears/basics/util/GetBeanUtil.java new file mode 100644 index 0000000..fb6f7b5 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/GetBeanUtil.java @@ -0,0 +1,26 @@ +package com.lightyears.basics.util; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class GetBeanUtil implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + public void setApplicationContext(ApplicationContext context) { + GetBeanUtil.applicationContext = context; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static Object getBean(Class classObj) { + return applicationContext.getBean(classObj); + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } +} \ No newline at end of file diff --git a/basics/src/main/java/com/lightyears/basics/util/MD5Utils.java b/basics/src/main/java/com/lightyears/basics/util/MD5Utils.java new file mode 100644 index 0000000..019bb9b --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/MD5Utils.java @@ -0,0 +1,51 @@ +package com.lightyears.basics.util; + +import java.security.MessageDigest; + +/** + * Created by tanhao on 2019/3/18. + */ +public class MD5Utils { + private static final String hexDigIts[] = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"}; + + /** + * MD5加密 + * @param origin 字符 + * @param charsetname 编码 UTF-8 + * @return + */ + public static String MD5Encode(String origin, String charsetname){ + String resultString = null; + try{ + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if(null == charsetname || "".equals(charsetname)){ + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + }else{ + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + }catch (Exception e){ + } + return resultString; + } + + + public static String byteArrayToHexString(byte b[]){ + StringBuffer resultSb = new StringBuffer(); + for(int i = 0; i < b.length; i++){ + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + public static String byteToHexString(byte b){ + int n = b; + if(n < 0){ + n += 256; + } + int d1 = n / 16; + int d2 = n % 16; + return hexDigIts[d1] + hexDigIts[d2]; + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/util/RedisCache.java b/basics/src/main/java/com/lightyears/basics/util/RedisCache.java new file mode 100644 index 0000000..56e4f9e --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/RedisCache.java @@ -0,0 +1,231 @@ +package com.lightyears.basics.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * spring redis 工具类 + **/ +@Component +public class RedisCache { + + @Autowired + public RedisTemplate redisTemplate; + + /** + * 判断key是否存在 + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + */ + public void setCacheObject(final String key, final T value) { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param timeout 时间 + * @param timeUnit 时间颗粒度 + */ + public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout) { + return expire(key, timeout, TimeUnit.SECONDS); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @param unit 时间单位 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout, final TimeUnit unit) { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return 缓存键值对应的数据 + */ + public T getCacheObject(final String key) { + ValueOperations operation = redisTemplate.opsForValue(); + return operation.get(key); + } + + /** + * 删除单个对象 + * + * @param key + */ + public boolean deleteObject(final String key) { + return redisTemplate.delete(key); + } + + /** + * 删除指定前缀的缓存 + * @param key + * @return + */ + public Long deleteByPrefix(final String key) { + Set keys = redisTemplate.keys(key.concat("*")); + return redisTemplate.delete(keys); + } + + /** + * 删除集合对象 + * + * @param collection 多个对象 + * @return + */ + public long deleteObject(final Collection collection) { + return redisTemplate.delete(collection); + } + + /** + * 缓存List数据 + * + * @param key 缓存的键值 + * @return 缓存的对象 + */ + public long setCacheList(final String key, final List dataList) { + Long count = redisTemplate.opsForList().rightPushAll(key, dataList); + return count == null ? 0 : count; + } + + /** + * 获得缓存的list对象 + * + * @param key 缓存的键值 + * @return 缓存键值对应的数据 + */ + public List getCacheList(final String key) { + return redisTemplate.opsForList().range(key, 0, -1); + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public long setCacheSet(final String key, final Set dataSet) { + Long count = redisTemplate.opsForSet().add(key, dataSet); + return count == null ? 0 : count; + } + + /** + * 获得缓存的set + * + * @param key + * @return + */ + public Set getCacheSet(final String key) { + return redisTemplate.opsForSet().members(key); + } + + /** + * 缓存Map + * + * @param key + * @param dataMap + */ + public void setCacheMap(final String key, final Map dataMap) { + if (dataMap != null) { + redisTemplate.opsForHash().putAll(key, dataMap); + } + } + + /** + * 获得缓存的Map + * + * @param key + * @return + */ + public Map getCacheMap(final String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 往Hash中存入数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @param value 值 + */ + public void setCacheMapValue(final String key, final String hKey, final T value) { + redisTemplate.opsForHash().put(key, hKey, value); + } + + /** + * 获取Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public T getCacheMapValue(final String key, final String hKey) { + HashOperations opsForHash = redisTemplate.opsForHash(); + return opsForHash.get(key, hKey); + } + + /** + * 获取多个Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键集合 + * @return Hash对象集合 + */ + public List getMultiCacheMapValue(final String key, final Collection hKeys) { + return redisTemplate.opsForHash().multiGet(key, hKeys); + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public Collection keys(final String pattern) { + return redisTemplate.keys(pattern); + } +} \ No newline at end of file diff --git a/basics/src/main/java/com/lightyears/basics/util/ResultUtil.java b/basics/src/main/java/com/lightyears/basics/util/ResultUtil.java new file mode 100644 index 0000000..7556d7e --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/ResultUtil.java @@ -0,0 +1,44 @@ +package com.lightyears.basics.util; + +import cn.hutool.crypto.digest.MD5; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; + +/** + * 返回 数据 指定数据结构 + * + * @author Melody + */ +@Slf4j +public class ResultUtil { + public static final ObjectMapper mapper = new ObjectMapper(); + public static ResModeBase result(int code, String mes) { + return result(code, mes, null); + } + + public static ResModeBase result(int code, String mes, Object data) { + String key = ""; + String dataStr = ""; + if(data == null){ + key = MD5.create().digestHex(MD5.create().digestHex(StaticUtil.PRIVATE_KEY)); + } else { + try { + if (data instanceof String){ + dataStr = data.toString(); + } else { + dataStr = mapper.writeValueAsString(data); + } + key = MD5.create().digestHex(MD5.create().digestHex(dataStr.concat(StaticUtil.PRIVATE_KEY))); + }catch (JsonProcessingException ex){ + log.error("json解析错误", ex); + return new ResModeBase(MessageEnum.SERVER_ERROR.getCode(), MessageEnum.SERVER_ERROR.getMessage(), key, null); + } + + } + return new ResModeBase(code, mes, key, data); + } + +} diff --git a/basics/src/main/java/com/lightyears/basics/util/ScheduledFutureHolder.java b/basics/src/main/java/com/lightyears/basics/util/ScheduledFutureHolder.java new file mode 100644 index 0000000..d50af22 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/ScheduledFutureHolder.java @@ -0,0 +1,46 @@ +package com.lightyears.basics.util; +import java.util.concurrent.ScheduledFuture; + +/** + * 任务执行的包装类 + */ +public class ScheduledFutureHolder { + private ScheduledFuture scheduledFuture; + + private Class runnableClass; + + private String corn; + + public ScheduledFuture getScheduledFuture() { + return scheduledFuture; + } + + public void setScheduledFuture(ScheduledFuture scheduledFuture) { + this.scheduledFuture = scheduledFuture; + } + + public Class getRunnableClass() { + return runnableClass; + } + + public void setRunnableClass(Class runnableClass) { + this.runnableClass = runnableClass; + } + + public String getCorn() { + return corn; + } + + public void setCorn(String corn) { + this.corn = corn; + } + + @Override + public String toString() { + return "ScheduledFutureHolder{" + + "scheduledFuture=" + scheduledFuture + + ", runnableClass=" + runnableClass + + ", corn='" + corn + '\'' + + '}'; + } +} diff --git a/basics/src/main/java/com/lightyears/basics/util/SpecialTool.java b/basics/src/main/java/com/lightyears/basics/util/SpecialTool.java new file mode 100644 index 0000000..1a236cd --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/SpecialTool.java @@ -0,0 +1,50 @@ +package com.lightyears.basics.util; + +import java.util.List; +import java.util.Map; + +/** + * 文 件 名 : 特殊处理工具 + * 创 建 人:HL + * 日 期:2019-8-12 + * 修 改 人:HL + * 日 期:2019-8-12 + * 描 述: 分页、 + * 版 本 号:2.0 + */ +public class SpecialTool { + public static SpecialTool specialTool = new SpecialTool(); + + //时间格式 + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + //集合判断是否为空 + + public boolean ifGather(Object o) { + if ((o instanceof List && null == o) || (o instanceof Map && null == o)) { + return true; + } + return false; + } + + //字符串判断是否为空 + public boolean isEmpty(String s) { + if (null == s || s.equals("")) { + return true; + } + return false; + } + + + /** + * 将字符串的首字母转大写 + * @param str 需要转换的字符串 + * @return + */ + private static String captureName(String str) { + // 进行字母的ascii编码前移,效率要高于截取字符串进行转换的操作 + char[] cs=str.toCharArray(); + cs[0]-=32; + return String.valueOf(cs); + } +} diff --git a/basics/src/main/java/com/lightyears/basics/util/StaticUtil.java b/basics/src/main/java/com/lightyears/basics/util/StaticUtil.java new file mode 100644 index 0000000..73e52f7 --- /dev/null +++ b/basics/src/main/java/com/lightyears/basics/util/StaticUtil.java @@ -0,0 +1,56 @@ +package com.lightyears.basics.util; + + +import java.util.HashMap; +import java.util.Map; + +/** + * 静态工具栏 :目前数据较小 且又想减少服务器压力,特建此类 做静态缓存 + */ +public class StaticUtil { + // ------------------------系统类----------------------- + //金币极限操作 防范静态变量 + public static Map goldSyn = new HashMap(); + // 数据加解密盐 + public static final String PRIVATE_KEY = "123144123"; + + // ---------------------------------redis ----------------------------------------- + // 在线用户信息 + public static final String ONLINE_USER_PUBLIC_KEY="mineClearance:onlineUser:"; + // 在线用户TOKEN + public static final String ONLINE_USER_TOKEN="mineClearance:onlineToken:"; + // 排行榜 + public static final String RANK_LIST = "mineClearance:rankList:"; + // 闯关排行 + public static final String CLEARANCE_RANK_LIST = "mineClearance:clearanceList"; + + // 挑战榜所有缓存前缀 + public static final String CHALLENGE="mineClearance:challenge:*"; + // 开启中的挑战榜信息 + public static final String CHALLENGE_INSTANCE="mineClearance:challenge:instance:"; + // 开启中的挑战榜排名信息 mineClearance:challenge:rank:instance + public static final String CHALLENGE_INSTANCE_RANK="mineClearance:challenge:rank:"; + // 开启中的挑战榜每个排名的信息 mineClearance:challenge:rankDetail:instance:rank + public static final String CHALLENGE_INSTANCE_RANK_DETAIL="mineClearance:challenge:rankDetail:"; + // 正在挑战的用户,mineClearance:challenge:onlineUser: instanceId : rank: playerId + public static final String CHALLENGE_ONLINE_USER="mineClearance:challenge:onlineUser:"; + // -------------------------------------公告类------------------------------------------ + // 挑战榜结算 奖励发放备注 + public static final String CHALLENGE_REMARK = "你在挑战榜:%s 的名次为:%s, 获得%s %s"; + // 挑战榜奖励发放公告 标题 + public static final String CHALLENGE_NOTICE_TITLE = "挑战榜奖励发放"; + // 闯关信息提示 已有多少人到达 + public static final String CLEARANCE_LOG_TEXT_HAVE = "当前已有 %s 的玩家到达这一层!"; + // 闯关信息提示 已超过多少人 + public static final String CLEARANCE_LOG_TEXT_OVER = "你已超过 %s 的玩家!"; + + //----------------------------挑战榜task-------------------------- + // 锁榜时间 + public static final String LOCKE_TIME = " 23:00:00"; + // 结算时间 + public static final String SETTLEMENT_TIME = " 23:45:00"; + // 挑战榜初始化时间 + public static final String CHALLENGE_INIT_TIME = " 1:00:00"; + // 挑战榜redis刷新时间 + public static final String CHALLENGE_REFRESH_TIME = " 1:05:00"; +} diff --git a/basics/src/main/resources/application-dev.yml b/basics/src/main/resources/application-dev.yml new file mode 100644 index 0000000..25c2d62 --- /dev/null +++ b/basics/src/main/resources/application-dev.yml @@ -0,0 +1,67 @@ +qbs-switch: + swagger-open: true #swagger开关(true:打开, false:关闭) +spring: + application: + name: mine-clearance-basic + main: + allow-bean-definition-overriding: true + allow-circular-references: true + # 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题 + jackson: + time-zone: GMT+8 + datasource: + username: root + password: 43626546 + url: jdbc:mysql://localhost:3306/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 20 + max-active: 80 + min-idle: 20 + max-wait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictabkeIdleTimeMillis: 1800000 + validationQuery: SELECT 1 + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + # 配置监控统计拦截的filters,去掉后监控界面sql无法统计。‘wall’用于防火墙 + filters: stat,wall + # cloud: + # nacos: + # discovery: + # server-addr: localhost:8848 + redis: + # Redis服务器地址 + host: localhost + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + password: 123456 + # 连接超时时间 + timeout: 1000ms + lettuce: + pool: + # 连接池最大连接数 + max-active: 8 + # 连接池最大空闲连接数 + max-idle: 8 + # 连接池最小空闲连接数 + min-idle: 0 + # 连接池最大阻塞等待时间,负值表示没有限制 + max-wait: -1ms +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + type-aliases-package: com.lightyears.common.domain + global-config: + banner: false + db-config: + id-type: input + configuration: + # 控制台SQL日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: false \ No newline at end of file diff --git a/basics/src/main/resources/application-prod.yml b/basics/src/main/resources/application-prod.yml new file mode 100644 index 0000000..801cfed --- /dev/null +++ b/basics/src/main/resources/application-prod.yml @@ -0,0 +1,73 @@ +qbs-switch: + swagger-open: true #swagger开关(true:打开, false:关闭) +spring: + application: + name: mine-clearance-basic + main: + allow-bean-definition-overriding: true + allow-circular-references: true + # 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题 + jackson: + time-zone: GMT+8 + datasource: + username: root + # password: 1476346288@mysql + password: 1813547935mysql + # 基础 + url: jdbc:mysql://127.0.0.1:3306/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull + # 本地 + # url: jdbc:mysql://39.106.21.14:3986/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 20 + max-active: 80 + min-idle: 20 + max-wait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictabkeIdleTimeMillis: 1800000 + validationQuery: SELECT 1 + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + # 配置监控统计拦截的filters,去掉后监控界面sql无法统计。‘wall’用于防火墙 + filters: stat,wall + # cloud: + # nacos: + # discovery: + # server-addr: localhost:8848 + redis: + # Redis服务器地址 + host: localhost + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + # password: 1476346288@redis + password: 123456 + # 连接超时时间 + timeout: 1000ms + lettuce: + pool: + # 连接池最大连接数 + max-active: 8 + # 连接池最大空闲连接数 + max-idle: 8 + # 连接池最小空闲连接数 + min-idle: 0 + # 连接池最大阻塞等待时间,负值表示没有限制 + # max-wait: -1ms + max-wait: 3 +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + type-aliases-package: com.lightyears.common.domain + global-config: + banner: false + db-config: + id-type: input + configuration: + # 控制台SQL日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: false \ No newline at end of file diff --git a/basics/src/main/resources/application.yml b/basics/src/main/resources/application.yml new file mode 100644 index 0000000..3027359 --- /dev/null +++ b/basics/src/main/resources/application.yml @@ -0,0 +1,11 @@ +server: + port: 18633 + tomcat: + uri-encoding: UTF-8 +logging: + config: classpath:log.xml +spring: + profiles: + active: dev +appconfig: + version: 197.0 \ No newline at end of file diff --git a/basics/src/main/resources/log.xml b/basics/src/main/resources/log.xml new file mode 100644 index 0000000..6e850e2 --- /dev/null +++ b/basics/src/main/resources/log.xml @@ -0,0 +1,51 @@ + + + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + logs/basics/sys.log + + + + + + logs/basics/sys.%d.%i.log + + 30 + + + 10MB + + + + + + %d %p (%file:%line\)- %m%n + + + UTF-8 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/basics/src/main/resources/mapper/AssertLogMapper.xml b/basics/src/main/resources/mapper/AssertLogMapper.xml new file mode 100644 index 0000000..e446a15 --- /dev/null +++ b/basics/src/main/resources/mapper/AssertLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/basics/src/main/resources/mapper/ClearanceLogMapper.xml b/basics/src/main/resources/mapper/ClearanceLogMapper.xml new file mode 100644 index 0000000..eb7311c --- /dev/null +++ b/basics/src/main/resources/mapper/ClearanceLogMapper.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/basics/src/main/resources/mapper/ListRankMapper.xml b/basics/src/main/resources/mapper/ListRankMapper.xml new file mode 100644 index 0000000..214a6d8 --- /dev/null +++ b/basics/src/main/resources/mapper/ListRankMapper.xml @@ -0,0 +1,79 @@ + + + + + UPDATE `sl_list_rank` + SET + `player_name` = NULL, + `player_id` = NULL, + `challenge_time` = NULL, + `game_data` = NULL + WHERE + `instance_id` = ${instanceId} + and `player_id` = ${playerId} + + + + + diff --git a/basics/src/main/resources/mapper/LogMapper.xml b/basics/src/main/resources/mapper/LogMapper.xml new file mode 100644 index 0000000..481f9d6 --- /dev/null +++ b/basics/src/main/resources/mapper/LogMapper.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + diff --git a/basics/src/main/resources/mapper/NoticeMapper.xml b/basics/src/main/resources/mapper/NoticeMapper.xml new file mode 100644 index 0000000..1dbbe1b --- /dev/null +++ b/basics/src/main/resources/mapper/NoticeMapper.xml @@ -0,0 +1,31 @@ + + + + + + diff --git a/basics/src/main/resources/mapper/PlayerAssetsMapper.xml b/basics/src/main/resources/mapper/PlayerAssetsMapper.xml new file mode 100644 index 0000000..fbdfd2a --- /dev/null +++ b/basics/src/main/resources/mapper/PlayerAssetsMapper.xml @@ -0,0 +1,14 @@ + + + + + update sl_player_assets set number = number + #{gold}, version = version +1 where id = #{id} and version = ${version} + + + update sl_player_assets set number = number - #{gold}, version = version +1 where id = #{id} and version = ${version} + + + + diff --git a/basics/src/main/resources/mapper/PlayerMapper.xml b/basics/src/main/resources/mapper/PlayerMapper.xml new file mode 100644 index 0000000..d0d660b --- /dev/null +++ b/basics/src/main/resources/mapper/PlayerMapper.xml @@ -0,0 +1,11 @@ + + + + + update sl_player set user_gold = 1 where update_time <= ${dateNum}; + + + + update sl_player set user_gold = 0 where update_time > ${dateNum}; + + diff --git a/basics/src/main/resources/mapper/RecordMapper.xml b/basics/src/main/resources/mapper/RecordMapper.xml new file mode 100644 index 0000000..ff7f33c --- /dev/null +++ b/basics/src/main/resources/mapper/RecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/basics/src/test/java/com/lightyears/basics/BasicsTests.java b/basics/src/test/java/com/lightyears/basics/BasicsTests.java new file mode 100644 index 0000000..a0d2079 --- /dev/null +++ b/basics/src/test/java/com/lightyears/basics/BasicsTests.java @@ -0,0 +1,25 @@ +package com.lightyears.basics; + +import com.lightyears.basics.service.INoticeService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = BasicsApp.class) +public class BasicsTests { + + @Resource + private INoticeService noticeService; + + @Test + public void contextLoads() { +// ResModeBase dto = systemService.publishNotice(Notice.builder().title("服务器停机维护通知").content("为了保障更好的在线游戏服务,扫雷F服务器将在2022年10月2日 03:00~05:00进行停机维护,届时将停止所有在线服务!").build()); + + noticeService.deleteNoticeForTask(); + } + +} diff --git a/challenge/pom.xml b/challenge/pom.xml new file mode 100644 index 0000000..19a1c81 --- /dev/null +++ b/challenge/pom.xml @@ -0,0 +1,149 @@ + + + + mine_clearance + com.lightyears.mine_clearance + 1.0 + + 4.0.0 + + challenge + + + + org.springframework.boot + spring-boot-starter-web + + + com.baomidou + mybatis-plus-boot-starter + + + org.springframework.boot + spring-boot-starter-aop + + + mysql + mysql-connector-java + + + + com.alibaba + druid-spring-boot-starter + + + + com.alibaba + fastjson + + + com.baomidou + mybatis-plus-generator + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + org.apache.commons + commons-pool2 + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.freemarker + freemarker + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + + org.apache.rocketmq + rocketmq-spring-boot-starter + + + + cn.hutool + hutool-all + + + commons-io + commons-io + + + org.apache.commons + commons-collections4 + + + org.apache.rocketmq + rocketmq-spring-boot-starter + + + com.lightyears.mine_clearance + common + + + org.projectlombok + lombok + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + + challenge + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + utf-8 + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.lightyears.challenge.ChallengeApp + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + \ No newline at end of file diff --git a/challenge/src/main/java/com/lightyears/challenge/ChallengeApp.java b/challenge/src/main/java/com/lightyears/challenge/ChallengeApp.java new file mode 100644 index 0000000..3476e8d --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/ChallengeApp.java @@ -0,0 +1,19 @@ +package com.lightyears.challenge; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.util.TimeZone; + +@EnableScheduling +@SpringBootApplication +@EnableTransactionManagement +public class ChallengeApp { + public static void main(String[] args) { + // 设置时区 + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + SpringApplication.run(ChallengeApp.class, args); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/annotation/DataVerification.java b/challenge/src/main/java/com/lightyears/challenge/annotation/DataVerification.java new file mode 100644 index 0000000..9502f15 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/annotation/DataVerification.java @@ -0,0 +1,9 @@ +package com.lightyears.challenge.annotation; + +import java.lang.annotation.*; + +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface DataVerification { +} diff --git a/challenge/src/main/java/com/lightyears/challenge/aspect/DataVerificationAspect.java b/challenge/src/main/java/com/lightyears/challenge/aspect/DataVerificationAspect.java new file mode 100644 index 0000000..e45c35c --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/aspect/DataVerificationAspect.java @@ -0,0 +1,65 @@ +package com.lightyears.challenge.aspect; + +import cn.hutool.crypto.digest.MD5; +import com.github.pagehelper.util.StringUtil; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.challenge.exception.GlobalException; +import com.lightyears.challenge.util.StaticUtil; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.util.Collection; +import java.util.Map; + +@Aspect +@Component +public class DataVerificationAspect { + /** + * 过滤类 + * 指定自定义注解为切入点 + **/ + @Pointcut("@annotation(com.lightyears.challenge.annotation.DataVerification)") + public void checkPoint() { + } + + /** + * 前置 + */ + @Before("checkPoint()") + public void doAround(JoinPoint joinPoint) throws GlobalException { + RequestAttributes ra = RequestContextHolder.getRequestAttributes(); + ServletRequestAttributes sra = (ServletRequestAttributes) ra; + assert sra != null; + HttpServletRequest request = sra.getRequest(); + String checkKey = request.getHeader("checkKey"); + Map paramMap = request.getParameterMap(); + StringBuffer paramsStr = new StringBuffer(); + + if (StringUtil.isEmpty(checkKey)) { + throw new GlobalException(MessageEnum.CHECK_KEY_ERROR); + } + Object[] params = joinPoint.getArgs(); + if(paramMap.size() > 0) { + Collection values = paramMap.values(); + for (String[] value : values) { + paramsStr.append(value[0]); + } + } else { + if(params.length == 1) { + paramsStr.append(params[0].toString()); + } + } + String testKey = MD5.create().digestHex(MD5.create().digestHex(paramsStr.append(StaticUtil.PRIVATE_KEY).toString())); + if (!checkKey.equals(testKey)) { + throw new GlobalException(MessageEnum.CHECK_KEY_ERROR); + } + } + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/config/AppConfig.java b/challenge/src/main/java/com/lightyears/challenge/config/AppConfig.java new file mode 100644 index 0000000..e01de97 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/config/AppConfig.java @@ -0,0 +1,16 @@ +package com.lightyears.challenge.config; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@NoArgsConstructor +@AllArgsConstructor +@ConfigurationProperties(prefix = "appconfig") +public class AppConfig { + private Float version; +} diff --git a/challenge/src/main/java/com/lightyears/challenge/configuration/RedisConfig.java b/challenge/src/main/java/com/lightyears/challenge/configuration/RedisConfig.java new file mode 100644 index 0000000..d6c8736 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/configuration/RedisConfig.java @@ -0,0 +1,86 @@ +package com.lightyears.challenge.configuration; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; + +// 开启redis缓存功能 +@EnableCaching +// 备注这是一个配置类 +@Configuration +public class RedisConfig extends CachingConfigurerSupport { + + /** + * 配置redis模板文件 + * @param redisConnectionFactory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + RedisSerializer serializer = redisSerializer(); + // 创建RedisTemplate对象 + RedisTemplate redisTemplate = new RedisTemplate<>(); + // 配置连接工厂 + redisTemplate.setConnectionFactory(redisConnectionFactory); + // redis key 序列化方式使用stringSerial + redisTemplate.setKeySerializer(new StringRedisSerializer()); + // redis value 序列化方式使用jackson + redisTemplate.setValueSerializer(serializer); + // redis hash key 序列化方式使用stringSerial + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + // redis hash value 序列化方式使用jackson + redisTemplate.setHashValueSerializer(serializer); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + /** + * 配置序列化 + * @return + */ + @Bean + public RedisSerializer redisSerializer() { + // 定义Jackson2JsonRedisSerializer序列化对象 + Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class); + ObjectMapper objectMapper = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会报异常 + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + serializer.setObjectMapper(objectMapper); + return serializer; + } + + /** + * 自定义缓存管理器 + * @param redisConnectionFactory + * @return + */ + @Bean + public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) { + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory); + RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration + .defaultCacheConfig() + // 设置value 为自动转json的Object + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer())) + // 缓存有效期为一天 + .entryTtl(Duration.ofDays(1)); + return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration); + } + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/configuration/ScheduledConfig.java b/challenge/src/main/java/com/lightyears/challenge/configuration/ScheduledConfig.java new file mode 100644 index 0000000..4e82962 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/configuration/ScheduledConfig.java @@ -0,0 +1,24 @@ +package com.lightyears.challenge.configuration; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; + +import java.util.TimeZone; + +@Configuration +public class ScheduledConfig { + @Bean + public ThreadPoolTaskScheduler threadPoolTaskScheduler() { + ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); + threadPoolTaskScheduler.setPoolSize(3); + threadPoolTaskScheduler.setRemoveOnCancelPolicy(true); + return threadPoolTaskScheduler; + } + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() { + return jacksonObjectMapperBuilder -> + jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8")); + } +} \ No newline at end of file diff --git a/challenge/src/main/java/com/lightyears/challenge/controller/BaseController.java b/challenge/src/main/java/com/lightyears/challenge/controller/BaseController.java new file mode 100644 index 0000000..4ca08ac --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/controller/BaseController.java @@ -0,0 +1,55 @@ +package com.lightyears.challenge.controller; + +import com.lightyears.challenge.util.RedisCache; +import com.lightyears.challenge.util.StaticUtil; +import com.lightyears.common.domain.entity.Player; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class BaseController { + + @Autowired + private RedisCache redisCache; + + /** + * 得到request对象 + * + * @return + */ + public HttpServletRequest getRequest() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getRequest(); + return request; + } + + /** + * 得到respones对象 + * @return + */ + public HttpServletResponse getResponse() { + HttpServletResponse request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getResponse(); + return request; + } + + /** + * 得到当前登录用户信息 + * + * @return + */ + public Player getUserInfo() { + // 获取请求头中的token数据 + String token = getRequest().getHeader("Tracecode"); + if(token == null) { + token = this.getRequest().getParameter("Tracecode"); + } + String key = StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(token); + // 获取登录用户信息 + Player user = redisCache.getCacheObject(key); + return user; + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/controller/ChallengeController.java b/challenge/src/main/java/com/lightyears/challenge/controller/ChallengeController.java new file mode 100644 index 0000000..606e97d --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/controller/ChallengeController.java @@ -0,0 +1,109 @@ +package com.lightyears.challenge.controller; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.lightyears.challenge.annotation.DataVerification; +import com.lightyears.challenge.schedule.DynamicCornTask; +import com.lightyears.challenge.service.IChallengeService; +import com.lightyears.challenge.util.ResultUtil; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.Player; +import com.lightyears.common.domain.enums.MessageEnum; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@CrossOrigin +@RestController +@RequestMapping("/challenge") +@Api("扫雷 挑战榜调用接口:") +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class ChallengeController extends BaseController{ + + private final IChallengeService challengeServiceImpl; + private final DynamicCornTask dynamicCornTask; + + @DataVerification + @GetMapping("/list") + @ApiOperation(value = "榜单列表", notes = "挑战榜") + public ResModeBase list() { + return challengeServiceImpl.getList(); + } + + @RequestMapping(value = "/rankList", method = RequestMethod.POST) + @ApiOperation(value = "挑战榜列表", notes = "挑战榜") + @DataVerification + public ResModeBase rankList( + @ApiParam(value = "当前页", example = "1") @RequestParam(value = "pageIndex") Integer pageIndex, + @ApiParam(value = "每页数量", example = "1") @RequestParam(value = "pageSize") Integer pageSize, + @ApiParam(value = "榜单id", example = "1") @RequestParam(value = "id") Integer id) { + return challengeServiceImpl.rankList(pageIndex, pageSize, id); + } + + @DataVerification + @RequestMapping(value = "/admissionTicket", method = RequestMethod.POST) + @ApiOperation(value = "挑战门票费-开始挑战", notes = "挑战榜") + public ResModeBase admissionTicket( @ApiParam(value = "榜单id", example = "1") @RequestParam(value = "instanceId") Integer instanceId, + @ApiParam(value = "将要挑战的名次", example = "1") @RequestParam(value = "rank")Integer rank, + @ApiParam(value = "货币数量", example = "1") @RequestParam(value = "gold") Integer gold, + @ApiParam(value = "货币类型", example = "1") @RequestParam(value = "type") Integer type, + @ApiParam(value = "操作备注", example = "1") @RequestParam(value = "remark") String remark) { + return challengeServiceImpl.admissionTicket(instanceId, rank, gold, type,remark, this.getUserInfo().getUser_id()); + } + + @DataVerification + @RequestMapping(value = "/challengeDataSubmit", method = RequestMethod.POST) + @ApiOperation(value = "挑战结算", notes = "挑战榜") + public ResModeBase challengeDataSubmit( @ApiParam(value = "榜单id", example = "1") @RequestParam(value = "instanceId") Integer instanceId, + @ApiParam(value = "挑战名次", example = "1") @RequestParam(value = "rank") Integer rank, + @ApiParam(value = "游戏数据", example = "1") @RequestParam(value = "gameData") String gameData, + @ApiParam(value = "挑战用时", example = "1") @RequestParam(value = "challengeTime") Integer challengeTime, + @ApiParam(value = "挑战时原榜主id", example = "1") @RequestParam(value = "ownerId") Integer ownerId) { + Player player = this.getUserInfo(); + return challengeServiceImpl.challengeDataSubmit(instanceId,rank,gameData,challengeTime,ownerId, player.getUser_id(), player.getUser_name()); + } + + @DataVerification + @GetMapping("/playerAssert") + @ApiOperation(value = "获取玩家资产信息", notes = "挑战榜") + public ResModeBase playerAssert(){ + return challengeServiceImpl.playerAssert(this.getUserInfo().getUser_id()); + } + + @DataVerification + @GetMapping("/getMyRankInfo") + @ApiOperation(value = "获取玩家在榜单中的名次信息", notes = "挑战榜") + public ResModeBase getPlayerRankInfo(@ApiParam(value = "榜单id", example = "1") @RequestParam(value = "instanceId") Integer instanceId){ + return challengeServiceImpl.getPlayerRankInfo(instanceId, this.getUserInfo().getUser_id()); + } + + @PostMapping("/resetTaskTime") + public ResModeBase resetChallengeTaskTime(@RequestParam(value = "lockDate") String lockDateStr, + @RequestParam(value = "settlementDate") String settlementDateStr, + @RequestParam(value = "initDate") String initDateStr, + @RequestParam(value = "refreshDateStr") String refreshDateStr){ + // 锁榜 + DateTime lockDate = DateUtil.parse(lockDateStr); + // 结算 + DateTime settlementDate = DateUtil.parse(settlementDateStr); + // 初始化 + DateTime initDate = DateUtil.parse(initDateStr); + // 刷新 + DateTime refreshDate = DateUtil.parse(refreshDateStr); + + // 发起重置时间 + dynamicCornTask.initChallengeTask(lockDate, settlementDate, initDate, refreshDate); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), "请求成功!"); + } + + @PostMapping("/refreshRankCache") + public ResModeBase refreshRankCache(@RequestParam(value = "key")Integer key, @RequestParam(value = "instanceId") Integer instanceId, @RequestParam(value = "playerId") Integer playerId, @RequestParam(value = "rankNum") Integer rankNum){ + if(key == 43626546) { + challengeServiceImpl.clearRankByInstancePlayerId(instanceId, playerId, rankNum); + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/AssertLogMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/AssertLogMapper.java new file mode 100644 index 0000000..d8eae4a --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/AssertLogMapper.java @@ -0,0 +1,18 @@ +package com.lightyears.challenge.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.AssertLog; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface AssertLogMapper extends BaseMapper { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/ListBaseMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/ListBaseMapper.java new file mode 100644 index 0000000..d8a79ca --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/ListBaseMapper.java @@ -0,0 +1,17 @@ +package com.lightyears.challenge.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.ListBase; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface ListBaseMapper extends BaseMapper { +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/ListInstanceMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/ListInstanceMapper.java new file mode 100644 index 0000000..1a9b393 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/ListInstanceMapper.java @@ -0,0 +1,41 @@ +package com.lightyears.challenge.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.ListInstanceDto; +import com.lightyears.common.domain.entity.ListInstance; +import com.lightyears.common.domain.dto.ListInstanceDto; +import com.lightyears.common.domain.entity.ListInstance; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface ListInstanceMapper extends BaseMapper { + + /** + * 奖池增加 + * @param instanceId 榜实例id + * @param awardSize 奖池要增加的数 + * @param assetsType 货币类型 + * @return + */ + int updateInstanceAwardSize(@Param("instanceId") Integer instanceId,@Param("awardSize") Integer awardSize,@Param("assetsType") Integer assetsType); + + /** + * 获取榜单列表 + * + * @return + */ + List getListInstances(); +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/ListRankMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/ListRankMapper.java new file mode 100644 index 0000000..0286858 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/ListRankMapper.java @@ -0,0 +1,25 @@ +package com.lightyears.challenge.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.entity.ListRank; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface ListRankMapper extends BaseMapper { + int initRank(@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId); + List getRankList(@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId, @Param("state") Integer state); + List getNewRankList (@Param("instanceId") Integer instanceId, @Param("playerId") Integer playerId); + ListRankDto getRankByInsRank(@Param("instanceId") Integer instanceId,@Param("rank") Integer rank); +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/LogMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/LogMapper.java new file mode 100644 index 0000000..181a0e0 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/LogMapper.java @@ -0,0 +1,19 @@ +package com.lightyears.challenge.dao; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.Log; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface LogMapper extends BaseMapper { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/NoticeMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/NoticeMapper.java new file mode 100644 index 0000000..524c9ff --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/NoticeMapper.java @@ -0,0 +1,18 @@ +package com.lightyears.challenge.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.Notice; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +@Mapper +public interface NoticeMapper extends BaseMapper { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/PlayerAssetsMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/PlayerAssetsMapper.java new file mode 100644 index 0000000..8c48604 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/PlayerAssetsMapper.java @@ -0,0 +1,32 @@ +package com.lightyears.challenge.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + *

+ * Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Mapper +public interface PlayerAssetsMapper extends BaseMapper { + // 货币存放服务器 + int addGold(@Param("id") int id, @Param("gold") int gold, @Param("version") Long version); + + // 从服务器取出货币 + int reduceGold(@Param("id") int id,@Param("gold") int gold, @Param("version") Long version); + /** + * 获取用户资产 + * @param playerId + * @return + */ + List getPlayerAssets(@Param("playerId") int playerId); +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/PlayerMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/PlayerMapper.java new file mode 100644 index 0000000..bcdd692 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/PlayerMapper.java @@ -0,0 +1,17 @@ +package com.lightyears.challenge.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.Player; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 扫雷玩家表 Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface PlayerMapper extends BaseMapper { +} diff --git a/challenge/src/main/java/com/lightyears/challenge/dao/RecordMapper.java b/challenge/src/main/java/com/lightyears/challenge/dao/RecordMapper.java new file mode 100644 index 0000000..f068725 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/dao/RecordMapper.java @@ -0,0 +1,18 @@ +package com.lightyears.challenge.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.Record; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 游戏存档 Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface RecordMapper extends BaseMapper { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/exception/BussinessException.java b/challenge/src/main/java/com/lightyears/challenge/exception/BussinessException.java new file mode 100644 index 0000000..4b9ab64 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/exception/BussinessException.java @@ -0,0 +1,18 @@ +package com.lightyears.challenge.exception; + + +import com.lightyears.common.domain.enums.MessageEnum; + +/** + * @author fengshuonan + * @Description 业务异常的封装 + */ +public class BussinessException extends GlobalException { + public BussinessException(MessageEnum messageEnum) { + super(messageEnum.getCode(), messageEnum.getMessage()); + } + + public BussinessException(Integer code, String message) { + super(code, message); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/exception/GlobalException.java b/challenge/src/main/java/com/lightyears/challenge/exception/GlobalException.java new file mode 100644 index 0000000..b507e75 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/exception/GlobalException.java @@ -0,0 +1,47 @@ +package com.lightyears.challenge.exception; + + +import com.lightyears.common.domain.enums.MessageEnum; + +/*** + * 全局异常捕捉 统一返回 model + * */ +public class GlobalException extends RuntimeException { + + //友好提示的code码 + protected int friendlyCode; + + //友好提示 + protected String friendlyMsg; + + + protected GlobalException(int friendlyCode, String friendlyMsg) { + this.setValues(friendlyCode, friendlyMsg); + } + + public GlobalException(MessageEnum messageEnum) { + this.setValues(messageEnum.getCode(), messageEnum.getMessage()); + } + + private void setValues(int friendlyCode, String friendlyMsg) { + this.friendlyCode = friendlyCode; + this.friendlyMsg = friendlyMsg; + } + + public int getCode() { + return friendlyCode; + } + + public void setCode(int code) { + this.friendlyCode = code; + } + + public String getMessage() { + return friendlyMsg; + } + + public void setMessage(String message) { + this.friendlyMsg = message; + } + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/exception/MyExceptionHandle.java b/challenge/src/main/java/com/lightyears/challenge/exception/MyExceptionHandle.java new file mode 100644 index 0000000..9d6cb67 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/exception/MyExceptionHandle.java @@ -0,0 +1,26 @@ +package com.lightyears.challenge.exception; + +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.challenge.util.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +@Slf4j +@ControllerAdvice +public class MyExceptionHandle { + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public ResModeBase handle(Exception e) { + if (e instanceof GlobalException) { + GlobalException myException = (GlobalException) e; + return ResultUtil.result(myException.getCode(), myException.getMessage()); + } else { + log.error("系统异常", e); + return ResultUtil.result(MessageEnum.UNKNOWN_ERROR.getCode(), MessageEnum.UNKNOWN_ERROR.getMessage()); + } + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/filter/TokenFilter.java b/challenge/src/main/java/com/lightyears/challenge/filter/TokenFilter.java new file mode 100644 index 0000000..0a2f86c --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/filter/TokenFilter.java @@ -0,0 +1,116 @@ +package com.lightyears.challenge.filter; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.util.StringUtil; +import com.lightyears.challenge.config.AppConfig; +import com.lightyears.common.domain.entity.Player; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.challenge.util.RedisCache; +import com.lightyears.challenge.util.StaticUtil; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.annotation.Resource; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@Component +public class TokenFilter implements Filter{ + @Resource + private RedisCache redisCache; + @Resource + private AppConfig appConfig; + + @Override + public void init(FilterConfig filterConfig) { + ServletContext servletContext = filterConfig.getServletContext(); + ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); + redisCache = (RedisCache) ctx.getBean("redisCache"); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + // 刷新缓存不验证 + if(request.getRequestURI().indexOf("refreshRankCache")<0){ + // 版本号验证 + String version = request.getHeader("version"); + if (StrUtil.isEmpty(version)) { + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + try{ + Float versionCode = Float.valueOf(version); + if(versionCode < appConfig.getVersion()){ + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + }catch (Exception e) { + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + } + + String tracecode = request.getHeader("Tracecode"); + Boolean flag = request.getRequestURI().indexOf("touristLogin")<0 && request.getRequestURI().indexOf("getSystemTime") < 0 && request.getRequestURI().indexOf("swagger-ui")<0 && request.getRequestURI().indexOf("swagger-resources")<0 && request.getRequestURI().indexOf("v2") < 0 && request.getRequestURI().indexOf("refreshRankCache")<0; + + // 登录放行 + if(flag){ + // 判断身份码, 是否已登录 + if((StringUtil.isEmpty(tracecode) || !redisCache.hasKey(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode)))){ + /** + * 不是登录 || 身份码不存在 || 未在登录列表 就拒绝访问 + */ + this.authcReq(response, MessageEnum.SYSTEM_ERROR.getCode(), MessageEnum.SYSTEM_ERROR.getMessage()); + return; + } + Player player = redisCache.getCacheObject(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode)); + String token = redisCache.getCacheObject(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString())).toString(); + if(!tracecode.equals(token)) { + /** + * 登录失效,已被异地登录 + */ + this.authcReq(response, MessageEnum.LOCATION_ERROR.getCode(), MessageEnum.LOCATION_ERROR.getMessage()); + return; + } + // 重置身份缓存过期时间 + redisCache.expire(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString()), 1, TimeUnit.HOURS); + // 重置身份认证过期时间 + redisCache.expire(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode), 1, TimeUnit.HOURS); + } + + //执行 + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + + } + + /** + * 响应访问 + * @param response + * @throws IOException + */ + private void authcReq(HttpServletResponse response, Integer code, String msg) throws IOException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentType("application/json; charset=utf-8"); + PrintWriter writer = response.getWriter(); + Map map = new HashMap<>(); + map.put("code", code); + map.put("msg", msg); + writer.print(JSONObject.toJSON(map)); + } + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/init/ChallengeDataInit.java b/challenge/src/main/java/com/lightyears/challenge/init/ChallengeDataInit.java new file mode 100644 index 0000000..6697464 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/init/ChallengeDataInit.java @@ -0,0 +1,131 @@ +package com.lightyears.challenge.init; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lightyears.challenge.dao.ListBaseMapper; +import com.lightyears.challenge.dao.ListInstanceMapper; +import com.lightyears.challenge.dao.ListRankMapper; +import com.lightyears.common.domain.dto.ListInstanceDto; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.dto.OrdinaryRankDto; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.challenge.schedule.DynamicCornTask; +import com.lightyears.challenge.util.RedisCache; +import com.lightyears.challenge.util.StaticUtil; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.annotation.Resource; +import java.util.Arrays; +import java.util.List; + +/** + * 挑战数据初始化 + */ +@Component +public class ChallengeDataInit { + @Resource + private RedisCache redisCache; + @Resource + private ListRankMapper listRankMapper; + @Resource + private ListInstanceMapper listInstanceMapper; + @Resource + private ListBaseMapper listBaseMapper; + @Resource + private DynamicCornTask dynamicCornTask; + + @PostConstruct + public void init() { + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE); + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL); + this.initData(true); + } + + @PreDestroy + public void destroy() { + // 系统运行结束 + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE); + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL); + // 写入持久层 + } + + // 刷新挑战榜的缓存数据 + public void refreshData() { + // 删除上一周期的挑战榜缓存数据 + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE); + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL); + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_ONLINE_USER); + // 写入新一周期的挑战榜缓存数据 + this.initData(false); + } + + private void initData(Boolean isStart){ + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL); + // 写入开启中挑战榜实例信息 + List instances = this.initInstance(); + if(isStart){ + // 启动挑战榜定时任务 + initChallengeTask(); + } + + instances.stream().forEach(instance -> { + List ranks = this.initranks(instance.getId()); + // 存入 + redisCache.lSetAll(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(instance.getId().toString()), ranks); + }); + } + + /** + * 存入榜实例信息 + * @return + */ + public List initInstance (){ + redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE); + List instances = this.listInstanceMapper.getListInstances(); + if (!CollectionUtils.isEmpty(instances)){ + redisCache.setCacheObject(StaticUtil.CHALLENGE_INSTANCE, instances); + } + return instances; + } + + /** + * 写入开启中挑战榜的排名信息 + * @param instanceId 榜实例id + * @return + */ + public List initranks (Integer instanceId){ +// redisCache.deleteByPrefix(StaticUtil.CHALLENGE_INSTANCE_RANK.concat(instanceId.toString())); + List ranks = listRankMapper.getRankList(instanceId, null, null); +// if (!CollectionUtils.isEmpty(ranks)){ +// redisCache.setCacheList(StaticUtil.CHALLENGE_INSTANCE_RANK.concat(instanceId.toString()), ranks); +// } + return ranks; + } + + /** + * 启动挑战榜定时任务 + */ + public void initChallengeTask(){ + List list = listBaseMapper.selectList(new QueryWrapper().orderByDesc("init_date")); + if (!CollectionUtils.isEmpty(list)){ + ListBase bases = list.get(0); + // 锁榜 周日 晚上11:00 + DateTime lockDate = DateUtil.offsetDay(DateUtil.parse(bases.getInitDate().concat(StaticUtil.LOCKE_TIME)), bases.getSettlementDay() - 1); + // 结算 周一 晚上11:45 + DateTime settlementDate = DateUtil.offsetDay(DateUtil.parse(bases.getInitDate().concat(StaticUtil.SETTLEMENT_TIME)), bases.getSettlementDay()); + // 初始化 周二 早上1:00 + DateTime initDate = DateUtil.offsetDay(DateUtil.parse(bases.getInitDate().concat(StaticUtil.CHALLENGE_INIT_TIME)), bases.getSettlementDay() + 1); + // 缓存刷新 周二 早上1:05 + DateTime refreshData = DateUtil.offsetDay(DateUtil.parse(bases.getInitDate().concat(StaticUtil.CHALLENGE_REFRESH_TIME)), bases.getSettlementDay() + 1); + // 启动定时任务 + dynamicCornTask.initChallengeTask(lockDate, settlementDate, initDate, refreshData); + } + } + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/listener/AdmissionTicketListener.java b/challenge/src/main/java/com/lightyears/challenge/listener/AdmissionTicketListener.java new file mode 100644 index 0000000..99fb1e4 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/listener/AdmissionTicketListener.java @@ -0,0 +1,50 @@ +package com.lightyears.challenge.listener; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.lightyears.challenge.dao.ListInstanceMapper; +import com.lightyears.common.domain.dto.ListPoolChangeDto; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.entity.ListInstance; +import com.lightyears.challenge.util.RedisCache; +import com.lightyears.challenge.util.StaticUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Component +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +@RocketMQMessageListener(topic = "admissionTicket", selectorExpression = "submit",consumerGroup = "challengeRankTicket") +public class AdmissionTicketListener implements RocketMQListener { + + private final ListInstanceMapper listInstanceMapper; + private final RedisCache redisCache; + + @Override + @Transactional + public void onMessage(ListPoolChangeDto dto) { + log.info("报名消息已成功接收!"); + ListInstance instance = listInstanceMapper.selectById(dto.getInstanceId()); + String key = StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(dto.getInstanceId().toString()); + if(instance != null && instance.getStatus() == 1){ + Object obj = redisCache.lGetIndex(key, dto.getRank()-1); + if(obj == null) + return; + String json = JSONObject.toJSONString(obj) ; + ListRankDto rankDto = JSON.parseObject(json, ListRankDto.class); + + Integer num = rankDto.getChallenges() == null ? 0 : rankDto.getChallenges(); + rankDto.setChallenges(num + 1); + // 挑战人数+1 + redisCache.lUpdateIndex(key, dto.getRank()-1, rankDto); + // 更新奖池大小 + listInstanceMapper.updateInstanceAwardSize(dto.getInstanceId(), (int) (dto.getGold()*instance.getInPondFee()), dto.getType()); + } + log.info("报名消息已消费完成"); + } +} \ No newline at end of file diff --git a/challenge/src/main/java/com/lightyears/challenge/listener/RankDataUpdateListener.java b/challenge/src/main/java/com/lightyears/challenge/listener/RankDataUpdateListener.java new file mode 100644 index 0000000..70b24f4 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/listener/RankDataUpdateListener.java @@ -0,0 +1,56 @@ +package com.lightyears.challenge.listener; + +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.dto.RankDataDto; +import com.lightyears.challenge.service.IListRankService; +import com.lightyears.challenge.util.RedisCache; +import com.lightyears.challenge.util.StaticUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Slf4j +@Component +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +@RocketMQMessageListener(topic = "rankUpdate", selectorExpression = "submit", consumerGroup = "challengeRank") +public class RankDataUpdateListener implements RocketMQListener { + + private final IListRankService listRankService; + private final RedisCache redisCache; + + @Override + @Transactional + public void onMessage(RankDataDto dto) { + log.info("结算消息已成功接收!"); + ListRankDto rankDto = dto.getRankDto(); + // 查询未结算的原排名信息 + List ranks = listRankService.getPlayerRankInfo(null, dto.getMyId()); + for (ListRankDto rank : ranks){ + // 重置该挑战榜单下的其他名次信息 + int num = listRankService.initRank(rank.getInstanceId(), dto.getMyId()); + // 更新原排名缓存 + if(num > 0) { + rank.setChallengeTime(null); + rank.setPlayerId(null); + rank.setPlayerName(null); + rank.setGameData(null); + redisCache.lUpdateIndex(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(rank.getInstanceId().toString()), rank.getRankNum() - 1, rank); + } + } + + rankDto.setPlayerId(dto.getMyId()); + rankDto.setPlayerName(dto.getMyName()); + rankDto.setChallengeTime(dto.getChallengeTime()); + // 更新缓存 + redisCache.lUpdateIndex(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(dto.getInstanceId().toString()), rankDto.getRankNum() - 1, rankDto); + // 写入数据库 + listRankService.updateRankInfo(dto.getInstanceId(), dto.getRankNum(), dto.getGameData(), dto.getChallengeTime(), dto.getMyId(), dto.getMyName()); + log.info("结算消息已成功消费!"); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeCacheRefreshTask.java b/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeCacheRefreshTask.java new file mode 100644 index 0000000..81d43b4 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeCacheRefreshTask.java @@ -0,0 +1,42 @@ +package com.lightyears.challenge.schedule; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.challenge.init.ChallengeDataInit; +import com.lightyears.challenge.service.IListBaseService; +import com.lightyears.challenge.util.GetBeanUtil; +import com.lightyears.challenge.util.StaticUtil; +import org.springframework.util.CollectionUtils; + +import java.util.List; + +public class ChallengeCacheRefreshTask implements Runnable{ + @Override + public void run() { + ChallengeDataInit challengeDataInit = (ChallengeDataInit) GetBeanUtil.getBean(ChallengeDataInit.class); + IListBaseService listBaseService = (IListBaseService)GetBeanUtil.getBean("listBaseServiceImpl"); + DynamicCornTask dynamicCornTask = (DynamicCornTask) GetBeanUtil.getBean(DynamicCornTask.class); + // 刷新挑战榜数据 + challengeDataInit.refreshData(); + // 开启下一周期的任务 + List listBases = listBaseService.list(); + if(!CollectionUtils.isEmpty(listBases)){ + ListBase listBase = listBases.get(0); + // 锁榜 结束日 晚上11:00 + DateTime lockDate = DateUtil.offsetDay(DateUtil.parse(listBase.getInitDate().concat(StaticUtil.LOCKE_TIME)), listBase.getSettlementDay() - 1); + // 结算 结束日 晚上11:45 + DateTime settlementDate = DateUtil.offsetDay(DateUtil.parse(listBase.getInitDate().concat(StaticUtil.SETTLEMENT_TIME)), listBase.getSettlementDay()); + // 初始化 结束日第二天 早上1:00 + DateTime initDate = DateUtil.offsetDay(DateUtil.parse(listBase.getInitDate().concat(StaticUtil.CHALLENGE_INIT_TIME)), listBase.getSettlementDay() + 1); + // 缓存刷新 结束日第二天 早上1:00 + DateTime refreshDate = DateUtil.offsetDay(DateUtil.parse(listBase.getInitDate().concat(StaticUtil.CHALLENGE_REFRESH_TIME)), listBase.getSettlementDay() + 1); + for (ListBase base : listBases) { + // 修改初始化日期 + base.setInitDate(initDate.toDateStr()); + } + // 重置定时任务 + dynamicCornTask.resetChallengeTask(lockDate, settlementDate, initDate, refreshDate); + } + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeLockTask.java b/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeLockTask.java new file mode 100644 index 0000000..e4f90d4 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeLockTask.java @@ -0,0 +1,29 @@ +package com.lightyears.challenge.schedule; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.lightyears.common.domain.entity.ListInstance; +import com.lightyears.challenge.service.IListInstanceService; +import com.lightyears.challenge.util.GetBeanUtil; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; + +public class ChallengeLockTask implements Runnable{ + @Override + @Transactional + public void run() { + IListInstanceService listInstanceService = (IListInstanceService) GetBeanUtil.getBean("listInstanceServiceImpl"); + // 查询开启中的挑战榜实例 + List listInstances = listInstanceService.list(new QueryWrapper().eq("status", 1)); + // 结算每个实例榜单 + listInstances.stream().forEach(listInstance ->{ + // 结算日期 + listInstance.setSettlementDate(new Date()); + // 已截止,待结算 + listInstance.setStatus(3); + // 修改实例榜信息 + listInstanceService.updateById(listInstance); + }); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeSettlementTask.java b/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeSettlementTask.java new file mode 100644 index 0000000..730db4e --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/schedule/ChallengeSettlementTask.java @@ -0,0 +1,94 @@ +package com.lightyears.challenge.schedule; + +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.lightyears.challenge.service.*; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.common.domain.entity.ListInstance; +import com.lightyears.common.domain.entity.Notice; +import com.lightyears.common.domain.enums.AssetsTypeEnum; +import com.lightyears.challenge.util.GetBeanUtil; +import com.lightyears.challenge.util.RedisCache; +import com.lightyears.challenge.util.StaticUtil; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class ChallengeSettlementTask implements Runnable{ + @Override + @Transactional + public void run() { + IListBaseService listBaseService = (IListBaseService)GetBeanUtil.getBean("listBaseServiceImpl"); + IListInstanceService listInstanceService = (IListInstanceService) GetBeanUtil.getBean("listInstanceServiceImpl"); + IListRankService listRankService = (IListRankService) GetBeanUtil.getBean("listRankServiceImpl"); + IGameSystemService gameSystemService = (IGameSystemService)GetBeanUtil.getBean("gameSystemServiceImpl"); + INoticeService noticeService = (INoticeService) GetBeanUtil.getBean("noticeServiceImpl"); + RedisCache redisCache = (RedisCache)GetBeanUtil.getBean("redisCache"); + // 查询待结算的挑战榜实例 + List listInstances = listInstanceService.list(new QueryWrapper().eq("status", 3)); + // 结算每个实例榜单 + listInstances.stream().forEach(listInstance -> { + BigDecimal awardSize = new BigDecimal(listInstance.getAwardSize()); + String[] distribution = ObjectUtils.isEmpty(listInstance.getDistribution()) || listInstance.getDistribution().length() < listInstance.getMaxPlayerNum() ? defaultDistribution(listInstance.getMaxPlayerNum()) : listInstance.getDistribution().split(","); + List ranks = listRankService.getRankList(listInstance.getId()); + BigDecimal hundred = new BigDecimal(100); + for (int i = 0; i < ranks.size(); i++) { + ListRankDto rank = ranks.get(i); + if (!ObjectUtils.isEmpty(rank.getPlayerId())){ + BigDecimal distributionNum = new BigDecimal(distribution[i]).divide(hundred); + Integer bonus = awardSize.multiply(distributionNum).setScale(0, BigDecimal.ROUND_HALF_DOWN).intValue(); + if (bonus > 0){ + // 排名玩家奖励发放 + gameSystemService.pushGold(rank.getPlayerId(), bonus, listInstance.getAssetsType(), String.format(StaticUtil.CHALLENGE_REMARK, listInstance.getName(), rank.getRankNum(), bonus, AssetsTypeEnum.getNameById(listInstance.getAssetsType()))); + // 奖励通知写入 + Notice notice = new Notice().builder() + .playerId(rank.getPlayerId()) + .status(0) + .type(1) + .createDate(new Date()) + .title(StaticUtil.CHALLENGE_NOTICE_TITLE) + .content(String.format(StaticUtil.CHALLENGE_REMARK, listInstance.getName(), rank.getRankNum(), bonus, AssetsTypeEnum.getNameById(listInstance.getAssetsType()))).build(); + noticeService.save(notice); + } + } + } + // 结算日期 + listInstance.setSettlementDate(new Date()); + // 已截止 + listInstance.setStatus(2); + // 修改实例榜信息 + listInstanceService.updateById(listInstance); + // 删除这次挑战榜所有缓存 + redisCache.deleteByPrefix(StaticUtil.CHALLENGE); + // 修改初始化时间 + listBaseService.update(new LambdaUpdateWrapper().set(ListBase::getInitDate, DateUtil.today()).eq(ListBase::getId, listInstance.getListId())); + }); + } + private String[] defaultDistribution(Integer maxNum) { + List arr = new ArrayList<>(); + for (int i = 0; i < maxNum; i++) { + arr.add(calc(i, 0, 100, maxNum).intValue() + ""); + } + return arr.toArray(new String[]{}); + } + /** + * @param curtime + * @param begin + * @param end + * @param duration + * @return + */ + private Float controlWeightRote(Integer curtime, Integer begin, Integer end, Integer duration) { + return (curtime == 0) ? begin * 1.0F : end * (curtime / duration - 1) + begin; + } + + private Float calc(Integer curtime, Integer begin, Integer end, Integer duration) { + return controlWeightRote(curtime, begin, end, duration) - controlWeightRote(curtime - 1, begin, end, duration); + } +} \ No newline at end of file diff --git a/challenge/src/main/java/com/lightyears/challenge/schedule/DynamicCornTask.java b/challenge/src/main/java/com/lightyears/challenge/schedule/DynamicCornTask.java new file mode 100644 index 0000000..76d8b1e --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/schedule/DynamicCornTask.java @@ -0,0 +1,145 @@ +package com.lightyears.challenge.schedule; + +import cn.hutool.core.date.DateTime; +import com.lightyears.challenge.util.CronUtils; +import com.lightyears.challenge.util.ScheduledFutureHolder; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronTrigger; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.concurrent.ScheduledFuture; + +@Slf4j +@Component +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class DynamicCornTask { + private final ThreadPoolTaskScheduler threadPoolTaskScheduler; + //存储任务执行的包装类 + private HashMap scheduleMap = new HashMap<>(); + + /** + *启动任务 + * 如果不想手动触发任务可以使用 @PostConstruct注解来启动 + */ + public void startTask(Runnable task, String corn) { + try { + //将任务交给任务调度器执行 + ScheduledFuture schedule = threadPoolTaskScheduler.schedule(task, new CronTrigger(corn)); + + //将任务包装成ScheduledFutureHolder + ScheduledFutureHolder scheduledFutureHolder = new ScheduledFutureHolder(); + scheduledFutureHolder.setScheduledFuture(schedule); + scheduledFutureHolder.setRunnableClass(task.getClass()); + scheduledFutureHolder.setCorn(corn); + + scheduleMap.put(task.getClass().getName(),scheduledFutureHolder); + log.info("定时任务启动成功:".concat(task.getClass().getName())); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /** + * 查询所有的任务 + */ + public void queryTask(){ + scheduleMap.forEach((k,v)->{ + System.out.println(k+" "+v); + System.out.println(v.getCorn()); + }); + } + + /** + * 停止任务 + * @param className + */ + public void stopTask(String className){ + if(scheduleMap.containsKey(className)){//如果包含这个任务 + ScheduledFuture scheduledFuture = scheduleMap.get(className).getScheduledFuture(); + if(scheduledFuture!=null){ + scheduledFuture.cancel(true); + } + } + } + + + /** + * 重启任务,修改任务的触发时间 + * @param className + * @throws InstantiationException + * @throws IllegalAccessException + */ + public void restartTask(String className, String corn){ + if(scheduleMap.containsKey(className)){//如果包含这个任务 + + ScheduledFutureHolder scheduledFutureHolder = scheduleMap.get(className); + ScheduledFuture scheduledFuture = scheduledFutureHolder.getScheduledFuture(); + if(scheduledFuture!=null) { + try { + //先停掉任务 + scheduledFuture.cancel(true); + + //修改触发时间重新启动任务 + Runnable runnable = null; + + runnable = scheduledFutureHolder.getRunnableClass().newInstance(); + + ScheduledFuture schedule = threadPoolTaskScheduler.schedule(runnable, new CronTrigger(corn)); + + scheduledFutureHolder.setScheduledFuture(schedule); + scheduledFutureHolder.setCorn(corn); + + scheduleMap.put(scheduledFutureHolder.getRunnableClass().getName(), scheduledFutureHolder); + }catch(Exception e){ + log.error("定时任务重置失败:".concat(className)); + log.error("详细错误信息:", e); + } + } + } + } + + /** + * 挑战榜定时任务重启 + * @param lockDate 锁榜日期时间 + * @param settlementDate 结算日期时间 + * @param initDate 初始化新榜日期时间 + * @param refreshDate 缓存刷新时间 + */ + public void resetChallengeTask(DateTime lockDate, DateTime settlementDate, DateTime initDate, DateTime refreshDate){ + restartTask(ChallengeLockTask.class.getName(), CronUtils.getCron(lockDate)); + restartTask(ChallengeSettlementTask.class.getName(), CronUtils.getCron(settlementDate)); + restartTask(InitChallengeTask.class.getName(), CronUtils.getCron(initDate)); + restartTask(ChallengeCacheRefreshTask.class.getName(), CronUtils.getCron(refreshDate)); + log.info("下次锁榜时间:".concat(lockDate.toString())); + log.info("下次结算时间:".concat(settlementDate.toString())); + log.info("下次初始化时间:".concat(initDate.toString())); + log.info("下次刷新时间:".concat(refreshDate.toString())); + log.info("挑战榜定时任务启动成功"); + } + + /** + * 挑战榜定时任务启动 + * @param lockDate 锁榜日期时间 + * @param settlementDate 结算日期时间 + * @param initDate 初始化新榜日期时间 + * @param refreshDate 缓存刷新时间 + */ + public void initChallengeTask(DateTime lockDate, DateTime settlementDate, DateTime initDate, DateTime refreshDate){ + // 每5分钟刷新挑战实例的奖池 + startTask(new RefreshInstanceListTask(), "0 */1 * * * ?"); + startTask(new ChallengeLockTask(), CronUtils.getCron(lockDate)); + startTask(new ChallengeSettlementTask(), CronUtils.getCron(settlementDate)); + startTask(new InitChallengeTask(), CronUtils.getCron(initDate)); + startTask(new ChallengeCacheRefreshTask(), CronUtils.getCron(refreshDate)); + log.info("下次锁榜时间:".concat(lockDate.toString())); + log.info("下次结算时间:".concat(settlementDate.toString())); + log.info("下次初始化时间:".concat(initDate.toString())); + log.info("下次刷新时间:".concat(refreshDate.toString())); + log.info("挑战榜定时任务启动成功"); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/schedule/InitChallengeTask.java b/challenge/src/main/java/com/lightyears/challenge/schedule/InitChallengeTask.java new file mode 100644 index 0000000..17e1113 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/schedule/InitChallengeTask.java @@ -0,0 +1,35 @@ +package com.lightyears.challenge.schedule; + +import com.lightyears.challenge.service.IListBaseService; +import com.lightyears.challenge.service.IListInstanceService; +import com.lightyears.challenge.service.IListRankService; +import com.lightyears.challenge.util.GetBeanUtil; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.common.domain.entity.ListInstance; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +public class InitChallengeTask implements Runnable { + @Override + @Transactional + public void run() { + IListInstanceService listInstanceService = (IListInstanceService) GetBeanUtil.getBean("listInstanceServiceImpl"); + IListBaseService listBaseService = (IListBaseService)GetBeanUtil.getBean("listBaseServiceImpl"); + IListRankService listRankService = (IListRankService) GetBeanUtil.getBean("listRankServiceImpl"); + + List listBases = listBaseService.list(); + List instances = new ArrayList<>(); + if(!CollectionUtils.isEmpty(listBases)){ + for (ListBase base : listBases) { + ListInstance instance = listInstanceService.saveInstanceByBase(base); + instances.add(instance); + for (int i = 0; i < instance.getMaxPlayerNum(); i++) { + listRankService.saveRankByInstance(instance.getId(), i+1); + } + } + } + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/schedule/RefreshInstanceListTask.java b/challenge/src/main/java/com/lightyears/challenge/schedule/RefreshInstanceListTask.java new file mode 100644 index 0000000..7ddac29 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/schedule/RefreshInstanceListTask.java @@ -0,0 +1,13 @@ +package com.lightyears.challenge.schedule; + +import com.lightyears.challenge.init.ChallengeDataInit; +import com.lightyears.challenge.util.GetBeanUtil; + +public class RefreshInstanceListTask implements Runnable{ + + @Override + public void run() { + ChallengeDataInit challengeDataInit = (ChallengeDataInit) GetBeanUtil.getBean("challengeDataInit"); + challengeDataInit.initInstance(); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/IChallengeService.java b/challenge/src/main/java/com/lightyears/challenge/service/IChallengeService.java new file mode 100644 index 0000000..f4b1e2f --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/IChallengeService.java @@ -0,0 +1,13 @@ +package com.lightyears.challenge.service; + +import com.lightyears.common.domain.dto.ResModeBase; + +public interface IChallengeService { + ResModeBase getList(); + ResModeBase rankList(Integer pageIndex, Integer pageSize, Integer id); + ResModeBase challengeDataSubmit(Integer instanceId, Integer rank, String gameData, Integer challengeTime, Integer ownerId, Integer myId, String myName); + ResModeBase playerAssert(Integer playerId); + ResModeBase admissionTicket(Integer instanceId, Integer rank, Integer gold, Integer type, String remark, Integer playerId); + ResModeBase getPlayerRankInfo(Integer instanceId, Integer playerId); + void clearRankByInstancePlayerId(Integer instanceId, Integer playerId, Integer rankNum); +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/IGameSystemService.java b/challenge/src/main/java/com/lightyears/challenge/service/IGameSystemService.java new file mode 100644 index 0000000..81dae88 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/IGameSystemService.java @@ -0,0 +1,9 @@ +package com.lightyears.challenge.service; + + +import com.lightyears.common.domain.dto.ResModeBase; + +public interface IGameSystemService { + + ResModeBase pushGold(Integer userId, int gold, int type, String remark); +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/IListBaseService.java b/challenge/src/main/java/com/lightyears/challenge/service/IListBaseService.java new file mode 100644 index 0000000..5e5c598 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/IListBaseService.java @@ -0,0 +1,16 @@ +package com.lightyears.challenge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.ListBase; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +public interface IListBaseService extends IService { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/IListInstanceService.java b/challenge/src/main/java/com/lightyears/challenge/service/IListInstanceService.java new file mode 100644 index 0000000..09776aa --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/IListInstanceService.java @@ -0,0 +1,18 @@ +package com.lightyears.challenge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.common.domain.entity.ListInstance; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +public interface IListInstanceService extends IService { + + ListInstance saveInstanceByBase(ListBase base); +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/IListRankService.java b/challenge/src/main/java/com/lightyears/challenge/service/IListRankService.java new file mode 100644 index 0000000..ee53145 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/IListRankService.java @@ -0,0 +1,24 @@ +package com.lightyears.challenge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.entity.ListRank; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +public interface IListRankService extends IService { + ListRank saveRankByInstance(Integer instanceId, Integer rank); + int initRank(Integer instanceId,Integer playerId); + int updateRankInfo(Integer instanceId, Integer rank, String gameData, Integer challengeTime, Integer playerId, String playerName); + ListRankDto getRankByInsRank(Integer instanceId, Integer rank); + List getRankList(Integer instanceId); + List getPlayerRankInfo(Integer instanceId, Integer playerId); +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/ILogService.java b/challenge/src/main/java/com/lightyears/challenge/service/ILogService.java new file mode 100644 index 0000000..d6aba21 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/ILogService.java @@ -0,0 +1,15 @@ +package com.lightyears.challenge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.Log; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface ILogService extends IService { +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/INoticeService.java b/challenge/src/main/java/com/lightyears/challenge/service/INoticeService.java new file mode 100644 index 0000000..7bc4106 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/INoticeService.java @@ -0,0 +1,16 @@ +package com.lightyears.challenge.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.Notice; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +public interface INoticeService extends IService { +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/IPlayerAssetsService.java b/challenge/src/main/java/com/lightyears/challenge/service/IPlayerAssetsService.java new file mode 100644 index 0000000..d2ccf45 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/IPlayerAssetsService.java @@ -0,0 +1,33 @@ +package com.lightyears.challenge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; + +import java.util.List; + +/** + *

+ * 服务类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +public interface IPlayerAssetsService extends IService { + /** + * 添加金币 + * @param id id + * @param gold 增加后的金币 + */ + Integer addGold(int id, int gold); + + /** + * 扣除金币 + * @param id id + * @param gold 需要扣减的金币 + */ + Integer reduceGold(int id, int gold); + + List getPlayerAssets(int playerId); +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/IPlayerService.java b/challenge/src/main/java/com/lightyears/challenge/service/IPlayerService.java new file mode 100644 index 0000000..ba89dfd --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/IPlayerService.java @@ -0,0 +1,16 @@ +package com.lightyears.challenge.service; + + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.Player; + +/** + *

+ * 扫雷玩家表 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface IPlayerService extends IService { +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/IRecordService.java b/challenge/src/main/java/com/lightyears/challenge/service/IRecordService.java new file mode 100644 index 0000000..791126b --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/IRecordService.java @@ -0,0 +1,16 @@ +package com.lightyears.challenge.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.Record; + +/** + *

+ * 游戏存档 服务类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +public interface IRecordService extends IService { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/ChallengeServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/ChallengeServiceImpl.java new file mode 100644 index 0000000..abf8e96 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/ChallengeServiceImpl.java @@ -0,0 +1,231 @@ +package com.lightyears.challenge.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.github.pagehelper.Page; +import com.github.pagehelper.PageInfo; +import com.lightyears.challenge.dao.AssertLogMapper; +import com.lightyears.challenge.dao.ListInstanceMapper; +import com.lightyears.common.domain.dto.*; +import com.lightyears.common.domain.entity.AssertLog; +import com.lightyears.common.domain.entity.ListInstance; +import com.lightyears.common.domain.entity.PlayerAssets; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.challenge.init.ChallengeDataInit; +import com.lightyears.challenge.service.IChallengeService; +import com.lightyears.challenge.service.IListRankService; +import com.lightyears.challenge.service.IPlayerAssetsService; +import com.lightyears.challenge.util.RedisCache; +import com.lightyears.challenge.util.ResultUtil; +import com.lightyears.challenge.util.StaticUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Validated +@Service("challengeServiceImpl") +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class ChallengeServiceImpl implements IChallengeService { + + private final RedisCache redisCache; + private final ListInstanceMapper listInstanceMapper; + private final IListRankService listRankServiceImpl; + private final ChallengeDataInit challengeDataInit; + private final RocketMQTemplate rocketMQTemplate; + private final AssertLogMapper assertLogMapper; + private final IPlayerAssetsService playerAssetsService; + + @Override + public ResModeBase getList() { + List dtos = this.redisCache.getCacheObject(StaticUtil.CHALLENGE_INSTANCE); + if(CollectionUtils.isEmpty(dtos)) { + // 如果缓存无,查询数据库 + dtos = challengeDataInit.initInstance(); + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), dtos); + } + + @Override + public ResModeBase rankList(Integer pageIndex, Integer pageSize, Integer id) { + Long total = redisCache.lGetListSize(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(id.toString())); + // 计算当前需要显示的数据下标起始值 + int startIndex = (pageIndex - 1) * pageSize; + int endIndex = Math.min(startIndex + pageSize,total.intValue()) - 1; + // 缓存中读取对应实例榜的排名数据 + List objectList = redisCache.lGet(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(id.toString()), startIndex, endIndex); + List listRankDtos = new ArrayList<>(); + objectList.stream().forEach(item -> { + String json = JSONObject.toJSONString(item) ; + listRankDtos.add(JSON.parseObject(json, ListRankDto.class)); + }); + if (CollectionUtils.isEmpty(listRankDtos)) { + return ResultUtil.result(MessageEnum.ADD_ERROR.getCode(), "暂无该排行排名数据"); + } + // 创建Page类 + Page page = new Page(pageIndex, pageSize); + // 为Page类中的total属性赋值 + page.setTotal(total); + // 从链表中截取需要显示的子链表,并加入到Page + page.addAll(listRankDtos); + // 以Page创建PageInfo + PageInfo pageInfo = new PageInfo(page); + pageInfo.getList().stream().forEach(rankDto -> { + rankDto.setGameData(null); + }); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), pageInfo); + } + + @Override + @Transactional + public ResModeBase challengeDataSubmit(Integer instanceId, Integer rank, String gameData, Integer challengeTime, Integer ownerId, Integer myId, String myName){ + Integer code = 2; + ListRankDto rankDto; + ListInstance listInstance = listInstanceMapper.selectById(instanceId); + // 挑战榜不存在或者挑战榜不为开启状态 + if (ObjectUtils.isEmpty(listInstance) || listInstance.getStatus() != 1){ + return ResultUtil.result(MessageEnum.ERROR.getCode(), "提交失败,挑战榜已关闭"); + } + /** + * TODO: + * 1.获取指定榜单与名次的listRank + * 2.比较对局时间判断是否挑战成功 + * (挑战成功则写入信息到挑战榜,返回1.挑战成功; + * 挑战失败则判断挑战榜主id是否是原挑战榜主id,是则返回2.挑战失败; + * 否则返回 3.已被其他人抢先挑战成功) + */ + // 获取指定榜单与名次的listRank + Object obj = redisCache.lGetIndex(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(instanceId.toString()), rank-1); + if(obj == null){ + rankDto= listRankServiceImpl.getRankByInsRank(instanceId, rank); + if(ObjectUtils.isEmpty(rankDto)){ + log.error("未查询到挑战的排名信息"); + return ResultUtil.result(MessageEnum.ERROR.getCode(), "未查询到挑战的排名信息"); + } + } else { + String json = JSONObject.toJSONString(obj) ; + rankDto = JSON.parseObject(json, ListRankDto.class); + } + if(rankDto.getChallengeTime() == null || challengeTime < rankDto.getChallengeTime()){ + RankDataDto rankDataDto = RankDataDto.builder().rankDto(rankDto).instanceId(instanceId).rankNum(rank).gameData(gameData).challengeTime(challengeTime).myId(myId).myName(myName).build(); + code = 1; + SendCallback callback = new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + log.info("消息已成功发送"); + } + @Override + public void onException(Throwable throwable) { + log.info("消息发送异常,发送失败"); + } + }; + rocketMQTemplate.asyncSend("rankUpdate:submit",rankDataDto,callback); + } else { + // 挑战的榜主与现在的榜主是否是同一用户 + if (!rankDto.getPlayerId().equals(ownerId) && ownerId != -1) { + code = 3; + } + } + // 移除正在挑战的信息 + redisCache.deleteObject(StaticUtil.CHALLENGE_ONLINE_USER.concat(instanceId.toString()).concat(":".concat(rank.toString()).concat(":".concat(myId.toString())))); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), code); + } + + @Override + public ResModeBase admissionTicket(Integer instanceId, Integer rank, Integer gold, Integer type, String remark, Integer playerId) { + ListInstance instance = listInstanceMapper.selectOne(new QueryWrapper().eq("id", instanceId).eq("status", 1)); + if(ObjectUtils.isEmpty(instance)){ + log.error("未查询到挑战榜信息,挑战榜实例id:".concat(instanceId.toString())); + return ResultUtil.result(MessageEnum.ERROR.getCode(), "挑战榜已关闭!"); + } + Object obj = redisCache.lGetIndex(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(instanceId.toString()), rank-1); + if(obj == null){ + log.error("未查询到挑战的排名信息"); + return ResultUtil.result(MessageEnum.ERROR.getCode(), "未查询到挑战的排名信息"); + } + Long time = System.currentTimeMillis() / 1000; + try{ + + PlayerAssets playerAssets = playerAssetsService.getOne(new LambdaQueryWrapper().eq(PlayerAssets::getPlayerId, playerId).eq(PlayerAssets::getType, type).orderByDesc(PlayerAssets::getId).last("limit 1")); + if(playerAssets == null){ + log.error("未查询到玩家资产信息,玩家id:".concat(playerId.toString())); + return ResultUtil.result(MessageEnum.ERROR.getCode(), "玩家资产信息不存在!"); + } + // 扣除玩家指定货币 + playerAssetsService.reduceGold(playerAssets.getId(), gold); + //3 写入变化记录 + assertLogMapper.insert(AssertLog.builder().playerId(playerId).createDate(new Date()).assertChangeNum(-gold).assertType(type).remark(remark).build()); + + ListPoolChangeDto dto = ListPoolChangeDto.builder().rank(rank).userId(playerId).instanceId(instanceId).gold(gold).type(type).remark(remark).build(); + SendCallback callback = new SendCallback() { + @Override + public void onSuccess(SendResult sendResult) { + log.info("消息已成功发送"); + } + @Override + public void onException(Throwable throwable) { + log.error("发送异常", throwable); + log.info("消息发送异常,发送失败"); + } + }; + rocketMQTemplate.asyncSend("admissionTicket:submit",dto,callback); + // 写入正在挑战的人 设置最长40分钟 + redisCache.setCacheObject(StaticUtil.CHALLENGE_ONLINE_USER.concat(instanceId.toString()).concat(":".concat(rank.toString()).concat(":".concat(playerId.toString()))), time.toString(), 40, TimeUnit.MINUTES); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), "操作成功"); + }catch (Exception ex){ + log.error("报名失败,挑战扣费失败!", ex); + return ResultUtil.result(MessageEnum.ERROR.getCode(), MessageEnum.SUCCESS.getMessage(), "报名失败,挑战扣费失败!"); + } + } + + @Override + public ResModeBase playerAssert(Integer playerId) { + List assets = playerAssetsService.getPlayerAssets(playerId); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), assets); + } + + @Override + public ResModeBase getPlayerRankInfo(Integer instanceId, Integer playerId) { + List dtos = listRankServiceImpl.getPlayerRankInfo(instanceId, playerId); + ListRankDto dto = null; + if (!CollectionUtils.isEmpty(dtos)){ + dto = dtos.get(0); + dto.setGameData(null); + } + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), dto); + } + + @Override + public void clearRankByInstancePlayerId(Integer instanceId, Integer playerId, Integer rankNum){ + int i = listRankServiceImpl.initRank(instanceId, playerId); + ListRankDto dto = redisCache.getCacheObject(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(instanceId.toString()).concat(":".concat(rankNum.toString()))); + if(dto != null && playerId == dto.getPlayerId()){ + dto.setChallengeTime(null); + dto.setPlayerId(null); + dto.setPlayerName(null); + dto.setGameData(null); + redisCache.setCacheObject(StaticUtil.CHALLENGE_INSTANCE_RANK_DETAIL.concat(dto.getInstanceId().toString()).concat(":".concat(dto.getRankNum().toString())), dto); + + } + if(i > 0){ + // 刷新榜单 + challengeDataInit.initranks(instanceId); + } + } + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/GameSystemServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/GameSystemServiceImpl.java new file mode 100644 index 0000000..a9cf2fe --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/GameSystemServiceImpl.java @@ -0,0 +1,72 @@ +package com.lightyears.challenge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; +import com.lightyears.challenge.dao.*; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.AssertLog; +import com.lightyears.common.domain.entity.PlayerAssets; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.challenge.service.IGameSystemService; +import com.lightyears.challenge.service.ILogService; +import com.lightyears.challenge.service.IPlayerAssetsService; +import com.lightyears.challenge.util.RedisCache; +import com.lightyears.challenge.util.ResultUtil; +import com.lightyears.challenge.util.StaticUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Date; + +@Slf4j +@Service("gameSystemServiceImpl") +public class GameSystemServiceImpl implements IGameSystemService { + + @Resource + private PlayerMapper playerMapper; + @Resource + private RecordMapper recordMapper; + @Resource + private ILogService logService; + @Resource + private RedisCache redisCache; + @Resource + private IPlayerAssetsService playerAssetsService; + @Resource + private AssertLogMapper assertLogMapper; + @Resource + private ListRankMapper listRankMapper; + @Resource + private NoticeMapper noticeMapper; + @Resource + private IGameSystemService gameSystemService; + Interner pool = Interners.newWeakInterner(); + private static final int AssetLimit = 999999; + + + @Override + @Transactional + public ResModeBase pushGold(Integer userId, int gold, int type, String remark) { + //1. 查询金额, 设置资产上限 + PlayerAssets playerAssets = playerAssetsService.getOne(new QueryWrapper().eq("player_id", userId).eq("type", type).last("limit 1")); + Integer playerAssetsNumber = playerAssets == null? 0 : playerAssets.getNumber(); + int nowGold = Math.min(playerAssetsNumber +gold , AssetLimit); + // 2.写入改变数量 + if (ObjectUtils.isEmpty(playerAssets)) { + playerAssetsService.save(PlayerAssets.builder().playerId(userId).type(type).number(nowGold).version(0L).build()); + } else { + playerAssetsService.addGold(playerAssets.getId(), nowGold - playerAssetsNumber); + } + //3 写入变化记录 + assertLogMapper.insert(AssertLog.builder().playerId(userId).createDate(new Date()).assertChangeNum(nowGold - playerAssetsNumber).assertType(type).remark(remark).build()); + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage(), nowGold); + } + + + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/ListBaseServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/ListBaseServiceImpl.java new file mode 100644 index 0000000..4b45b04 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/ListBaseServiceImpl.java @@ -0,0 +1,20 @@ +package com.lightyears.challenge.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.challenge.dao.ListBaseMapper; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.challenge.service.IListBaseService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Service(value = "listBaseServiceImpl") +public class ListBaseServiceImpl extends ServiceImpl implements IListBaseService { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/ListInstanceServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/ListInstanceServiceImpl.java new file mode 100644 index 0000000..9416597 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/ListInstanceServiceImpl.java @@ -0,0 +1,51 @@ +package com.lightyears.challenge.service.impl; + +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.challenge.dao.ListInstanceMapper; +import com.lightyears.common.domain.entity.ListBase; +import com.lightyears.common.domain.entity.ListInstance; +import com.lightyears.challenge.service.IListInstanceService; +import org.springframework.stereotype.Service; + +import java.util.Date; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Service(value = "listInstanceServiceImpl") +public class ListInstanceServiceImpl extends ServiceImpl implements IListInstanceService { + + @Override + public ListInstance saveInstanceByBase(ListBase base){ + String startDate = DateUtil.now(); + Date date = DateUtil.parse(startDate); + // 7 周日锁榜 周一晚上结算 + DateTime endDate = DateUtil.offsetDay(date, base.getSettlementDay() - 1); + String startDateStr = DateUtil.format(date, "yyyy-MM-dd"); + String endDateStr = DateUtil.format(endDate, "yyyy-MM-dd"); + ListInstance instance = ListInstance.builder().listId(base.getId()) + .listDate(startDateStr.concat("~".concat(endDateStr))) + .ticketsNum(base.getTicketsNum()) + .assetsType(base.getAssetsType()) + .createDate(new Date()) + .mapSize(base.getMapSize()) + .status(1) + .entryThreshold(base.getEntryThreshold()) + .awardSize(base.getInitAwardSize()) + .inPondFee(base.getInPondFee()) + .maxPlayerNum(base.getMaxPlayerNum()) + .mineNumSection(base.getMineNumSection()) + .name(base.getName()) + .distribution(base.getDistribution()) + .remark("系统自动生成").build(); + this.baseMapper.insert(instance); + return instance; + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/ListRankServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/ListRankServiceImpl.java new file mode 100644 index 0000000..3d298ad --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/ListRankServiceImpl.java @@ -0,0 +1,66 @@ +package com.lightyears.challenge.service.impl; + +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.challenge.dao.ListRankMapper; +import com.lightyears.common.domain.dto.ListRankDto; +import com.lightyears.common.domain.entity.ListRank; +import com.lightyears.challenge.service.IListRankService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Service(value = "listRankServiceImpl") +public class ListRankServiceImpl extends ServiceImpl implements IListRankService { + + @Resource + private ListRankMapper listRankMapper; + + @Override + public ListRank saveRankByInstance(Integer instanceId, Integer rank){ + ListRank data = ListRank.builder().rankNum(rank).instanceId(instanceId).createDate(new Date()).build(); + listRankMapper.insert(data); + return data; + } + + @Override + public int initRank(Integer instanceId,Integer playerId){ + int num = listRankMapper.initRank(instanceId, playerId); + return num; + } + + @Override + @Transactional + public int updateRankInfo(Integer instanceId, Integer rank, String gameData, Integer challengeTime, Integer playerId, String playerName) { + ListRank rankInfo = ListRank.builder().instanceId(instanceId).rankNum(rank).gameData(gameData).challengeTime(challengeTime).playerId(playerId).playerName(playerName).updateDate(new Date()).build(); + return listRankMapper.update(rankInfo, new UpdateWrapper().eq("instance_id", instanceId).eq("rank_num", rank)); + } + + @Override + public ListRankDto getRankByInsRank(Integer instanceId, Integer rank){ + return listRankMapper.getRankByInsRank(instanceId, rank); + } + + @Override + public List getRankList(Integer instanceId) { + return listRankMapper.getRankList(instanceId, null, null); + } + + @Override + public List getPlayerRankInfo(Integer instanceId, Integer playerId){ + // 只查开启中挑战榜的数据 + List dtos = listRankMapper.getNewRankList(instanceId, playerId); + return dtos; + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/LogServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/LogServiceImpl.java new file mode 100644 index 0000000..0833937 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/LogServiceImpl.java @@ -0,0 +1,19 @@ +package com.lightyears.challenge.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.challenge.dao.LogMapper; +import com.lightyears.common.domain.entity.Log; +import com.lightyears.challenge.service.ILogService; +import org.springframework.stereotype.Service; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class LogServiceImpl extends ServiceImpl implements ILogService { +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/NoticeServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/NoticeServiceImpl.java new file mode 100644 index 0000000..619f64e --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/NoticeServiceImpl.java @@ -0,0 +1,20 @@ +package com.lightyears.challenge.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.challenge.dao.NoticeMapper; +import com.lightyears.common.domain.entity.Notice; +import com.lightyears.challenge.service.INoticeService; +import org.springframework.stereotype.Service; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-18 + */ +@Service(value = "noticeServiceImpl") +public class NoticeServiceImpl extends ServiceImpl implements INoticeService { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/PlayerAssetsServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/PlayerAssetsServiceImpl.java new file mode 100644 index 0000000..8c65f68 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/PlayerAssetsServiceImpl.java @@ -0,0 +1,76 @@ +package com.lightyears.challenge.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.challenge.dao.PlayerAssetsMapper; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import com.lightyears.common.domain.entity.PlayerAssets; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.challenge.exception.BussinessException; +import com.lightyears.challenge.service.IPlayerAssetsService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + *

+ * 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-16 + */ +@Slf4j +@Service +public class PlayerAssetsServiceImpl extends ServiceImpl implements IPlayerAssetsService { + + @Override + public Integer addGold(int id, int gold){ + PlayerAssets playerAssets = baseMapper.selectById(id); + if(ObjectUtils.isEmpty(playerAssets)){ + log.error("减少金币异常------------没有查到资产信息"); + throw new BussinessException(MessageEnum.ERROR.getCode(), "减少金币异常------------没有查到资产信息!"); + } + int result = 0; + try{ + result = baseMapper.addGold(playerAssets.getId(), gold, playerAssets.getVersion()); + }catch (Exception ex){ + log.error("写入金币异常", ex); + throw new BussinessException(MessageEnum.ERROR.getCode(), "写入金币异常!"); + } + + if(result < 1){ + this.addGold(id, gold); + } + return gold; + } + + @Override + public Integer reduceGold(int id, int gold){ + PlayerAssets playerAssets = baseMapper.selectById(id); + if(ObjectUtils.isEmpty(playerAssets)){ + log.error("减少金币异常------------没有查到资产信息"); + throw new BussinessException(MessageEnum.ERROR.getCode(), "减少金币异常------------没有查到资产信息!"); + } + int result = 0; + if(playerAssets.getNumber() < gold){ + return -999; + } + try { + result = baseMapper.reduceGold(playerAssets.getId(), gold, playerAssets.getVersion()); + } catch (Exception ex){ + log.error("写入金币异常", ex); + throw new BussinessException(MessageEnum.ERROR.getCode(), "写入金币异常!"); + } + if(result < 1){ + this.reduceGold(id, gold); + } + return playerAssets.getNumber() - gold; + } + + @Override + public List getPlayerAssets(int playerId){ + return baseMapper.getPlayerAssets(playerId); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/PlayerServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/PlayerServiceImpl.java new file mode 100644 index 0000000..f6a0c9c --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/PlayerServiceImpl.java @@ -0,0 +1,20 @@ +package com.lightyears.challenge.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.challenge.dao.PlayerMapper; +import com.lightyears.challenge.service.IPlayerService; +import com.lightyears.common.domain.entity.Player; +import org.springframework.stereotype.Service; + +/** + *

+ * 扫雷玩家表 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class PlayerServiceImpl extends ServiceImpl implements IPlayerService { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/service/impl/RecordServiceImpl.java b/challenge/src/main/java/com/lightyears/challenge/service/impl/RecordServiceImpl.java new file mode 100644 index 0000000..54162aa --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/service/impl/RecordServiceImpl.java @@ -0,0 +1,20 @@ +package com.lightyears.challenge.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.challenge.dao.RecordMapper; +import com.lightyears.common.domain.entity.Record; +import com.lightyears.challenge.service.IRecordService; +import org.springframework.stereotype.Service; + +/** + *

+ * 游戏存档 服务实现类 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Service +public class RecordServiceImpl extends ServiceImpl implements IRecordService { + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/util/CronUtils.java b/challenge/src/main/java/com/lightyears/challenge/util/CronUtils.java new file mode 100644 index 0000000..62ac378 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/util/CronUtils.java @@ -0,0 +1,37 @@ +package com.lightyears.challenge.util; + +import cn.hutool.core.date.DateTime; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Objects; + +/** + * 日期转换cron表达式 + */ +public class CronUtils { + + /*** + * 功能描述:日期转换cron表达式 + * @param dateStr + * @return + */ + public static String formatDateByPattern(String dateStr) { + String formatTimeStr = null; + if (Objects.nonNull(dateStr)) { + LocalDateTime time = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + formatTimeStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ?")); + } + return formatTimeStr; + } + + /*** + * @param dateTime : 时间点 + * @return + */ + public static String getCron(DateTime dateTime) { + return formatDateByPattern(dateTime.toString()); + } + +} + diff --git a/challenge/src/main/java/com/lightyears/challenge/util/GetBeanUtil.java b/challenge/src/main/java/com/lightyears/challenge/util/GetBeanUtil.java new file mode 100644 index 0000000..29f4e6a --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/util/GetBeanUtil.java @@ -0,0 +1,26 @@ +package com.lightyears.challenge.util; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class GetBeanUtil implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + public void setApplicationContext(ApplicationContext context) { + GetBeanUtil.applicationContext = context; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static Object getBean(Class classObj) { + return applicationContext.getBean(classObj); + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } +} \ No newline at end of file diff --git a/challenge/src/main/java/com/lightyears/challenge/util/MD5Utils.java b/challenge/src/main/java/com/lightyears/challenge/util/MD5Utils.java new file mode 100644 index 0000000..506f043 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/util/MD5Utils.java @@ -0,0 +1,51 @@ +package com.lightyears.challenge.util; + +import java.security.MessageDigest; + +/** + * Created by tanhao on 2019/3/18. + */ +public class MD5Utils { + private static final String hexDigIts[] = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"}; + + /** + * MD5加密 + * @param origin 字符 + * @param charsetname 编码 UTF-8 + * @return + */ + public static String MD5Encode(String origin, String charsetname){ + String resultString = null; + try{ + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if(null == charsetname || "".equals(charsetname)){ + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + }else{ + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + }catch (Exception e){ + } + return resultString; + } + + + public static String byteArrayToHexString(byte b[]){ + StringBuffer resultSb = new StringBuffer(); + for(int i = 0; i < b.length; i++){ + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + public static String byteToHexString(byte b){ + int n = b; + if(n < 0){ + n += 256; + } + int d1 = n / 16; + int d2 = n % 16; + return hexDigIts[d1] + hexDigIts[d2]; + } + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/util/RedisCache.java b/challenge/src/main/java/com/lightyears/challenge/util/RedisCache.java new file mode 100644 index 0000000..c24ca03 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/util/RedisCache.java @@ -0,0 +1,383 @@ +package com.lightyears.challenge.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * spring redis 工具类 + **/ +@Component +public class RedisCache { + + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private StringRedisTemplate stringRedisTemplate; + + /** + * 判断key是否存在 + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + */ + public void setCacheObject(final String key, final T value) { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param timeout 时间 + * @param timeUnit 时间颗粒度 + */ + public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout) { + return expire(key, timeout, TimeUnit.SECONDS); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @param unit 时间单位 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout, final TimeUnit unit) { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return 缓存键值对应的数据 + */ + public T getCacheObject(final String key) { + ValueOperations operation = redisTemplate.opsForValue(); + return operation.get(key); + } + + /** + * 删除单个对象 + * + * @param key + */ + public boolean deleteObject(final String key) { + return redisTemplate.delete(key); + } + + /** + * 删除指定前缀的缓存 + * @param key + * @return + */ + public Long deleteByPrefix(final String key) { + Set keys = redisTemplate.keys(key.concat("*")); + return redisTemplate.delete(keys); + } + + /** + * 删除集合对象 + * + * @param collection 多个对象 + * @return + */ + public long deleteObject(final Collection collection) { + return redisTemplate.delete(collection); + } + + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSetAll(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public long setCacheSet(final String key, final Set dataSet) { + Long count = redisTemplate.opsForSet().add(key, dataSet); + return count == null ? 0 : count; + } + + /** + * 获得缓存的set + * + * @param key + * @return + */ + public Set getCacheSet(final String key) { + return redisTemplate.opsForSet().members(key); + } + + /** + * 缓存Map + * + * @param key + * @param dataMap + */ + public void setCacheMap(final String key, final Map dataMap) { + if (dataMap != null) { + redisTemplate.opsForHash().putAll(key, dataMap); + } + } + + /** + * 获得缓存的Map + * + * @param key + * @return + */ + public Map getCacheMap(final String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 往Hash中存入数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @param value 值 + */ + public void setCacheMapValue(final String key, final String hKey, final T value) { + redisTemplate.opsForHash().put(key, hKey, value); + } + + /** + * 获取Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public T getCacheMapValue(final String key, final String hKey) { + HashOperations opsForHash = redisTemplate.opsForHash(); + return opsForHash.get(key, hKey); + } + + /** + * 获取多个Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键集合 + * @return Hash对象集合 + */ + public List getMultiCacheMapValue(final String key, final Collection hKeys) { + return redisTemplate.opsForHash().multiGet(key, hKeys); + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public Collection keys(final String pattern) { + return redisTemplate.keys(pattern); + } + + public StringRedisTemplate getStringRedisTemplate() { + return stringRedisTemplate; + } + + public RedisTemplate getRedisTemplate() { + return redisTemplate; + } +} \ No newline at end of file diff --git a/challenge/src/main/java/com/lightyears/challenge/util/ResultUtil.java b/challenge/src/main/java/com/lightyears/challenge/util/ResultUtil.java new file mode 100644 index 0000000..76af22d --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/util/ResultUtil.java @@ -0,0 +1,44 @@ +package com.lightyears.challenge.util; + +import cn.hutool.crypto.digest.MD5; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; + +/** + * 返回 数据 指定数据结构 + * + * @author Melody + */ +@Slf4j +public class ResultUtil { + public static final ObjectMapper mapper = new ObjectMapper(); + public static ResModeBase result(int code, String mes) { + return result(code, mes, null); + } + + public static ResModeBase result(int code, String mes, Object data) { + String key = ""; + String dataStr = ""; + if(data == null){ + key = MD5.create().digestHex(MD5.create().digestHex(StaticUtil.PRIVATE_KEY)); + } else { + try { + if (data instanceof String){ + dataStr = data.toString(); + } else { + dataStr = mapper.writeValueAsString(data); + } + key = MD5.create().digestHex(MD5.create().digestHex(dataStr.concat(StaticUtil.PRIVATE_KEY))); + }catch (JsonProcessingException ex){ + log.error("json解析错误", ex); + return new ResModeBase(MessageEnum.SERVER_ERROR.getCode(), MessageEnum.SERVER_ERROR.getMessage(), key, null); + } + + } + return new ResModeBase(code, mes, key, data); + } + +} diff --git a/challenge/src/main/java/com/lightyears/challenge/util/ScheduledFutureHolder.java b/challenge/src/main/java/com/lightyears/challenge/util/ScheduledFutureHolder.java new file mode 100644 index 0000000..0eb2335 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/util/ScheduledFutureHolder.java @@ -0,0 +1,46 @@ +package com.lightyears.challenge.util; +import java.util.concurrent.ScheduledFuture; + +/** + * 任务执行的包装类 + */ +public class ScheduledFutureHolder { + private ScheduledFuture scheduledFuture; + + private Class runnableClass; + + private String corn; + + public ScheduledFuture getScheduledFuture() { + return scheduledFuture; + } + + public void setScheduledFuture(ScheduledFuture scheduledFuture) { + this.scheduledFuture = scheduledFuture; + } + + public Class getRunnableClass() { + return runnableClass; + } + + public void setRunnableClass(Class runnableClass) { + this.runnableClass = runnableClass; + } + + public String getCorn() { + return corn; + } + + public void setCorn(String corn) { + this.corn = corn; + } + + @Override + public String toString() { + return "ScheduledFutureHolder{" + + "scheduledFuture=" + scheduledFuture + + ", runnableClass=" + runnableClass + + ", corn='" + corn + '\'' + + '}'; + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/util/SpecialTool.java b/challenge/src/main/java/com/lightyears/challenge/util/SpecialTool.java new file mode 100644 index 0000000..2546e09 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/util/SpecialTool.java @@ -0,0 +1,50 @@ +package com.lightyears.challenge.util; + +import java.util.List; +import java.util.Map; + +/** + * 文 件 名 : 特殊处理工具 + * 创 建 人:HL + * 日 期:2019-8-12 + * 修 改 人:HL + * 日 期:2019-8-12 + * 描 述: 分页、 + * 版 本 号:2.0 + */ +public class SpecialTool { + public static SpecialTool specialTool = new SpecialTool(); + + //时间格式 + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + //集合判断是否为空 + + public boolean ifGather(Object o) { + if ((o instanceof List && null == o) || (o instanceof Map && null == o)) { + return true; + } + return false; + } + + //字符串判断是否为空 + public boolean isEmpty(String s) { + if (null == s || s.equals("")) { + return true; + } + return false; + } + + + /** + * 将字符串的首字母转大写 + * @param str 需要转换的字符串 + * @return + */ + private static String captureName(String str) { + // 进行字母的ascii编码前移,效率要高于截取字符串进行转换的操作 + char[] cs=str.toCharArray(); + cs[0]-=32; + return String.valueOf(cs); + } +} diff --git a/challenge/src/main/java/com/lightyears/challenge/util/StaticUtil.java b/challenge/src/main/java/com/lightyears/challenge/util/StaticUtil.java new file mode 100644 index 0000000..af76b19 --- /dev/null +++ b/challenge/src/main/java/com/lightyears/challenge/util/StaticUtil.java @@ -0,0 +1,56 @@ +package com.lightyears.challenge.util; + + +import java.util.HashMap; +import java.util.Map; + +/** + * 静态工具栏 :目前数据较小 且又想减少服务器压力,特建此类 做静态缓存 + */ +public class StaticUtil { + // ------------------------系统类----------------------- + //金币极限操作 防范静态变量 + public static Map goldSyn = new HashMap(); + // 数据加解密盐 + public static final String PRIVATE_KEY = "123144123"; + + // ---------------------------------redis ----------------------------------------- + // 在线用户信息 + public static final String ONLINE_USER_PUBLIC_KEY="mineClearance:onlineUser:"; + // 在线用户TOKEN + public static final String ONLINE_USER_TOKEN="mineClearance:onlineToken:"; + // 排行榜 + public static final String RANK_LIST = "mineClearance:rankList:"; + // 闯关排行 + public static final String CLEARANCE_RANK_LIST = "mineClearance:clearanceList"; + + // 挑战榜所有缓存前缀 + public static final String CHALLENGE="mineClearance:challenge:*"; + // 开启中的挑战榜信息 + public static final String CHALLENGE_INSTANCE="mineClearance:challenge:instance:"; + // 开启中的挑战榜排名信息 mineClearance:challenge:rank:instance + public static final String CHALLENGE_INSTANCE_RANK="mineClearance:challenge:rank:"; + // 开启中的挑战榜每个排名的信息 mineClearance:challenge:rankDetail:instance:rank + public static final String CHALLENGE_INSTANCE_RANK_DETAIL="mineClearance:challenge:rankDetail:"; + // 正在挑战的用户,mineClearance:challenge:onlineUser: instanceId : rank: playerId + public static final String CHALLENGE_ONLINE_USER="mineClearance:challenge:onlineUser:"; + // -------------------------------------公告类------------------------------------------ + // 挑战榜结算 奖励发放备注 + public static final String CHALLENGE_REMARK = "你在挑战榜:%s 的名次为:%s, 获得%s %s"; + // 挑战榜奖励发放公告 标题 + public static final String CHALLENGE_NOTICE_TITLE = "挑战榜奖励发放"; + // 闯关信息提示 已有多少人到达 + public static final String CLEARANCE_LOG_TEXT_HAVE = "当前已有 %s 的玩家到达这一层!"; + // 闯关信息提示 已超过多少人 + public static final String CLEARANCE_LOG_TEXT_OVER = "你已超过 %s 的玩家!"; + + //----------------------------挑战榜task-------------------------- + // 锁榜时间 + public static final String LOCKE_TIME = " 23:00:00"; + // 结算时间 + public static final String SETTLEMENT_TIME = " 23:45:00"; + // 挑战榜初始化时间 + public static final String CHALLENGE_INIT_TIME = " 1:00:00"; + // 挑战榜redis刷新时间 + public static final String CHALLENGE_REFRESH_TIME = " 1:05:00"; +} diff --git a/challenge/src/main/resources/application-dev.yml b/challenge/src/main/resources/application-dev.yml new file mode 100644 index 0000000..ed88594 --- /dev/null +++ b/challenge/src/main/resources/application-dev.yml @@ -0,0 +1,67 @@ +qbs-switch: + swagger-open: true #swagger开关(true:打开, false:关闭) +spring: + application: + name: mine-clearance-challenge + main: + allow-bean-definition-overriding: true + allow-circular-references: true + # 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题 + jackson: + time-zone: GMT+8 + datasource: + username: root + password: 43626546 + url: jdbc:mysql://42.192.76.87:3306/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 20 + max-active: 80 + min-idle: 20 + max-wait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictabkeIdleTimeMillis: 1800000 + validationQuery: SELECT 1 + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + # 配置监控统计拦截的filters,去掉后监控界面sql无法统计。‘wall’用于防火墙 + filters: stat,wall + # cloud: + # nacos: + # discovery: + # server-addr: localhost:8848 + redis: + # Redis服务器地址 + host: localhost + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + password: 123456 + # 连接超时时间 + timeout: 1000ms + lettuce: + pool: + # 连接池最大连接数 + max-active: 8 + # 连接池最大空闲连接数 + max-idle: 8 + # 连接池最小空闲连接数 + min-idle: 0 + # 连接池最大阻塞等待时间,负值表示没有限制 + max-wait: -1ms +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + type-aliases-package: com.lightyears.common.domain + global-config: + banner: false + db-config: + id-type: input + configuration: + # 控制台SQL日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: false \ No newline at end of file diff --git a/challenge/src/main/resources/application-prod.yml b/challenge/src/main/resources/application-prod.yml new file mode 100644 index 0000000..dad5317 --- /dev/null +++ b/challenge/src/main/resources/application-prod.yml @@ -0,0 +1,73 @@ +qbs-switch: + swagger-open: false #swagger开关(true:打开, false:关闭) +spring: + application: + name: mine-clearance-challenge + main: + allow-bean-definition-overriding: true + allow-circular-references: true + # 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题 + jackson: + time-zone: GMT+8 + datasource: + username: root + password: 1476346288@mysql + #password: 1813547935mysql + # 挑战 + url: jdbc:mysql://172.26.101.6:3986/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull + # 本地 + # url: jdbc:mysql://39.106.21.14:3986/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 20 + max-active: 80 + min-idle: 20 + max-wait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictabkeIdleTimeMillis: 1800000 + validationQuery: SELECT 1 + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + # 配置监控统计拦截的filters,去掉后监控界面sql无法统计。‘wall’用于防火墙 + filters: stat,wall + # cloud: + # nacos: + # discovery: + # server-addr: localhost:8848 + redis: + # Redis服务器地址 + # host: localhost + host: 172.26.101.6 + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器连接端口 + port: 7963 + # Redis服务器连接密码(默认为空) + password: 1476346288@redis + #password: 123456 + lettuce: + pool: + # 连接池最大连接数 + max-active: 8 + # 连接池最大空闲连接数 + max-idle: 8 + # 连接池最小空闲连接数 + min-idle: 0 + # 连接池最大阻塞等待时间,负值表示没有限制 + # max-wait: -1ms + max-wait: -1ms + shutdown-timeout: 100ms +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + type-aliases-package: com.lightyears.common.domain + global-config: + banner: false + db-config: + id-type: input + configuration: + # 控制台SQL日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: false \ No newline at end of file diff --git a/challenge/src/main/resources/application.yml b/challenge/src/main/resources/application.yml new file mode 100644 index 0000000..0c8de5c --- /dev/null +++ b/challenge/src/main/resources/application.yml @@ -0,0 +1,21 @@ +server: + port: 18632 + tomcat: + uri-encoding: UTF-8 + #最大等待连接数 + accept-count: 1000 + #最大线程数 + server.tomcat.max-threads: 800 + #最小工作线程数 + server.tomcat.min-spare-threads: 100 +logging: + config: classpath:log.xml +rocketmq: + name-server: localhost:9876 + producer: + group: mineClearance +spring: + profiles: + active: prod +appconfig: + version: 197.0 \ No newline at end of file diff --git a/challenge/src/main/resources/log.xml b/challenge/src/main/resources/log.xml new file mode 100644 index 0000000..d2bfda1 --- /dev/null +++ b/challenge/src/main/resources/log.xml @@ -0,0 +1,72 @@ + + + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + logs/challenge/sys.log + + + + + + logs/challenge/sys.%d.%i.log + + 30 + + + 10MB + + + + + + %d %p (%file:%line\)- %m%n + + + UTF-8 + + + + + logs/rocketmq_client.log + + logs/rocketmq_client.%d{yyyy-MM-dd}.%i.log + + 30 + + + 10MB + + + + %d{yy-MM-dd.HH:mm:ss.SSS} [%-16t] %-5p %-22c{0} %X{ServiceId} - %m%n + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/challenge/src/main/resources/mapper/AssertLogMapper.xml b/challenge/src/main/resources/mapper/AssertLogMapper.xml new file mode 100644 index 0000000..29d77b7 --- /dev/null +++ b/challenge/src/main/resources/mapper/AssertLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/challenge/src/main/resources/mapper/ListBaseMapper.xml b/challenge/src/main/resources/mapper/ListBaseMapper.xml new file mode 100644 index 0000000..19eb3a9 --- /dev/null +++ b/challenge/src/main/resources/mapper/ListBaseMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/challenge/src/main/resources/mapper/ListInstanceMapper.xml b/challenge/src/main/resources/mapper/ListInstanceMapper.xml new file mode 100644 index 0000000..ac46002 --- /dev/null +++ b/challenge/src/main/resources/mapper/ListInstanceMapper.xml @@ -0,0 +1,32 @@ + + + + + + UPDATE sl_list_instance + SET award_size = award_size + #{awardSize} + where id = #{instanceId} + and assets_type = #{assetsType} + + + + diff --git a/challenge/src/main/resources/mapper/ListRankMapper.xml b/challenge/src/main/resources/mapper/ListRankMapper.xml new file mode 100644 index 0000000..fdec6f3 --- /dev/null +++ b/challenge/src/main/resources/mapper/ListRankMapper.xml @@ -0,0 +1,81 @@ + + + + + UPDATE `sl_list_rank` + SET + `player_name` = NULL, + `player_id` = NULL, + `challenge_time` = NULL, + `game_data` = NULL + WHERE + `instance_id` = ${instanceId} + and `player_id` = ${playerId} + + + + + diff --git a/challenge/src/main/resources/mapper/LogMapper.xml b/challenge/src/main/resources/mapper/LogMapper.xml new file mode 100644 index 0000000..3769aeb --- /dev/null +++ b/challenge/src/main/resources/mapper/LogMapper.xml @@ -0,0 +1,4 @@ + + + + diff --git a/challenge/src/main/resources/mapper/NoticeMapper.xml b/challenge/src/main/resources/mapper/NoticeMapper.xml new file mode 100644 index 0000000..ec16440 --- /dev/null +++ b/challenge/src/main/resources/mapper/NoticeMapper.xml @@ -0,0 +1,4 @@ + + + + diff --git a/challenge/src/main/resources/mapper/PlayerAssetsMapper.xml b/challenge/src/main/resources/mapper/PlayerAssetsMapper.xml new file mode 100644 index 0000000..c4d26ab --- /dev/null +++ b/challenge/src/main/resources/mapper/PlayerAssetsMapper.xml @@ -0,0 +1,14 @@ + + + + + update sl_player_assets set number = number + #{gold}, version = version +1 where id = #{id} and version = ${version} + + + update sl_player_assets set number = number - #{gold}, version = version +1 where id = #{id} and version = ${version} + + + + diff --git a/challenge/src/main/resources/mapper/PlayerMapper.xml b/challenge/src/main/resources/mapper/PlayerMapper.xml new file mode 100644 index 0000000..21b023e --- /dev/null +++ b/challenge/src/main/resources/mapper/PlayerMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/challenge/src/main/resources/mapper/RecordMapper.xml b/challenge/src/main/resources/mapper/RecordMapper.xml new file mode 100644 index 0000000..8aa8d26 --- /dev/null +++ b/challenge/src/main/resources/mapper/RecordMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..a56ea3e --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,38 @@ + + + + mine_clearance + com.lightyears.mine_clearance + 1.0 + + 4.0.0 + + common + + + + com.baomidou + mybatis-plus-boot-starter + + + + com.alibaba + fastjson + + + org.projectlombok + lombok + provided + + + com.fasterxml.jackson.core + jackson-annotations + 2.13.3 + compile + + + + + \ No newline at end of file diff --git a/common/src/main/java/com/lightyears/common/domain/dto/ClearanceRankDto.java b/common/src/main/java/com/lightyears/common/domain/dto/ClearanceRankDto.java new file mode 100644 index 0000000..c32f628 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/ClearanceRankDto.java @@ -0,0 +1,30 @@ +package com.lightyears.common.domain.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Objects; + +/** + * 玩家关卡 + */ +@Data +public class ClearanceRankDto implements Serializable { + // 玩家id + private Integer playerId; + // 玩家最高关卡 + private Integer layersNum; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ClearanceRankDto that = (ClearanceRankDto) o; + return Objects.equals(playerId, that.playerId); + } + + @Override + public int hashCode() { + return Objects.hash(playerId); + } +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/ListInstanceDto.java b/common/src/main/java/com/lightyears/common/domain/dto/ListInstanceDto.java new file mode 100644 index 0000000..984dc9d --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/ListInstanceDto.java @@ -0,0 +1,78 @@ +package com.lightyears.common.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ListInstanceDto { + /** + * id + */ + private Integer id; + + /** + * base榜单id + */ + private Integer listId; + + /** + * 榜单名称 + */ + private String name; + + /** + * 榜单周期 + */ + private String listDate; + + /** + * 地雷数区间 + */ + private String mineNumSection; + + /** + * 地图大小 + */ + private String mapSize; + + /** + *入场费多少比例进入奖池 + */ + private Float inPondFee; + + /** + * 当前奖池 + */ + private Integer awardSize; + + /** + * 资产限制 + */ + private Integer entryThreshold; + + /** + * 门票数量 + */ + private Integer ticketsNum; + + /** + * 货币类型 + */ + private Integer assetsType; + + /** + * 状态(0.未开启,1.开启中,2.已截止,3.待结算) + */ + private Integer status; + + /** + * 名次分成 + */ + private String distribution; + +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/ListPoolChangeDto.java b/common/src/main/java/com/lightyears/common/domain/dto/ListPoolChangeDto.java new file mode 100644 index 0000000..da46e83 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/ListPoolChangeDto.java @@ -0,0 +1,25 @@ +package com.lightyears.common.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ListPoolChangeDto { + // 用户id + private Integer userId; + // 榜实例id + private Integer instanceId; + // 货币数 + private Integer gold; + // 货币类型 + private Integer type; + // 扣费说明 + private String remark; + // 挑战名次 + private Integer rank; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/ListRankDto.java b/common/src/main/java/com/lightyears/common/domain/dto/ListRankDto.java new file mode 100644 index 0000000..243a0df --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/ListRankDto.java @@ -0,0 +1,53 @@ +package com.lightyears.common.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Objects; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ListRankDto implements Serializable { + /** + * 名次id + */ + private Integer id; + /** + * 挑战榜实例id + */ + private Integer instanceId; + /** + * 名次 + */ + private Integer rankNum; + + /** + * 用户名称 + */ + private String playerName; + + /** + * 用户id + */ + private Integer playerId; + + /** + * 挑战用时 + */ + private Integer challengeTime; + + /** + * 挑战人数 + */ + private Integer challenges; + + /** + * 游戏数据 + */ + private String gameData; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/MainLandRankInfoDto.java b/common/src/main/java/com/lightyears/common/domain/dto/MainLandRankInfoDto.java new file mode 100644 index 0000000..2fe0752 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/MainLandRankInfoDto.java @@ -0,0 +1,11 @@ +package com.lightyears.common.domain.dto; + +import lombok.Data; + +@Data +public class MainLandRankInfoDto { + // 积分数量 + private Integer integralNum = 0; + // 排名 + private Integer rankNum = 0; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/NoticeDto.java b/common/src/main/java/com/lightyears/common/domain/dto/NoticeDto.java new file mode 100644 index 0000000..34cc511 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/NoticeDto.java @@ -0,0 +1,44 @@ +package com.lightyears.common.domain.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class NoticeDto implements Serializable { + /** + * id + */ + private Integer id; + /** + * 标题 + */ + private String title; + /** + * 类型 0.系统,1.个人 + */ + private Integer type; + /** + * 状态(0.未读, 1.已读,2.已过期) + */ + private Integer status; + /** + * 内容 + */ + private String content; + /** + * 创建时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8") + private Date createDate; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/OrdinaryRankDto.java b/common/src/main/java/com/lightyears/common/domain/dto/OrdinaryRankDto.java new file mode 100644 index 0000000..c7f7968 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/OrdinaryRankDto.java @@ -0,0 +1,55 @@ +package com.lightyears.common.domain.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Objects; + +@Data +public class OrdinaryRankDto implements Serializable { + /** + * id 综合榜无id + */ + private Integer id; + /** + * 用户id + */ + private Integer user_id; + /** + * 游戏时间 + */ + private Integer game_time; + /** + * bv3 + */ + private Float bv3; + /** + * bvs3 + */ + private Float bvs3; + /** + * + */ + private Integer nf; + /** + * 用户名 + */ + private String user_name; + /** + * 排名 + */ + private Integer ranking; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + OrdinaryRankDto that = (OrdinaryRankDto) o; + return Objects.equals(user_id, that.user_id); + } + + @Override + public int hashCode() { + return Objects.hash(user_id); + } +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/Params.java b/common/src/main/java/com/lightyears/common/domain/dto/Params.java new file mode 100644 index 0000000..ce8ec0b --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/Params.java @@ -0,0 +1,23 @@ +package com.lightyears.common.domain.dto; + +import lombok.Data; + +@Data +public class Params { + + /** + * 数据 + */ + private T record; + + /** + * 当前页 列表分页查询必传 + */ + private Integer pageNum = 1; + + /** + * 每页条数 列表分页查询必传 + */ + private Integer pageSize = 10; + +} \ No newline at end of file diff --git a/common/src/main/java/com/lightyears/common/domain/dto/PlayerClearanceLogInfoDto.java b/common/src/main/java/com/lightyears/common/domain/dto/PlayerClearanceLogInfoDto.java new file mode 100644 index 0000000..52fbc3a --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/PlayerClearanceLogInfoDto.java @@ -0,0 +1,22 @@ +package com.lightyears.common.domain.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 玩家最高关卡信息 + */ +@Data +public class PlayerClearanceLogInfoDto implements Serializable { + // 玩家id + private Integer playerId; + // 玩家名称 + private String playerName; + // 关卡数 + private Integer clearanceNum; + // 关卡说明 + private String remark; + // 排名超过率 + private String rankRate; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/RankDataDto.java b/common/src/main/java/com/lightyears/common/domain/dto/RankDataDto.java new file mode 100644 index 0000000..b69a988 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/RankDataDto.java @@ -0,0 +1,41 @@ +package com.lightyears.common.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RankDataDto { + /** + * 榜单数据 + */ + private ListRankDto rankDto; + /** + * 榜单实例id + */ + private Integer instanceId; + /** + * 榜单名次 + */ + private Integer rankNum; + /** + * 游戏数据 + */ + private String gameData; + /** + * 挑战时间 + */ + private Integer challengeTime; + /** + * 我的id + */ + private Integer myId; + /** + * 我的用户名 + */ + private String myName; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/RankDto.java b/common/src/main/java/com/lightyears/common/domain/dto/RankDto.java new file mode 100644 index 0000000..110fea4 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/RankDto.java @@ -0,0 +1,15 @@ +package com.lightyears.common.domain.dto; + +import lombok.Data; + +@Data +public class RankDto extends RankModel{ + // 分数 + private Integer score = 0; + + public RankDto(RankModel dto, Integer score){ + this.setUserId(dto.getUserId()); + this.setUserName(dto.getUserName()); + this.setScore(score); + } +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/RankInitModel.java b/common/src/main/java/com/lightyears/common/domain/dto/RankInitModel.java new file mode 100644 index 0000000..817e9a5 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/RankInitModel.java @@ -0,0 +1,14 @@ +package com.lightyears.common.domain.dto; + +import lombok.Builder; +import lombok.Data; + +@Data +public class RankInitModel { + // 玩家id + private Integer userId; + // 玩家昵称 + private String userName; + // 积分数量 + private Integer num; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/RankModel.java b/common/src/main/java/com/lightyears/common/domain/dto/RankModel.java new file mode 100644 index 0000000..233c8df --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/RankModel.java @@ -0,0 +1,20 @@ +package com.lightyears.common.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class RankModel implements Serializable { + private static final long serialVersionUID = 1L; + // 玩家id + private Integer userId; + // 玩家昵称 + private String userName; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/ResModeBase.java b/common/src/main/java/com/lightyears/common/domain/dto/ResModeBase.java new file mode 100644 index 0000000..cd96426 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/ResModeBase.java @@ -0,0 +1,62 @@ +package com.lightyears.common.domain.dto; +/* + ** + *文 件 名:返回客户端数据模型 + *创 建 人:HL + *日 期:2019-8-12 + *修 改 人:HL + *日 期:2019-8-12 + *描 述:分页对象 + *版 本 号:1.0 + */ + +public class ResModeBase { + private int code; + private String message; + private String key; + private Object data; + + public ResModeBase(int code, String message, String key, Object data) { + this.code = code; + this.message = message; + this.data = data; + this.key = key; + } + + public ResModeBase(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/SimplePlayerAssert.java b/common/src/main/java/com/lightyears/common/domain/dto/SimplePlayerAssert.java new file mode 100644 index 0000000..27b1b81 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/SimplePlayerAssert.java @@ -0,0 +1,24 @@ +package com.lightyears.common.domain.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class SimplePlayerAssert implements Serializable { + /** + * 资产类型(0.金币,1.门票,2.中级门票,3.高级门票) + */ + private Integer type; + + /** + * 资产数量 + */ + private Integer number; +} diff --git a/common/src/main/java/com/lightyears/common/domain/dto/SlicedQueryResult.java b/common/src/main/java/com/lightyears/common/domain/dto/SlicedQueryResult.java new file mode 100644 index 0000000..3ead4a8 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/dto/SlicedQueryResult.java @@ -0,0 +1,43 @@ +package com.lightyears.common.domain.dto; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 每页查询返回对象 + * + * @author Melody + * + * @param + */ +@Data +public class SlicedQueryResult implements Serializable { + + private static final long serialVersionUID = -1732171018957130308L; + + /** + * 页码 + */ + private Integer pageNo; + /** + * 每页数量 + */ + private Integer pageSize; + /** + * 数据量 + */ + private Long recordCount; + /** + * 数据集合 + */ + private List rows; + + public SlicedQueryResult(Integer pageNo, Integer pageSize, Long recordCount, List rows) { + this.pageNo = pageNo; + this.pageSize = pageSize; + this.recordCount = recordCount; + this.rows = rows; + } +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/AssertLog.java b/common/src/main/java/com/lightyears/common/domain/entity/AssertLog.java new file mode 100644 index 0000000..b81f06d --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/AssertLog.java @@ -0,0 +1,70 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * 资产日志 + * @author hellor + * @since 2022-03-16 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_assert_log") +public class AssertLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 用户id + */ + @TableField("player_id") + private Integer playerId; + + /** + * 资产变化数 + */ + @TableField("assert_change_num") + private Integer assertChangeNum; + + /** + * 资产类型 + */ + @TableField("assert_type") + private Integer assertType; + + /** + * 变化时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("create_date") + private Date createDate; + + /** + * 备注 + */ + @TableField("remark") + private String remark; + + +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/ClearanceLog.java b/common/src/main/java/com/lightyears/common/domain/entity/ClearanceLog.java new file mode 100644 index 0000000..41a7653 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/ClearanceLog.java @@ -0,0 +1,69 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lightyears.common.domain.dto.ClearanceRankDto; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * 通关日志 + *

+ * + * @author hellor + * @since 2022-06-02 + */ +@Data +@TableName("sl_clearance_log") +public class ClearanceLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId("id") + private Integer id; + + /** + * 玩家id + */ + @TableField("player_id") + private Integer playerId; + + /** + * 关卡数 + */ + @TableField("layers_num") + private Integer layersNum; + + /** + * 游戏数据 + */ + @TableField("data") + private String data; + + /** + * 创建时间 + */ + @TableField("create_time") + private Date createTime; + + /** + * 最后修改时间 + */ + @TableField("last_update_time") + private Date lastUpdateTime; + + + public ClearanceRankDto coverRank(){ + ClearanceRankDto rankDto = new ClearanceRankDto(); + rankDto.setLayersNum(this.getLayersNum()); + rankDto.setPlayerId(this.getPlayerId()); + return rankDto; + } +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/ListBase.java b/common/src/main/java/com/lightyears/common/domain/entity/ListBase.java new file mode 100644 index 0000000..1f9f02e --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/ListBase.java @@ -0,0 +1,105 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 挑战榜主表 + * @author hellor + * @since 2022-03-16 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_list_base") +public class ListBase implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 榜单名称 + */ + @TableField("name") + private String name; + + /** + * 门票数 + */ + @TableField("tickets_num") + private Integer ticketsNum; + + /** + * 货币类型 + */ + @TableField("assets_type") + private Integer assetsType; + + /** + * 地雷数区间 + */ + @TableField("mine_num_section") + private String mineNumSection; + + /** + * 地图大小 + */ + @TableField("map_size") + private String mapSize; + + /** + * 资产限制 + */ + @TableField("entry_threshold") + private Integer entryThreshold; + + /** + * 榜单人数 + */ + @TableField("max_player_num") + private Integer maxPlayerNum; + + /** + *入场费多少比例进入奖池 + */ + @TableField("in_pond_fee") + private Float inPondFee; + + /** + * 名次的分配比重 + */ + @TableField("distribution") + private String distribution; + + /** + * 初始化日期 + */ + @TableField("init_date") + private String initDate; + + /** + * 距离结算天数 + */ + @TableField("settlement_day") + private Integer settlementDay; + + /** + * 初始奖池大小 + */ + @TableField("init_award_size") + private Integer initAwardSize; +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/ListInstance.java b/common/src/main/java/com/lightyears/common/domain/entity/ListInstance.java new file mode 100644 index 0000000..c860b25 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/ListInstance.java @@ -0,0 +1,136 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * 挑战榜实例 + * @author hellor + * @since 2022-03-16 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_list_instance") +public class ListInstance implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 榜单id + */ + @TableField("list_id") + private Integer listId; + + /** + * 榜单名称 + */ + @TableField("name") + private String name; + + /** + * 榜单周期 + */ + @TableField("list_date") + private String listDate; + + /** + * 榜单人数 + */ + @TableField("max_player_num") + private Integer maxPlayerNum; + + /** + *入场费多少比例进入奖池 + */ + @TableField("in_pond_fee") + private Float inPondFee; + + /** + * 地雷数区间 + */ + @TableField("mine_num_section") + private String mineNumSection; + + /** + * 地图大小 + */ + @TableField("map_size") + private String mapSize; + + /** + * 当前奖池 + */ + @TableField("award_size") + private Integer awardSize; + + /** + * 资产限制 + */ + @TableField("entry_threshold") + private Integer entryThreshold; + + /** + * 门票数 + */ + @TableField("tickets_num") + private Integer ticketsNum; + + /** + * 货币类型 + */ + @TableField("assets_type") + private Integer assetsType; + + /** + * 状态(0.未开启,1.开启中,2.已截止) + */ + @TableField("status") + private Integer status; + + /** + * 创建时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("create_date") + private Date createDate; + + /** + * 结算日期 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("settlement_date") + private Date settlementDate; + + /** + * 备注 + */ + @TableField("remark") + private String remark; + + /** + * 名次的分配比重 + */ + @TableField("distribution") + private String distribution; +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/ListRank.java b/common/src/main/java/com/lightyears/common/domain/entity/ListRank.java new file mode 100644 index 0000000..1ef2402 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/ListRank.java @@ -0,0 +1,90 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + * 挑战榜 + * @author hellor + * @since 2022-03-16 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_list_rank") +public class ListRank implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 挑战榜实例id + */ + @TableField(value = "instance_id") + private Integer instanceId; + + /** + * 名次 + */ + @TableField("rank_num") + private Integer rankNum; + + /** + * 用户名称 + */ + @TableField("player_name") + private String playerName; + + /** + * 用户id + */ + @TableField("player_id") + private Integer playerId; + + /** + * 挑战用时 + */ + @TableField("challenge_time") + private Integer challengeTime; + + /** + * 游戏数据 + */ + @TableField("game_data") + private String gameData; + + /** + * 修改时间(榜主打榜成功时间) + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("update_date") + private Date updateDate; + + /** + * 创建时间 + */ + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField("create_date") + private Date createDate; + + +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/Log.java b/common/src/main/java/com/lightyears/common/domain/entity/Log.java new file mode 100644 index 0000000..91904ab --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/Log.java @@ -0,0 +1,80 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Data +@Builder +@TableName("sl_log") +@NoArgsConstructor +@AllArgsConstructor +public class Log implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @TableField("user_id") + private Integer user_id; + + /** + * 创建时间 秒 + */ + @TableField("creation_time") + private Integer creation_time; + + /** + * 游戏时间(毫秒级) + */ + @TableField("game_time") + private Integer game_time; + + @TableField("bvs3") + private Float bvs3; + + @TableField("bv3") + private Float bv3; + + /** + * 游戏录像 + */ + @TableField("video") + private String video; + + /** + * 杂项(游戏数据) + */ + @TableField("game_info") + private String game_info; + + /** + * 游戏难度:1 - 普通 2 困难 3 大师 4 超凡 + */ + @TableField("level") + private Integer level; + + @TableField("nf") + private Boolean nf; + + @TableField("game_type") + private String game_type; + + +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/MainlandLog.java b/common/src/main/java/com/lightyears/common/domain/entity/MainlandLog.java new file mode 100644 index 0000000..4d9c04c --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/MainlandLog.java @@ -0,0 +1,72 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * 游戏 完成记录 表 游戏难度:1 - 普通 2 困难 3 大师 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Data +@Builder +@TableName("sl_log") +@NoArgsConstructor +@AllArgsConstructor +public class MainlandLog implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + @TableField("user_id") + private Integer user_id; + /** + * 游戏时间(毫秒级) + */ + @TableField("game_time") + private Integer game_time; + + @TableField("bvs3") + private Float bvs3; + + @TableField("bv3") + private Float bv3; + /** + * 游戏录像 + */ + @TableField("video") + private String video; + /** + * 杂项(游戏数据) + */ + @TableField("game_info") + private String game_info; + + /** + * 游戏难度:1 - 普通 2 困难 3 大师 4 超凡 + */ + @TableField("level") + private Integer level; + + @TableField("nf") + private Boolean nf; + /** + * 创建时间 秒 + */ + @TableField("creation_time") + private Integer creation_time; + +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/Notice.java b/common/src/main/java/com/lightyears/common/domain/entity/Notice.java new file mode 100644 index 0000000..638a144 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/Notice.java @@ -0,0 +1,98 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +/** + *

+ * + *

+ * + * @author hellor + * @since 2022-03-18 + */ +@Data +@Builder +@TableName("sl_notice") +@AllArgsConstructor +@NoArgsConstructor +public class Notice implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId("id") + private Integer id; + + /** + * 玩家ID + */ + @TableField("player_id") + private Integer playerId; + + /** + * 标题 + */ + @TableField("title") + private String title; + + /** + * 内容 + */ + @TableField("content") + private String content; + + /** + * 类型(0.系统,1.个人) + */ + @TableField("type") + private Integer type; + + /** + * 状态(0.未读, 1.已读,2.已过期) + */ + @TableField("status") + private Integer status; + + /** + * 读取时间 + */ + @TableField("read_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date readTime; + + /** + * 过期天数(单位:天) + */ + @TableField("expiration_day") + private Integer expirationDay; + + /** + * 创建时间 + */ + @TableField("create_date") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createDate; + + /** + * 备注 + */ + @TableField("remark") + private String remark; + + +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/Player.java b/common/src/main/java/com/lightyears/common/domain/entity/Player.java new file mode 100644 index 0000000..a3eba5c --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/Player.java @@ -0,0 +1,119 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.lightyears.common.domain.dto.SimplePlayerAssert; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +/** + *

+ * 扫雷玩家表 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_player") +public class Player implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(value = "user_id", type = IdType.AUTO) + private Integer user_id; + + /** + * 昵称 + */ + @TableField("user_name") + private String user_name; + + /** + * 三方登录唯一ID 例如:QQ,微信 + */ + @TableField("open_id") + private String open_id; + + /** + * 性别 + */ + @TableField("sex") + private String sex; + + @TableField("age") + private Integer age; + + /** + * 地区 + */ + @TableField("distric") + private String distric; + + /** + * 启用1 禁用0 + */ + @TableField("status") + private Integer status; + + /** + * 创建时间 + */ + @TableField("creation_time") + private Integer creation_time; + + /** + * 最后登录时间 + */ + @TableField("update_time") + private Integer update_time; + + /** + * 金币、积分 + */ + @TableField("user_gold") + private Integer user_gold; + + /** + * 隐藏分 + */ + @TableField("user_rank") + private Integer user_rank; + + /** + * 本地存档ID + */ + @TableField("local_id") + private Integer local_id; + + /** + * 登录token 提示每次登录自动并记录 + */ + @TableField("token") + private String token; + + @TableField("update_name_count") + private Integer update_name_count; + + /** + * 是否是新用户 + */ + @TableField(exist = false) + private Boolean newUser; + + /** + * 用户资产 + */ + @TableField(exist = false) + private List playerAssets; +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/PlayerAssets.java b/common/src/main/java/com/lightyears/common/domain/entity/PlayerAssets.java new file mode 100644 index 0000000..8c80168 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/PlayerAssets.java @@ -0,0 +1,55 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 用户资产 + * @author hellor + * @since 2022-03-16 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_player_assets") +public class PlayerAssets implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键id + */ + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 用户id + */ + @TableField("player_id") + private Integer playerId; + + /** + * 资产类型(0.金币,1.门票,2.中级门票,3.高级门票) + */ + @TableField("type") + private Integer type; + + /** + * 资产数量 + */ + @TableField("number") + private Integer number; + + @TableField("version") + private Long version; + +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/PlayerIntegral.java b/common/src/main/java/com/lightyears/common/domain/entity/PlayerIntegral.java new file mode 100644 index 0000000..acbd9d2 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/PlayerIntegral.java @@ -0,0 +1,53 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.io.Serializable; +import java.util.Date; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_player_integral") +public class PlayerIntegral implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 玩家id + */ + @TableField("user_id") + private Integer userId; + + /** + * 积分数量 + */ + @TableField("num") + private Integer num; + + /** + * 创建时间 秒 + */ + @TableField("create_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + private Date createTime; + + /** + * 版本号 + */ + @TableField("version") + private Integer version; +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/PlayerIntegralDetail.java b/common/src/main/java/com/lightyears/common/domain/entity/PlayerIntegralDetail.java new file mode 100644 index 0000000..b51049e --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/PlayerIntegralDetail.java @@ -0,0 +1,52 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_player_integral_detail") +public class PlayerIntegralDetail { + + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + + /** + * 玩家id + */ + @TableField("user_id") + private Integer userId; + + /** + * 积分数量 + */ + @TableField("num") + private Integer num; + + /** + * 创建时间 秒 + */ + @TableField("create_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") + private Date createTime; + + /** + * 备注 + */ + @TableField("remark") + private String remark; + +} diff --git a/common/src/main/java/com/lightyears/common/domain/entity/Record.java b/common/src/main/java/com/lightyears/common/domain/entity/Record.java new file mode 100644 index 0000000..01cc2af --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/entity/Record.java @@ -0,0 +1,74 @@ +package com.lightyears.common.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + *

+ * 游戏存档 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("sl_record") +public class Record implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 存档id + */ + @TableId(value = "local_id", type = IdType.AUTO) + private Integer local_id; + + /** + * 用户ID + */ + @TableField("user_id") + private Integer user_id; + + /** + * 存档名称 + */ + @TableField("record_name") + private String record_name; + + /** + * 存档数据 + */ + @TableField("record") + private String record; + + /** + * 创建存档时间 + */ + @TableField("creation_time") + private Integer creation_time; + + /** + * 最后修改时间 + */ + @TableField("updata_time") + private Integer updata_time; + + /** + * 0 皮肤 1 记录 2游戏设置 + */ + @TableField("record_type") + private Integer record_type; + + +} diff --git a/common/src/main/java/com/lightyears/common/domain/enums/AssetsTypeEnum.java b/common/src/main/java/com/lightyears/common/domain/enums/AssetsTypeEnum.java new file mode 100644 index 0000000..1a76138 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/enums/AssetsTypeEnum.java @@ -0,0 +1,39 @@ +package com.lightyears.common.domain.enums; + +public enum AssetsTypeEnum { + GOLD_COIN(0, "金币"); + + int id; + String name; + + AssetsTypeEnum(Integer id, String name) { + this.id = id; + this.name = name; + } + + public Integer getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setId(Integer id) { + this.id = id; + } + + public static String getNameById(Integer id) { + AssetsTypeEnum[] enums = values(); + for (AssetsTypeEnum assetsTypeEnum : enums) { + if (assetsTypeEnum.getId().equals(id)) { + return assetsTypeEnum.getName(); + } + } + return "未知类型"; + } +} diff --git a/common/src/main/java/com/lightyears/common/domain/enums/MessageEnum.java b/common/src/main/java/com/lightyears/common/domain/enums/MessageEnum.java new file mode 100644 index 0000000..7d1aff3 --- /dev/null +++ b/common/src/main/java/com/lightyears/common/domain/enums/MessageEnum.java @@ -0,0 +1,104 @@ +package com.lightyears.common.domain.enums; + +/** + * 枚举:系统级提示信息 + * + * @author Melody + */ +public enum MessageEnum { + SUCCESS_S(200, "成功[%s]"), + SUCCESS(200, "操作成功"), + ADD_SUCCESS(200, "新增成功"), + UPDATE_SUCCESS(200, "修改成功"), + DEL_SUCCESS(200, "删除成功"), + GAME_TOKEN_CREATE(200, "游戏Token生成成功"), + GAME_HUGE_GOLD(200, "金币存储过大上限单次5w!"), + + + ERROR_S(603, "失败[%s]"), + ERROR(603, "操作失败"), + ADD_ERROR(603, "新增失败"), + UPDATE_ERROR(603, "修改失败"), + DEL_ERROR(603, "删除失败"), + + /** + * 其他 + */ + MOTION_SAFEGUARD(500, "极限操作预防!请不要频繁操作!"), + LOCATION_ERROR(501, "认证已失效,已被异地登录!"), + SYSTEM_ERROR(502, "非法访问!"), + VERSION_ERROR(503, "应用版本过低,请升级!"), + LOGIN_USERNAME_ERROR(504, "该账号已被封禁,无法登陆!"), + CHECK_KEY_ERROR(505, "操作失败,数据校验错误!"), + CHECK_LOGGING_ERROR(506, "注销失败,身份验证不一致!"), + + /** + * 文件上传 + */ + FILE_READING_ERROR(700, "FILE_READING_ERROR!"), + FILE_NOT_FOUND(700, "FILE_NOT_FOUND!"), + + /** + * 错误的请求 + */ + REQUEST_NULL(600, "请求有错误"), + SERVER_ERROR(600, "服务器异常"), + UNKNOWN_ERROR(600, "未知错误"), + + /*** + * 用户错误提示 + * */ + LOG_USER_SUCCESS(200, "用户登录成功"), + LOG_USER_ERROR(550, "用户登录失败"), + LOG_USER_DATA_ERROR(550, "账号密码不对"), + LOG_USER_IS_NULL(550, "用户不存在或账号密码不对"), + LOG_USER_IS_FALSE(550, "账户冻结"), + LOG_USER_ID_ERROR(550, "ID错误查无此人"), + LOG_USER_LOG_S(550, "账号已在其他地方登陆"), + LOG_NO_USER_DATA(550, "未登录"), + LOG_NO_TOKEN_ID(550, "tokenID 丢失"), + + /*** + *游戏错误提示 700系列 + * */ + GAME_TOKEN_ERROR(700, "游戏ID错误/或不存在"), + GAME_GOLD_PUSH_ERROR(700, "游戏金币存储失败"), + GAME_GOLD_PULL_MAX_ERROR(700, "存储金币不足,最大取出[%s]"), + + + /*** + * 存档相关提示 800系列 + * */ + GAME_RECORD_ID_IS_NULL(800, "存档ID不存在"), + GAME_RECORD_ERROR(800, "数据存档失败"), + + /*** + * 游戏其他提示信息 900 系列 + * */ + GAME_SAVE_LOG_ADD_ERROR(900, "游戏完成提交记录失败"), + GAME_UPDATE_ERROR_COUNT(900, "该账号已经修改过一次昵称!"); + + + int code; + String message; + + MessageEnum(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + }} diff --git a/mainland/pom.xml b/mainland/pom.xml new file mode 100644 index 0000000..2ca9de3 --- /dev/null +++ b/mainland/pom.xml @@ -0,0 +1,146 @@ + + + + mine_clearance + com.lightyears.mine_clearance + 1.0 + + 4.0.0 + + mainland + + + 8 + 8 + + + + org.springframework.boot + spring-boot-starter-web + + + com.baomidou + mybatis-plus-boot-starter + + + org.springframework.boot + spring-boot-starter-aop + + + mysql + mysql-connector-java + + + + com.alibaba + druid-spring-boot-starter + + + + com.alibaba + fastjson + + + com.baomidou + mybatis-plus-generator + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + org.apache.commons + commons-pool2 + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + org.freemarker + freemarker + + + com.google.guava + guava + 20.0 + + + + + cn.hutool + hutool-all + + + commons-io + commons-io + + + org.apache.commons + commons-collections4 + + + com.lightyears.mine_clearance + common + + + org.projectlombok + lombok + provided + + + junit + junit + test + + + org.springframework.boot + spring-boot-starter-test + test + + + + + mainland + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + utf-8 + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.lightyears.basics.BasicsApp + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + \ No newline at end of file diff --git a/mainland/src/main/java/com/lightyears/mainland/MainlandApp.java b/mainland/src/main/java/com/lightyears/mainland/MainlandApp.java new file mode 100644 index 0000000..b678fb7 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/MainlandApp.java @@ -0,0 +1,19 @@ +package com.lightyears.mainland; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.util.TimeZone; + +@EnableScheduling +@SpringBootApplication +@EnableTransactionManagement +public class MainlandApp { + public static void main(String[] args) { + // 设置时区 + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + SpringApplication.run(MainlandApp.class, args); + } +} \ No newline at end of file diff --git a/mainland/src/main/java/com/lightyears/mainland/annotation/DataVerification.java b/mainland/src/main/java/com/lightyears/mainland/annotation/DataVerification.java new file mode 100644 index 0000000..66f5a01 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/annotation/DataVerification.java @@ -0,0 +1,9 @@ +package com.lightyears.mainland.annotation; + +import java.lang.annotation.*; + +@Documented +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface DataVerification { +} diff --git a/mainland/src/main/java/com/lightyears/mainland/aspect/DataVerificationAspect.java b/mainland/src/main/java/com/lightyears/mainland/aspect/DataVerificationAspect.java new file mode 100644 index 0000000..5c2eee5 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/aspect/DataVerificationAspect.java @@ -0,0 +1,65 @@ +package com.lightyears.mainland.aspect; + +import cn.hutool.crypto.digest.MD5; +import com.github.pagehelper.util.StringUtil; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.mainland.exception.GlobalException; +import com.lightyears.mainland.util.StaticUtil; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.util.Collection; +import java.util.Map; + +@Aspect +@Component +public class DataVerificationAspect { + /** + * 过滤类 + * 指定自定义注解为切入点 + **/ + @Pointcut("@annotation(com.lightyears.mainland.annotation.DataVerification)") + public void checkPoint() { + } + + /** + * 前置 + */ + @Before("checkPoint()") + public void doAround(JoinPoint joinPoint) throws GlobalException { + RequestAttributes ra = RequestContextHolder.getRequestAttributes(); + ServletRequestAttributes sra = (ServletRequestAttributes) ra; + assert sra != null; + HttpServletRequest request = sra.getRequest(); + String checkKey = request.getHeader("checkKey"); + Map paramMap = request.getParameterMap(); + StringBuffer paramsStr = new StringBuffer(); + + if (StringUtil.isEmpty(checkKey)) { + throw new GlobalException(MessageEnum.CHECK_KEY_ERROR); + } + Object[] params = joinPoint.getArgs(); + if(paramMap.size() > 0) { + Collection values = paramMap.values(); + for (String[] value : values) { + paramsStr.append(value[0]); + } + } else { + if(params.length == 1) { + paramsStr.append(params[0].toString()); + } + } + String testKey = MD5.create().digestHex(MD5.create().digestHex(paramsStr.append(StaticUtil.PRIVATE_KEY).toString())); + if (!checkKey.equals(testKey)) { + throw new GlobalException(MessageEnum.CHECK_KEY_ERROR); + } + } + +} diff --git a/mainland/src/main/java/com/lightyears/mainland/config/AppConfig.java b/mainland/src/main/java/com/lightyears/mainland/config/AppConfig.java new file mode 100644 index 0000000..8a7a88c --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/config/AppConfig.java @@ -0,0 +1,16 @@ +package com.lightyears.mainland.config; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component +@NoArgsConstructor +@AllArgsConstructor +@ConfigurationProperties(prefix = "appconfig") +public class AppConfig { + private Float version; +} diff --git a/mainland/src/main/java/com/lightyears/mainland/controller/BaseController.java b/mainland/src/main/java/com/lightyears/mainland/controller/BaseController.java new file mode 100644 index 0000000..2a0d25f --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/controller/BaseController.java @@ -0,0 +1,55 @@ +package com.lightyears.mainland.controller; + +import com.lightyears.common.domain.entity.Player; +import com.lightyears.mainland.util.RedisCache; +import com.lightyears.mainland.util.StaticUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class BaseController { + + @Autowired + private RedisCache redisCache; + + /** + * 得到request对象 + * + * @return + */ + public HttpServletRequest getRequest() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getRequest(); + return request; + } + + /** + * 得到respones对象 + * @return + */ + public HttpServletResponse getResponse() { + HttpServletResponse request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getResponse(); + return request; + } + + /** + * 得到当前登录用户信息 + * + * @return + */ + public Player getUserInfo() { + // 获取请求头中的token数据 + String token = getRequest().getHeader("Tracecode"); + if(token == null) { + token = this.getRequest().getParameter("Tracecode"); + } + String key = StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(token); + // 获取登录用户信息 + Player user = redisCache.getCacheObject(key); + return user; + } +} diff --git a/mainland/src/main/java/com/lightyears/mainland/controller/MainlandController.java b/mainland/src/main/java/com/lightyears/mainland/controller/MainlandController.java new file mode 100644 index 0000000..734ac98 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/controller/MainlandController.java @@ -0,0 +1,14 @@ +package com.lightyears.mainland.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@CrossOrigin +@RestController +@RequiredArgsConstructor +@RequestMapping("/mainland") +public class MainlandController { + +} diff --git a/mainland/src/main/java/com/lightyears/mainland/exception/BussinessException.java b/mainland/src/main/java/com/lightyears/mainland/exception/BussinessException.java new file mode 100644 index 0000000..3a94b67 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/exception/BussinessException.java @@ -0,0 +1,18 @@ +package com.lightyears.mainland.exception; + + +import com.lightyears.common.domain.enums.MessageEnum; + +/** + * @author fengshuonan + * @Description 业务异常的封装 + */ +public class BussinessException extends GlobalException { + public BussinessException(MessageEnum messageEnum) { + super(messageEnum.getCode(), messageEnum.getMessage()); + } + + public BussinessException(Integer code, String message) { + super(code, message); + } +} diff --git a/mainland/src/main/java/com/lightyears/mainland/exception/GlobalException.java b/mainland/src/main/java/com/lightyears/mainland/exception/GlobalException.java new file mode 100644 index 0000000..a2ed9b6 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/exception/GlobalException.java @@ -0,0 +1,46 @@ +package com.lightyears.mainland.exception; + +import com.lightyears.common.domain.enums.MessageEnum; + +/*** + * 全局异常捕捉 统一返回 model + * */ +public class GlobalException extends RuntimeException { + + //友好提示的code码 + protected int friendlyCode; + + //友好提示 + protected String friendlyMsg; + + + protected GlobalException(int friendlyCode, String friendlyMsg) { + this.setValues(friendlyCode, friendlyMsg); + } + + public GlobalException(MessageEnum messageEnum) { + this.setValues(messageEnum.getCode(), messageEnum.getMessage()); + } + + private void setValues(int friendlyCode, String friendlyMsg) { + this.friendlyCode = friendlyCode; + this.friendlyMsg = friendlyMsg; + } + + public int getCode() { + return friendlyCode; + } + + public void setCode(int code) { + this.friendlyCode = code; + } + + public String getMessage() { + return friendlyMsg; + } + + public void setMessage(String message) { + this.friendlyMsg = message; + } + +} diff --git a/mainland/src/main/java/com/lightyears/mainland/exception/MyExceptionHandle.java b/mainland/src/main/java/com/lightyears/mainland/exception/MyExceptionHandle.java new file mode 100644 index 0000000..4b8a153 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/exception/MyExceptionHandle.java @@ -0,0 +1,26 @@ +package com.lightyears.mainland.exception; + +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.mainland.util.ResultUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +@Slf4j +@ControllerAdvice +public class MyExceptionHandle { + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public ResModeBase handle(Exception e) { + if (e instanceof GlobalException) { + GlobalException myException = (GlobalException) e; + return ResultUtil.result(myException.getCode(), myException.getMessage()); + } else { + log.error("系统异常", e); + return ResultUtil.result(MessageEnum.UNKNOWN_ERROR.getCode(), MessageEnum.UNKNOWN_ERROR.getMessage()); + } + } +} diff --git a/mainland/src/main/java/com/lightyears/mainland/filter/TokenFilter.java b/mainland/src/main/java/com/lightyears/mainland/filter/TokenFilter.java new file mode 100644 index 0000000..c7c6acc --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/filter/TokenFilter.java @@ -0,0 +1,119 @@ +package com.lightyears.mainland.filter; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.util.StringUtil; +import com.lightyears.common.domain.entity.Player; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.mainland.config.AppConfig; +import com.lightyears.mainland.util.RedisCache; +import com.lightyears.mainland.util.StaticUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.annotation.Resource; +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Component +public class TokenFilter implements Filter{ + @Resource + private RedisCache redisCache; + @Resource + private AppConfig appConfig; + + @Override + public void init(FilterConfig filterConfig) { + ServletContext servletContext = filterConfig.getServletContext(); + ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext); + redisCache = (RedisCache) ctx.getBean("redisCache"); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + // 刷新缓存不验证 + if(request.getRequestURI().indexOf("refreshRankCache")<0){ + // 版本号验证 + String version = request.getHeader("version"); + if (StrUtil.isEmpty(version)) { + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + try{ + Float versionCode = Float.valueOf(version); +// log.info("version :" + appConfig.getVersion()); + if(versionCode < appConfig.getVersion()) { + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + }catch (Exception e) { + this.authcReq(response, MessageEnum.VERSION_ERROR.getCode(), MessageEnum.VERSION_ERROR.getMessage()); + return; + } + } + + String tracecode = request.getHeader("Tracecode"); + Boolean flag = request.getRequestURI().indexOf("touristLogin")<0 && request.getRequestURI().indexOf("getSystemTime") < 0 && request.getRequestURI().indexOf("swagger-ui")<0 && request.getRequestURI().indexOf("swagger-resources")<0 && request.getRequestURI().indexOf("v2") < 0 && request.getRequestURI().indexOf("refreshRankCache")<0; + + // 登录放行 + if(flag){ + // 判断身份码, 是否已登录 + if((StringUtil.isEmpty(tracecode) || !redisCache.hasKey(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode)))){ + /** + * 不是登录 || 身份码不存在 || 未在登录列表 就拒绝访问 + */ + this.authcReq(response, MessageEnum.SYSTEM_ERROR.getCode(), MessageEnum.SYSTEM_ERROR.getMessage()); + return; + } + Player player = redisCache.getCacheObject(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode)); + String token = redisCache.getCacheObject(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString())).toString(); + if(!tracecode.equals(token)) { + /** + * 登录失效,已被异地登录 + */ + this.authcReq(response, MessageEnum.LOCATION_ERROR.getCode(), MessageEnum.LOCATION_ERROR.getMessage()); + return; + } + // 重置身份缓存过期时间 + redisCache.expire(StaticUtil.ONLINE_USER_TOKEN.concat(player.getUser_id().toString()), 1, TimeUnit.HOURS); + // 重置身份认证过期时间 + redisCache.expire(StaticUtil.ONLINE_USER_PUBLIC_KEY.concat(tracecode), 1, TimeUnit.HOURS); + } + + //执行 + filterChain.doFilter(servletRequest, servletResponse); + } + + @Override + public void destroy() { + + } + + /** + * 响应访问 + * @param response + * @throws IOException + */ + private void authcReq(HttpServletResponse response, Integer code, String msg) throws IOException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentType("application/json; charset=utf-8"); + PrintWriter writer = response.getWriter(); + Map map = new HashMap<>(); + map.put("code", code); + map.put("msg", msg); + writer.print(JSONObject.toJSON(map)); + } + +} diff --git a/mainland/src/main/java/com/lightyears/mainland/init/MainlandDataInit.java b/mainland/src/main/java/com/lightyears/mainland/init/MainlandDataInit.java new file mode 100644 index 0000000..725e8e5 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/init/MainlandDataInit.java @@ -0,0 +1,33 @@ +package com.lightyears.mainland.init; + +import com.lightyears.mainland.service.IMainlandLogService; +import com.lightyears.mainland.service.IPlayerIntegralService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +; + +/** + * 雷神大陆模式数据初始化 + */ +@Component +@RequiredArgsConstructor +public class MainlandDataInit { + private final IPlayerIntegralService playerIntegralService; + private final IMainlandLogService mainlandLogService; + + @PostConstruct + public void init() { + // 写入积分排行榜缓存 + playerIntegralService.initRankList(mainlandLogService.getRankThreshold()); + } + + @PreDestroy + public void destroy() { + // 写入持久层 + } + +} diff --git a/mainland/src/main/java/com/lightyears/mainland/mapper/MainlandLogMapper.java b/mainland/src/main/java/com/lightyears/mainland/mapper/MainlandLogMapper.java new file mode 100644 index 0000000..85e20e6 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/mapper/MainlandLogMapper.java @@ -0,0 +1,12 @@ +package com.lightyears.mainland.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.MainlandLog; +import org.apache.ibatis.annotations.Mapper; + +/** + * 雷神大陆数据记录 + */ +@Mapper +public interface MainlandLogMapper extends BaseMapper { +} diff --git a/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerIntegralDetailMapper.java b/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerIntegralDetailMapper.java new file mode 100644 index 0000000..07ba4c1 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerIntegralDetailMapper.java @@ -0,0 +1,12 @@ +package com.lightyears.mainland.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.PlayerIntegralDetail; +import org.apache.ibatis.annotations.Mapper; + +/** + * 玩家积分明细表mapper + */ +@Mapper +public interface PlayerIntegralDetailMapper extends BaseMapper { +} diff --git a/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerIntegralMapper.java b/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerIntegralMapper.java new file mode 100644 index 0000000..abddb7b --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerIntegralMapper.java @@ -0,0 +1,22 @@ +package com.lightyears.mainland.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.PlayerIntegral; +import com.lightyears.common.domain.dto.RankInitModel; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 玩家积分表mapper + */ +@Mapper +public interface PlayerIntegralMapper extends BaseMapper { + /** + * 获取排行榜列表 + * @param beginNum + * @return + */ + List getIntegralRank(@Param("beginNum") Integer beginNum); +} diff --git a/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerMapper.java b/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerMapper.java new file mode 100644 index 0000000..f4d8335 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/mapper/PlayerMapper.java @@ -0,0 +1,18 @@ +package com.lightyears.mainland.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.lightyears.common.domain.entity.Player; +import org.apache.ibatis.annotations.Mapper; + +/** + *

+ * 扫雷玩家表 Mapper 接口 + *

+ * + * @author hellor + * @since 2022-03-09 + */ +@Mapper +public interface PlayerMapper extends BaseMapper { + +} diff --git a/mainland/src/main/java/com/lightyears/mainland/schedule/MainlandTask.java b/mainland/src/main/java/com/lightyears/mainland/schedule/MainlandTask.java new file mode 100644 index 0000000..3d83990 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/schedule/MainlandTask.java @@ -0,0 +1,28 @@ +package com.lightyears.mainland.schedule; + +import com.lightyears.common.domain.dto.RankModel; +import com.lightyears.mainland.util.RedisCache; +import com.lightyears.mainland.util.StaticUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor(onConstructor = @_(@Autowired)) +public class MainlandTask { + + private final RedisCache redisCache; + + /** + * 每日 0点执行 清空积分增长日榜 + */ + @Scheduled(cron = "0 0 0 * * ?") + public void deleteNotices(){ + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(StaticUtil.MAINLAND_DAY_RANK); + operations.removeRange(0, -1); + } +} diff --git a/mainland/src/main/java/com/lightyears/mainland/service/IMainlandLogService.java b/mainland/src/main/java/com/lightyears/mainland/service/IMainlandLogService.java new file mode 100644 index 0000000..eda950b --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/service/IMainlandLogService.java @@ -0,0 +1,65 @@ +package com.lightyears.mainland.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.github.pagehelper.PageInfo; +import com.lightyears.common.domain.dto.MainLandRankInfoDto; +import com.lightyears.common.domain.dto.RankDto; +import com.lightyears.common.domain.dto.RankModel; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.MainlandLog; +import com.lightyears.common.domain.entity.Player; + +import java.util.Set; + +public interface IMainlandLogService extends IService { + /** + * 游戏数据保存 + * @param player 玩家信息 + * @param level 等级 + * @param game_time 游戏时间 + * @param bvs3 + * @param bv3 + * @param video + * @param gameinfo + * @param nf + * @param integralNum 积分操作数量 + * @return + */ + ResModeBase saveMainlandLog(Player player, Integer level, int game_time, float bvs3, float bv3, String video, String gameinfo, boolean nf, int integralNum); + /** + * 获取进入排行版的积分数量门槛值 + * @return + */ + Integer getRankThreshold(); + + /** + * 获取玩家积分及排名信息 + * @param rankModel + * @return + */ + MainLandRankInfoDto getPlayerRankInfo(RankModel rankModel); + + /** + * 获取录像数据 + * @param playerId 玩家id + * @return + */ + String getMainlandGameInfo(Integer playerId); + + + /** + * 获取日积分增长榜 + * @param pageIndex 页码 + * @param pageSize 页大小 + * @return + */ + PageInfo getDayRank(int pageIndex, int pageSize); + + /** + * 获取我的排名上下范围内的玩家列表 + * @param rankModel 玩家信息 + * @param rangeNum 范围值 + * @return + */ + Set getRankRangeList(RankModel rankModel, int rangeNum); +} diff --git a/mainland/src/main/java/com/lightyears/mainland/service/IPlayerIntegralDetailService.java b/mainland/src/main/java/com/lightyears/mainland/service/IPlayerIntegralDetailService.java new file mode 100644 index 0000000..f8ab9de --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/service/IPlayerIntegralDetailService.java @@ -0,0 +1,10 @@ +package com.lightyears.mainland.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.PlayerIntegralDetail; + +/** + * 玩家积分明细service + */ +public interface IPlayerIntegralDetailService extends IService { +} diff --git a/mainland/src/main/java/com/lightyears/mainland/service/IPlayerIntegralService.java b/mainland/src/main/java/com/lightyears/mainland/service/IPlayerIntegralService.java new file mode 100644 index 0000000..f22ecbd --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/service/IPlayerIntegralService.java @@ -0,0 +1,24 @@ +package com.lightyears.mainland.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.lightyears.common.domain.entity.PlayerIntegral; + +/** + * 玩家积分service + */ +public interface IPlayerIntegralService extends IService { + /** + * 积分加/减操作 + * @param num 操作数量 + * @param playerId 玩家id + * @param remark 操作备注 + * @return + */ + int saveIntegral(Integer num, Integer playerId, String remark); + + /** + * 积分排名列表 + * @param beginNum 门槛值 + */ + void initRankList(Integer beginNum); +} diff --git a/mainland/src/main/java/com/lightyears/mainland/service/impl/MainlandLogServiceImpl.java b/mainland/src/main/java/com/lightyears/mainland/service/impl/MainlandLogServiceImpl.java new file mode 100644 index 0000000..49a1675 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/service/impl/MainlandLogServiceImpl.java @@ -0,0 +1,191 @@ +package com.lightyears.mainland.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.github.pagehelper.Page; +import com.github.pagehelper.PageInfo; +import com.lightyears.common.domain.dto.MainLandRankInfoDto; +import com.lightyears.common.domain.dto.RankDto; +import com.lightyears.common.domain.dto.RankModel; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.entity.MainlandLog; +import com.lightyears.common.domain.entity.Player; +import com.lightyears.common.domain.entity.PlayerIntegral; +import com.lightyears.common.domain.enums.MessageEnum; +import com.lightyears.mainland.exception.BussinessException; +import com.lightyears.mainland.mapper.MainlandLogMapper; +import com.lightyears.mainland.service.IMainlandLogService; +import com.lightyears.mainland.service.IPlayerIntegralService; +import com.lightyears.mainland.util.RedisCache; +import com.lightyears.mainland.util.ResultUtil; +import com.lightyears.mainland.util.StaticUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.data.redis.core.ZSetOperations; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service +@RequiredArgsConstructor +public class MainlandLogServiceImpl extends ServiceImpl implements IMainlandLogService { + + private final RedisCache redisCache; + private final IPlayerIntegralService playerIntegralService; + + @Override + @Transactional(rollbackFor = Exception.class) + public ResModeBase saveMainlandLog(Player player, Integer level, int game_time, float bvs3, float bv3, String video, String gameinfo, boolean nf, int integralNum) { + int req = -1; + //1 检验是否存在记录 + MainlandLog isTrue = getOne(new QueryWrapper().eq("user_id", player.getUser_id()).orderByDesc("creation_time").last("limit 1")); + MainlandLog data = MainlandLog.builder() + .user_id(player.getUser_id()) + .creation_time(Integer.parseInt(System.currentTimeMillis() / 1000 + "")) + .game_time(game_time) + .bvs3(bvs3) + .bv3(bv3) + .video(video) + .game_info(gameinfo) + .level(level) + .nf(nf) + .build(); + if (null != isTrue) { + if (game_time < isTrue.getGame_time()) { + data.setId(isTrue.getId()); + req = this.updateById(data)?2:0; + } + } else { + //存储 + req = this.save(data)?1:0; + } + int num = playerIntegralService.saveIntegral(integralNum, player.getUser_id(), "游戏对局"); + // 排除成绩不计入排行的用户 + if (req < 1) { + throw new BussinessException(MessageEnum.GAME_SAVE_LOG_ADD_ERROR); + } + RankModel rankModel = RankModel.builder().userId(player.getUser_id()).userName(player.getUser_name()).build(); + // 是否达到段位积分要求 && 玩家成绩计入排行榜 + if(num >= getRankThreshold() && player.getUser_gold() == 0){ + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(StaticUtil.INTEGRAL_RANK_KEY); + operations.add(rankModel, num); + } + // 写入积分增长日榜 + BoundZSetOperations dayRank = redisCache.redisTemplate.boundZSetOps(StaticUtil.MAINLAND_DAY_RANK); + Double score = Optional.of(dayRank.score(rankModel)).orElse(0D); + dayRank.add(rankModel, score+num); + + return ResultUtil.result(MessageEnum.SUCCESS.getCode(), MessageEnum.SUCCESS.getMessage()); + } + + @Override + public MainLandRankInfoDto getPlayerRankInfo(RankModel rankModel) { + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(StaticUtil.INTEGRAL_RANK_KEY); + Long rankNum = operations.reverseRank(rankModel); + Double num = operations.score(rankModel); + MainLandRankInfoDto rankInfoDto = new MainLandRankInfoDto(); + if(rankNum != null){ + PlayerIntegral playerIntegral = playerIntegralService.getOne(new LambdaQueryWrapper().eq(PlayerIntegral::getUserId, rankModel.getUserId()).orderByDesc(PlayerIntegral::getNum).last("limit 1")); + if(playerIntegral == null){ + return rankInfoDto; + } + rankInfoDto.setIntegralNum(playerIntegral.getNum()); + } else { + rankInfoDto.setIntegralNum(num.intValue()); + rankInfoDto.setRankNum(rankNum.intValue()); + } + return rankInfoDto; + } + + @Override + public String getMainlandGameInfo(Integer playerId){ + Object value = redisCache.getCacheObject(StaticUtil.MAINLAND_GAME_INFO_KEY.concat(playerId.toString())); + if (value == null) { + MainlandLog mainlandLog = baseMapper.selectOne(new LambdaQueryWrapper().eq(MainlandLog::getUser_id, playerId).orderByAsc(MainlandLog::getGame_time).last("limit 1")); + if(mainlandLog == null){ + throw new BussinessException(MessageEnum.GAME_RECORD_ERROR); + } + // 缓存10分钟 + redisCache.setCacheObject(StaticUtil.MAINLAND_GAME_INFO_KEY.concat(playerId.toString()), mainlandLog.getGame_info(), 10, TimeUnit.MINUTES); + return mainlandLog.getGame_info(); + } + return value.toString(); + } + + @Override + public PageInfo getDayRank(int pageIndex, int pageSize){ + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(StaticUtil.MAINLAND_DAY_RANK); + List results = new ArrayList(); + Page page = new Page(pageIndex, pageSize); + if(operations == null || operations.size() == 0){ + } else { + Set> objs = operations.reverseRangeByScoreWithScores(0, -1); + List> cacheObjs = new ArrayList>(); + cacheObjs.addAll(objs); + int total = objs.size(); + page.setTotal(total); + //计算当前需要显示的数据下标起始值 + int startIndex = (pageIndex - 1) * pageSize; + int endIndex = Math.min(startIndex + pageSize, total); + // 截取数据 + cacheObjs = cacheObjs.subList(startIndex,endIndex); + // 写入返回体 + for (ZSetOperations.TypedTuple obj : cacheObjs){ + results.add(new RankDto(obj.getValue(), obj.getScore().intValue())); + } + } + //从链表中截取需要显示的子链表,并加入到Page + page.addAll(results); + //以Page创建PageInfo + PageInfo pageInfo = new PageInfo<>(page); + return pageInfo; + } + + @Override + public Set getRankRangeList(RankModel rankModel, int rangeNum){ + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(StaticUtil.INTEGRAL_RANK_KEY); + Set results = new HashSet(); + if(operations != null || operations.size() == 0){ + Long rankNum = operations.rank(rankModel); + Long startIndex = rankNum - rangeNum; + Long endIndex = rankNum + rangeNum; + Set> objs = operations.reverseRangeWithScores(startIndex >= 0 ? startIndex : startIndex + 1, endIndex); + for (ZSetOperations.TypedTuple obj : objs){ + results.add(new RankDto(obj.getValue(), obj.getScore().intValue())); + } + return results; + } + return results; + } + + /** + * 获取灵阶的起点: 200,500,2100,4100,19100,40000,100000 + * 0-200 + * 200-500 + * 501-2100 灵阶 + * 2101-4100 + * 4101-19100 + * 19101-40000 + * 40001-100000 + * > 1000001 + * + * @return + */ + @Override + public Integer getRankThreshold(){ + String integralInterval = redisCache.getCacheObject(StaticUtil.SYS_INTEGRAL_INTERVAL); + if(!StrUtil.isEmpty(integralInterval)){ + String[] integralIntervals = integralInterval.split(","); + if(integralIntervals.length > 2){ + return Integer.parseInt(integralIntervals[2].split("-")[0]); + } + } + return -1; + } +} diff --git a/mainland/src/main/java/com/lightyears/mainland/service/impl/PlayerIntegralDetailServiceImpl.java b/mainland/src/main/java/com/lightyears/mainland/service/impl/PlayerIntegralDetailServiceImpl.java new file mode 100644 index 0000000..48340b7 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/service/impl/PlayerIntegralDetailServiceImpl.java @@ -0,0 +1,13 @@ +package com.lightyears.mainland.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.lightyears.common.domain.entity.PlayerIntegralDetail; +import com.lightyears.mainland.mapper.PlayerIntegralDetailMapper; +import com.lightyears.mainland.service.IPlayerIntegralDetailService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class PlayerIntegralDetailServiceImpl extends ServiceImpl implements IPlayerIntegralDetailService { +} diff --git a/mainland/src/main/java/com/lightyears/mainland/service/impl/PlayerIntegralServiceImpl.java b/mainland/src/main/java/com/lightyears/mainland/service/impl/PlayerIntegralServiceImpl.java new file mode 100644 index 0000000..79de81a --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/service/impl/PlayerIntegralServiceImpl.java @@ -0,0 +1,73 @@ +package com.lightyears.mainland.service.impl; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; +import com.lightyears.common.domain.entity.PlayerIntegral; +import com.lightyears.common.domain.entity.PlayerIntegralDetail; +import com.lightyears.mainland.mapper.PlayerIntegralMapper; +import com.lightyears.common.domain.dto.RankInitModel; +import com.lightyears.common.domain.dto.RankModel; +import com.lightyears.mainland.service.IPlayerIntegralDetailService; +import com.lightyears.mainland.service.IPlayerIntegralService; +import com.lightyears.mainland.util.RedisCache; +import com.lightyears.mainland.util.StaticUtil; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.BoundZSetOperations; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.Date; +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class PlayerIntegralServiceImpl extends ServiceImpl implements IPlayerIntegralService { + private final IPlayerIntegralDetailService playerIntegralDetailService; + private final RedisCache redisCache; + Interner pool = Interners.newWeakInterner(); + + @Override + @Transactional(rollbackFor = Exception.class) + public int saveIntegral(Integer num, Integer playerId, String remark){ + synchronized (pool.intern("integral-".concat(playerId.toString()))) { + int numR = 0; + Date now = new Date(); + PlayerIntegral playerIntegral = baseMapper.selectOne(new LambdaQueryWrapper().eq(PlayerIntegral::getUserId, playerId).last("limit 1")); + if(playerIntegral == null) { + playerIntegral = PlayerIntegral.builder().createTime(now).userId(playerId).num(num).build(); + numR = baseMapper.insert(playerIntegral); + } else { + playerIntegral.setNum(playerIntegral.getNum() + num); + numR = baseMapper.update(null, new LambdaUpdateWrapper().set(PlayerIntegral::getNum, playerIntegral.getNum()).set(PlayerIntegral::getVersion, playerIntegral.getVersion() + 1).eq(PlayerIntegral::getId, playerIntegral.getId())); + } + if(numR > 0){ + PlayerIntegralDetail playerIntegralDetail = PlayerIntegralDetail.builder().createTime(now).num(num).userId(playerId).remark(remark).build(); + playerIntegralDetailService.save(playerIntegralDetail); + return playerIntegral.getNum(); + } else { + return 0; + } + } + } + + @Override + public void initRankList(Integer beginNum){ + List list = baseMapper.getIntegralRank(beginNum); + if(CollectionUtils.isEmpty(list)){ + return; + } + redisCache.deleteByPrefix(StaticUtil.INTEGRAL_RANK_KEY); + BoundZSetOperations operations = redisCache.redisTemplate.boundZSetOps(StaticUtil.INTEGRAL_RANK_KEY); + for (RankInitModel item : list){ + RankModel rankModel = RankModel.builder().userId(item.getUserId()).userName(item.getUserName()).build(); + operations.add(rankModel, item.getNum()); + } + } +} diff --git a/mainland/src/main/java/com/lightyears/mainland/util/CronUtils.java b/mainland/src/main/java/com/lightyears/mainland/util/CronUtils.java new file mode 100644 index 0000000..c04277a --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/util/CronUtils.java @@ -0,0 +1,37 @@ +package com.lightyears.mainland.util; + +import cn.hutool.core.date.DateTime; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Objects; + +/** + * 日期转换cron表达式 + */ +public class CronUtils { + + /*** + * 功能描述:日期转换cron表达式 + * @param dateStr + * @return + */ + public static String formatDateByPattern(String dateStr) { + String formatTimeStr = null; + if (Objects.nonNull(dateStr)) { + LocalDateTime time = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + formatTimeStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ?")); + } + return formatTimeStr; + } + + /*** + * @param dateTime : 时间点 + * @return + */ + public static String getCron(DateTime dateTime) { + return formatDateByPattern(dateTime.toString()); + } + +} + diff --git a/mainland/src/main/java/com/lightyears/mainland/util/GetBeanUtil.java b/mainland/src/main/java/com/lightyears/mainland/util/GetBeanUtil.java new file mode 100644 index 0000000..22c9481 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/util/GetBeanUtil.java @@ -0,0 +1,26 @@ +package com.lightyears.mainland.util; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class GetBeanUtil implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + public void setApplicationContext(ApplicationContext context) { + GetBeanUtil.applicationContext = context; + } + + public static Object getBean(String name) { + return applicationContext.getBean(name); + } + + public static Object getBean(Class classObj) { + return applicationContext.getBean(classObj); + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } +} \ No newline at end of file diff --git a/mainland/src/main/java/com/lightyears/mainland/util/MD5Utils.java b/mainland/src/main/java/com/lightyears/mainland/util/MD5Utils.java new file mode 100644 index 0000000..1c41726 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/util/MD5Utils.java @@ -0,0 +1,51 @@ +package com.lightyears.mainland.util; + +import java.security.MessageDigest; + +/** + * Created by tanhao on 2019/3/18. + */ +public class MD5Utils { + private static final String hexDigIts[] = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"}; + + /** + * MD5加密 + * @param origin 字符 + * @param charsetname 编码 UTF-8 + * @return + */ + public static String MD5Encode(String origin, String charsetname){ + String resultString = null; + try{ + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if(null == charsetname || "".equals(charsetname)){ + resultString = byteArrayToHexString(md.digest(resultString.getBytes())); + }else{ + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + }catch (Exception e){ + } + return resultString; + } + + + public static String byteArrayToHexString(byte b[]){ + StringBuffer resultSb = new StringBuffer(); + for(int i = 0; i < b.length; i++){ + resultSb.append(byteToHexString(b[i])); + } + return resultSb.toString(); + } + + public static String byteToHexString(byte b){ + int n = b; + if(n < 0){ + n += 256; + } + int d1 = n / 16; + int d2 = n % 16; + return hexDigIts[d1] + hexDigIts[d2]; + } + +} diff --git a/mainland/src/main/java/com/lightyears/mainland/util/RedisCache.java b/mainland/src/main/java/com/lightyears/mainland/util/RedisCache.java new file mode 100644 index 0000000..24d7805 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/util/RedisCache.java @@ -0,0 +1,231 @@ +package com.lightyears.mainland.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * spring redis 工具类 + **/ +@Component +public class RedisCache { + + @Autowired + public RedisTemplate redisTemplate; + + /** + * 判断key是否存在 + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + */ + public void setCacheObject(final String key, final T value) { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param timeout 时间 + * @param timeUnit 时间颗粒度 + */ + public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout) { + return expire(key, timeout, TimeUnit.SECONDS); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @param unit 时间单位 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout, final TimeUnit unit) { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return 缓存键值对应的数据 + */ + public T getCacheObject(final String key) { + ValueOperations operation = redisTemplate.opsForValue(); + return operation.get(key); + } + + /** + * 删除单个对象 + * + * @param key + */ + public boolean deleteObject(final String key) { + return redisTemplate.delete(key); + } + + /** + * 删除指定前缀的缓存 + * @param key + * @return + */ + public Long deleteByPrefix(final String key) { + Set keys = redisTemplate.keys(key.concat("*")); + return redisTemplate.delete(keys); + } + + /** + * 删除集合对象 + * + * @param collection 多个对象 + * @return + */ + public long deleteObject(final Collection collection) { + return redisTemplate.delete(collection); + } + + /** + * 缓存List数据 + * + * @param key 缓存的键值 + * @return 缓存的对象 + */ + public long setCacheList(final String key, final List dataList) { + Long count = redisTemplate.opsForList().rightPushAll(key, dataList); + return count == null ? 0 : count; + } + + /** + * 获得缓存的list对象 + * + * @param key 缓存的键值 + * @return 缓存键值对应的数据 + */ + public List getCacheList(final String key) { + return redisTemplate.opsForList().range(key, 0, -1); + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public long setCacheSet(final String key, final Set dataSet) { + Long count = redisTemplate.opsForSet().add(key, dataSet); + return count == null ? 0 : count; + } + + /** + * 获得缓存的set + * + * @param key + * @return + */ + public Set getCacheSet(final String key) { + return redisTemplate.opsForSet().members(key); + } + + /** + * 缓存Map + * + * @param key + * @param dataMap + */ + public void setCacheMap(final String key, final Map dataMap) { + if (dataMap != null) { + redisTemplate.opsForHash().putAll(key, dataMap); + } + } + + /** + * 获得缓存的Map + * + * @param key + * @return + */ + public Map getCacheMap(final String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 往Hash中存入数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @param value 值 + */ + public void setCacheMapValue(final String key, final String hKey, final T value) { + redisTemplate.opsForHash().put(key, hKey, value); + } + + /** + * 获取Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public T getCacheMapValue(final String key, final String hKey) { + HashOperations opsForHash = redisTemplate.opsForHash(); + return opsForHash.get(key, hKey); + } + + /** + * 获取多个Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键集合 + * @return Hash对象集合 + */ + public List getMultiCacheMapValue(final String key, final Collection hKeys) { + return redisTemplate.opsForHash().multiGet(key, hKeys); + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public Collection keys(final String pattern) { + return redisTemplate.keys(pattern); + } +} \ No newline at end of file diff --git a/mainland/src/main/java/com/lightyears/mainland/util/ResultUtil.java b/mainland/src/main/java/com/lightyears/mainland/util/ResultUtil.java new file mode 100644 index 0000000..d29bace --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/util/ResultUtil.java @@ -0,0 +1,44 @@ +package com.lightyears.mainland.util; + +import cn.hutool.crypto.digest.MD5; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.lightyears.common.domain.dto.ResModeBase; +import com.lightyears.common.domain.enums.MessageEnum; +import lombok.extern.slf4j.Slf4j; + +/** + * 返回 数据 指定数据结构 + * + * @author Melody + */ +@Slf4j +public class ResultUtil { + public static final ObjectMapper mapper = new ObjectMapper(); + public static ResModeBase result(int code, String mes) { + return result(code, mes, null); + } + + public static ResModeBase result(int code, String mes, Object data) { + String key = ""; + String dataStr = ""; + if(data == null){ + key = MD5.create().digestHex(MD5.create().digestHex(StaticUtil.PRIVATE_KEY)); + } else { + try { + if (data instanceof String){ + dataStr = data.toString(); + } else { + dataStr = mapper.writeValueAsString(data); + } + key = MD5.create().digestHex(MD5.create().digestHex(dataStr.concat(StaticUtil.PRIVATE_KEY))); + }catch (JsonProcessingException ex){ + log.error("json解析错误", ex); + return new ResModeBase(MessageEnum.SERVER_ERROR.getCode(), MessageEnum.SERVER_ERROR.getMessage(), key, null); + } + + } + return new ResModeBase(code, mes, key, data); + } + +} diff --git a/mainland/src/main/java/com/lightyears/mainland/util/ScheduledFutureHolder.java b/mainland/src/main/java/com/lightyears/mainland/util/ScheduledFutureHolder.java new file mode 100644 index 0000000..92c10a0 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/util/ScheduledFutureHolder.java @@ -0,0 +1,46 @@ +package com.lightyears.mainland.util; +import java.util.concurrent.ScheduledFuture; + +/** + * 任务执行的包装类 + */ +public class ScheduledFutureHolder { + private ScheduledFuture scheduledFuture; + + private Class runnableClass; + + private String corn; + + public ScheduledFuture getScheduledFuture() { + return scheduledFuture; + } + + public void setScheduledFuture(ScheduledFuture scheduledFuture) { + this.scheduledFuture = scheduledFuture; + } + + public Class getRunnableClass() { + return runnableClass; + } + + public void setRunnableClass(Class runnableClass) { + this.runnableClass = runnableClass; + } + + public String getCorn() { + return corn; + } + + public void setCorn(String corn) { + this.corn = corn; + } + + @Override + public String toString() { + return "ScheduledFutureHolder{" + + "scheduledFuture=" + scheduledFuture + + ", runnableClass=" + runnableClass + + ", corn='" + corn + '\'' + + '}'; + } +} diff --git a/mainland/src/main/java/com/lightyears/mainland/util/SpecialTool.java b/mainland/src/main/java/com/lightyears/mainland/util/SpecialTool.java new file mode 100644 index 0000000..79e35c5 --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/util/SpecialTool.java @@ -0,0 +1,50 @@ +package com.lightyears.mainland.util; + +import java.util.List; +import java.util.Map; + +/** + * 文 件 名 : 特殊处理工具 + * 创 建 人:HL + * 日 期:2019-8-12 + * 修 改 人:HL + * 日 期:2019-8-12 + * 描 述: 分页、 + * 版 本 号:2.0 + */ +public class SpecialTool { + public static SpecialTool specialTool = new SpecialTool(); + + //时间格式 + public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + + //集合判断是否为空 + + public boolean ifGather(Object o) { + if ((o instanceof List && null == o) || (o instanceof Map && null == o)) { + return true; + } + return false; + } + + //字符串判断是否为空 + public boolean isEmpty(String s) { + if (null == s || s.equals("")) { + return true; + } + return false; + } + + + /** + * 将字符串的首字母转大写 + * @param str 需要转换的字符串 + * @return + */ + private static String captureName(String str) { + // 进行字母的ascii编码前移,效率要高于截取字符串进行转换的操作 + char[] cs=str.toCharArray(); + cs[0]-=32; + return String.valueOf(cs); + } +} diff --git a/mainland/src/main/java/com/lightyears/mainland/util/StaticUtil.java b/mainland/src/main/java/com/lightyears/mainland/util/StaticUtil.java new file mode 100644 index 0000000..76c874c --- /dev/null +++ b/mainland/src/main/java/com/lightyears/mainland/util/StaticUtil.java @@ -0,0 +1,28 @@ +package com.lightyears.mainland.util; + + +/** + * 静态工具栏 :目前数据较小 且又想减少服务器压力,特建此类 做静态缓存 + */ +public class StaticUtil { + // ------------------------系统类----------------------- + // 数据加解密盐 + public static final String PRIVATE_KEY = "123144123"; + + // ---------------------------------redis ----------------------------------------- + // 在线用户信息 + public static final String ONLINE_USER_PUBLIC_KEY="mineClearance:onlineUser:"; + // 在线用户TOKEN + public static final String ONLINE_USER_TOKEN="mineClearance:onlineToken:"; + + // 闯关排行 + // 雷神大陆模式 位阶积分区间key + public static final String SYS_INTEGRAL_INTERVAL = "mineClearance:sys:integralInterval"; + // 雷神大陆模式 积分排名基础榜 + public static final String INTEGRAL_RANK_KEY = "mineClearance:mainland:integral:baseRank"; + // 雷神大陆模式 游戏录像信息缓存 + public static final String MAINLAND_GAME_INFO_KEY = "mineClearance:mainland:gameInfo:"; + // 日积分榜 + public static final String MAINLAND_DAY_RANK = "mineClearance:mainland:dayRank"; + +} diff --git a/mainland/src/main/resources/application-dev.yml b/mainland/src/main/resources/application-dev.yml new file mode 100644 index 0000000..115ab05 --- /dev/null +++ b/mainland/src/main/resources/application-dev.yml @@ -0,0 +1,67 @@ +qbs-switch: + swagger-open: true #swagger开关(true:打开, false:关闭) +spring: + application: + name: mine-clearance-maindland + main: + allow-bean-definition-overriding: true + allow-circular-references: true + # 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题 + jackson: + time-zone: GMT+8 + datasource: + username: root + password: 43626546 + url: jdbc:mysql://localhost:3306/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 20 + max-active: 80 + min-idle: 20 + max-wait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictabkeIdleTimeMillis: 1800000 + validationQuery: SELECT 1 + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + # 配置监控统计拦截的filters,去掉后监控界面sql无法统计。‘wall’用于防火墙 + filters: stat,wall + # cloud: + # nacos: + # discovery: + # server-addr: localhost:8848 + redis: + # Redis服务器地址 + host: localhost + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + password: 123456 + # 连接超时时间 + timeout: 1000ms + lettuce: + pool: + # 连接池最大连接数 + max-active: 8 + # 连接池最大空闲连接数 + max-idle: 8 + # 连接池最小空闲连接数 + min-idle: 0 + # 连接池最大阻塞等待时间,负值表示没有限制 + max-wait: -1ms +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + type-aliases-package: com.lightyears.common.domain + global-config: + banner: false + db-config: + id-type: input + configuration: + # 控制台SQL日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: false \ No newline at end of file diff --git a/mainland/src/main/resources/application-prod.yml b/mainland/src/main/resources/application-prod.yml new file mode 100644 index 0000000..94dc2fa --- /dev/null +++ b/mainland/src/main/resources/application-prod.yml @@ -0,0 +1,73 @@ +qbs-switch: + swagger-open: true #swagger开关(true:打开, false:关闭) +spring: + application: + name: mine-clearance-maindland + main: + allow-bean-definition-overriding: true + allow-circular-references: true + # 全局配置响应日期格式和时区为东八区,解决日期类型返回前端少八个小时的问题 + jackson: + time-zone: GMT+8 + datasource: + username: root + # password: 1476346288@mysql + password: 1813547935mysql + # 基础 + url: jdbc:mysql://127.0.0.1:3306/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull + # 本地 + # url: jdbc:mysql://39.106.21.14:3986/saolei_v2_db?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true + driver-class-name: com.mysql.cj.jdbc.Driver + type: com.alibaba.druid.pool.DruidDataSource + druid: + initial-size: 20 + max-active: 80 + min-idle: 20 + max-wait: 60000 + timeBetweenEvictionRunsMillis: 60000 + minEvictabkeIdleTimeMillis: 1800000 + validationQuery: SELECT 1 + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + # 配置监控统计拦截的filters,去掉后监控界面sql无法统计。‘wall’用于防火墙 + filters: stat,wall + # cloud: + # nacos: + # discovery: + # server-addr: localhost:8848 + redis: + # Redis服务器地址 + host: localhost + # Redis数据库索引(默认为0) + database: 0 + # Redis服务器连接端口 + port: 6379 + # Redis服务器连接密码(默认为空) + # password: 1476346288@redis + password: 123456 + # 连接超时时间 + timeout: 1000ms + lettuce: + pool: + # 连接池最大连接数 + max-active: 8 + # 连接池最大空闲连接数 + max-idle: 8 + # 连接池最小空闲连接数 + min-idle: 0 + # 连接池最大阻塞等待时间,负值表示没有限制 + # max-wait: -1ms + max-wait: 3 +mybatis-plus: + mapper-locations: classpath*:mapper/**/*Mapper.xml + type-aliases-package: com.lightyears.common.domain + global-config: + banner: false + db-config: + id-type: input + configuration: + # 控制台SQL日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: false \ No newline at end of file diff --git a/mainland/src/main/resources/application.yml b/mainland/src/main/resources/application.yml new file mode 100644 index 0000000..87855dc --- /dev/null +++ b/mainland/src/main/resources/application.yml @@ -0,0 +1,11 @@ +server: + port: 18631 + tomcat: + uri-encoding: UTF-8 +logging: + config: classpath:log.xml +spring: + profiles: + active: prod +appconfig: + version: 197.0 \ No newline at end of file diff --git a/mainland/src/main/resources/log.xml b/mainland/src/main/resources/log.xml new file mode 100644 index 0000000..9c566c7 --- /dev/null +++ b/mainland/src/main/resources/log.xml @@ -0,0 +1,51 @@ + + + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + logs/mainland/sys.log + + + + + + logs/mainland/sys.%d.%i.log + + 30 + + + 10MB + + + + + + %d %p (%file:%line\)- %m%n + + + UTF-8 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mainland/src/main/resources/mapper/MainlandLogMapper.xml b/mainland/src/main/resources/mapper/MainlandLogMapper.xml new file mode 100644 index 0000000..091c5b2 --- /dev/null +++ b/mainland/src/main/resources/mapper/MainlandLogMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/mainland/src/main/resources/mapper/PlayerIntegralDetailMapper.xml b/mainland/src/main/resources/mapper/PlayerIntegralDetailMapper.xml new file mode 100644 index 0000000..56a6820 --- /dev/null +++ b/mainland/src/main/resources/mapper/PlayerIntegralDetailMapper.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/mainland/src/main/resources/mapper/PlayerIntegralMapper.xml b/mainland/src/main/resources/mapper/PlayerIntegralMapper.xml new file mode 100644 index 0000000..816481f --- /dev/null +++ b/mainland/src/main/resources/mapper/PlayerIntegralMapper.xml @@ -0,0 +1,18 @@ + + + + + \ No newline at end of file diff --git a/mainland/src/main/resources/mapper/PlayerMapper.xml b/mainland/src/main/resources/mapper/PlayerMapper.xml new file mode 100644 index 0000000..439bccd --- /dev/null +++ b/mainland/src/main/resources/mapper/PlayerMapper.xml @@ -0,0 +1,4 @@ + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..3cfbd86 --- /dev/null +++ b/pom.xml @@ -0,0 +1,113 @@ + + + + 4.0.0 + + com.lightyears.mine_clearance + mine_clearance + pom + 1.0 + + basics + challenge + common + admin + mainland + + + mine_clearance + + + org.springframework.boot + spring-boot-starter-parent + 2.6.4 + + + + + 3.5.1 + 1.1.10 + 1.2.83 + 1.4.1 + 2.3.30 + 2.2.1 + 5.7.22 + 2.5 + 4.4 + + + + + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + com.github.jsqlparser + jsqlparser + + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + com.alibaba + fastjson + ${fastjson.version} + + + com.baomidou + mybatis-plus-generator + ${mybatis-plus.version} + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.version} + + + + org.freemarker + freemarker + ${freemaker.version} + + + + org.apache.rocketmq + rocketmq-spring-boot-starter + ${rocketmq.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + commons-io + commons-io + ${commons-io.version} + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + com.lightyears.mine_clearance + common + ${project.version} + + + +