赞
踩
关于业绩分配,常常会出现几家公司或者几个人合作的情况,那么合作之后创造出来的业绩价值如何分配的呢?有可能是1:1或者3:7.或者是3:3:4等等。那么我们针对这种情况就设计出来了一套比例分成系统。
代码如下所示:
主代码:
- package com.handler.mark.cardperformance;
-
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.dataplatform.dto.base.IBaseOrgDTO;
- import com.dataplatform.enums.DimensionChannelGroupEnum;
- import com.dataplatform.model.ApplyDetailInfo;
- import com.dataplatform.util.MarkByProportionUtil;
- import org.apache.commons.lang3.StringUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import redis.clients.jedis.ShardedJedis;
- import redis.clients.jedis.ShardedJedisPool;
-
- import java.math.BigInteger;
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * Created by on 2018/7/20.
- */
-
- /**
- * 比例分成算法
- * @author
- * @date 2018-07-26
- * @version 1.0
- *
- */
- public class WeightRoundRobinBo {
-
- private static final int DEF_CURRENT_INDEX = -1;
- private static final int DEF_CURRENT_WEIGHT = 0;
-
- private static final String KEY_CURRENT_INDEX = "currentIndex";
- private static final String KEY_CURRENT_WEIGHT = "currentWeight";
-
- private Logger LOG = LoggerFactory.getLogger(WeightRoundRobinBo.class);
-
- private ShardedJedisPool shardedJedisPool;
-
- @SuppressWarnings("unused")
- private WeightRoundRobinBo() {
- }
-
- /**
- * 自定义构造方法
- * @param orgListOfChannel 渠道所对应机构列表
- * @param currentEnum
- * @param applyDetailInfo 当前进件信息
- * @param shardedJedisPool
- */
- public WeightRoundRobinBo(List<? extends IBaseOrgDTO> orgListOfChannel, DimensionChannelGroupEnum currentEnum, ApplyDetailInfo applyDetailInfo, ShardedJedisPool shardedJedisPool) {
- this.orgListOfChannel = orgListOfChannel;
- this.shardedJedisPool = shardedJedisPool;
- try(ShardedJedis jedis = shardedJedisPool.getResource()){
-
-
- /** 持卡用户进件与新用户进件分开打标*/
- this.redisKey = MarkByProportionUtil.getRedisKeyOfCurrentWight(
- currentEnum.getDimensionCode(),
- currentEnum.getChannelGroupCode(),
- applyDetailInfo.getSource(),
- applyDetailInfo.getIsCardHolder()
- );
-
- if(StringUtils.isBlank(redisKey)){
- throw new RuntimeException("illegal parameters: redisKey is null");
- }
-
- JSONObject json = JSON.parseObject(jedis.get(this.redisKey));
-
- String currentIndexStr = json == null ? null : json.getString(KEY_CURRENT_INDEX);
- String currentWeightStr = json == null ? null : json.getString(KEY_CURRENT_WEIGHT);
-
- this.currentIndex = StringUtils.isNumeric(currentIndexStr) ? Integer.parseInt(currentIndexStr) : DEF_CURRENT_INDEX;
- this.currentWeight = StringUtils.isNumeric(currentWeightStr) ? Integer.parseInt(currentWeightStr) : DEF_CURRENT_WEIGHT;
- this.orgCount = orgListOfChannel.size();
- this.maxWeight = greatestWeight();
- this.gcdWeight = greatestCommonDivisor();
-
-
- this.initStatus = true;
-
- }catch (Exception e){
- LOG.error("WeightRoundRobin init error: ", e);
- }
- }
-
- /**
- * 上次选择机构
- */
- private int currentIndex = DEF_CURRENT_INDEX;
- /**
- * 当前调度的权值
- */
- private int currentWeight = DEF_CURRENT_WEIGHT;
- /**
- * 最大权重
- */
- private int maxWeight;
- /**
- * 权重的最大公约数
- */
- private int gcdWeight;
- /**
- * 机构数量
- */
- private int orgCount;
-
- private List<? extends IBaseOrgDTO> orgListOfChannel = new ArrayList<>();
-
- /**
- * redis上保存当前index和weight的key
- */
- private String redisKey;
-
- /**
- * 是否初始化
- */
- private boolean initStatus = false;
-
- /**
- * 获取两个数的最大公约数
- */
- private int greaterCommonDivisor(int a, int b) {
- BigInteger aBig = new BigInteger(String.valueOf(a));
- BigInteger bBig = new BigInteger(String.valueOf(b));
- return aBig.gcd(bBig).intValue();
- }
-
- /**
- * 遍历获取所有机构比例的最大公约数
- */
- private int greatestCommonDivisor() {
- int divisor = 0;
- for (int index = 0, len = orgListOfChannel.size(); index < len - 1; index++) {
- if (index == 0) {
- divisor = greaterCommonDivisor(
- orgListOfChannel.get(index).getProportion(), orgListOfChannel.get(index + 1).getProportion());
- } else {
- divisor = greaterCommonDivisor(divisor, orgListOfChannel.get(index).getProportion());
- }
- }
- return divisor;
- }
-
- /**
- * 遍历获取最大的机构占比(权重)
- */
- private int greatestWeight() {
- int weight = 0;
- for (IBaseOrgDTO orgObj : orgListOfChannel) {
- if (weight < orgObj.getProportion()) {
- weight = orgObj.getProportion();
- }
- }
- return weight;
- }
-
- /**
- * 根据权重轮询获取当前org
- *
- * @gcdWeight 权重的最大公约数
- * @currentIndex 用于记录当前轮询链表的位置
- * @currentWeight 用于记录当前权重值
- * @orgListOfChannel 用于当前进件的渠道所对应的分成机构列表
- *
- *
- * 初始从最大的权重(占比)进行分配 currentWeight = maxWeight
- *
- * 非初始情况,根据redis缓存中保存的位置currentIndex和currentWeight继续分配
- *
- * 遍历机构列表,每次遍历输出大于等于currentWeight的机构对象
- *
- * 每次遍历完,将currentWeight减去 所有机构权重值的最大公约数,再次遍历输出
- *
- * 直到currentWeight小于等于零,即完成了一遍权重轮询,每一个权重值都输出了对应比例的次数
- *
- *
- */
- private IBaseOrgDTO getOrgInfo() {
- while (true) {
- currentIndex = (currentIndex + 1) % orgCount;
- if (currentIndex == 0) {
- currentWeight = currentWeight - gcdWeight;
- if (currentWeight <= 0) {
- currentWeight = maxWeight;
- if (currentWeight == 0) {
- return null;
- }
- }
- }
- if (orgListOfChannel.get(currentIndex).getProportion() >= currentWeight) {
- return orgListOfChannel.get(currentIndex);
- }
- }
- }
-
- /**
- * 输出org后,将currentIndex和currentWeight更新到redis上
- */
- private void updateRedis(){
- JSONObject json = new JSONObject();
- json.put(KEY_CURRENT_INDEX, currentIndex);
- json.put(KEY_CURRENT_WEIGHT, currentWeight);
-
- try(ShardedJedis jedis = shardedJedisPool.getResource()){
- jedis.set(this.redisKey, json.toJSONString());
- }catch (Exception e){
- LOG.error("updateRedis error: ", e);
- }
-
- }
-
- public IBaseOrgDTO execute(){
- IBaseOrgDTO org = null;
- if(initStatus) {
- org = getOrgInfo();
- updateRedis();
- }
- return org;
- }
-
- }
- package com.cmbc.util;
-
- import org.apache.commons.lang3.StringUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- /**
- * Created by on 2018/8/13.
- */
- public class MarkByProportionUtil {
-
- private static Logger LOG = LoggerFactory.getLogger(MarkByProportionUtil.class);
-
- /**
- * 比例打标redis key前缀
- */
- public static final String REDIS_KEY_PREFIX = "WSDP_index&weight";
-
- /**
- * 比例打标redis key分隔符
- */
- public static final String REDIS_KEY_SEPARATOR = ":";
-
- public static String getRedisKeyOfCurrentWight(String dimensionCode, String channelGroupCode, String channel, int isCardHolder) {
-
- if (StringUtils.isAnyBlank(dimensionCode, channelGroupCode, channel)) {
- LOG.error("illegal parameters: dimensionCode:{}, channelGroupCode:{}, channel:{}", dimensionCode, channelGroupCode, channel);
- }
-
- /** 固定前缀 + 维度code + 渠道组code + 渠道代码 + 是否持卡人 */
- String key = new StringBuffer()
- .append(REDIS_KEY_PREFIX)
- .append(REDIS_KEY_SEPARATOR)
- .append(dimensionCode)
- .append(REDIS_KEY_SEPARATOR)
- .append(channelGroupCode)
- .append(REDIS_KEY_SEPARATOR)
- .append(channel)
- .append("_")
- .append(isCardHolder)
- .toString();
-
- return key;
- }
- }
- package com.cmbc.dto.base;
-
- /**
- * Created by on 2018/7/22.
- */
- public interface IBaseOrgDTO {
-
- /**
- * 获取机构id
- * @return
- */
- public abstract Integer getOrgId();
-
- /**
- * 获取比例
- * @return
- */
- public abstract Integer getProportion();
-
- /**
- * 获取机构类型
- * @return
- */
- public abstract String getOrgType();
- }
调用方法:
- /** 按比例分成 */
- WeightRoundRobinBo wrr = new WeightRoundRobinBo(orgList, rule, applyDetailInfo,
- cacheService.getShardedJedisPool());
-
- org = wrr.execute();
- if (null == org) {
-
- LOG.error(ErrorEnums.ERR_10013.getMsg());
- return ErrorEnums.ERR_10013.getMsg();
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。