|
@@ -4,10 +4,7 @@ import cn.hutool.core.util.StrUtil;
|
|
|
import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallInsightDTO;
|
|
|
import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallTrendDTO;
|
|
|
import com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallTrendDetailDTO;
|
|
|
-import com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallCompetitorVO;
|
|
|
-import com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallInsightVO;
|
|
|
-import com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallTrendDtlVO;
|
|
|
-import com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallTrendVO;
|
|
|
+import com.pig4cloud.pig.statistics.api.vo.uninstall.*;
|
|
|
import com.pig4cloud.pig.statistics.service.UninstallAnalyseService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
@@ -127,13 +124,6 @@ public class UninstallAnalyseServiceImpl implements UninstallAnalyseService {
|
|
|
/**
|
|
|
* 生成随机数量列表
|
|
|
*/
|
|
|
- private List<Integer> generateRandomCounts(int size, int min, int max) {
|
|
|
- List<Integer> counts = new ArrayList<>();
|
|
|
- for (int i = 0; i < size; i++) {
|
|
|
- counts.add(min + random.nextInt(max - min));
|
|
|
- }
|
|
|
- return counts;
|
|
|
- }
|
|
|
|
|
|
/**
|
|
|
* 计算比率列表
|
|
@@ -142,113 +132,223 @@ public class UninstallAnalyseServiceImpl implements UninstallAnalyseService {
|
|
|
return (double)numerators / denominator * 100;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 计算比率列表(分子为列表)
|
|
|
- */
|
|
|
- private List<Double> calculateRates(List<Integer> numerators, List<Integer> denominators) {
|
|
|
- List<Double> rates = new ArrayList<>();
|
|
|
- for (int i = 0; i < numerators.size(); i++) {
|
|
|
- if (denominators.get(i) == 0) {
|
|
|
- rates.add(0.0);
|
|
|
+ @Override
|
|
|
+ public UninstallInsightVO getUninstallDeviceActive(GetUninstallInsightDTO dto) {
|
|
|
+ return getUninstallDeviceActiveVO(dto);
|
|
|
+ }
|
|
|
+
|
|
|
+ public UninstallInsightVO getUninstallDeviceActiveVO(GetUninstallInsightDTO dto) {
|
|
|
+ // 1. 安装存量时长分布
|
|
|
+ String[] ranges = {"0-7天", "8-15天", "16-30天", "31-45天", "46-60天", "61-90天", "90天以上"};
|
|
|
+ int n = ranges.length;
|
|
|
+ double[] raw = new double[n];
|
|
|
+ double sum = 0;
|
|
|
+ for (int i = 0; i < n; i++) {
|
|
|
+ raw[i] = 10 + random.nextDouble() * 90;
|
|
|
+ sum += raw[i];
|
|
|
+ }
|
|
|
+ List<InstallStockVO> installStockList = new ArrayList<>();
|
|
|
+ int totalDevice = 1000 + random.nextInt(1000);
|
|
|
+ double percentSum = 0;
|
|
|
+ int uninstallSum = 0;
|
|
|
+ for (int i = 0; i < n; i++) {
|
|
|
+ InstallStockVO vo = new InstallStockVO();
|
|
|
+ vo.setTime(ranges[i]);
|
|
|
+ if (i < n - 1) {
|
|
|
+ vo.setUninstallRate(Math.round(raw[i] / sum * 10000.0) / 100.0);
|
|
|
+ percentSum += vo.getUninstallRate();
|
|
|
+ vo.setUninstallCount((int)Math.round(vo.getUninstallRate() / 100 * totalDevice));
|
|
|
+ uninstallSum += vo.getUninstallCount();
|
|
|
+ } else {
|
|
|
+ vo.setUninstallRate(Math.round((100.0 - percentSum) * 100.0) / 100.0);
|
|
|
+ vo.setUninstallCount(totalDevice - uninstallSum);
|
|
|
+ }
|
|
|
+ installStockList.add(vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 历史卸载次数分布
|
|
|
+ String[] counts = {"6次以上", "5次", "4次", "3次", "2次", "1次"};
|
|
|
+ int m = counts.length;
|
|
|
+ double[] raw2 = new double[m];
|
|
|
+ double sum2 = 0;
|
|
|
+ for (int i = 0; i < m; i++) {
|
|
|
+ raw2[i] = 10 + random.nextDouble() * 90;
|
|
|
+ sum2 += raw2[i];
|
|
|
+ }
|
|
|
+ List<com.pig4cloud.pig.statistics.api.vo.uninstall.HisUnInstallCountVO> hisList = new ArrayList<>();
|
|
|
+ int totalUninstall = 500 + random.nextInt(500);
|
|
|
+ double percentSum2 = 0;
|
|
|
+ int uninstallSum2 = 0;
|
|
|
+ for (int i = 0; i < m; i++) {
|
|
|
+ com.pig4cloud.pig.statistics.api.vo.uninstall.HisUnInstallCountVO vo = new com.pig4cloud.pig.statistics.api.vo.uninstall.HisUnInstallCountVO();
|
|
|
+ vo.setCount(counts[i]);
|
|
|
+ if (i < m - 1) {
|
|
|
+ double rate = Math.round(raw2[i] / sum2 * 10000.0) / 100.0;
|
|
|
+ vo.setRate(String.valueOf(rate));
|
|
|
+ percentSum2 += rate;
|
|
|
+ int num = (int)Math.round(rate / 100 * totalUninstall);
|
|
|
+ vo.setNum(String.valueOf(num));
|
|
|
+ uninstallSum2 += num;
|
|
|
} else {
|
|
|
- rates.add((double) numerators.get(i) / denominators.get(i) * 100);
|
|
|
+ double rate = Math.round((100.0 - percentSum2) * 100.0) / 100.0;
|
|
|
+ vo.setRate(String.valueOf(rate));
|
|
|
+ vo.setNum(String.valueOf(totalUninstall - uninstallSum2));
|
|
|
}
|
|
|
+ hisList.add(vo);
|
|
|
}
|
|
|
- return rates;
|
|
|
+
|
|
|
+ UninstallInsightVO vo = new UninstallInsightVO();
|
|
|
+ vo.setLifecycleDistribution(installStockList);
|
|
|
+ vo.setUninstallDistribution(hisList);
|
|
|
+ return vo;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public UninstallInsightVO getUninstallInsight(GetUninstallInsightDTO dto) {
|
|
|
- /*UninstallInsightVO vo = new UninstallInsightVO();
|
|
|
-
|
|
|
- // 生成生命周期分布数据
|
|
|
- vo.setLifecycleDistribution(Map.of(
|
|
|
- "1-7天", random.nextInt(100),
|
|
|
- "8-30天", random.nextInt(80),
|
|
|
- "1-3个月", random.nextInt(60),
|
|
|
- "3-6个月", random.nextInt(40),
|
|
|
- "6个月以上", random.nextInt(20)
|
|
|
- ));
|
|
|
-
|
|
|
- // 生成使用热度数据
|
|
|
- vo.setUsageHeatBeforeUninstall(Map.of(
|
|
|
- "0-1次", random.nextDouble() * 50,
|
|
|
- "1-3次", random.nextDouble() * 30,
|
|
|
- "3-5次", random.nextDouble() * 20,
|
|
|
- "5次以上", random.nextDouble() * 10
|
|
|
- ));
|
|
|
-
|
|
|
- // 生成崩溃统计数据
|
|
|
- vo.setCrashStats(Map.of(
|
|
|
- "0次", random.nextInt(100),
|
|
|
- "1-3次", random.nextInt(80),
|
|
|
- "3-5次", random.nextInt(50),
|
|
|
- "5次以上", random.nextInt(20)
|
|
|
- ));
|
|
|
-
|
|
|
- // 根据请求参数生成可选特征数据
|
|
|
- if (Boolean.TRUE.equals(dto.getIncludeDevice())) {
|
|
|
- vo.setDeviceFeatures(Map.of(
|
|
|
- "Android", random.nextDouble() * 70,
|
|
|
- "iOS", random.nextDouble() * 30
|
|
|
- ));
|
|
|
+ public com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallBeforeVO uninstallBefore(com.pig4cloud.pig.statistics.api.dto.uninstall.GetUninstallInsightDTO dto) {
|
|
|
+ // 1. 卸载时间差分布
|
|
|
+ String[] timeRanges = {"0-7天", "8-15天", "16-30天", "31-45天", "46-60天", "61-90天", "90天以上"};
|
|
|
+ List<com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallTimeDiffVO> timeDiffs = new ArrayList<>();
|
|
|
+ int total = 1000 + random.nextInt(1000);
|
|
|
+ double percentSum = 0;
|
|
|
+ int countSum = 0;
|
|
|
+ double[] raw = new double[timeRanges.length];
|
|
|
+ double sum = 0;
|
|
|
+ for (int i = 0; i < timeRanges.length; i++) {
|
|
|
+ raw[i] = 10 + random.nextDouble() * 90;
|
|
|
+ sum += raw[i];
|
|
|
}
|
|
|
-
|
|
|
- if (Boolean.TRUE.equals(dto.getIncludeRegion())) {
|
|
|
- vo.setRegionFeatures(Map.of(
|
|
|
- "华东", random.nextDouble() * 40,
|
|
|
- "华北", random.nextDouble() * 30,
|
|
|
- "华南", random.nextDouble() * 20,
|
|
|
- "其他", random.nextDouble() * 10
|
|
|
- ));
|
|
|
+ for (int i = 0; i < timeRanges.length; i++) {
|
|
|
+ com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallTimeDiffVO vo = new com.pig4cloud.pig.statistics.api.vo.uninstall.UninstallTimeDiffVO();
|
|
|
+ vo.setTime(timeRanges[i]);
|
|
|
+ if (i < timeRanges.length - 1) {
|
|
|
+ vo.setRate(Math.round(raw[i] / sum * 10000.0) / 100.0);
|
|
|
+ percentSum += vo.getRate();
|
|
|
+ vo.setCount((int)Math.round(vo.getRate() / 100 * total));
|
|
|
+ countSum += vo.getCount();
|
|
|
+ } else {
|
|
|
+ vo.setRate(Math.round((100.0 - percentSum) * 100.0) / 100.0);
|
|
|
+ vo.setCount(total - countSum);
|
|
|
+ }
|
|
|
+ timeDiffs.add(vo);
|
|
|
}
|
|
|
-
|
|
|
- if (Boolean.TRUE.equals(dto.getIncludeBehavior())) {
|
|
|
- vo.setLastBehaviorFeatures(Map.of(
|
|
|
- "浏览", random.nextDouble() * 50,
|
|
|
- "搜索", random.nextDouble() * 30,
|
|
|
- "购买", random.nextDouble() * 20
|
|
|
- ));
|
|
|
+
|
|
|
+ // 2. 卸载前7天使用次数分布
|
|
|
+ String[] countRanges = {"6次以上", "5次", "4次", "3次", "2次", "1次"};
|
|
|
+ List<UninstallBeforeSevenVO> beforeSevens = new ArrayList<>();
|
|
|
+ int total2 = 500 + random.nextInt(500);
|
|
|
+ double percentSum2 = 0;
|
|
|
+ int countSum2 = 0;
|
|
|
+ double[] raw2 = new double[countRanges.length];
|
|
|
+ double sum2 = 0;
|
|
|
+ for (int i = 0; i < countRanges.length; i++) {
|
|
|
+ raw2[i] = 10 + random.nextDouble() * 90;
|
|
|
+ sum2 += raw2[i];
|
|
|
}
|
|
|
-
|
|
|
- return vo;*/
|
|
|
- return null;
|
|
|
+ for (int i = 0; i < countRanges.length; i++) {
|
|
|
+ UninstallBeforeSevenVO vo = new UninstallBeforeSevenVO();
|
|
|
+ vo.setTime(countRanges[i]);
|
|
|
+ if (i < countRanges.length - 1) {
|
|
|
+ vo.setRate(Math.round(raw2[i] / sum2 * 10000.0) / 100.0);
|
|
|
+ percentSum2 += vo.getRate();
|
|
|
+ vo.setCount((int)Math.round(vo.getRate() / 100 * total2));
|
|
|
+ countSum2 += vo.getCount();
|
|
|
+ } else {
|
|
|
+ vo.setRate(Math.round((100.0 - percentSum2) * 100.0) / 100.0);
|
|
|
+ vo.setCount(total2 - countSum2);
|
|
|
+ }
|
|
|
+ beforeSevens.add(vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 卸载前干扰指标
|
|
|
+ List<UninstallBeforeInterfereVO> interfereList = new ArrayList<>();
|
|
|
+ String[] interfereTypes = {"前七天崩溃次数", "前7天推送接受"};
|
|
|
+ for (String type : interfereTypes) {
|
|
|
+ UninstallBeforeInterfereVO vo = new UninstallBeforeInterfereVO();
|
|
|
+ vo.setType(type);
|
|
|
+ Map<String, Integer> value = new LinkedHashMap<>();
|
|
|
+ for (String c : countRanges) {
|
|
|
+ value.put(c, 1 + random.nextInt(100));
|
|
|
+ }
|
|
|
+ vo.setValue(value);
|
|
|
+ interfereList.add(vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 4. 卸载前行为还原
|
|
|
+ List<UninstallBeforeActionVO> actionList = new ArrayList<>();
|
|
|
+ String[] actionTypes = {"高频浏览页面TOP10", "最终浏览页面TOP10"};
|
|
|
+ for (String actionType : actionTypes) {
|
|
|
+ UninstallBeforeActionVO vo = new UninstallBeforeActionVO();
|
|
|
+ vo.setActionType(actionType);
|
|
|
+ Map<String, Integer> value = new LinkedHashMap<>();
|
|
|
+ for (int i = 1; i <= 10; i++) {
|
|
|
+ value.put("页面" + i, 1 + random.nextInt(100));
|
|
|
+ }
|
|
|
+ vo.setValue(value);
|
|
|
+ actionList.add(vo);
|
|
|
+ }
|
|
|
+ // 下单、invest
|
|
|
+ UninstallBeforeActionVO orderInvest = new UninstallBeforeActionVO();
|
|
|
+ orderInvest.setActionType("下单/Invest");
|
|
|
+ Map<String, Integer> orderInvestMap = new LinkedHashMap<>();
|
|
|
+ orderInvestMap.put("下单", 1 + random.nextInt(100));
|
|
|
+ orderInvestMap.put("invest", 1 + random.nextInt(100));
|
|
|
+ orderInvest.setValue(orderInvestMap);
|
|
|
+ actionList.add(orderInvest);
|
|
|
+
|
|
|
+ UninstallBeforeVO result = new UninstallBeforeVO();
|
|
|
+ result.setUninstallTimeDiffs(timeDiffs);
|
|
|
+ result.setUninstallBeforeSevens(beforeSevens);
|
|
|
+ result.setUninstallBeforeInterferences(interfereList);
|
|
|
+ result.setUninstallBeforeActions(actionList);
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public UninstallCompetitorVO getUninstallCompetitor(GetUninstallTrendDTO dto) {
|
|
|
- UninstallCompetitorVO vo = new UninstallCompetitorVO();
|
|
|
-
|
|
|
- // 生成竞品类型列表
|
|
|
- List<String> competitorTypes = List.of("竞品A", "竞品B", "竞品C", "竞品D");
|
|
|
- vo.setCompetitorTypes(competitorTypes);
|
|
|
-
|
|
|
- // 生成流向各竞品的用户数量
|
|
|
- Map<String, Integer> competitorCounts = Map.of(
|
|
|
- "竞品A", random.nextInt(200),
|
|
|
- "竞品B", random.nextInt(150),
|
|
|
- "竞品C", random.nextInt(100),
|
|
|
- "竞品D", random.nextInt(50)
|
|
|
- );
|
|
|
- vo.setCompetitorUserCounts(competitorCounts);
|
|
|
-
|
|
|
- // 计算总用户数(包括未知去向)
|
|
|
- int total = competitorCounts.values().stream().mapToInt(Integer::intValue).sum() + random.nextInt(100);
|
|
|
-
|
|
|
- // 计算各竞品占比
|
|
|
- Map<String, Double> competitorPercentages = Map.of(
|
|
|
- "竞品A", (double) competitorCounts.get("竞品A") / total * 100,
|
|
|
- "竞品B", (double) competitorCounts.get("竞品B") / total * 100,
|
|
|
- "竞品C", (double) competitorCounts.get("竞品C") / total * 100,
|
|
|
- "竞品D", (double) competitorCounts.get("竞品D") / total * 100
|
|
|
- );
|
|
|
- vo.setCompetitorUserPercentages(competitorPercentages);
|
|
|
-
|
|
|
- // 设置未知去向数据
|
|
|
- int unknownCount = total - competitorCounts.values().stream().mapToInt(Integer::intValue).sum();
|
|
|
- vo.setUnknownCount(unknownCount);
|
|
|
- vo.setUnknownPercentage((double) unknownCount / total * 100);
|
|
|
-
|
|
|
- return vo;
|
|
|
+ public List<UninstallOfterAPPOV> uninstallAfter(GetUninstallInsightDTO dto) {
|
|
|
+ List<UninstallOfterAPPOV> list = new ArrayList<>();
|
|
|
+ String[] appNames = {"微信", "QQ", "抖音", "淘宝", "京东", "美团", "拼多多", "快手", "B站", "微博"};
|
|
|
+ int total = 1000 + random.nextInt(1000);
|
|
|
+ double percentSum = 0;
|
|
|
+ int countSum = 0;
|
|
|
+ double[] raw = new double[appNames.length];
|
|
|
+ double sum = 0;
|
|
|
+ for (int i = 0; i < appNames.length; i++) {
|
|
|
+ raw[i] = 10 + random.nextDouble() * 90;
|
|
|
+ sum += raw[i];
|
|
|
+ }
|
|
|
+ for (int i = 0; i < appNames.length; i++) {
|
|
|
+ UninstallOfterAPPOV vo = new UninstallOfterAPPOV();
|
|
|
+ vo.setAppName(appNames[i]);
|
|
|
+ if (i < appNames.length - 1) {
|
|
|
+ vo.setProportion(String.valueOf(Math.round(raw[i] / sum * 10000.0) / 100.0));
|
|
|
+ percentSum += Double.parseDouble(vo.getProportion());
|
|
|
+ vo.setCount((int)Math.round(Double.parseDouble(vo.getProportion()) / 100 * total));
|
|
|
+ countSum += vo.getCount();
|
|
|
+ } else {
|
|
|
+ vo.setProportion(String.valueOf(Math.round((100.0 - percentSum) * 100.0) / 100.0));
|
|
|
+ vo.setCount(total - countSum);
|
|
|
+ }
|
|
|
+ list.add(vo);
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<UninstallSYSOV> uninstallSys(GetUninstallInsightDTO dto) {
|
|
|
+ List<UninstallSYSOV> list = new ArrayList<>();
|
|
|
+ String[] dimensions = {"Android", "iOS"};
|
|
|
+ for (String dim : dimensions) {
|
|
|
+ UninstallSYSOV vo = new UninstallSYSOV();
|
|
|
+ vo.setDimensionName(dim);
|
|
|
+ List<Map<String, Integer>> dist = new ArrayList<>();
|
|
|
+ for (int i = 1; i <= 5; i++) {
|
|
|
+ Map<String, Integer> map = new LinkedHashMap<>();
|
|
|
+ map.put("版本" + i, 1 + random.nextInt(1000));
|
|
|
+ dist.add(map);
|
|
|
+ }
|
|
|
+ vo.setDistribution(dist);
|
|
|
+ list.add(vo);
|
|
|
+ }
|
|
|
+ return list;
|
|
|
}
|
|
|
}
|