package com.izouma.nineth.service; import com.alipay.mychain.sdk.vm.abi.datatype.Int; import com.izouma.nineth.domain.Rice; import com.izouma.nineth.domain.RiceOperationRecord; import com.izouma.nineth.domain.RiceUserWaterDropRecord; import com.izouma.nineth.domain.User; import com.izouma.nineth.dto.PageQuery; import com.izouma.nineth.dto.R; import com.izouma.nineth.dto.RiceDTO; import com.izouma.nineth.enums.RiceOperationType; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.RiceOperationRecordRepo; import com.izouma.nineth.repo.RiceRepo; import com.izouma.nineth.repo.RiceUserWaterDropRecordRepo; import com.izouma.nineth.repo.UserRepo; import com.izouma.nineth.utils.JpaUtils; import com.izouma.nineth.utils.SecurityUtils; import lombok.AllArgsConstructor; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import javax.json.Json; import javax.json.JsonArray; import javax.json.JsonObject; import javax.json.JsonReader; import java.io.StringReader; import java.time.LocalDateTime; import java.util.*; @Service @AllArgsConstructor public class RiceService { private static final int MAX_NICKNAME_LENGTH = 6; private static final String UPDATE_SUCCESS_MSG = "修改成功"; private RiceRepo riceRepo; private RiceUserWaterDropRecordRepo riceUserWaterDropRecordRepo; private RiceOperationRecordRepo riceOperationRecordRepo; private UserRepo userRepo; private SysConfigService sysConfigService; public Page all(PageQuery pageQuery) { return riceRepo.findAll(JpaUtils.toSpecification(pageQuery, Rice.class), JpaUtils.toPageRequest(pageQuery)); } //点击水稻游戏,进行初始化 public Rice getCurrentRiceUser(User authenticatedUser) throws BusinessException { Long id = authenticatedUser.getId(); Optional byId = userRepo.findByIdAndDelFalse(id); String nickname = null; String avatar = null; if (byId.isPresent()) { User user = byId.get(); nickname = user.getNickname(); avatar = user.getAvatar(); } else { throw new BusinessException("用户不存在"); } Optional byUserId = riceRepo.findByUserId(id); if (byUserId.isPresent()) { Rice rice = byUserId.get(); return rice; } else { Rice rice = new Rice(); rice.setUserId(id); rice.setAvatar(avatar); rice.setNickname(nickname); rice.setLevel(0L); rice.setWaterDropCount(0L); rice.setSignCount(0L); rice.setSelfScore(0L); rice.setSelfActivityScore(0L); rice.setEmpiricalValue(0L); riceRepo.save(rice); return rice; } } //修改昵称 public R updateNickName(Long userId, String nickname) { String trimmedNickname = StringUtils.trim(nickname); if (trimmedNickname.length() > MAX_NICKNAME_LENGTH) { return R.error("昵称不能超过" + MAX_NICKNAME_LENGTH + "个字符"); } riceRepo.updateNickName(userId, trimmedNickname); return R.success(UPDATE_SUCCESS_MSG); } /** * 获取当前等级 * * @param empiricalValue * @return */ public Map getCurrentLevel(Long empiricalValue) { String jsonString = sysConfigService.getString("rice_level"); User authenticatedUser = SecurityUtils.getAuthenticatedUser(); Long authId = authenticatedUser.getId(); Optional byUserId = riceRepo.findByUserId(authId); if (byUserId.isPresent()) { Rice rice = byUserId.get(); empiricalValue = rice.getEmpiricalValue(); JsonReader jsonReader = Json.createReader(new StringReader(jsonString)); JsonArray jsonArray = jsonReader.readArray(); Long currentLevel = null; Long currentStart = null; Long nextStart = null; for (int i = 0; i < jsonArray.size(); i++) { JsonObject jsonObject = jsonArray.getJsonObject(i); Long start = Long.valueOf(jsonObject.getInt("start")); if (empiricalValue >= start && empiricalValue < (i result = new HashMap<>(); result.put("currentLevel", currentLevel); double levelUpPercentage; if (nextStart != null) { levelUpPercentage = (double)(empiricalValue - currentStart) / (nextStart - currentStart); } else { levelUpPercentage = 1.0; } result.put("levelUpPercentage", levelUpPercentage); return result; } else { throw new BusinessException("没有配置对应的等级对应经验值"); } } else { throw new BusinessException("用户不存在"); } } /** * 任务初始化.显示各个任务能否点击 * * @return R */ public R taskInitialization() { User authenticatedUser = SecurityUtils.getAuthenticatedUser(); Long authId = authenticatedUser.getId(); Optional byUserId = riceRepo.findByUserId(authId); if (byUserId.isPresent()) { Rice rice = byUserId.get(); Long lastSignInTime = rice.getLastSignInTime(); Long currentTime = System.currentTimeMillis(); // 判断上次签到时间是否为空,如果为空,则默认为从未签到过 if (lastSignInTime == null) { return R.success("未签到").add("isSignedIn", false).add("exchangeCount", rice.getExchangeCount() == null ? 0 : rice.getExchangeCount()).add("waterDropCount", rice.getWaterDropCount()); } // 判断今天是否已经签到过 if (DateUtils.isSameDay(new Date(lastSignInTime), new Date(currentTime))) { return R.success("已签到").add("isSignedIn", true).add("exchangeCount", rice.getExchangeCount() == null ? 0 : rice.getExchangeCount()).add("waterDropCount", rice.getWaterDropCount()); } else { return R.success("未签到").add("isSignedIn", false).add("exchangeCount", rice.getExchangeCount() == null ? 0 : rice.getExchangeCount()).add("waterDropCount", rice.getWaterDropCount()); } } return R.error("查询失败"); } /** * 获取当前用户积分 */ public R getCurrentScore() { User authenticatedUser = SecurityUtils.getAuthenticatedUser(); Long authId = authenticatedUser.getId(); Optional byUserId = riceRepo.findByUserId(authId); if (byUserId.isPresent()) { Rice rice = byUserId.get(); Long selfScore = rice.getSelfScore(); return R.success("获取到当前用户积分").add("selfScore", selfScore); } return R.error("获取失败"); } //在RiceService中添加一个方法用于更新所有用户的排名。 public void updateScoreRank() { List allRices = riceRepo.findAll(); allRices.sort(Comparator.comparing(Rice::getSelfScore).reversed()); for (int i = 0; i < allRices.size(); i++) { Rice rice = allRices.get(i); // rice.setScoreRank(i + 1); riceRepo.save(rice); } } public List getTop100(Long userId) { List top100Rices = riceRepo.findTop100OrderByEmpiricalValueDesc(); List result = new ArrayList<>(); // 计算自己的排名 int selfRank = 0; for (int i = 0; i < top100Rices.size(); i++) { if (top100Rices.get(i).getId().equals(userId)) { selfRank = i + 1; break; } } for (int i = 0; i < top100Rices.size(); i++) { Rice rice = top100Rices.get(i); RiceDTO riceDTO = new RiceDTO(); BeanUtils.copyProperties(rice, riceDTO); riceDTO.setScoreRank(i + 1); // 判断是否上榜 if (i < 100) { riceDTO.setOnTop100(true); } else { riceDTO.setOnTop100(false); } // 如果是自己,则设置自己的头像、昵称、等级和离上榜还差多少名 if (rice.getId().equals(userId)) { riceDTO.setAvatar(rice.getAvatar()); riceDTO.setNickname(rice.getNickname()); riceDTO.setLevel(rice.getLevel()); if (i < 100) { riceDTO.setRankGap(0); } else { riceDTO.setRankGap(i + 1 - 100); } } result.add(riceDTO); } return result; } //计算自己排名 public R getRiceUserRank(Long userId) { Optional rice1 = riceRepo.findByUserId(userId); if (!rice1.isPresent()) { return R.error("用户不存在"); } List top100Rices = riceRepo.findByOrderBySelfScoreDesc(); List result = new ArrayList<>(); RiceDTO dto = new RiceDTO(); // 计算自己的排名 int selfRank = 0; for (int i = 0; i < top100Rices.size(); i++) { if (top100Rices.get(i).getUserId().equals(userId)) { selfRank = i + 1; break; } } for (int i = 0; i < top100Rices.size(); i++) { Rice rice = top100Rices.get(i); RiceDTO riceDTO = new RiceDTO(); BeanUtils.copyProperties(rice, riceDTO); riceDTO.setScoreRank(i + 1); // 判断是否上榜 if (i < 100) { riceDTO.setOnTop100(true); } else { riceDTO.setOnTop100(false); } // 如果是自己,则设置自己的头像、昵称、等级和离上榜还差多少名 if (rice.getUserId().equals(userId)) { riceDTO.setAvatar(rice.getAvatar()); riceDTO.setNickname(rice.getNickname()); riceDTO.setLevel(rice.getLevel()); if (i < 100) { riceDTO.setRankGap(0); } else { riceDTO.setRankGap(i + 1 - 100); } BeanUtils.copyProperties(riceDTO, dto); } } if (dto == null) { return R.error("用户不存在"); } return R.success(dto); } //浇水 public R watering() { // 获取当前用户 ID, User authenticatedUser = SecurityUtils.getAuthenticatedUser(); Long authId = authenticatedUser.getId(); Optional byUserId = riceRepo.findByUserId(authId); if (byUserId.isPresent()) { Rice rice = byUserId.get(); Long waterDropCount = rice.getWaterDropCount(); Long beforeWaterDropCount = rice.getWaterDropCount(); Long beforeEmpiricalValue = rice.getEmpiricalValue(); // 如果水滴次数为 0,返回不能浇水的提示 if (waterDropCount == 0) { return R.error("水滴次数已用完,无法浇水").add("can", false); } // 浇水成功,更新水滴次数,经验值加2 rice.setWaterDropCount(waterDropCount - 1); rice.setEmpiricalValue(rice.getEmpiricalValue()+2); riceRepo.save(rice); createRiceOperationRecord(authId, RiceOperationType.WATER_DROP, 1L,beforeWaterDropCount , rice.getWaterDropCount()); createRiceOperationRecord(authId, RiceOperationType.EMPIRICAL_VALUE, 2L,beforeEmpiricalValue , rice.getEmpiricalValue()); // Save watering record RiceUserWaterDropRecord record = new RiceUserWaterDropRecord(); record.setUserId(authId); record.setWateringTime(LocalDateTime.now()); riceUserWaterDropRecordRepo.save(record); return R.success("浇水成功").add("can", true).add("time", waterDropCount - 1); } return R.error("浇水失败").add("can", false); } //根据用户ID和今日时间获取今日浇水次数的方法 public Long getTodayWateringCount(Long userId) { List records = riceUserWaterDropRecordRepo.findByUserId(userId); Long count = records.stream() .filter(RiceUserWaterDropRecord::isToday) .count(); return count; } /** * 每浇水一次可获得2经验值,升级所需经验值为下一等级所配置的经验值标准。按照以下方式来计算用户升级所需水滴数 * @param rice * @return */ public Long getWaterDropNeededForLevelUp(Rice rice) { Long currentEmpiricalValue = rice.getEmpiricalValue(); String jsonString = sysConfigService.getString("rice_level"); JsonReader jsonReader = Json.createReader(new StringReader(jsonString)); JsonArray jsonArray = jsonReader.readArray(); for (int i = 0; i < jsonArray.size(); i++) { JsonObject jsonObject = jsonArray.getJsonObject(i); Long start = Long.valueOf(jsonObject.getInt("start")); Long nextStart = 0L; if (i + 1 < jsonArray.size()) { JsonObject nextJsonObject = jsonArray.getJsonObject(i + 1); nextStart = Long.valueOf(nextJsonObject.getInt("start")); } if (currentEmpiricalValue >= start && currentEmpiricalValue < nextStart) { Long levelUpEmpiricalValue = nextStart - currentEmpiricalValue; Long waterDropNeededForLevelUp = levelUpEmpiricalValue / 2; return waterDropNeededForLevelUp; } } throw new BusinessException("没有配置对应的等级对应经验值"); } //签到 public R signIn(Long userId) { Optional byUserId = riceRepo.findByUserId(userId); if (byUserId.isPresent()) { Rice rice = byUserId.get(); Long lastSignInTime = rice.getLastSignInTime(); Long currentTime = System.currentTimeMillis(); Long beforeWaterDropCount = rice.getWaterDropCount(); Long beforeEmpiricalValue = rice.getEmpiricalValue(); // 判断上次签到时间是否为空,如果为空,则默认为从未签到过 if (lastSignInTime == null) { rice.setWaterDropCount(rice.getWaterDropCount() + 1); rice.setSignCount(rice.getSignCount() + 1); rice.setLastSignInTime(currentTime); riceRepo.save(rice); createRiceOperationRecord(userId,RiceOperationType.WATER_DROP, (long) 1,beforeWaterDropCount,rice.getWaterDropCount()); return R.success("签到成功").add("can",true).add("waterDropCount",rice.getWaterDropCount()); } // 判断今天是否已经签到过 if (DateUtils.isSameDay(new Date(lastSignInTime), new Date(currentTime))) { return R.error("今天已经签到过了").add("can",false); } // 签到成功,水滴数加1,签到次数加1,更新签到时间 rice.setWaterDropCount(rice.getWaterDropCount() + 1); rice.setSignCount(rice.getSignCount() + 1); rice.setLastSignInTime(currentTime); riceRepo.save(rice); createRiceOperationRecord(userId,RiceOperationType.WATER_DROP, (long) 1,beforeWaterDropCount,rice.getWaterDropCount()); return R.success("签到成功").add("can",true).add("waterDropCount",rice.getWaterDropCount()); } return R.error("签到失败").add("can",false); } @Transactional public R exchangeScoreForWaterDrop(User authenticatedUser) { Long authId = authenticatedUser.getId(); Optional byUserId = riceRepo.findByUserId(authId); if (byUserId.isPresent()) { Rice rice = byUserId.get(); Long selfScore = rice.getSelfScore(); Long beforeSelfScore = rice.getSelfScore(); Integer waterDropCount = Math.toIntExact(rice.getWaterDropCount()); Long beforeWaterDropCount = rice.getWaterDropCount(); // 每次兑换需要消耗的积分和最大兑换次数 int exchangeScore = 2; int maxExchangeCount = 10; // 计算当前可兑换的次数和消耗的积分 if(rice.getExchangeCount()==null){ rice.setExchangeCount(0); } int exchangeCount = Math.min((int) (selfScore / exchangeScore), maxExchangeCount-rice.getExchangeCount()); int totalScore = exchangeCount * exchangeScore; if (exchangeCount > 0) { rice.setSelfScore(selfScore - totalScore); rice.setWaterDropCount((long) (waterDropCount + exchangeCount)); riceRepo.save(rice); createRiceOperationRecord(authId,RiceOperationType.WATER_DROP, (long) exchangeCount,beforeWaterDropCount,rice.getWaterDropCount()); return R.success("兑换成功").add("exchangeCount", exchangeCount).add("waterDropCount", rice.getWaterDropCount()); } else if(exchangeCount==0){ return R.error("今天已经兑换满10滴水滴了"); } else { return R.error("兑换失败,当前积分不足").add("exchangeCount", 0).add("waterDropCount", rice.getWaterDropCount()); } } return R.error("兑换失败,用户不存在"); } private void createRiceOperationRecord(Long userId, RiceOperationType type, Long amount, Long beforeAmount, Long afterAmount) { RiceOperationRecord record = new RiceOperationRecord(); record.setUserId(userId); record.setType(type); record.setAmount(amount); record.setBeforeAmount(beforeAmount); record.setAfterAmount(afterAmount); riceOperationRecordRepo.save(record); } //活动积分兑换水滴,无上限. public R exchangeActivityScoreForWaterDrop(User authenticatedUser) { // 检查用户活动积分是否足够 Optional optionalRice = riceRepo.findById(authenticatedUser.getId()); if (!optionalRice.isPresent()) { return R.error("未找到用户信息"); } Rice rice = optionalRice.get(); Long currentActivityPoints = rice.getSelfActivityScore(); Long beforeWaterDropCount = rice.getWaterDropCount(); // 计算兑换的水滴数量 Long exchangedWaterDropCount = (long) Math.floor(currentActivityPoints / 2.0); if (exchangedWaterDropCount <= 0) { return R.error("活动积分不足以兑换水滴").add("times",exchangedWaterDropCount); } // 更新用户活动积分和水滴数 rice.setSelfActivityScore(currentActivityPoints - (Long) exchangedWaterDropCount*2); rice.setWaterDropCount(rice.getWaterDropCount() + exchangedWaterDropCount); riceRepo.save(rice); // 记录水滴操作记录 createRiceOperationRecord(authenticatedUser.getId(), RiceOperationType.WATER_DROP, exchangedWaterDropCount, beforeWaterDropCount, rice.getWaterDropCount()); createRiceOperationRecord(authenticatedUser.getId(), RiceOperationType.SELF_ACTIVITY_SCORE, (Long) exchangedWaterDropCount*2, currentActivityPoints, rice.getSelfActivityScore()); return R.success("兑换成功").add("times", exchangedWaterDropCount); } }