package cn.fw.morax.service.biz.calculator.eval.reward; import cn.fw.morax.common.utils.PublicUtil; import cn.fw.morax.domain.bo.eval.EvalGroupUserShop; import cn.fw.morax.domain.db.eval.*; import cn.fw.morax.domain.enums.*; import cn.fw.morax.service.biz.CommonService; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.sun.org.apache.regexp.internal.RE; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * @author jiangchao * @des: 排名正负激励 * @date 2023/2/1 11:03 */ @Component @Slf4j @RequiredArgsConstructor public class EvalRewardRankCalculator extends EvalRewardBaseCalculator { private final CommonService commonService; @Override public EvalRewardCalMethodEnum getCalMethod() { return EvalRewardCalMethodEnum.RANK; } @Override public BigDecimal calculate(EvalGroupUserShop param, EvalGroupReward rewardBO) { return null; } @Override public void calculateGroup(List userShops, EvalGroupReward reward) { userShops = userShops.stream().filter(userShop -> Boolean.FALSE.equals(userShop.getIgnored())).collect(Collectors.toList()); if (PublicUtil.isEmpty(userShops)) { return; } initReward(userShops); final Long evalGroupRewardId = reward.getId(); RankTypeEnum rankType = reward.getRankType(); List preconditions = queryPrecondition(evalGroupRewardId); List params = queryProjectParam(evalGroupRewardId, ParamTypeEnum.LADDER); if (CollectionUtils.isEmpty(params)) { return; } //计算排名 List rankLogs = calculateRankParamValue(userShops, evalGroupRewardId, params); Collections.sort(rankLogs); commonService.calcRank(rankLogs); saveRankLogs(evalGroupRewardId, rankLogs, RankIndicatorTypeEnum.REWARD_COMMISSION); Map poolUserShopMap = userShops.stream().collect(Collectors.toMap(EvalGroupUserShop::getPoolId, Function.identity(), (v1, v2) -> v1)); //计算金额 final BigDecimal personCount = BigDecimal.valueOf(userShops.size()); List ladders = queryRewardLadders(evalGroupRewardId); for (EvalGroupRewardLadders ladder : ladders) { final BigDecimal money = ladder.getMoney(); List matchRankLogs = matchRank(rankType, personCount, ladder, rankLogs); updateHitRankLog(matchRankLogs); for (EvalGroupRewardRankLog rankLog : matchRankLogs) { EvalGroupUserShop userShop = poolUserShopMap.get(rankLog.getPoolId()); boolean examined = examinePrecondition(userShop, preconditions); if (!examined) { userShop.setEvalGroupRewardAmount(BigDecimal.ZERO); continue; } userShop.setEvalGroupRewardAmount(money); BigDecimal hitCommissionValue = rankLog.getReachValue(); clearProjectHitLog(evalGroupRewardId, userShop); saveProjectHitLog(evalGroupRewardId, userShop, log -> { log.setRewardValue(money); log.setEvalGroupRewardLaddersId(ladder.getId()); log.setHitLadderValue(hitCommissionValue); log.setHitCommissionValue(hitCommissionValue); }); } } } /** * 匹配排名 * * @param rankType * @param personCount * @param ladder * @param rankLogs * @return */ public List matchRank(final RankTypeEnum rankType, final BigDecimal personCount, EvalGroupRewardLadders ladder, List rankLogs) { BigDecimal lower = ladder.getLower(); BigDecimal upper = ladder.getUpper(); RankOrderTypeEnum rankOrderType = ladder.getRankOrderType(); Integer startIndex ; Integer endIndex ; //百分比 if (RankTypeEnum.PERCENT.equals(rankType)) { if (RankOrderTypeEnum.NEGATIVE.equals(rankOrderType)) { lower = BigDecimal.ONE.subtract(ladder.getUpper()); upper = BigDecimal.ONE.subtract(ladder.getLower()); } startIndex = lower.multiply(personCount).divide(BigDecimal.ONE, 0, RoundingMode.FLOOR).intValue(); endIndex = upper.multiply(personCount).divide(BigDecimal.ONE, 0, RoundingMode.FLOOR).intValue(); if (startIndex > endIndex) { return new ArrayList<>(); } Integer finalEndIndex = endIndex,finalStartIndex = startIndex; List matchRankLogs = rankLogs.stream().filter(rankLog -> { return rankLog.getRank() > finalStartIndex && rankLog.getRank() <= finalEndIndex; }).collect(Collectors.toList()); return matchRankLogs; } //名次 if (RankOrderTypeEnum.NEGATIVE.equals(rankOrderType)) { startIndex = personCount.subtract(upper).intValue() + 1; endIndex = personCount.subtract(lower).intValue() + 1; } else { startIndex = ladder.getLower().intValue(); endIndex = ladder.getUpper().intValue(); } if (startIndex > endIndex) { return new ArrayList<>(); } Integer finalEndIndex = endIndex,finalStartIndex = startIndex; List matchRankLogs = rankLogs.stream().filter(rankLog -> { return rankLog.getRank() >= finalStartIndex && rankLog.getRank() <= finalEndIndex; }).collect(Collectors.toList()); return matchRankLogs; } }