Parcourir la source

流失卸载-卸载洞察

wangcl il y a 4 semaines
Parent
commit
8f3e81a622

+ 10 - 10
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/controller/UninstallAnalyseController.java

@@ -40,27 +40,27 @@ public class UninstallAnalyseController {
 	}
 
 	@PostMapping("/active")
-	@Operation(summary = "卸载设备活跃情况")
+	@Operation(summary = "卸载洞察-卸载设备活跃情况")
 	public R<UninstallInsightVO> getActive(@RequestBody GetUninstallInsightDTO dto)  {
-		return R.ok();
+		return R.ok(uninstallAnalyseService.getUninstallDeviceActive(dto));
 	}
 
 	@PostMapping("/uninstallBefore")
-	@Operation(summary = "卸载前状态")
+	@Operation(summary = "卸载洞察-卸载前状态")
 	public R<UninstallBeforeVO> uninstallBefore(@RequestBody GetUninstallInsightDTO dto) {
-		return R.ok();
+		return R.ok(uninstallAnalyseService.uninstallBefore(dto));
 	}
 
 	@PostMapping("/uninstallAfter")
-	@Operation(summary = "卸载后流失")
+	@Operation(summary = "卸载洞察-卸载后流失")
 	public R<List<UninstallOfterAPPOV>> uninstallAfter(@RequestBody GetUninstallInsightDTO dto) {
-		return R.ok();
+		return R.ok(uninstallAnalyseService.uninstallAfter(dto));
 	}
 
 	@PostMapping("/uninstallSys")
-	@Operation(summary = "设备系统分布")
+	@Operation(summary = "卸载洞察-设备系统分布")
 	public R<List<UninstallSYSOV>> uninstallSys(@RequestBody GetUninstallInsightDTO dto) {
-		return R.ok();
+		return R.ok(uninstallAnalyseService.uninstallSys(dto));
 	}
 
 
@@ -71,13 +71,13 @@ public class UninstallAnalyseController {
 	}
 
 	@PostMapping("/predict")
-	@Operation(summary = "卸载预测")
+	@Operation(summary = "卸载归因-卸载预测")
 	public R<UninstallPredictVO> getUninstallPredict(@RequestBody UninstallPredictDTO dto) {
 		return R.ok();
 	}
 
 	@PostMapping("/predict/detail")
-	@Operation(summary = "安装卸载比")
+	@Operation(summary = "卸载归因-安装卸载比")
 	public R<InstallUninstallRatioVO> getInstallUninstallRatio(@RequestBody InstallUninstallRatioDTO dto) {
 		return R.ok();
 	}

+ 16 - 11
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/UninstallAnalyseService.java

@@ -3,10 +3,7 @@ package com.pig4cloud.pig.statistics.service;
 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 java.util.List;
 
@@ -32,16 +29,24 @@ public interface UninstallAnalyseService {
 	List<UninstallTrendDtlVO> getUninstallTrendDetail(GetUninstallTrendDetailDTO dto);
 
 	/**
-	 * 获取卸载用户洞察
+	 * 卸载设备活跃情况(时长分布+历史卸载次数分布,模拟数据)
 	 * @param dto 查询参数
-	 * @return 用户洞察数据
+	 * @return UninstallInsightVO
 	 */
-	UninstallInsightVO getUninstallInsight(GetUninstallInsightDTO dto);
+	UninstallInsightVO getUninstallDeviceActive(GetUninstallInsightDTO dto);
 
 	/**
-	 * 获取流失去向分析
-	 * @param dto 查询参数
-	 * @return 流失去向数据
+	 * 卸载前状态
+	 */
+	UninstallBeforeVO uninstallBefore(GetUninstallInsightDTO dto);
+
+	/**
+	 * 卸载后流失
+	 */
+	List<UninstallOfterAPPOV> uninstallAfter(GetUninstallInsightDTO dto);
+
+	/**
+	 * 卸载后系统设备分布
 	 */
-	UninstallCompetitorVO getUninstallCompetitor(GetUninstallTrendDTO dto);
+	List<UninstallSYSOV> uninstallSys(GetUninstallInsightDTO dto);
 }

+ 207 - 107
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UninstallAnalyseServiceImpl.java

@@ -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;
 	}
 }