From 24003857e7538d06df6004dbb1e20be2fb40caf2 Mon Sep 17 00:00:00 2001 From: wangfukang <15630117759@163.com> Date: Tue, 9 Jun 2026 18:31:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E6=8B=BC=E5=9B=A2=E6=95=B0?= =?UTF-8?q?=E6=8D=AE1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hiver-admin/test-output/test-report.html | 16 +- .../constant/DealingsRecordConstant.java | 2 +- .../planet/controller/PlanetController.java | 51 ++++- .../mall/planet/pojo/PlanetDailyLoopVo.java | 2 + .../hiver/mall/planet/pojo/PlanetHomeVo.java | 4 + .../mall/planet/pojo/PlanetRankItemVo.java | 3 + .../service/PlanetAdventurePkService.java | 7 +- .../planet/service/PlanetDrawService.java | 6 + .../mall/planet/service/PlanetService.java | 5 + .../service/impl/PlanetAdminServiceImpl.java | 44 ++++ .../impl/PlanetAdventurePkServiceImpl.java | 193 ++++++++++++++---- .../service/impl/PlanetBoxServiceImpl.java | 12 -- .../service/impl/PlanetDrawServiceImpl.java | 149 +++++++++++--- .../impl/PlanetOperateServiceImpl.java | 1 + .../service/impl/PlanetRankServiceImpl.java | 55 +++-- .../service/impl/PlanetServiceImpl.java | 142 ++++++++++--- .../service/impl/PlanetTicketServiceImpl.java | 28 --- .../hiver/mall/quartz/GroupBuyExpireTask.java | 37 ++-- .../quartz/PlanetAdventureSettleTask.java | 98 ++++++++- .../mall/quartz/PlanetDailyResetTask.java | 22 +- .../cc/hiver/mall/quartz/PlanetDrawTask.java | 6 +- .../mall/quartz/PlanetOperateSettleTask.java | 134 +----------- 22 files changed, 681 insertions(+), 336 deletions(-) diff --git a/hiver-admin/test-output/test-report.html b/hiver-admin/test-output/test-report.html index 430b10b6..e979ce1a 100644 --- a/hiver-admin/test-output/test-report.html +++ b/hiver-admin/test-output/test-report.html @@ -35,7 +35,7 @@ Hiver
  • -ÁùÔÂ 05, 2026 16:39:30 +ÁùÔÂ 09, 2026 18:01:00
  • @@ -84,7 +84,7 @@

    passTest

    -

    16:39:31 ÏÂÎç / 0.017 secs

    +

    18:01:01 ÏÂÎç / 0.021 secs

    @@ -92,9 +92,9 @@
    #test-id=1
    passTest
    -06.05.2026 16:39:31 -06.05.2026 16:39:31 -0.017 secs +06.09.2026 18:01:01 +06.09.2026 18:01:01 +0.021 secs
    @@ -104,7 +104,7 @@ Pass - 16:39:31 + 18:01:01 Test passed @@ -128,13 +128,13 @@

    Started

    -

    ÁùÔÂ 05, 2026 16:39:30

    +

    ÁùÔÂ 09, 2026 18:01:00

    Ended

    -

    ÁùÔÂ 05, 2026 16:39:31

    +

    ÁùÔÂ 09, 2026 18:01:01

    diff --git a/hiver-core/src/main/java/cc/hiver/core/common/constant/DealingsRecordConstant.java b/hiver-core/src/main/java/cc/hiver/core/common/constant/DealingsRecordConstant.java index 571472ea..dd0a7b53 100644 --- a/hiver-core/src/main/java/cc/hiver/core/common/constant/DealingsRecordConstant.java +++ b/hiver-core/src/main/java/cc/hiver/core/common/constant/DealingsRecordConstant.java @@ -15,7 +15,7 @@ public interface DealingsRecordConstant { /** * */ - String[] TYPE_REMARK = {"é…é€è®¢å•佣金","å”®åŽé€€æ¬¾","é…逿ޒå奖励","商家æçް","é…é€å‘˜æçް","å…å•奖励","商家结算","用户æçް","白嫖中奖"}; + String[] TYPE_REMARK = {"é…é€è®¢å•佣金","å”®åŽé€€æ¬¾","é…逿ޒå奖励","商家æçް","é…é€å‘˜æçް","å…å•奖励","商家结算","用户æçް","白嫖中奖","学院排ä½èµ›æŽ’å奖励"}; /** *交易类型:0:增加 1 æçް 2消费 3å”®åŽ diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java index ecbba0a7..36723e2a 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java @@ -4,10 +4,7 @@ import cc.hiver.core.common.exception.HiverException; import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.vo.Result; import cc.hiver.mall.planet.entity.PlanetDrawRecord; -import cc.hiver.mall.planet.pojo.PlanetBoxResultVo; -import cc.hiver.mall.planet.pojo.PlanetHomeVo; -import cc.hiver.mall.planet.pojo.PlanetHuntResultVo; -import cc.hiver.mall.planet.pojo.PlanetQuery; +import cc.hiver.mall.planet.pojo.*; import cc.hiver.mall.planet.service.*; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -91,6 +88,23 @@ public class PlanetController { } } + @ApiOperation(value = "星çƒè¡¥ç»™åœ°å›¾èšåˆæ•°æ®") + @RequestMapping(value = "/supply", method = RequestMethod.POST) + public Result supply(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getUserId())) { + return ResultUtil.error("用户idä¸èƒ½ä¸ºç©º"); + } + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + try { + final PlanetHomeVo vo = planetService.supply(query); + return new ResultUtil().setData(vo); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + @ApiOperation(value = "通缉榜TOP10") @RequestMapping(value = "/rank", method = RequestMethod.POST) public Result rank(@RequestBody PlanetQuery query) { @@ -100,6 +114,23 @@ public class PlanetController { return new ResultUtil<>().setData(rankService.rankTop(query.getRegionId(), 10, query.getUserId())); } + @ApiOperation(value = "通缉榜分页") + @RequestMapping(value = "/rank/page", method = RequestMethod.POST) + public Result rankPage(@RequestBody PlanetQuery query) { + if (StringUtils.isEmpty(query.getRegionId())) { + return ResultUtil.error(REGION_REQUIRED); + } + final Map data = new HashMap<>(8); + final com.baomidou.mybatisplus.extension.plugins.pagination.Page page = + rankService.rankPage(query.getRegionId(), query.getPageNumber(), query.getPageSize(), query.getUserId()); + data.put("rankList", page.getRecords()); + data.put("rankTotal", page.getTotal()); + data.put("rankTotalPages", page.getPages()); + data.put("rankPageNumber", page.getCurrent()); + data.put("remainHunt", huntService.remainHunt(query.getUserId())); + return new ResultUtil<>().setData(data); + } + @ApiOperation(value = "å‘起追æ•") @RequestMapping(value = "/hunt", method = RequestMethod.POST) public Result hunt(@RequestBody PlanetQuery query) { @@ -211,6 +242,7 @@ public class PlanetController { final Map data = new HashMap<>(4); data.put("record", record); data.put("winners", record == null ? null : drawService.winnersOfDraw(record.getId())); + data.put("history", drawService.recentDrawResults(query.getRegionId(), 10)); return new ResultUtil<>().setData(data); } catch (HiverException e) { return ResultUtil.error(e.getMessage()); @@ -619,6 +651,17 @@ public class PlanetController { } } + @ApiOperation(value = "æ˜Ÿçƒæ“‚å°-房间实时信æ¯") + @RequestMapping(value = "/adventure/pk/roomInfo", method = RequestMethod.POST) + @Transactional(propagation = Propagation.NOT_SUPPORTED) + public Result adventurePkRoomInfo(@RequestBody PlanetQuery query) { + try { + return new ResultUtil<>().setData(adventurePkService.roomInfo(query.getUserId(), query.getRegionId(), query.getRoomId())); + } catch (HiverException e) { + return ResultUtil.error(e.getMessage()); + } + } + @ApiOperation(value = "åŠ å…¥æ˜Ÿçƒæ“‚å°æˆ¿é—´") @RequestMapping(value = "/adventure/pk/join", method = RequestMethod.POST) @Transactional(propagation = Propagation.NOT_SUPPORTED) diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetDailyLoopVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetDailyLoopVo.java index d932c240..7698857c 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetDailyLoopVo.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetDailyLoopVo.java @@ -15,7 +15,9 @@ public class PlanetDailyLoopVo implements Serializable { private static final long serialVersionUID = 1L; private Integer todayCollectedTickets; private Integer myPoolTickets; + private Integer myWeightTickets; private Integer poolTicketTotal; + private Integer poolWeightTotal; private Integer poolJoinCount; private BigDecimal myProbability; private Integer suggestedAddTickets; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHomeVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHomeVo.java index 19d8f4b6..646dc250 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHomeVo.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetHomeVo.java @@ -2,6 +2,7 @@ package cc.hiver.mall.planet.pojo; import cc.hiver.mall.planet.entity.PlanetDrawWinner; import cc.hiver.mall.planet.entity.PlanetNews; +import cc.hiver.mall.planet.entity.PlanetReward; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -38,6 +39,9 @@ public class PlanetHomeVo implements Serializable { @ApiModelProperty(value = "期å·") private String periodNo; + @ApiModelProperty(value = "本期奖项é…ç½®") + private List rewardList; + // ---------- 我的星çƒä¸­å¿ƒ ---------- @ApiModelProperty(value = "我的券数é‡") private Integer myTicketCount; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetRankItemVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetRankItemVo.java index 8b2cc0b8..81a6db71 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetRankItemVo.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetRankItemVo.java @@ -50,6 +50,9 @@ public class PlanetRankItemVo implements Serializable { @ApiModelProperty(value = "是å¦å¼€å¯é˜²æŠ¤ç½©") private Boolean shielded; + @ApiModelProperty(value = "æ˜¯å¦æ‹¥æœ‰é˜²å¾¡å¡”") + private Boolean hasTower; + @ApiModelProperty(value = "是å¦éšèº«") private Boolean stealth; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdventurePkService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdventurePkService.java index a85f503a..d79f3668 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdventurePkService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdventurePkService.java @@ -3,6 +3,7 @@ package cc.hiver.mall.planet.service; import cc.hiver.mall.planet.entity.PlanetAdventureChallenge; import cc.hiver.mall.planet.entity.PlanetAdventurePkPlayer; import cc.hiver.mall.planet.entity.PlanetAdventurePkRoom; +import cc.hiver.mall.planet.entity.PlanetAdventureSession; import cc.hiver.mall.planet.pojo.PlanetAdventureChallengeResultVo; import cc.hiver.mall.planet.pojo.PlanetAdventurePkHallVo; import cc.hiver.mall.planet.pojo.PlanetAdventurePkPlayVo; @@ -20,6 +21,8 @@ public interface PlanetAdventurePkService { Page hotRooms(String userId, String regionId, Integer pageNumber, Integer pageSize); + PlanetAdventurePkPlayVo roomInfo(String userId, String regionId, String roomId); + PlanetAdventurePkRoom createRoom(String userId, String regionId, String nickname, String avatar, String college, String roomName, Integer maxPlayers, Integer publicFlag, String password, Integer entryTickets); @@ -32,6 +35,8 @@ public interface PlanetAdventurePkService { PlanetAdventurePkPlayVo leaveRoom(String userId, String regionId, String roomId, Integer remainingCards); + int autoSettleOverdueRooms(); + PlanetAdventureChallenge createChallenge(String userId, String regionId, String nickname, String avatar, String college, Integer durationSeconds); @@ -41,5 +46,5 @@ public interface PlanetAdventurePkService { String college, String challengeId, Integer cleared, Integer durationSeconds, Integer remainingCards); - List gloryTop(String regionId); + List gloryTop(String regionId); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetDrawService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetDrawService.java index 2bdf4024..90ffad4c 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetDrawService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetDrawService.java @@ -7,6 +7,7 @@ import cc.hiver.mall.planet.entity.PlanetPoolTicket; import cc.hiver.mall.planet.pojo.PlanetDailyLoopVo; import java.util.List; +import java.util.Map; /** * 白嫖星çƒ-开奖æœåŠ¡ @@ -52,6 +53,11 @@ public interface PlanetDrawService { */ List winnersOfDraw(String drawId); + /** + * 最近若干期开奖åŠä¸­å¥–åå•,按商圈隔离。 + */ + List> recentDrawResults(String regionId, int limit); + /** * 我的中奖记录(仅陿œ¬å•†åœˆ) */ diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetService.java index d9293ee3..8c69c6b0 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetService.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetService.java @@ -14,4 +14,9 @@ public interface PlanetService { * 首页èšåˆæ•°æ® */ PlanetHomeVo home(PlanetQuery query); + + /** + * 星çƒè¡¥ç»™åœ°å›¾èšåˆæ•°æ® + */ + PlanetHomeVo supply(PlanetQuery query); } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java index b22f1645..0995eb0a 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java @@ -12,6 +12,8 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.UUID; @@ -75,6 +77,40 @@ public class PlanetAdminServiceImpl implements PlanetAdminService { return UUID.randomUUID().toString().replace("-", ""); } + private Date nextDrawTime(Date from) { + final Calendar c = Calendar.getInstance(); + c.setTime(from); + c.set(Calendar.HOUR_OF_DAY, 22); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + if (!c.getTime().after(from)) { + c.add(Calendar.DAY_OF_MONTH, 1); + } + return c.getTime(); + } + + private void refreshPoolRewardAmount(String poolId) { + if (StringUtils.isEmpty(poolId)) { + return; + } + final PlanetPool pool = poolMapper.selectById(poolId); + if (pool == null) { + return; + } + final List rewards = rewardMapper.selectList(new LambdaQueryWrapper() + .eq(PlanetReward::getPoolId, poolId)); + BigDecimal total = BigDecimal.ZERO; + for (PlanetReward reward : rewards) { + final BigDecimal amount = reward.getAmount() == null ? BigDecimal.ZERO : reward.getAmount(); + final int quota = reward.getQuota() == null ? 0 : reward.getQuota(); + total = total.add(amount.multiply(BigDecimal.valueOf(quota))); + } + pool.setPoolAmount(total); + pool.setUpdateTime(new Date()); + poolMapper.updateById(pool); + } + private Page page(PageVo pageVo) { final int num = pageVo == null || pageVo.getPageNumber() <= 0 ? 1 : pageVo.getPageNumber(); final int size = pageVo == null || pageVo.getPageSize() <= 0 ? 10 : pageVo.getPageSize(); @@ -110,6 +146,9 @@ public class PlanetAdminServiceImpl implements PlanetAdminService { if (pool.getWinnerCount() == null) { pool.setWinnerCount(0); } + if (pool.getDrawTime() == null) { + pool.setDrawTime(nextDrawTime(new Date())); + } pool.setCreateTime(new Date()); pool.setUpdateTime(new Date()); poolMapper.insert(pool); @@ -144,12 +183,17 @@ public class PlanetAdminServiceImpl implements PlanetAdminService { } else { rewardMapper.updateById(reward); } + refreshPoolRewardAmount(reward.getPoolId()); return reward; } @Override public void deleteReward(String id) { + final PlanetReward reward = rewardMapper.selectById(id); rewardMapper.deleteById(id); + if (reward != null) { + refreshPoolRewardAmount(reward.getPoolId()); + } } @Override diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventurePkServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventurePkServiceImpl.java index 84c532b6..7c967f34 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventurePkServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventurePkServiceImpl.java @@ -25,6 +25,8 @@ import java.util.UUID; @Service public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { + private static final int AUTO_FAIL_REMAINING_CARDS = 999999; + @Autowired private PlanetAdventurePkRoomMapper roomMapper; @Autowired @@ -85,6 +87,23 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { .orderByDesc(PlanetAdventurePkRoom::getCreateTime)); } + @Override + public PlanetAdventurePkPlayVo roomInfo(String userId, String regionId, String roomId) { + if (StringUtils.isEmpty(userId)) throw new HiverException("用户idä¸èƒ½ä¸ºç©º"); + PlanetAdventurePkRoom room = mustRoom(roomId, regionId); + PlanetAdventurePkPlayer player = playerMapper.selectOne(new LambdaQueryWrapper() + .eq(PlanetAdventurePkPlayer::getRoomId, roomId) + .eq(PlanetAdventurePkPlayer::getUserId, userId) + .last("limit 1")); + PlanetAdventurePkPlayVo vo = new PlanetAdventurePkPlayVo(); + vo.setMode("pk"); + vo.setRoomId(room.getId()); + vo.setSeed(room.getRoomSeed()); + vo.setRoom(room); + vo.setPlayer(player); + return vo; + } + @Override @Transactional(rollbackFor = Exception.class) public PlanetAdventurePkRoom createRoom(String userId, String regionId, String nickname, String avatar, @@ -93,8 +112,11 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { require(userId, regionId); int players = maxPlayers == null ? 2 : Math.max(2, Math.min(5, maxPlayers)); int tickets = entryTickets == null ? 1 : Math.max(1, entryTickets); + String roomId = genId(); + ticketService.deductTickets(userId, regionId, tickets, + PlanetConstant.TICKET_TYPE_ADVENTURE_PK_ENTRY, roomId + "_" + userId, "æ˜Ÿçƒæ“‚å°å¼€æˆ¿å…¥åœºåˆ¸"); PlanetAdventurePkRoom room = new PlanetAdventurePkRoom(); - room.setId(genId()); + room.setId(roomId); room.setRoomName(StringUtils.isEmpty(roomName) ? "æ˜Ÿçƒæ“‚å°æˆ¿é—´" : roomName.trim()); room.setRegionId(regionId); room.setOwnerUserId(userId); @@ -106,11 +128,13 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { room.setPassword(password); room.setEntryTickets(tickets); room.setStatus(PlanetConstant.ADVENTURE_PK_ROOM_WAITING); - room.setPoolTickets(0); - room.setPlayerCount(0); + room.setPoolTickets(tickets); + room.setPlayerCount(1); room.setCreateTime(new Date()); room.setUpdateTime(new Date()); roomMapper.insert(room); + PlanetAdventurePkPlayer owner = newPkPlayer(roomId, regionId, userId, nickname, avatar, college, tickets); + playerMapper.insert(owner); return room; } @@ -141,22 +165,7 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { if (count >= room.getMaxPlayers()) throw new HiverException("房间人数已满"); ticketService.deductTickets(userId, regionId, room.getEntryTickets(), PlanetConstant.TICKET_TYPE_ADVENTURE_PK_ENTRY, roomId + "_" + userId, "æ˜Ÿçƒæ“‚å°å…¥åœºåˆ¸"); - PlanetAdventurePkPlayer player = new PlanetAdventurePkPlayer(); - player.setId(genId()); - player.setRoomId(roomId); - player.setRegionId(regionId); - player.setUserId(userId); - player.setNickname(nickname); - player.setAvatar(avatar); - player.setCollege(college); - player.setEntryTickets(room.getEntryTickets()); - player.setStatus(PlanetConstant.ADVENTURE_PK_PLAYER_PLAYING); - player.setCleared(0); - player.setRankNo(0); - player.setRewardTickets(0); - player.setStartTime(new Date()); - player.setCreateTime(new Date()); - player.setUpdateTime(new Date()); + PlanetAdventurePkPlayer player = newPkPlayer(roomId, regionId, userId, nickname, avatar, college, room.getEntryTickets()); playerMapper.insert(player); room.setPlayerCount(count + 1); room.setPoolTickets(nz(room.getPoolTickets()) + room.getEntryTickets()); @@ -172,6 +181,9 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { Integer durationSeconds, Integer remainingSeconds, Integer remainingCards) { if (StringUtils.isEmpty(userId)) throw new HiverException("用户idä¸èƒ½ä¸ºç©º"); PlanetAdventurePkRoom room = mustRoom(roomId, regionId); + if (room.getStatus() == PlanetConstant.ADVENTURE_PK_ROOM_SETTLED) { + throw new HiverException("房间已结算,无法æäº¤æˆç»©"); + } PlanetAdventurePkPlayer player = mustPlayer(roomId, userId); if (terminal(player)) throw new HiverException("本房间æˆç»©å·²æäº¤"); player.setCleared(cleared != null && cleared == 1 ? 1 : 0); @@ -192,6 +204,26 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { return submitRoom(userId, regionId, roomId, 0, 0, 0, remainingCards); } + @Override + @Transactional(rollbackFor = Exception.class) + public int autoSettleOverdueRooms() { + Date deadline = new Date(System.currentTimeMillis() - 30L * 60 * 1000); + List rooms = roomMapper.selectList(new LambdaQueryWrapper() + .in(PlanetAdventurePkRoom::getStatus, PlanetConstant.ADVENTURE_PK_ROOM_WAITING, PlanetConstant.ADVENTURE_PK_ROOM_PLAYING) + .lt(PlanetAdventurePkRoom::getCreateTime, deadline)); + int settled = 0; + for (PlanetAdventurePkRoom room : rooms) { + try { + if (settleOverdue(room)) { + settled++; + } + } catch (Exception ignored) { + // å•个房间异常ä¸å½±å“åŽç»­æˆ¿é—´ï¼Œå¤–层任务会记录总é‡ã€‚ + } + } + return settled; + } + @Override public PlanetAdventureChallenge createChallenge(String userId, String regionId, String nickname, String avatar, String college, Integer durationSeconds) { @@ -262,16 +294,71 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { .eq(PlanetAdventureSession::getStatus, PlanetConstant.ADVENTURE_SESSION_SUBMITTED) .eq(PlanetAdventureSession::getCheatFlag, "N") .orderByAsc(PlanetAdventureSession::getDurationSeconds) - .last("limit 3")); + .last("limit 5")); } private void settleIfReady(PlanetAdventurePkRoom room) { List players = playerMapper.selectList(new LambdaQueryWrapper() .eq(PlanetAdventurePkPlayer::getRoomId, room.getId())); - if (players.size() < room.getMaxPlayers()) return; for (PlanetAdventurePkPlayer p : players) { if (!terminal(p)) return; } + settleRoom(room, players, false); + } + + private boolean settleOverdue(PlanetAdventurePkRoom room) { + List players = playerMapper.selectList(new LambdaQueryWrapper() + .eq(PlanetAdventurePkPlayer::getRoomId, room.getId())); + if (players.isEmpty()) { + room.setStatus(PlanetConstant.ADVENTURE_PK_ROOM_SETTLED); + room.setSettleTime(new Date()); + room.setUpdateTime(new Date()); + roomMapper.updateById(room); + return true; + } + boolean noSubmitted = players.stream().noneMatch(this::terminal); + for (PlanetAdventurePkPlayer p : players) { + if (!terminal(p)) { + p.setStatus(PlanetConstant.ADVENTURE_PK_PLAYER_FAILED); + p.setCleared(0); + p.setDurationSeconds(0); + p.setRemainingSeconds(0); + p.setRemainingCards(AUTO_FAIL_REMAINING_CARDS); + p.setFinishTime(new Date()); + p.setUpdateTime(new Date()); + playerMapper.updateById(p); + } + } + List latestPlayers = playerMapper.selectList(new LambdaQueryWrapper() + .eq(PlanetAdventurePkPlayer::getRoomId, room.getId())); + settleRoom(room, latestPlayers, noSubmitted); + return true; + } + + private void settleRoom(PlanetAdventurePkRoom room, List players, boolean refundAll) { + if (players.size() == 1 && Objects.equals(players.get(0).getUserId(), room.getOwnerUserId())) { + PlanetAdventurePkPlayer owner = players.get(0); + ticketService.addTicketsWithoutBuff(owner.getUserId(), owner.getRegionId(), nz(owner.getEntryTickets()), + PlanetConstant.TICKET_TYPE_ADVENTURE_PK_REFUND, room.getId() + "_" + owner.getUserId(), "æ˜Ÿçƒæ“‚å°æ— äººå‚加退回"); + owner.setRewardTickets(nz(owner.getEntryTickets())); + owner.setRankNo(0); + owner.setUpdateTime(new Date()); + playerMapper.updateById(owner); + finishRoom(room, null); + return; + } + if (refundAll) { + for (PlanetAdventurePkPlayer p : players) { + ticketService.addTicketsWithoutBuff(p.getUserId(), p.getRegionId(), nz(p.getEntryTickets()), + PlanetConstant.TICKET_TYPE_ADVENTURE_PK_REFUND, room.getId() + "_" + p.getUserId(), "æ˜Ÿçƒæ“‚å°æ— äººæäº¤é€€å›ž"); + p.setRewardTickets(nz(p.getEntryTickets())); + p.setRankNo(0); + p.setUpdateTime(new Date()); + playerMapper.updateById(p); + } + finishRoom(room, null); + return; + } players.sort((a, b) -> { boolean ac = nz(a.getCleared()) == 1; boolean bc = nz(b.getCleared()) == 1; @@ -281,35 +368,59 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService { if (d != 0) return d; return Integer.compare(nz(b.getRemainingSeconds()), nz(a.getRemainingSeconds())); } - return Integer.compare(nz(a.getRemainingCards()), nz(b.getRemainingCards())); + int remain = Integer.compare(nz(a.getRemainingCards()), nz(b.getRemainingCards())); + if (remain != 0) return remain; + return Integer.compare(durationForRank(a), durationForRank(b)); }); boolean hasClear = players.stream().anyMatch(p -> nz(p.getCleared()) == 1); - if (!hasClear) { - for (PlanetAdventurePkPlayer p : players) { - ticketService.addTicketsWithoutBuff(p.getUserId(), p.getRegionId(), nz(p.getEntryTickets()), - PlanetConstant.TICKET_TYPE_ADVENTURE_PK_REFUND, room.getId() + "_" + p.getUserId(), "æ˜Ÿçƒæ“‚å°æ— äººé€šå…³é€€å›ž"); - p.setRewardTickets(nz(p.getEntryTickets())); - p.setRankNo(0); - playerMapper.updateById(p); - } - } else { - PlanetAdventurePkPlayer winner = players.get(0); - ticketService.addTicketsWithoutBuff(winner.getUserId(), winner.getRegionId(), nz(room.getPoolTickets()), - PlanetConstant.TICKET_TYPE_ADVENTURE_PK_REWARD, room.getId(), "æ˜Ÿçƒæ“‚å°ç¬¬ä¸€å通åƒå¥–æ± "); - for (int i = 0; i < players.size(); i++) { - PlanetAdventurePkPlayer p = players.get(i); - p.setRankNo(i + 1); - p.setRewardTickets(p.getUserId().equals(winner.getUserId()) ? nz(room.getPoolTickets()) : 0); - playerMapper.updateById(p); - } - room.setWinnerUserId(winner.getUserId()); + PlanetAdventurePkPlayer winner = players.get(0); + ticketService.addTicketsWithoutBuff(winner.getUserId(), winner.getRegionId(), nz(room.getPoolTickets()), + PlanetConstant.TICKET_TYPE_ADVENTURE_PK_REWARD, room.getId(), hasClear ? "æ˜Ÿçƒæ“‚å°ç¬¬ä¸€å通åƒå¥–æ± " : "æ˜Ÿçƒæ“‚å°æ¶ˆé™¤æœ€å¤šé€šåƒå¥–æ± "); + for (int i = 0; i < players.size(); i++) { + PlanetAdventurePkPlayer p = players.get(i); + p.setRankNo(i + 1); + p.setRewardTickets(p.getUserId().equals(winner.getUserId()) ? nz(room.getPoolTickets()) : 0); + p.setUpdateTime(new Date()); + playerMapper.updateById(p); } + finishRoom(room, winner.getUserId()); + } + + private void finishRoom(PlanetAdventurePkRoom room, String winnerUserId) { + room.setWinnerUserId(winnerUserId); room.setStatus(PlanetConstant.ADVENTURE_PK_ROOM_SETTLED); room.setSettleTime(new Date()); room.setUpdateTime(new Date()); roomMapper.updateById(room); } + private PlanetAdventurePkPlayer newPkPlayer(String roomId, String regionId, String userId, String nickname, + String avatar, String college, Integer entryTickets) { + PlanetAdventurePkPlayer player = new PlanetAdventurePkPlayer(); + player.setId(genId()); + player.setRoomId(roomId); + player.setRegionId(regionId); + player.setUserId(userId); + player.setNickname(nickname); + player.setAvatar(avatar); + player.setCollege(college); + player.setEntryTickets(entryTickets); + player.setStatus(PlanetConstant.ADVENTURE_PK_PLAYER_PLAYING); + player.setCleared(0); + player.setRankNo(0); + player.setRewardTickets(0); + player.setStartTime(new Date()); + player.setCreateTime(new Date()); + player.setUpdateTime(new Date()); + return player; + } + + private int durationForRank(PlanetAdventurePkPlayer player) { + if (nz(player.getDurationSeconds()) > 0) return nz(player.getDurationSeconds()); + if (nz(player.getRemainingSeconds()) > 0) return Math.max(0, 180 - nz(player.getRemainingSeconds())); + return Integer.MAX_VALUE; + } + private PlanetAdventurePkPlayVo playVo(PlanetAdventurePkRoom room, PlanetAdventurePkPlayer player) { PlanetAdventurePkPlayVo vo = new PlanetAdventurePkPlayVo(); vo.setMode("pk"); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBoxServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBoxServiceImpl.java index f191408d..356a686b 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBoxServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetBoxServiceImpl.java @@ -6,7 +6,6 @@ import cc.hiver.mall.planet.entity.PlanetTicket; import cc.hiver.mall.planet.mapper.PlanetTicketMapper; import cc.hiver.mall.planet.pojo.PlanetBoxResultVo; import cc.hiver.mall.planet.service.PlanetBoxService; -import cc.hiver.mall.planet.service.PlanetBuffService; import cc.hiver.mall.planet.service.PlanetNewsService; import cc.hiver.mall.planet.service.PlanetTicketService; import org.springframework.beans.factory.annotation.Autowired; @@ -31,9 +30,6 @@ public class PlanetBoxServiceImpl implements PlanetBoxService { @Autowired private PlanetTicketMapper ticketMapper; - @Autowired - private PlanetBuffService buffService; - @Autowired private PlanetNewsService newsService; @@ -83,14 +79,6 @@ public class PlanetBoxServiceImpl implements PlanetBoxService { vo.setMessage(name); } - private void grantBuff(String userId, String regionId, String type, String name, PlanetBoxResultVo vo) { - buffService.grantBuff(userId, regionId, type, "box"); - vo.setRewardType("buff"); - vo.setBuffType(type); - vo.setRewardName("获得「" + name + "ã€å¢žç›Š"); - vo.setMessage("幸è¿å®ç®±å¼€å‡ºã€Œ" + name + "ã€å¢žç›Š"); - } - private String safeName(String name) { return name == null || name.isEmpty() ? "神秘åŒå­¦" : name; } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java index ef757187..fa11266c 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java @@ -9,7 +9,10 @@ import cc.hiver.mall.planet.constant.PlanetConstant; import cc.hiver.mall.planet.entity.*; import cc.hiver.mall.planet.mapper.*; import cc.hiver.mall.planet.pojo.PlanetDailyLoopVo; -import cc.hiver.mall.planet.service.*; +import cc.hiver.mall.planet.service.PlanetDrawService; +import cc.hiver.mall.planet.service.PlanetNewsService; +import cc.hiver.mall.planet.service.PlanetTaskService; +import cc.hiver.mall.planet.service.PlanetTicketService; import cc.hiver.mall.service.mybatis.DealingsRecordService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; @@ -35,6 +38,8 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { /** æ¯æ—¥å¼€å¥–时刻(24å°æ—¶åˆ¶)ï¼Œåˆ°ç‚¹ç”±å®šæ—¶ä»»åŠ¡è‡ªåŠ¨å¼€å¥–ï¼Œæ¯æ—¥ä¸€æŠ½ */ private static final int DAILY_DRAW_HOUR = 22; + /** åŒä¸€ç”¨æˆ·ä¸­å¥–冷å´å¤©æ•°ï¼Œè®©æ›´å¤šåŒå­¦æœ‰æœºä¼šä¸­å¥– */ + private static final int WIN_COOLDOWN_DAYS = 7; @Autowired private PlanetPoolMapper poolMapper; @@ -60,9 +65,6 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { @Autowired private PlanetDrawWinnerMapper drawWinnerMapper; - @Autowired - private PlanetBuffService buffService; - @Autowired private PlanetNewsService newsService; @@ -132,7 +134,7 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { join.setCreateTime(new Date()); } join.setTickets((join.getTickets() == null ? 0 : join.getTickets()) + tickets); - join.setWeightTickets(join.getTickets()); + join.setWeightTickets(calcWeightTickets(join.getTickets())); join.setUpdateTime(new Date()); if (poolTicketMapper.selectById(join.getId()) == null) { poolTicketMapper.insert(join); @@ -155,10 +157,12 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { vo.setMyPoolTickets(myTickets); vo.setPoolTicketTotal(total); vo.setPoolJoinCount(countPoolJoin(pool.getId())); - vo.setMyProbability(probability(myTickets, total)); + final Integer totalWeight = sumPoolWeightTickets(pool.getId()); + final int myWeight = myJoin == null || myJoin.getWeightTickets() == null ? calcWeightTickets(myTickets) : myJoin.getWeightTickets(); + vo.setMyProbability(probability(myWeight, totalWeight)); final int suggested = myTickets <= 0 ? 3 : Math.min(10, Math.max(1, total / 20)); vo.setSuggestedAddTickets(suggested); - vo.setSuggestedProbability(probability(myTickets + suggested, total + suggested)); + vo.setSuggestedProbability(probability(calcWeightTickets(myTickets + suggested), totalWeight - myWeight + calcWeightTickets(myTickets + suggested))); vo.setMinutesToDraw(pool.getDrawTime() == null ? 0 : Math.max(0, (int) ((pool.getDrawTime().getTime() - System.currentTimeMillis()) / 60000L))); vo.setSignedToday(taskService.signedToday(userId, regionId)); vo.setBoxAvailable(boxAvailableQuick(userId, regionId)); @@ -178,7 +182,7 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { pool.setRegionId(regionId); pool.setPeriodNo(genPeriodNo()); pool.setTitle("白嫖星çƒÂ·æœ¬æœŸç“œåˆ†"); - pool.setPoolAmount(new BigDecimal("88.88")); + pool.setPoolAmount(BigDecimal.ZERO); pool.setDrawTime(nextDrawTime(now)); pool.setJoinCount(0); pool.setTicketTotal(0); @@ -190,6 +194,7 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { poolMapper.insert(pool); // 默认奖项 createDefaultRewards(pool); + refreshPoolRewardAmount(pool); return pool; } @@ -237,19 +242,17 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { final LambdaQueryWrapper rq = new LambdaQueryWrapper<>(); rq.eq(PlanetReward::getPoolId, poolId).orderByAsc(PlanetReward::getSort); final List rewards = rewardMapper.selectList(rq); + final BigDecimal poolAmount = sumRewardAmount(rewards); - // æ‰¹é‡æŸ¥è¯¢æ‰€æœ‰å‚与者的幸è¿ç³»æ•°ï¼Œä¸€æ¬¡æŸ¥åº“,é¿å…循环é€ä¸ªæŸ¥è¯¢ - final Set userIds = joins.stream().map(PlanetPoolTicket::getUserId).collect(Collectors.toCollection(LinkedHashSet::new)); - final Map luckyMap = buffService.luckyWeightFactors(userIds); - - // 构建加æƒå€™é€‰(æƒé‡= åˆ¸æ•°é‡ * 幸è¿ç³»æ•°) - final List poutPool = new ArrayList<>(); + // 构建加æƒå€™é€‰ï¼šæŠ•入券先按递å‡è§„则折算æƒé‡ï¼Œé˜²æ­¢å¤§æˆ·æ— é™å †åˆ¸åž„断。 + final List poolCandidates = new ArrayList<>(); int ticketTotal = 0; for (PlanetPoolTicket t : joins) { - final double factor = luckyMap.getOrDefault(t.getUserId(), 1.0); - final double weight = t.getTickets() * factor; - poutPool.add(new Candidate(t, weight)); - ticketTotal += t.getTickets(); + final int tickets = t.getTickets() == null ? 0 : t.getTickets(); + final int weightTickets = t.getWeightTickets() == null ? calcWeightTickets(tickets) : t.getWeightTickets(); + t.setWeightTickets(weightTickets); + poolCandidates.add(new Candidate(t, weightTickets)); + ticketTotal += tickets; } final Date now = new Date(); @@ -259,21 +262,24 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { record.setPoolId(pool.getId()); record.setRegionId(pool.getRegionId()); record.setPeriodNo(pool.getPeriodNo()); - record.setPoolAmount(pool.getPoolAmount()); + record.setPoolAmount(poolAmount); record.setJoinCount(joins.size()); record.setTicketTotal(ticketTotal); record.setStatus(1); record.setDrawTime(now); record.setCreateTime(now); + final Set cooldownUsers = recentWinnerUserIds(pool.getRegionId(), now); + boolean useCooldown = hasCandidate(poolCandidates, cooldownUsers); int winnerCount = 0; for (PlanetReward reward : rewards) { final int quota = reward.getQuota() == null ? 0 : reward.getQuota(); for (int i = 0; i < quota; i++) { - if (poutPoolEmpty(poutPool)) { + List usable = usableCandidates(poolCandidates, useCooldown ? cooldownUsers : Collections.emptySet()); + if (usable.isEmpty()) { break; } - final Candidate winner = pickWeighted(poutPoolUsable(poutPool)); + final Candidate winner = pickWeighted(usable); if (winner == null) { break; } @@ -290,6 +296,7 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { pool.setJoinCount(joins.size()); pool.setTicketTotal(ticketTotal); pool.setWinnerCount(winnerCount); + pool.setPoolAmount(poolAmount); pool.setUpdateTime(now); poolMapper.updateById(pool); @@ -327,6 +334,7 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { for (PlanetReward r : rewardMapper.selectList(rq)) { addReward(pool, r.getLevel(), r.getLevelName(), r.getAmount(), r.getQuota() == null ? 0 : r.getQuota(), r.getSort() == null ? 0 : r.getSort()); } + refreshPoolRewardAmount(pool); } @Override @@ -371,6 +379,24 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { return drawWinnerMapper.selectList(qw); } + @Override + public List> recentDrawResults(String regionId, int limit) { + requireRegion(regionId); + final int size = limit <= 0 ? 10 : Math.min(limit, 20); + final List records = drawRecordMapper.selectList(new LambdaQueryWrapper() + .eq(PlanetDrawRecord::getRegionId, regionId) + .orderByDesc(PlanetDrawRecord::getDrawTime) + .last("limit " + size)); + final List> result = new ArrayList<>(); + for (PlanetDrawRecord record : records) { + final Map item = new HashMap<>(4); + item.put("record", record); + item.put("winners", winnersOfDraw(record.getId())); + result.add(item); + } + return result; + } + @Override public List myWinning(String userId, String regionId) { requireRegion(regionId); @@ -482,25 +508,20 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { drawWinnerMapper.insert(winner); } - private boolean poutPoolEmpty(List pool) { - for (Candidate c : pool) { - if (!c.win) { - return false; - } - } - return true; - } - - private List poutPoolUsable(List pool) { + private List usableCandidates(List pool, Set cooldownUsers) { final List usable = new ArrayList<>(); for (Candidate c : pool) { - if (!c.win) { + if (!c.win && (cooldownUsers == null || !cooldownUsers.contains(c.ticket.getUserId()))) { usable.add(c); } } return usable; } + private boolean hasCandidate(List pool, Set cooldownUsers) { + return !usableCandidates(pool, cooldownUsers).isEmpty(); + } + private Candidate pickWeighted(List usable) { if (usable.isEmpty()) { return null; @@ -572,6 +593,16 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { return total; } + private int sumPoolWeightTickets(String poolId) { + final List joins = poolTicketMapper.selectList(new LambdaQueryWrapper() + .eq(PlanetPoolTicket::getPoolId, poolId)); + int total = 0; + for (PlanetPoolTicket join : joins) { + total += join.getWeightTickets() == null ? calcWeightTickets(join.getTickets() == null ? 0 : join.getTickets()) : join.getWeightTickets(); + } + return total; + } + private int countPoolJoin(String poolId) { return poolTicketMapper.selectCount(new LambdaQueryWrapper() .eq(PlanetPoolTicket::getPoolId, poolId) @@ -586,6 +617,60 @@ public class PlanetDrawServiceImpl implements PlanetDrawService { .divide(BigDecimal.valueOf(total), 2, BigDecimal.ROUND_HALF_UP); } + public static int calcWeightTickets(int tickets) { + if (tickets <= 0) { + return 0; + } + BigDecimal weight = BigDecimal.ZERO; + int remain = tickets; + int first = Math.min(remain, 3); + weight = weight.add(BigDecimal.valueOf(first)); + remain -= first; + if (remain > 0) { + int second = Math.min(remain, 7); + weight = weight.add(BigDecimal.valueOf(second).multiply(new BigDecimal("0.8"))); + remain -= second; + } + if (remain > 0) { + int third = Math.min(remain, 10); + weight = weight.add(BigDecimal.valueOf(third).multiply(new BigDecimal("0.6"))); + remain -= third; + } + if (remain > 0) { + weight = weight.add(BigDecimal.valueOf(remain).multiply(new BigDecimal("0.4"))); + } + return weight.setScale(0, BigDecimal.ROUND_HALF_UP).intValue(); + } + + private Set recentWinnerUserIds(String regionId, Date now) { + final Calendar c = Calendar.getInstance(); + c.setTime(now); + c.add(Calendar.DAY_OF_MONTH, -WIN_COOLDOWN_DAYS); + final List winners = drawWinnerMapper.selectList(new LambdaQueryWrapper() + .select(PlanetDrawWinner::getUserId) + .eq(PlanetDrawWinner::getRegionId, regionId) + .ge(PlanetDrawWinner::getCreateTime, c.getTime())); + return winners.stream().map(PlanetDrawWinner::getUserId).filter(StringUtils::isNotEmpty).collect(Collectors.toSet()); + } + + private BigDecimal sumRewardAmount(List rewards) { + BigDecimal total = BigDecimal.ZERO; + for (PlanetReward reward : rewards) { + final BigDecimal amount = reward.getAmount() == null ? BigDecimal.ZERO : reward.getAmount(); + final int quota = reward.getQuota() == null ? 0 : reward.getQuota(); + total = total.add(amount.multiply(BigDecimal.valueOf(quota))); + } + return total; + } + + private void refreshPoolRewardAmount(PlanetPool pool) { + final List rewards = rewardMapper.selectList(new LambdaQueryWrapper() + .eq(PlanetReward::getPoolId, pool.getId())); + pool.setPoolAmount(sumRewardAmount(rewards)); + pool.setUpdateTime(new Date()); + poolMapper.updateById(pool); + } + private int todayCollectedTickets(String userId, String regionId) { final Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR_OF_DAY, 0); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetOperateServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetOperateServiceImpl.java index 844ca2b3..71ae4719 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetOperateServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetOperateServiceImpl.java @@ -103,6 +103,7 @@ public class PlanetOperateServiceImpl implements PlanetOperateService { data.put("state", state); data.put("treeConfigs", treeConfigs(regionId)); data.put("treeOrders", treeOrders(userId, regionId)); + data.put("nextTowerConfig", getTowerLevel(regionId, nullToZero(state.getTowerLevel()) + 1)); data.put("landmarks", landmarkList(regionId)); data.put("staminaItems", staminaItems(regionId)); return data; diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetRankServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetRankServiceImpl.java index aa47a632..712fbe3f 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetRankServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetRankServiceImpl.java @@ -3,9 +3,10 @@ package cc.hiver.mall.planet.service.impl; import cc.hiver.core.common.redis.RedisTemplateHelper; import cc.hiver.mall.planet.constant.PlanetConstant; import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.entity.PlanetUserState; import cc.hiver.mall.planet.mapper.PlanetTicketMapper; +import cc.hiver.mall.planet.mapper.PlanetUserStateMapper; import cc.hiver.mall.planet.pojo.PlanetRankItemVo; -import cc.hiver.mall.planet.service.PlanetBuffService; import cc.hiver.mall.planet.service.PlanetRankService; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -37,7 +38,7 @@ public class PlanetRankServiceImpl implements PlanetRankService { private PlanetTicketMapper ticketMapper; @Autowired - private PlanetBuffService buffService; + private PlanetUserStateMapper userStateMapper; @Autowired private RedisTemplateHelper redisTemplateHelper; @@ -77,28 +78,27 @@ public class PlanetRankServiceImpl implements PlanetRankService { return page; } final Set userIds = tickets.stream().map(PlanetTicket::getUserId).collect(Collectors.toCollection(LinkedHashSet::new)); - final Map> buffMap = buffService.activeBuffTypes(userIds); + final Set towerUserIds = towerUserIds(regionId, userIds); final List result = new ArrayList<>(); int offset = (current - 1) * size; for (int i = 0; i < tickets.size(); i++) { PlanetTicket t = tickets.get(i); - final Set buffs = buffMap.get(t.getUserId()); - final boolean stealth = buffs != null && buffs.contains(PlanetConstant.BUFF_STEALTH); int rankNo = offset + i + 1; final PlanetRankItemVo vo = new PlanetRankItemVo(); vo.setRankNo(rankNo); vo.setUserId(t.getUserId()); - vo.setNickname(stealth ? "éšèº«ä¾ " : t.getNickname()); - vo.setAvatar(stealth ? null : t.getAvatar()); - vo.setCollege(stealth ? null : t.getCollege()); + vo.setNickname(t.getNickname()); + vo.setAvatar(t.getAvatar()); + vo.setCollege(t.getCollege()); vo.setTicketCount(t.getTicketCount()); vo.setDangerLevel(PlanetConstant.dangerLevel(t.getTicketCount())); vo.setDangerLevelName(PlanetConstant.dangerLevelName(t.getTicketCount())); vo.setRankKeepDays(t.getRankKeepDays() == null ? 0 : t.getRankKeepDays()); vo.setBountyTickets(PlanetConstant.bountyByRank(rankNo)); - vo.setShielded(buffs != null && buffs.contains(PlanetConstant.BUFF_SHIELD)); - vo.setStealth(stealth); + vo.setShielded(false); + vo.setHasTower(towerUserIds.contains(t.getUserId())); + vo.setStealth(false); vo.setSelf(t.getUserId() != null && t.getUserId().equals(currentUserId)); result.add(vo); } @@ -107,10 +107,9 @@ public class PlanetRankServiceImpl implements PlanetRankService { } /** - * 从数æ®åº“构建基础榜å•:先批é‡å–候选券记录,å†ä¸€æ¬¡æ€§æ‰¹é‡æŸ¥ BUFF,内存组装,é¿å…循环查库。 + * 从数æ®åº“构建基础榜å•:批é‡å–券记录åŽä¸€æ¬¡æ€§è¡¥é˜²å¾¡å¡”状æ€ï¼Œé¿å…循环查库。 */ private List buildRankFromDb(String regionId, int topN) { - // 多å–一些以便过滤éšèº«ç”¨æˆ·åŽä»èƒ½å‡‘满topN final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); if (StringUtils.isNotEmpty(regionId)) { qw.eq(PlanetTicket::getRegionId, regionId); @@ -123,15 +122,12 @@ public class PlanetRankServiceImpl implements PlanetRankService { if (tickets.isEmpty()) { return new ArrayList<>(); } - // æ‰¹é‡æŸ¥è¯¢å€™é€‰ç”¨æˆ·çš„生效 BUFF 类型,一次查库 final Set userIds = tickets.stream().map(PlanetTicket::getUserId).collect(Collectors.toCollection(LinkedHashSet::new)); - final Map> buffMap = buffService.activeBuffTypes(userIds); + final Set towerUserIds = towerUserIds(regionId, userIds); final List result = new ArrayList<>(); int rankNo = 0; for (PlanetTicket t : tickets) { - final Set buffs = buffMap.get(t.getUserId()); - final boolean stealth = buffs != null && buffs.contains(PlanetConstant.BUFF_STEALTH); rankNo++; if (rankNo > topN) { break; @@ -139,22 +135,39 @@ public class PlanetRankServiceImpl implements PlanetRankService { final PlanetRankItemVo vo = new PlanetRankItemVo(); vo.setRankNo(rankNo); vo.setUserId(t.getUserId()); - vo.setNickname(stealth ? "éšèº«ä¾ " : t.getNickname()); - vo.setAvatar(stealth ? null : t.getAvatar()); - vo.setCollege(stealth ? null : t.getCollege()); + vo.setNickname(t.getNickname()); + vo.setAvatar(t.getAvatar()); + vo.setCollege(t.getCollege()); vo.setTicketCount(t.getTicketCount()); vo.setDangerLevel(PlanetConstant.dangerLevel(t.getTicketCount())); vo.setDangerLevelName(PlanetConstant.dangerLevelName(t.getTicketCount())); vo.setRankKeepDays(t.getRankKeepDays() == null ? 0 : t.getRankKeepDays()); vo.setBountyTickets(PlanetConstant.bountyByRank(rankNo)); - vo.setShielded(buffs != null && buffs.contains(PlanetConstant.BUFF_SHIELD)); - vo.setStealth(stealth); + vo.setShielded(false); + vo.setHasTower(towerUserIds.contains(t.getUserId())); + vo.setStealth(false); vo.setSelf(false); result.add(vo); } return result; } + private Set towerUserIds(String regionId, Set userIds) { + if (userIds == null || userIds.isEmpty()) { + return Collections.emptySet(); + } + final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); + qw.select(PlanetUserState::getUserId) + .in(PlanetUserState::getUserId, userIds) + .gt(PlanetUserState::getTowerLevel, 0); + if (StringUtils.isNotEmpty(regionId)) { + qw.eq(PlanetUserState::getRegionId, regionId); + } + return userStateMapper.selectList(qw).stream() + .map(PlanetUserState::getUserId) + .collect(Collectors.toSet()); + } + private List readCache(String regionId, int topN) { try { final String json = redisTemplateHelper.get(cacheKey(regionId, topN)); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetServiceImpl.java index 9f818e83..2d130de2 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetServiceImpl.java @@ -1,18 +1,23 @@ package cc.hiver.mall.planet.service.impl; import cc.hiver.mall.planet.constant.PlanetConstant; -import cc.hiver.mall.planet.entity.PlanetPool; -import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.entity.*; +import cc.hiver.mall.planet.mapper.PlanetPoolTicketMapper; +import cc.hiver.mall.planet.mapper.PlanetRewardMapper; +import cc.hiver.mall.planet.mapper.PlanetTicketLogMapper; +import cc.hiver.mall.planet.pojo.PlanetDailyLoopVo; import cc.hiver.mall.planet.pojo.PlanetHomeVo; import cc.hiver.mall.planet.pojo.PlanetQuery; -import cc.hiver.mall.planet.pojo.PlanetRankItemVo; import cc.hiver.mall.planet.service.*; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Calendar; import java.util.Date; +import java.util.List; /** * 白嫖星çƒ-首页èšåˆæœåŠ¡å®žçŽ° @@ -31,9 +36,6 @@ public class PlanetServiceImpl implements PlanetService { @Autowired private PlanetTaskService taskService; - @Autowired - private PlanetBuffService buffService; - @Autowired private PlanetBoxService boxService; @@ -49,6 +51,15 @@ public class PlanetServiceImpl implements PlanetService { @Autowired private PlanetOperateService operateService; + @Autowired + private PlanetPoolTicketMapper poolTicketMapper; + + @Autowired + private PlanetTicketLogMapper ticketLogMapper; + + @Autowired + private PlanetRewardMapper rewardMapper; + @Override public PlanetHomeVo home(PlanetQuery query) { final String userId = query.getUserId(); @@ -70,6 +81,7 @@ public class PlanetServiceImpl implements PlanetService { vo.setCountdownMillis(0L); } vo.setJoinCount(pool.getJoinCount() == null ? 0 : pool.getJoinCount()); + vo.setRewardList(rewardsOfPool(pool.getId())); // 我的星çƒä¸­å¿ƒ vo.setMyTicketCount(ticket.getTicketCount() == null ? 0 : ticket.getTicketCount()); @@ -81,32 +93,104 @@ public class PlanetServiceImpl implements PlanetService { vo.setRemainHunt(huntService.remainHunt(userId)); vo.setLevel(PlanetConstant.dangerLevel(vo.getMyTicketCount())); vo.setMyRankNo(rankService.userRankNo(regionId, userId)); + vo.setDailyLoop(lightDailyLoop(userId, regionId, pool)); + vo.setUnreadWinning(drawService.unreadWinning(userId, regionId)); + return vo; + } - // 我生效的BUFF - /*final List myBuffs = new ArrayList<>(); - for (PlanetBuffRecord r : buffService.activeBuffs(userId)) { - final PlanetBuffVo bv = new PlanetBuffVo(); - bv.setId(r.getBuffId()); - bv.setType(r.getType()); - bv.setEffectValue(r.getEffectValue()); - bv.setActive(true); - bv.setActiveEndTime(r.getEndTime()); - myBuffs.add(bv); - } - vo.setMyBuffs(myBuffs);*/ - - // 儿¿å— + @Override + public PlanetHomeVo supply(PlanetQuery query) { + final String userId = query.getUserId(); + final String regionId = query.getRegionId(); + final PlanetHomeVo vo = new PlanetHomeVo(); + final PlanetTicket ticket = ticketService.getOrCreate(userId, regionId, + query.getNickname(), query.getAvatar(), query.getCollege()); + vo.setMyTicketCount(ticket.getTicketCount() == null ? 0 : ticket.getTicketCount()); vo.setTasks(taskService.listTasks(userId, regionId)); - final Page rankPage = rankService.rankPage(regionId, query.getPageNumber(), query.getPageSize(), userId); - vo.setRankList(rankPage.getRecords()); - vo.setRankTotal(rankPage.getTotal()); - vo.setRankTotalPages(rankPage.getPages()); - vo.setRankPageNumber(rankPage.getCurrent()); - vo.setBuffShop(buffService.shopList(userId, regionId)); vo.setNewsList(newsService.latest(regionId, 10)); vo.setOperate(operateService.overview(userId, regionId)); - vo.setDailyLoop(drawService.dailyLoop(userId, regionId)); - vo.setUnreadWinning(drawService.unreadWinning(userId, regionId)); return vo; } + + private PlanetDailyLoopVo lightDailyLoop(String userId, String regionId, PlanetPool pool) { + final PlanetDailyLoopVo vo = new PlanetDailyLoopVo(); + final PlanetPoolTicket myJoin = poolTicketMapper.selectOne(new LambdaQueryWrapper() + .eq(PlanetPoolTicket::getPoolId, pool.getId()) + .eq(PlanetPoolTicket::getUserId, userId) + .last("limit 1")); + final Integer total = sumPoolTickets(pool.getId()); + final Integer weightTotal = sumPoolWeightTickets(pool.getId()); + final int myTickets = myJoin == null || myJoin.getTickets() == null ? 0 : myJoin.getTickets(); + final int myWeight = myJoin == null || myJoin.getWeightTickets() == null ? calcWeightTickets(myTickets) : myJoin.getWeightTickets(); + vo.setMyPoolTickets(myTickets); + vo.setMyWeightTickets(myWeight); + vo.setPoolTicketTotal(total); + vo.setPoolWeightTotal(weightTotal); + vo.setMyProbability(probability(myWeight, weightTotal)); + final int suggested = myTickets <= 0 ? 3 : Math.min(10, Math.max(1, total / 20)); + vo.setSuggestedAddTickets(suggested); + vo.setSuggestedProbability(probability(calcWeightTickets(myTickets + suggested), weightTotal - myWeight + calcWeightTickets(myTickets + suggested))); + vo.setTodayCollectedTickets(todayCollectedTickets(userId, regionId)); + return vo; + } + + private Integer sumPoolTickets(String poolId) { + List joins = poolTicketMapper.selectList(new LambdaQueryWrapper() + .select(PlanetPoolTicket::getTickets) + .eq(PlanetPoolTicket::getPoolId, poolId)); + int total = 0; + for (PlanetPoolTicket join : joins) { + total += join.getTickets() == null ? 0 : join.getTickets(); + } + return total; + } + + private Integer sumPoolWeightTickets(String poolId) { + List joins = poolTicketMapper.selectList(new LambdaQueryWrapper() + .select(PlanetPoolTicket::getTickets, PlanetPoolTicket::getWeightTickets) + .eq(PlanetPoolTicket::getPoolId, poolId)); + int total = 0; + for (PlanetPoolTicket join : joins) { + total += join.getWeightTickets() == null ? calcWeightTickets(join.getTickets() == null ? 0 : join.getTickets()) : join.getWeightTickets(); + } + return total; + } + + private Integer todayCollectedTickets(String userId, String regionId) { + final Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY, 0); + c.set(Calendar.MINUTE, 0); + c.set(Calendar.SECOND, 0); + c.set(Calendar.MILLISECOND, 0); + final List logs = ticketLogMapper.selectList(new LambdaQueryWrapper() + .select(PlanetTicketLog::getChangeCount) + .eq(PlanetTicketLog::getUserId, userId) + .eq(PlanetTicketLog::getRegionId, regionId) + .gt(PlanetTicketLog::getChangeCount, 0) + .ge(PlanetTicketLog::getCreateTime, c.getTime())); + int total = 0; + for (PlanetTicketLog log : logs) { + total += log.getChangeCount() == null ? 0 : log.getChangeCount(); + } + return total; + } + + private BigDecimal probability(int mine, int total) { + if (mine <= 0 || total <= 0) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf(mine) + .multiply(BigDecimal.valueOf(100)) + .divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP); + } + + private Integer calcWeightTickets(int tickets) { + return PlanetDrawServiceImpl.calcWeightTickets(tickets); + } + + private List rewardsOfPool(String poolId) { + return rewardMapper.selectList(new LambdaQueryWrapper() + .eq(PlanetReward::getPoolId, poolId) + .orderByAsc(PlanetReward::getSort)); + } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTicketServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTicketServiceImpl.java index 82a17352..6e7ec98c 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTicketServiceImpl.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetTicketServiceImpl.java @@ -4,10 +4,8 @@ import cc.hiver.core.common.exception.HiverException; import cc.hiver.core.entity.User; import cc.hiver.core.service.UserService; import cc.hiver.mall.planet.constant.PlanetConstant; -import cc.hiver.mall.planet.entity.PlanetBuffRecord; import cc.hiver.mall.planet.entity.PlanetTicket; import cc.hiver.mall.planet.entity.PlanetTicketLog; -import cc.hiver.mall.planet.mapper.PlanetBuffRecordMapper; import cc.hiver.mall.planet.mapper.PlanetTicketLogMapper; import cc.hiver.mall.planet.mapper.PlanetTicketMapper; import cc.hiver.mall.planet.service.PlanetTicketService; @@ -18,9 +16,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.math.BigDecimal; import java.util.Date; -import java.util.List; import java.util.UUID; /** @@ -38,9 +34,6 @@ public class PlanetTicketServiceImpl implements PlanetTicketService { @Autowired private PlanetTicketLogMapper ticketLogMapper; - @Autowired - private PlanetBuffRecordMapper buffRecordMapper; - @Autowired private UserService userService; @@ -140,12 +133,7 @@ public class PlanetTicketServiceImpl implements PlanetTicketService { } } final PlanetTicket ticket = getOrCreate(userId, regionId, null, null, null); - // åŒå€BUFFåŠ æˆ int finalCount = baseCount; - final BigDecimal multiplier = getActiveDoubleMultiplier(userId); - if (multiplier != null && multiplier.compareTo(BigDecimal.ONE) > 0) { - finalCount = multiplier.multiply(BigDecimal.valueOf(baseCount)).intValue(); - } ticket.setTicketCount(ticket.getTicketCount() + finalCount); ticket.setTotalTicket(ticket.getTotalTicket() + finalCount); ticket.setUpdateTime(new Date()); @@ -223,22 +211,6 @@ public class PlanetTicketServiceImpl implements PlanetTicketService { return ticketLogMapper.selectPage(page, qw); } - private BigDecimal getActiveDoubleMultiplier(String userId) { - final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); - qw.eq(PlanetBuffRecord::getUserId, userId) - .eq(PlanetBuffRecord::getType, PlanetConstant.BUFF_DOUBLE) - .eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) - .gt(PlanetBuffRecord::getEndTime, new Date()) - .orderByDesc(PlanetBuffRecord::getEffectValue) - .last("limit 1"); - final List list = buffRecordMapper.selectList(qw); - if (list != null && !list.isEmpty()) { - final BigDecimal v = list.get(0).getEffectValue(); - return v == null ? BigDecimal.valueOf(2) : v; - } - return BigDecimal.ONE; - } - private void saveLog(String userId, String regionId, int change, int balance, String type, String sourceId, String remark) { final PlanetTicketLog logEntity = new PlanetTicketLog(); logEntity.setId(UUID.randomUUID().toString().replace("-", "")); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/GroupBuyExpireTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/GroupBuyExpireTask.java index 9bd28190..44ec7d78 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/GroupBuyExpireTask.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/GroupBuyExpireTask.java @@ -1,6 +1,7 @@ package cc.hiver.mall.quartz; import cc.hiver.mall.entity.MallOrderGroup; +import cc.hiver.mall.planet.service.PlanetAdventurePkService; import cc.hiver.mall.service.mybatis.MallOrderGroupService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; @@ -13,7 +14,7 @@ import java.util.List; /** * 拼团超时自动失败定时任务 - * æ¯30分钟扫æä¸€æ¬¡æ‹¼å›¢ä¸­ï¼ˆstatus=0/3)且已超过 expireTime 的拼团 + * æ¯5分钟扫æä¸€æ¬¡æ‹¼å›¢ä¸­ï¼ˆstatus=0/3)且已超过 expireTime 的拼团 */ @Slf4j @Component @@ -22,10 +23,13 @@ public class GroupBuyExpireTask { @Autowired private MallOrderGroupService mallOrderGroupService; + @Autowired + private PlanetAdventurePkService planetAdventurePkService; + /** * æ¯5分钟执行一次 */ - @Scheduled(cron = "0 0/30 * * * ?") + @Scheduled(cron = "0 0/5 * * * ?") public void expireOverdueGroups() { log.info("[拼团过期任务] 开始扫æè¶…时拼团..."); try { @@ -38,20 +42,29 @@ public class GroupBuyExpireTask { if (overdueGroups.isEmpty()) { log.info("[拼团过期任务] 无超时拼团"); - return; - } - - log.info("[拼团过期任务] å‘现 {} 个超时拼团,开始处ç†...", overdueGroups.size()); - for (MallOrderGroup group : overdueGroups) { - try { - mallOrderGroupService.expireGroup(group.getId()); - log.info("[拼团过期任务] 拼团 {} 处ç†å®Œæˆ", group.getId()); - } catch (Exception e) { - log.error("[拼团过期任务] å¤„ç†æ‹¼å›¢ {} 失败: {}", group.getId(), e.getMessage(), e); + } else { + log.info("[拼团过期任务] å‘现 {} 个超时拼团,开始处ç†...", overdueGroups.size()); + for (MallOrderGroup group : overdueGroups) { + try { + mallOrderGroupService.expireGroup(group.getId()); + log.info("[拼团过期任务] 拼团 {} 处ç†å®Œæˆ", group.getId()); + } catch (Exception e) { + log.error("[拼团过期任务] å¤„ç†æ‹¼å›¢ {} 失败: {}", group.getId(), e.getMessage(), e); + } } } } catch (Exception e) { log.error("[拼团过期任务] 任务执行异常: {}", e.getMessage(), e); } + expireOverduePkRooms(); + } + + private void expireOverduePkRooms() { + try { + int settled = planetAdventurePkService.autoSettleOverdueRooms(); + log.info("[拼团过期任务] æ˜Ÿçƒæ“‚å°è¶…时房间自动结算完æˆï¼Œå¤„ç† {} 个", settled); + } catch (Exception e) { + log.error("[拼团过期任务] æ˜Ÿçƒæ“‚å°è¶…时结算异常: {}", e.getMessage(), e); + } } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetAdventureSettleTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetAdventureSettleTask.java index dc409d9a..fdf85873 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetAdventureSettleTask.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetAdventureSettleTask.java @@ -1,17 +1,26 @@ package cc.hiver.mall.quartz; +import cc.hiver.core.common.constant.DealingsRecordConstant; +import cc.hiver.core.entity.User; +import cc.hiver.core.service.UserService; +import cc.hiver.mall.entity.DealingsRecord; import cc.hiver.mall.planet.constant.PlanetConstant; +import cc.hiver.mall.planet.entity.PlanetAdventureSession; import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.mapper.PlanetAdventureSessionMapper; import cc.hiver.mall.planet.mapper.PlanetTicketMapper; import cc.hiver.mall.planet.service.PlanetAdventureService; import cc.hiver.mall.planet.service.PlanetTicketService; +import cc.hiver.mall.service.mybatis.DealingsRecordService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 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.math.BigDecimal; import java.time.LocalDate; +import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -19,6 +28,14 @@ import java.util.stream.Collectors; @Component public class PlanetAdventureSettleTask { + private static final BigDecimal[] GLORY_REWARD_AMOUNTS = { + new BigDecimal("5.00"), + new BigDecimal("4.00"), + new BigDecimal("3.00"), + new BigDecimal("2.00"), + new BigDecimal("1.00") + }; + @Autowired private PlanetAdventureService adventureService; @@ -28,12 +45,22 @@ public class PlanetAdventureSettleTask { @Autowired private PlanetTicketService ticketService; + @Autowired + private PlanetAdventureSessionMapper sessionMapper; + + @Autowired + private UserService userService; + + @Autowired + private DealingsRecordService dealingsRecordService; + @Scheduled(cron = "0 30 21 * * ?") public void settleAdventureRanks() { try { int count = adventureService.settleDueRanks(); int rewardCount = rewardRegionTopTickets(); - log.info("[白嫖星çƒ] å­¦é™¢åŠ©æŽ¨èµ›ç»“ç®—å®Œæˆ count={}, rankRewardCount={}", count, rewardCount); + int cashRewardCount = rewardRegionGloryCash(); + log.info("[白嫖星çƒ] å­¦é™¢åŠ©æŽ¨èµ›ç»“ç®—å®Œæˆ count={}, rankRewardCount={}, cashRewardCount={}", count, rewardCount, cashRewardCount); } catch (Exception e) { log.error("[白嫖星çƒ] 学院助推赛结算异常: {}", e.getMessage(), e); } @@ -71,4 +98,73 @@ public class PlanetAdventureSettleTask { } return rewarded; } + + private int rewardRegionGloryCash() { + LocalDate today = LocalDate.now(); + List regionIds = sessionMapper.selectList(new LambdaQueryWrapper() + .select(PlanetAdventureSession::getRegionId) + .isNotNull(PlanetAdventureSession::getRegionId) + .eq(PlanetAdventureSession::getPlayDate, today) + .eq(PlanetAdventureSession::getStatus, PlanetConstant.ADVENTURE_SESSION_SUBMITTED) + .eq(PlanetAdventureSession::getCheatFlag, "N") + .groupBy(PlanetAdventureSession::getRegionId)).stream() + .map(PlanetAdventureSession::getRegionId) + .collect(Collectors.toList()); + int rewarded = 0; + String rewardDate = today.toString(); + for (String regionId : regionIds) { + List topList = sessionMapper.selectList(new LambdaQueryWrapper() + .eq(PlanetAdventureSession::getRegionId, regionId) + .eq(PlanetAdventureSession::getPlayDate, today) + .eq(PlanetAdventureSession::getStatus, PlanetConstant.ADVENTURE_SESSION_SUBMITTED) + .eq(PlanetAdventureSession::getCheatFlag, "N") + .orderByAsc(PlanetAdventureSession::getDurationSeconds) + .last("limit 5")); + if (topList == null || topList.isEmpty()) { + continue; + } + for (int i = 0; i < topList.size() && i < GLORY_REWARD_AMOUNTS.length; i++) { + if (rewardGloryCash(topList.get(i), i + 1, GLORY_REWARD_AMOUNTS[i], rewardDate)) { + rewarded++; + } + } + } + return rewarded; + } + + private boolean rewardGloryCash(PlanetAdventureSession session, int rankNo, BigDecimal amount, String rewardDate) { + if (session == null || session.getUserId() == null || amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) { + return false; + } + String linkId = "planet_adventure_glory_" + rewardDate + "_" + session.getRegionId() + "_" + rankNo + "_" + session.getUserId(); + long exists = dealingsRecordService.count(new LambdaQueryWrapper() + .eq(DealingsRecord::getLinkId, linkId) + .eq(DealingsRecord::getLinkUserId, session.getUserId()) + .eq(DealingsRecord::getRegionId, session.getRegionId())); + if (exists > 0) { + return false; + } + User user = userService.findById(session.getUserId()); + if (user == null) { + log.warn("[白嫖星çƒ] 学院助推赛è£è€€æ¦œçŽ°é‡‘å¥–åŠ±è·³è¿‡ï¼Œç”¨æˆ·ä¸å­˜åœ¨ userId={}, regionId={}, rankNo={}", + session.getUserId(), session.getRegionId(), rankNo); + return false; + } + user.setDepoBal((user.getDepoBal() == null ? BigDecimal.ZERO : user.getDepoBal()).add(amount)); + userService.update(user); + + DealingsRecord dealingsRecord = new DealingsRecord(); + dealingsRecord.setDealingsWay(DealingsRecordConstant.TYPE_REMARK[9]); + dealingsRecord.setAmount(amount); + dealingsRecord.setDealingsTime(new Date()); + dealingsRecord.setLinkId(linkId); + dealingsRecord.setLinkUserId(session.getUserId()); + dealingsRecord.setRegionId(session.getRegionId()); + dealingsRecord.setLinkType(DealingsRecordConstant.TYPE[0]); + dealingsRecord.setDealingsType(DealingsRecordConstant.DEALINGS_TYPE[0]); + dealingsRecord.setCreateBy(session.getUserId()); + dealingsRecord.setRemark("学院助推赛è£è€€æ¦œç¬¬" + rankNo + "å现金奖励"); + dealingsRecordService.save(dealingsRecord); + return true; + } } diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDailyResetTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDailyResetTask.java index a7998a15..7fb81a03 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDailyResetTask.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDailyResetTask.java @@ -1,9 +1,6 @@ package cc.hiver.mall.quartz; -import cc.hiver.mall.planet.constant.PlanetConstant; -import cc.hiver.mall.planet.entity.PlanetBuffRecord; import cc.hiver.mall.planet.entity.PlanetTicket; -import cc.hiver.mall.planet.mapper.PlanetBuffRecordMapper; import cc.hiver.mall.planet.mapper.PlanetTicketMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; @@ -19,9 +16,8 @@ import java.util.List; * 白嫖星çƒ-æ¯æ—¥é‡ç½®å®šæ—¶ä»»åŠ¡ *

    * æ¯æ—¥ 00:05 执行: - * 1. 过期BUFFç½®ä¸ºå¤±æ•ˆçŠ¶æ€ - * 2. é‡ç½®ä»Šæ—¥è¿½æ•/被追计数(展示用) - * 3. 更新连续霸榜天数 + * 1. é‡ç½®ä»Šæ—¥è¿½æ•/被追计数(展示用) + * 2. 更新连续霸榜天数 * * @author hiver */ @@ -32,26 +28,16 @@ public class PlanetDailyResetTask { @Autowired private PlanetTicketMapper ticketMapper; - @Autowired - private PlanetBuffRecordMapper buffRecordMapper; - @Scheduled(cron = "0 5 0 * * ?") public void dailyReset() { try { - // 1. 过期BUFF - final LambdaUpdateWrapper bw = new LambdaUpdateWrapper<>(); - bw.eq(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_ACTIVE) - .lt(PlanetBuffRecord::getEndTime, new Date()) - .set(PlanetBuffRecord::getStatus, PlanetConstant.BUFF_STATUS_EXPIRED); - buffRecordMapper.update(null, bw); - - // 2. é‡ç½®æ¯æ—¥è®¡æ•°(展示字段) + // 1. é‡ç½®æ¯æ—¥è®¡æ•°(展示字段) final LambdaUpdateWrapper tw = new LambdaUpdateWrapper<>(); tw.set(PlanetTicket::getHuntCountToday, 0) .set(PlanetTicket::getHuntedSuccessToday, 0); ticketMapper.update(null, tw); - // 3. 更新连续霸榜天数:ä»åœ¨TOP10的用户 keepDays+1,å¦åˆ™æ¸…é›¶ + // 2. 更新连续霸榜天数:ä»åœ¨TOP10的用户 keepDays+1,å¦åˆ™æ¸…é›¶ updateRankKeepDays(); log.info("[白嫖星çƒ] æ¯æ—¥é‡ç½®ä»»åŠ¡å®Œæˆ"); } catch (Exception e) { diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDrawTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDrawTask.java index 5775a0fc..c64efe29 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDrawTask.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetDrawTask.java @@ -7,8 +7,8 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** - * 白嫖星çƒ-到点开奖定时任务 - * æ¯åˆ†é’Ÿæ‰«æåˆ°è¾¾å¼€å¥–时间且未开奖的奖池并执行加æƒå¼€å¥– + * 白嫖星çƒ-æ¯æ—¥çŽ°é‡‘å¼€å¥–å®šæ—¶ä»»åŠ¡ + * æ¯å¤© 22:00 按校区扫æåˆ°è¾¾å¼€å¥–时间且未开奖的奖池并执行加æƒå¼€å¥– * * @author hiver */ @@ -19,7 +19,7 @@ public class PlanetDrawTask { @Autowired private PlanetDrawService drawService; - @Scheduled(cron = "0 * * * * ?") + @Scheduled(cron = "0 0 22 * * ?") public void drawDuePools() { try { final int count = drawService.drawDuePools(); diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetOperateSettleTask.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetOperateSettleTask.java index 5f0d60f5..87dc5f62 100644 --- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetOperateSettleTask.java +++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/quartz/PlanetOperateSettleTask.java @@ -1,9 +1,12 @@ package cc.hiver.mall.quartz; import cc.hiver.mall.planet.constant.PlanetConstant; -import cc.hiver.mall.planet.entity.*; -import cc.hiver.mall.planet.mapper.*; -import cc.hiver.mall.planet.service.PlanetTicketService; +import cc.hiver.mall.planet.entity.PlanetEconomyAudit; +import cc.hiver.mall.planet.entity.PlanetTicket; +import cc.hiver.mall.planet.entity.PlanetTicketLog; +import cc.hiver.mall.planet.mapper.PlanetEconomyAuditMapper; +import cc.hiver.mall.planet.mapper.PlanetTicketLogMapper; +import cc.hiver.mall.planet.mapper.PlanetTicketMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -19,136 +22,19 @@ import java.util.stream.Collectors; @Component public class PlanetOperateSettleTask { - @Autowired - private PlanetLandmarkRoundMapper landmarkRoundMapper; - @Autowired - private PlanetLandmarkBidMapper landmarkBidMapper; - @Autowired - private PlanetLandmarkConfigMapper landmarkConfigMapper; - @Autowired - private PlanetLandmarkRewardLogMapper landmarkRewardLogMapper; @Autowired private PlanetEconomyAuditMapper economyAuditMapper; @Autowired private PlanetTicketLogMapper ticketLogMapper; @Autowired private PlanetTicketMapper ticketMapper; - @Autowired - private PlanetTicketService ticketService; private static String genId() { return UUID.randomUUID().toString().replace("-", ""); } /** - * æ¯æ™š22点åŽç»“算校园地标。失败åªè®°å½•日志,é¿å…å½±å“开奖主æµç¨‹ã€‚ - */ - @Scheduled(cron = "0 3 22 * * ?") - @Transactional(rollbackFor = Exception.class) - public void settleLandmarks() { - final LambdaQueryWrapper qw = new LambdaQueryWrapper<>(); - qw.eq(PlanetLandmarkRound::getStatus, PlanetConstant.LANDMARK_ROUND_RUNNING) - .le(PlanetLandmarkRound::getRoundDate, LocalDate.now()); - final List rounds = landmarkRoundMapper.selectList(qw); - for (PlanetLandmarkRound round : rounds) { - try { - settleRound(round); - } catch (Exception e) { - log.error("[白嫖星çƒ] 地标结算失败 roundId={}, {}", round.getId(), e.getMessage(), e); - } - } - if (!rounds.isEmpty()) { - log.info("[白嫖星çƒ] åœ°æ ‡ç»“ç®—å®Œæˆ roundCount={}", rounds.size()); - } - } - - private void settleRound(PlanetLandmarkRound round) { - final PlanetLandmarkConfig landmark = landmarkConfigMapper.selectById(round.getLandmarkId()); - if (landmark == null) { - round.setStatus(PlanetConstant.LANDMARK_ROUND_SETTLED); - round.setSettleTime(new Date()); - round.setUpdateTime(new Date()); - landmarkRoundMapper.updateById(round); - return; - } - final LambdaQueryWrapper bq = new LambdaQueryWrapper<>(); - bq.eq(PlanetLandmarkBid::getRoundId, round.getId()).eq(PlanetLandmarkBid::getStatus, 0); - final List bids = landmarkBidMapper.selectList(bq); - if (bids == null || bids.isEmpty()) { - round.setStatus(PlanetConstant.LANDMARK_ROUND_SETTLED); - round.setSettleTime(new Date()); - round.setUpdateTime(new Date()); - landmarkRoundMapper.updateById(round); - return; - } - final Map userInvest = bids.stream().collect(Collectors.groupingBy( - PlanetLandmarkBid::getUserId, Collectors.summingInt(b -> b.getInvestTickets() == null ? 0 : b.getInvestTickets()))); - final String winnerUserId = userInvest.entrySet().stream() - .max(Comparator.comparingInt(Map.Entry::getValue)) - .map(Map.Entry::getKey).orElse(null); - final int winnerContribution = winnerUserId == null ? 0 : userInvest.get(winnerUserId); - int totalBurn = 0; - for (PlanetLandmarkBid bid : bids) { - final boolean winner = winnerUserId != null && winnerUserId.equals(bid.getUserId()); - bid.setIsWinner(winner ? 1 : 0); - bid.setStatus(1); - if (winner) { - bid.setRefundTickets(0); - bid.setBurnTickets(bid.getInvestTickets()); - } else { - final int invest = bid.getInvestTickets() == null ? 0 : bid.getInvestTickets(); - final int burn = Math.min(1, invest); - final int refund = Math.max(0, invest - burn); - bid.setBurnTickets(burn); - bid.setRefundTickets(refund); - totalBurn += burn; - if (refund > 0) { - ticketService.addTicketsWithoutBuff(bid.getUserId(), bid.getRegionId(), refund, - PlanetConstant.TICKET_TYPE_LANDMARK_REFUND, bid.getId(), "校园地标未å é¢†é€€å›ž"); - } - } - bid.setUpdateTime(new Date()); - landmarkBidMapper.updateById(bid); - } - grantLandmarkReward(round, landmark, winnerUserId); - round.setOwnerUserId(winnerUserId); - round.setOwnerContribution(winnerContribution); - round.setTotalBurn(totalBurn); - round.setStatus(PlanetConstant.LANDMARK_ROUND_SETTLED); - round.setSettleTime(new Date()); - round.setUpdateTime(new Date()); - landmarkRoundMapper.updateById(round); - } - - private void grantLandmarkReward(PlanetLandmarkRound round, PlanetLandmarkConfig landmark, String winnerUserId) { - if (winnerUserId == null || !"ticket".equals(landmark.getBenefitType())) { - return; - } - final int reward = landmark.getBenefitValue() == null ? 0 : landmark.getBenefitValue().intValue(); - if (reward <= 0) { - return; - } - final String sourceId = round.getId() + "_reward"; - final int added = ticketService.addTicketsWithoutBuff(winnerUserId, round.getRegionId(), reward, - PlanetConstant.TICKET_TYPE_LANDMARK_REWARD, sourceId, "å é¢†æ ¡å›­åœ°æ ‡æ”¶ç›Šï¼š" + landmark.getName()); - if (added > 0) { - final PlanetLandmarkRewardLog log = new PlanetLandmarkRewardLog(); - log.setId(genId()); - log.setRoundId(round.getId()); - log.setLandmarkId(landmark.getId()); - log.setRegionId(round.getRegionId()); - log.setUserId(winnerUserId); - log.setBenefitType(landmark.getBenefitType()); - log.setBenefitValue(landmark.getBenefitValue()); - log.setTicketAmount(reward); - log.setSourceId(sourceId); - log.setCreateTime(new Date()); - landmarkRewardLogMapper.insert(log); - } - } - - /** - * æ¯æ—¥ç»æµŽå®¡è®¡ï¼šç”¨åˆ¸æµæ°´åšåŒºåŸŸå‡€å¢ž/回收统计,å‘现净增过高时标记预警。 + * æ¯æ—¥ç»æµŽå®¡è®¡ï¼šä¿ç•™å½“å‰ä»åœ¨ä½¿ç”¨çš„券树ã€é˜²å¾¡å¡”ã€å¥–æ± ç­‰åˆ¸æµæ°´ç»Ÿè®¡ã€‚ */ @Scheduled(cron = "0 20 0 * * ?") @Transactional(rollbackFor = Exception.class) @@ -175,7 +61,6 @@ public class PlanetOperateSettleTask { int burnTickets = 0; int plantOutput = 0; int searchTransfer = 0; - int landmarkBurn = 0; int upgradeBurn = 0; int poolBurn = 0; for (PlanetTicketLog log : logs) { @@ -188,8 +73,7 @@ public class PlanetOperateSettleTask { final String type = log.getType(); if (PlanetConstant.TICKET_TYPE_TREE_HARVEST.equals(type)) plantOutput += Math.max(0, change); if (PlanetConstant.TICKET_TYPE_SEARCH.equals(type)) searchTransfer += Math.max(0, change); - if (PlanetConstant.TICKET_TYPE_LANDMARK_BID.equals(type)) landmarkBurn += Math.max(0, -change); - if (PlanetConstant.TICKET_TYPE_WAREHOUSE_UPGRADE.equals(type) || PlanetConstant.TICKET_TYPE_TOWER_UPGRADE.equals(type)) upgradeBurn += Math.max(0, -change); + if (PlanetConstant.TICKET_TYPE_TOWER_UPGRADE.equals(type)) upgradeBurn += Math.max(0, -change); if (PlanetConstant.TICKET_TYPE_DRAW.equals(type)) poolBurn += Math.max(0, -change); } final Long activeUsers = ticketMapper.selectCount(new LambdaQueryWrapper() @@ -207,7 +91,7 @@ public class PlanetOperateSettleTask { audit.setNetTickets(newTickets - burnTickets); audit.setPlantOutput(plantOutput); audit.setSearchTransfer(searchTransfer); - audit.setLandmarkBurn(landmarkBurn); + audit.setLandmarkBurn(0); audit.setUpgradeBurn(upgradeBurn); audit.setPoolBurn(poolBurn); audit.setActiveUserCount(activeUsers == null ? 0 : activeUsers.intValue());