package com.kioor.utils;

import com.kioor.dto.Monster2GoodsDTO;
import com.github.javafaker.Faker;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author kioor
 * @ClassName RandomUtils
 * @description: 随机概率工具
 *  常见四种概率算法：
 *      1.常规做法，直接配置概率，程序直接判定
 *      2.在1的基础上，加个保底次数，当连续不发生的次数高于保底时，强制发生
 *      3.设置基础概率，事件不发生概率翻倍
 *      4.设置数组，将事件发生概率变成数组元素
 * @date 2023年07月26日
 * @version: 1.0
 */
public class RandomUtils {
    static Faker faker = new Faker(Locale.CHINA);

    private static final ThreadLocalRandom RANDOM =
            ThreadLocalRandom.current();
    /**
     * 怪物掉落物品计算（对象列表）
     * @param monster2GoodsDTOList 对象列表
     * @return 筛选后的对象列表
     */
    public static List<Monster2GoodsDTO> obtainGoods(List<Monster2GoodsDTO> monster2GoodsDTOList){
        List<Monster2GoodsDTO> backMonster2GoodsDTOList = new ArrayList<>();
        for(Monster2GoodsDTO monster2GoodsDTO:monster2GoodsDTOList){
            if(isLuck(monster2GoodsDTO.getGoodsProb())){
                backMonster2GoodsDTOList.add(monster2GoodsDTO);
            }
        }
        return backMonster2GoodsDTOList;
    }


    /**
     * 怪物掉落物品计算（数组）
     * @param propArr 将概率按照顺序放入数组
     * @return 命中的数组下标
     */
    public static int[] obtainGoods(BigDecimal[] propArr){
        StringBuffer indexStr = new StringBuffer();
        List<Monster2GoodsDTO> backMonster2GoodsDTOList = new ArrayList<>();
        for(int i=0;i<propArr.length;i++){
            if(isLuck(propArr[i])){
                indexStr.append(i).append(",");
            }
        }
        if(indexStr.length()==0){
            return new int[0];
        }
        return Arrays.asList(indexStr.toString().split(",")).stream().mapToInt(Integer::parseInt).toArray();
    }
    /**
     * 由概率随机是否触发
     *
     * @param chance 0.000000 - 1.000000
     * @return boolean
     */
    public static final boolean isLuck(BigDecimal chance) {
        // chance = 50.0;// 测试：50%成功
        int chanceInt = chance.multiply(new BigDecimal("1000000")).intValue();
        int randomNum = RANDOM.nextInt(1000000);
        return randomNum <= chanceInt;
    }

    public static void main(String[] args) {

        /**
         * 怪物掉落物品计算（对象列表）
         */
        List<Monster2GoodsDTO> monster2GoodsDTOList = new ArrayList<>();

        Monster2GoodsDTO monster2GoodsDTO1 = new Monster2GoodsDTO(1000000L,"金疮药",new BigDecimal("0.100000"));
        monster2GoodsDTOList.add(monster2GoodsDTO1);

        Monster2GoodsDTO monster2GoodsDTO2 = new Monster2GoodsDTO(1000001L,"柿饼",new BigDecimal("0.100000"));
        monster2GoodsDTOList.add(monster2GoodsDTO2);

        Monster2GoodsDTO monster2GoodsDTO3 = new Monster2GoodsDTO(2000000L,"青铜甲",new BigDecimal("0.010000"));
        monster2GoodsDTOList.add(monster2GoodsDTO3);

        Monster2GoodsDTO monster2GoodsDTO4 = new Monster2GoodsDTO(2000001L,"青铜盔",new BigDecimal("0.010000"));
        monster2GoodsDTOList.add(monster2GoodsDTO4);

        Monster2GoodsDTO monster2GoodsDTO5 = new Monster2GoodsDTO(2000002L,"青铜靴",new BigDecimal("0.010000"));
        monster2GoodsDTOList.add(monster2GoodsDTO5);

        Monster2GoodsDTO monster2GoodsDTO6 = new Monster2GoodsDTO(2000003L,"青铜戒",new BigDecimal("0.010000"));
        monster2GoodsDTOList.add(monster2GoodsDTO6);

        Monster2GoodsDTO monster2GoodsDTO7 = new Monster2GoodsDTO(2000004L,"青铜镯",new BigDecimal("0.910000"));
        monster2GoodsDTOList.add(monster2GoodsDTO7);

        Monster2GoodsDTO monster2GoodsDTO8 = new Monster2GoodsDTO(2000005L,"青铜项链",new BigDecimal("0.010000"));
        monster2GoodsDTOList.add(monster2GoodsDTO8);

        Monster2GoodsDTO monster2GoodsDTO9 = new Monster2GoodsDTO(2000006L,"青铜剑",new BigDecimal("0.010000"));
        monster2GoodsDTOList.add(monster2GoodsDTO9);

        Monster2GoodsDTO monster2GoodsDTO10 = new Monster2GoodsDTO(2000007L,"青铜棍",new BigDecimal("0.010000"));
        monster2GoodsDTOList.add(monster2GoodsDTO10);

        Monster2GoodsDTO monster2GoodsDTO11 = new Monster2GoodsDTO(2000008L,"青铜刀",new BigDecimal("0.010000"));
        monster2GoodsDTOList.add(monster2GoodsDTO11);

//        //单次测试
//        List<Monster2GoodsDTO> backMonster2GoodsDTOList1 = obtainGoods(monster2GoodsDTOList);
//        for(Monster2GoodsDTO backMonster2GoodsDTO:backMonster2GoodsDTOList1) {
//            System.out.println(backMonster2GoodsDTO.getGoodsName());
//        }

        //批量测试
//        int count = 100;
//        Map<String,Integer> result = new HashMap<>();
//        for(int i=0;i<count;i++) {
//            List<Monster2GoodsDTO> backMonster2GoodsDTOList = obtainGoods(monster2GoodsDTOList);
//            for(Monster2GoodsDTO backMonster2GoodsDTO:backMonster2GoodsDTOList){
//                if(result.containsKey(backMonster2GoodsDTO.getGoodsName())){
//                    result.put(backMonster2GoodsDTO.getGoodsName(),result.get(backMonster2GoodsDTO.getGoodsName())+1);
//                }else {
//                    result.put(backMonster2GoodsDTO.getGoodsName(),1);
//                }
//            }
//        }
//        result.forEach((key,value)->{
//            System.out.println(key+":"+value);
//        });

        /**
         * 怪物掉落物品计算（数组）
         */
        BigDecimal[] propArr = new BigDecimal[monster2GoodsDTOList.size()];
        for(int i=0;i<monster2GoodsDTOList.size();i++){
            propArr[i] = monster2GoodsDTOList.get(i).getGoodsProb();
        }
        int[] resultIndex = obtainGoods(propArr);
        System.out.println(Arrays.toString(resultIndex));
    }
}
