1 package com.ranfa.lib.calc;
3 import java.math.BigDecimal;
4 import java.math.RoundingMode;
5 import java.util.concurrent.CompletableFuture;
6 import java.util.concurrent.ExecutorService;
7 import java.util.concurrent.Executors;
8 import java.util.concurrent.atomic.AtomicBoolean;
9 import java.util.concurrent.atomic.AtomicInteger;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
14 import com.ranfa.lib.concurrent.CountedThreadFactory;
22 public class FanCalc {
24 private static final Logger logger = LoggerFactory.getLogger(FanCalc.class);
25 private static final ExecutorService async = Executors.newCachedThreadPool(new CountedThreadFactory(() -> "DRS", "FanCalcThread", false));
29 * 端数切り上げ(スコア*0.001*ルーム補正値*センター、ゲスト効果補正値*プロデュース方針補正値)
30 * ルーム、センター、ゲスト、プロデュース方針の補正値は百分率。計算時に自動で変換します
31 * @param score ライブで獲得したスコアを入力します
32 * @param room ルームアイテムによる補正値を百分率のまま(xxx%)入力します
33 * @param center センター、ゲスト効果による補正値を百分率のまま入力します
34 * @param produce プロデュース方針による補正値を百分率のまま入力します
35 * @return 一人あたりの獲得ファン数。1回のライブで獲得出来るファン数はこの値の5倍です
37 public static int fan(int score, int room, int center, int produce, int premium) {
38 BigDecimal toPercent = new BigDecimal(100);
39 BigDecimal res = new BigDecimal(0);
40 BigDecimal roomPercent = new BigDecimal(room).divide(toPercent);
41 BigDecimal centerPercent = new BigDecimal(center).divide(toPercent);
42 BigDecimal producePercent = new BigDecimal(produce).divide(toPercent);
43 BigDecimal premiumPercent = new BigDecimal(premium).divide(toPercent);
44 BigDecimal corrections = new BigDecimal(-1)
47 res = res.add(new BigDecimal(score))
48 .multiply(corrections)
49 .divide(new BigDecimal("1000"));
50 res = res.setScale(0,RoundingMode.UP);
51 BigDecimal resCorrected = res.multiply(producePercent);
52 resCorrected = resCorrected.setScale(0,RoundingMode.UP);
53 BigDecimal resPremiumed = resCorrected.multiply(premiumPercent);
54 resPremiumed = resPremiumed.setScale(0, RoundingMode.UP);
55 return (resPremiumed.compareTo(BigDecimal.ZERO) == 0) ? 0 : Integer.parseInt(resPremiumed.toString());
58 public static CompletableFuture<Integer> fanAsync(int score, int room, int center, int produce, int premium) {
59 return CompletableFuture.supplyAsync(() -> fan(score, room, center, produce, premium), async);
64 * 初期実装の思想は並列処理による再帰計算。
66 * @param multiplier LIVEの繰り返し回数
67 * @param room ルームアイテム補正値(百分率)
68 * @param center センター、ゲスト効果による補正値
69 * @param produce プロデュース方針にとる補正値
70 * @param premium プレミアムパスによる補正値
71 * @return LIVE一回当たりの目標スコア
73 public static CompletableFuture<Integer> scoreAsync(int fan, int multiplier, int room, int center, int produce, int premium) {
74 return CompletableFuture.supplyAsync(() -> score(fan, multiplier, room, center, produce, premium), async);
79 * @param multiplier LIVEの繰り返し回数
80 * @param room ルームアイテム補正値(百分率)
81 * @param center センター、ゲスト効果による補正値
82 * @param produce プロデュース方針にとる補正値
83 * @param premium プレミアムパスによる補正値
84 * @return LIVE一回当たりの目標スコア
86 private static int score(int fan, int multiplier, int room, int center, int produce, int premium) {
87 BigDecimal goalFan = new BigDecimal(fan).divide(new BigDecimal(multiplier), 0, RoundingMode.UP);
88 final AtomicInteger result = new AtomicInteger(0);
89 final AtomicBoolean flag = new AtomicBoolean(false);
90 logger.info("Started to calculate score at dedicated thread.");
92 int localFan = fan(result.incrementAndGet(), room, center, produce, premium) * 5;
93 if(goalFan.compareTo(new BigDecimal(localFan)) <= 0) {
97 logger.info("Finished calculating. Estimated Fan value : {}", result.intValue());
98 return Integer.parseInt(result.toString());