2026.1.13提交,jyt版本

This commit is contained in:
wangran
2026-01-13 20:18:06 +08:00
parent a2c5aca8dc
commit 714bd99b06
3 changed files with 1052 additions and 232 deletions

View File

@@ -31,7 +31,7 @@ public class AppTrafficController {
if (request == null) {
request = new AppTrafficQueryRequest();
}
String operator = null;
String networkType = null;
String appName = null;
@@ -41,7 +41,7 @@ public class AppTrafficController {
Double maxDownloadTraffic = null;
String startDate = null;
String endDate = null;
// 处理运营商参数ALL 或不传表示查询所有
if (request.getOperator() != null && !request.getOperator().trim().isEmpty()) {
String op = request.getOperator().trim().toUpperCase();
@@ -49,17 +49,17 @@ public class AppTrafficController {
operator = op;
}
}
// 处理网络制式
if (request.getNetworkType() != null && !request.getNetworkType().trim().isEmpty()) {
networkType = request.getNetworkType().trim();
}
// 处理APP名称
if (request.getAppName() != null && !request.getAppName().trim().isEmpty()) {
appName = request.getAppName().trim();
}
// 处理上传流量范围
if (request.getMinUploadTraffic() != null) {
minUploadTraffic = request.getMinUploadTraffic();
@@ -67,7 +67,7 @@ public class AppTrafficController {
if (request.getMaxUploadTraffic() != null) {
maxUploadTraffic = request.getMaxUploadTraffic();
}
// 处理下载流量范围
if (request.getMinDownloadTraffic() != null) {
minDownloadTraffic = request.getMinDownloadTraffic();
@@ -75,7 +75,7 @@ public class AppTrafficController {
if (request.getMaxDownloadTraffic() != null) {
maxDownloadTraffic = request.getMaxDownloadTraffic();
}
// 处理日期范围:将 yyyy-MM-dd 格式转换为 yyyyMMdd
if (request.getStartDate() != null && !request.getStartDate().trim().isEmpty()) {
startDate = request.getStartDate().trim().replace("-", "");
@@ -83,29 +83,29 @@ public class AppTrafficController {
if (request.getEndDate() != null && !request.getEndDate().trim().isEmpty()) {
endDate = request.getEndDate().trim().replace("-", "");
}
// 按条件查询
List<AppTraffic> list = appTrafficService.getByCondition(
operator, networkType, appName,
minUploadTraffic, maxUploadTraffic, minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
// 打印到控制台
System.out.println("====== app_traffic query ======");
System.out.println("Operator: " + (operator != null ? operator : "ALL"));
System.out.println("Network Type: " + (networkType != null ? networkType : "ALL"));
System.out.println("APP Name: " + (appName != null ? appName : "ALL"));
System.out.println("Upload Traffic Range: " +
(minUploadTraffic != null ? minUploadTraffic : "MIN") + " ~ " +
(maxUploadTraffic != null ? maxUploadTraffic : "MAX"));
System.out.println("Download Traffic Range: " +
(minDownloadTraffic != null ? minDownloadTraffic : "MIN") + " ~ " +
(maxDownloadTraffic != null ? maxDownloadTraffic : "MAX"));
System.out.println("Upload Traffic Range: " +
(minUploadTraffic != null ? minUploadTraffic : "MIN") + " ~ " +
(maxUploadTraffic != null ? maxUploadTraffic : "MAX"));
System.out.println("Download Traffic Range: " +
(minDownloadTraffic != null ? minDownloadTraffic : "MIN") + " ~ " +
(maxDownloadTraffic != null ? maxDownloadTraffic : "MAX"));
System.out.println("Start Date: " + (startDate != null ? startDate : "ALL"));
System.out.println("End Date: " + (endDate != null ? endDate : "ALL"));
System.out.println("Total records: " + list.size());
System.out.println("================================================");
return list;
}
@@ -120,11 +120,11 @@ public class AppTrafficController {
if (request == null) {
request = new AppTrafficQueryRequest();
}
String operator = null;
String startDate = null;
String endDate = null;
// 处理运营商参数ALL 或不传表示查询所有
if (request.getOperator() != null && !request.getOperator().trim().isEmpty()) {
String op = request.getOperator().trim().toUpperCase();
@@ -132,7 +132,7 @@ public class AppTrafficController {
operator = op;
}
}
// 处理日期范围:将 yyyy-MM-dd 格式转换为 yyyyMMdd
if (request.getStartDate() != null && !request.getStartDate().trim().isEmpty()) {
startDate = request.getStartDate().trim().replace("-", "");
@@ -140,10 +140,10 @@ public class AppTrafficController {
if (request.getEndDate() != null && !request.getEndDate().trim().isEmpty()) {
endDate = request.getEndDate().trim().replace("-", "");
}
// 查询流量占比统计
List<AppTrafficRatioDTO> result = appTrafficService.getAppTrafficRatio(operator, startDate, endDate);
// 打印到控制台
System.out.println("====== app_traffic ratio statistics ======");
System.out.println("Operator: " + (operator != null ? operator : "ALL"));
@@ -151,15 +151,15 @@ public class AppTrafficController {
System.out.println("End Date: " + (endDate != null ? endDate : "ALL"));
System.out.println("Total apps: " + result.size());
for (AppTrafficRatioDTO dto : result) {
System.out.println("APP: " + dto.getAppName() +
" (" + dto.getPackageName() + ")" +
", Operator: " + dto.getOperator() +
", Total Traffic: " + dto.getTotalTraffic() +
", Ratio: " + dto.getTrafficRatio() + "%" +
", Records: " + dto.getRecordCount());
System.out.println("APP: " + dto.getAppName() +
" (" + dto.getPackageName() + ")" +
", Operator: " + dto.getOperator() +
", Total Traffic: " + dto.getTotalTraffic() +
", Ratio: " + dto.getTrafficRatio() + "%" +
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
return result;
}
@@ -175,7 +175,7 @@ public class AppTrafficController {
if (request == null) {
request = new com.bigdata.dto.AppTrafficTimeSeriesRequest();
}
String operator = null;
String networkType = null;
Double minUploadTraffic = null;
@@ -185,7 +185,7 @@ public class AppTrafficController {
String timeGranularity = "DAY"; // 默认按天
String startDate = null;
String endDate = null;
// 处理运营商参数ALL 或不传表示查询所有
if (request.getOperator() != null && !request.getOperator().trim().isEmpty()) {
String op = request.getOperator().trim().toUpperCase();
@@ -193,12 +193,12 @@ public class AppTrafficController {
operator = op;
}
}
// 处理网络制式
if (request.getNetworkType() != null && !request.getNetworkType().trim().isEmpty()) {
networkType = request.getNetworkType().trim();
}
// 处理流量范围
if (request.getMinUploadTraffic() != null) {
minUploadTraffic = request.getMinUploadTraffic();
@@ -212,12 +212,12 @@ public class AppTrafficController {
if (request.getMaxDownloadTraffic() != null) {
maxDownloadTraffic = request.getMaxDownloadTraffic();
}
// 处理时间粒度
if (request.getTimeGranularity() != null && !request.getTimeGranularity().trim().isEmpty()) {
timeGranularity = request.getTimeGranularity().trim().toUpperCase();
}
// 处理日期范围:将 yyyy-MM-dd 格式转换为 yyyyMMdd
if (request.getStartDate() != null && !request.getStartDate().trim().isEmpty()) {
startDate = request.getStartDate().trim().replace("-", "");
@@ -225,15 +225,15 @@ public class AppTrafficController {
if (request.getEndDate() != null && !request.getEndDate().trim().isEmpty()) {
endDate = request.getEndDate().trim().replace("-", "");
}
// 查询时间序列数据
List<com.bigdata.dto.AppTrafficTimeSeriesDTO> result =
List<com.bigdata.dto.AppTrafficTimeSeriesDTO> result =
appTrafficService.getAppTrafficTimeSeries(
operator, networkType,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
timeGranularity, startDate, endDate);
// 打印到控制台
System.out.println("====== app_traffic time series ======");
System.out.println("Operator: " + (operator != null ? operator : "ALL"));
@@ -243,7 +243,7 @@ public class AppTrafficController {
System.out.println("End Date: " + (endDate != null ? endDate : "ALL"));
System.out.println("Total records: " + result.size());
System.out.println("================================================");
return result;
}
@@ -259,7 +259,7 @@ public class AppTrafficController {
if (request == null) {
request = new com.bigdata.dto.AppTrafficUsageRequest();
}
String operator = null;
String networkType = null;
String landmark = null;
@@ -269,7 +269,7 @@ public class AppTrafficController {
Double maxDownloadTraffic = null;
String startDate = null;
String endDate = null;
// 处理运营商参数ALL 或不传表示查询所有
if (request.getOperator() != null && !request.getOperator().trim().isEmpty()) {
String op = request.getOperator().trim().toUpperCase();
@@ -277,17 +277,17 @@ public class AppTrafficController {
operator = op;
}
}
// 处理网络制式
if (request.getNetworkType() != null && !request.getNetworkType().trim().isEmpty()) {
networkType = request.getNetworkType().trim();
}
// 处理典型地标
if (request.getLandmark() != null && !request.getLandmark().trim().isEmpty()) {
landmark = request.getLandmark().trim();
}
// 处理流量范围
if (request.getMinUploadTraffic() != null) {
minUploadTraffic = request.getMinUploadTraffic();
@@ -301,7 +301,7 @@ public class AppTrafficController {
if (request.getMaxDownloadTraffic() != null) {
maxDownloadTraffic = request.getMaxDownloadTraffic();
}
// 处理日期范围:将 yyyy-MM-dd 格式转换为 yyyyMMdd
if (request.getStartDate() != null && !request.getStartDate().trim().isEmpty()) {
startDate = request.getStartDate().trim().replace("-", "");
@@ -309,40 +309,40 @@ public class AppTrafficController {
if (request.getEndDate() != null && !request.getEndDate().trim().isEmpty()) {
endDate = request.getEndDate().trim().replace("-", "");
}
// 查询流量使用情况统计
List<com.bigdata.dto.AppTrafficUsageDTO> result =
List<com.bigdata.dto.AppTrafficUsageDTO> result =
appTrafficService.getAppTrafficUsage(
operator, networkType, landmark,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
// 打印到控制台
System.out.println("====== app_traffic usage statistics ======");
System.out.println("Operator: " + (operator != null ? operator : "ALL"));
System.out.println("Network Type: " + (networkType != null ? networkType : "ALL"));
System.out.println("Landmark: " + (landmark != null ? landmark : "ALL"));
System.out.println("Upload Traffic Range: " +
(minUploadTraffic != null ? minUploadTraffic : "MIN") + " ~ " +
(maxUploadTraffic != null ? maxUploadTraffic : "MAX"));
System.out.println("Download Traffic Range: " +
(minDownloadTraffic != null ? minDownloadTraffic : "MIN") + " ~ " +
(maxDownloadTraffic != null ? maxDownloadTraffic : "MAX"));
System.out.println("Upload Traffic Range: " +
(minUploadTraffic != null ? minUploadTraffic : "MIN") + " ~ " +
(maxUploadTraffic != null ? maxUploadTraffic : "MAX"));
System.out.println("Download Traffic Range: " +
(minDownloadTraffic != null ? minDownloadTraffic : "MIN") + " ~ " +
(maxDownloadTraffic != null ? maxDownloadTraffic : "MAX"));
System.out.println("Start Date: " + (startDate != null ? startDate : "ALL"));
System.out.println("End Date: " + (endDate != null ? endDate : "ALL"));
System.out.println("Total apps: " + result.size());
for (com.bigdata.dto.AppTrafficUsageDTO dto : result) {
System.out.println("APP: " + dto.getAppName() +
" (" + dto.getPackageName() + ")" +
", Operator: " + dto.getOperator() +
", Network: " + dto.getNetworkType() +
", Landmark: " + dto.getLandmark() +
", Total Traffic: " + dto.getTotalTraffic() +
", Records: " + dto.getRecordCount());
System.out.println("APP: " + dto.getAppName() +
" (" + dto.getPackageName() + ")" +
", Operator: " + dto.getOperator() +
", Network: " + dto.getNetworkType() +
", Landmark: " + dto.getLandmark() +
", Total Traffic: " + dto.getTotalTraffic() +
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
return result;
}
@@ -359,26 +359,26 @@ public class AppTrafficController {
if (request == null) {
request = new com.bigdata.dto.AppTrafficRegionTopRequest();
}
// 查询区域top1 APP
List<com.bigdata.dto.AppTrafficRegionTopDTO> result = appTrafficService.getRegionTopApp(request);
// 打印到控制台
System.out.println("====== app_traffic region top1 statistics ======");
System.out.println("Operator: " + (request.getOperator() != null ? request.getOperator() : "ALL"));
System.out.println("Network Type: " + (request.getNetworkType() != null ? request.getNetworkType() : "ALL"));
System.out.println("Start Date: " + (request.getStartDate() != null ? request.getStartDate() : "ALL"));
System.out.println("End Date: " + (request.getEndDate() != null ? request.getEndDate() : "ALL"));
System.out.println("Grid: " + request.getGridRows() + "x" + request.getGridCols() + " = " +
(request.getGridRows() * request.getGridCols()) + " regions");
System.out.println("Grid: " + request.getGridRows() + "x" + request.getGridCols() + " = " +
(request.getGridRows() * request.getGridCols()) + " regions");
System.out.println("Total regions with data: " + result.size());
for (com.bigdata.dto.AppTrafficRegionTopDTO dto : result) {
System.out.println("Region [" + dto.getRowIndex() + "," + dto.getColIndex() +
"] (" + dto.getCenterLat() + "," + dto.getCenterLon() +
") Top1: " + dto.getAppName() +
" (" + dto.getPackageName() + ")" +
", Traffic: " + dto.getTotalTraffic() +
", Records: " + dto.getRecordCount());
System.out.println("Region [" + dto.getRowIndex() + "," + dto.getColIndex() +
"] (" + dto.getCenterLat() + "," + dto.getCenterLon() +
") Top1: " + dto.getAppName() +
" (" + dto.getPackageName() + ")" +
", Traffic: " + dto.getTotalTraffic() +
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
@@ -733,7 +733,359 @@ public class AppTrafficController {
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
return result;
}
/**
* 统计各手机网络质量使用情况,支持按运营商、网络制式、流量范围和日期范围筛选
* @param request 查询请求参数,所有字段均为可选
* @return 手机网络质量使用情况统计列表,按总流量降序排列
*/
@PostMapping("/appTraffic/phoneQuality")
public List<com.bigdata.dto.PhoneQualityUsageDTO> getPhoneQualityUsage(
@RequestBody(required = false) com.bigdata.dto.PhoneQualityUsageRequest request) {
// 如果请求体为空,创建默认请求对象
if (request == null) {
request = new com.bigdata.dto.PhoneQualityUsageRequest();
}
String operator = null;
String networkType = null;
Double minUploadTraffic = null;
Double maxUploadTraffic = null;
Double minDownloadTraffic = null;
Double maxDownloadTraffic = null;
String startDate = null;
String endDate = null;
// 处理运营商参数ALL 或不传表示查询所有
if (request.getOperator() != null && !request.getOperator().trim().isEmpty()) {
String op = request.getOperator().trim().toUpperCase();
if (!"ALL".equals(op)) {
operator = op;
}
}
// 处理网络制式
if (request.getNetworkType() != null && !request.getNetworkType().trim().isEmpty()) {
networkType = request.getNetworkType().trim();
}
// 处理流量范围
if (request.getMinUploadTraffic() != null) {
minUploadTraffic = request.getMinUploadTraffic();
}
if (request.getMaxUploadTraffic() != null) {
maxUploadTraffic = request.getMaxUploadTraffic();
}
if (request.getMinDownloadTraffic() != null) {
minDownloadTraffic = request.getMinDownloadTraffic();
}
if (request.getMaxDownloadTraffic() != null) {
maxDownloadTraffic = request.getMaxDownloadTraffic();
}
// 处理日期范围:将 yyyy-MM-dd 格式转换为 yyyyMMdd
if (request.getStartDate() != null && !request.getStartDate().trim().isEmpty()) {
startDate = request.getStartDate().trim().replace("-", "");
}
if (request.getEndDate() != null && !request.getEndDate().trim().isEmpty()) {
endDate = request.getEndDate().trim().replace("-", "");
}
// 查询手机网络质量使用情况统计
List<com.bigdata.dto.PhoneQualityUsageDTO> result =
appTrafficService.getPhoneQualityUsage(
operator, networkType,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
// 打印到控制台
System.out.println("====== app_traffic phone quality statistics ======");
System.out.println("Operator: " + (operator != null ? operator : "ALL"));
System.out.println("Network Type: " + (networkType != null ? networkType : "ALL"));
System.out.println("Upload Traffic Range: " +
(minUploadTraffic != null ? minUploadTraffic : "MIN") + " ~ " +
(maxUploadTraffic != null ? maxUploadTraffic : "MAX"));
System.out.println("Download Traffic Range: " +
(minDownloadTraffic != null ? minDownloadTraffic : "MIN") + " ~ " +
(maxDownloadTraffic != null ? maxDownloadTraffic : "MAX"));
System.out.println("Start Date: " + (startDate != null ? startDate : "ALL"));
System.out.println("End Date: " + (endDate != null ? endDate : "ALL"));
System.out.println("Total phones: " + result.size());
for (com.bigdata.dto.PhoneQualityUsageDTO dto : result) {
System.out.println("Phone: " + dto.getPhoneModel() +
", OS: " + dto.getOs() +
", OS Version: " + dto.getOsVersion() +
", Operator: " + dto.getOperator() +
", Total Traffic: " + dto.getTotalTraffic() +
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
return result;
}
/**
* 统计各手机流量占比,支持按运营商、网络制式、流量范围和日期范围筛选
* @param request 查询请求参数,所有字段均为可选
* @return 手机流量占比统计列表,按总流量降序排列
*/
@PostMapping("/appTraffic/phoneTrafficRatio")
public List<com.bigdata.dto.PhoneTrafficRatioDTO> getPhoneTrafficRatio(
@RequestBody(required = false) AppTrafficQueryRequest request) {
// 如果请求体为空,创建默认请求对象
if (request == null) {
request = new AppTrafficQueryRequest();
}
String operator = null;
String networkType = null;
Double minUploadTraffic = null;
Double maxUploadTraffic = null;
Double minDownloadTraffic = null;
Double maxDownloadTraffic = null;
String startDate = null;
String endDate = null;
// 处理运营商参数ALL 或不传表示查询所有
if (request.getOperator() != null && !request.getOperator().trim().isEmpty()) {
String op = request.getOperator().trim().toUpperCase();
if (!"ALL".equals(op)) {
operator = op;
}
}
// 处理网络制式
if (request.getNetworkType() != null && !request.getNetworkType().trim().isEmpty()) {
networkType = request.getNetworkType().trim();
}
// 处理流量范围
if (request.getMinUploadTraffic() != null) {
minUploadTraffic = request.getMinUploadTraffic();
}
if (request.getMaxUploadTraffic() != null) {
maxUploadTraffic = request.getMaxUploadTraffic();
}
if (request.getMinDownloadTraffic() != null) {
minDownloadTraffic = request.getMinDownloadTraffic();
}
if (request.getMaxDownloadTraffic() != null) {
maxDownloadTraffic = request.getMaxDownloadTraffic();
}
// 处理日期范围:将 yyyy-MM-dd 格式转换为 yyyyMMdd
if (request.getStartDate() != null && !request.getStartDate().trim().isEmpty()) {
startDate = request.getStartDate().trim().replace("-", "");
}
if (request.getEndDate() != null && !request.getEndDate().trim().isEmpty()) {
endDate = request.getEndDate().trim().replace("-", "");
}
// 查询手机流量占比统计
List<com.bigdata.dto.PhoneTrafficRatioDTO> result =
appTrafficService.getPhoneTrafficRatio(
operator, networkType,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
// 打印到控制台
System.out.println("====== app_traffic phone traffic ratio statistics ======");
System.out.println("Operator: " + (operator != null ? operator : "ALL"));
System.out.println("Network Type: " + (networkType != null ? networkType : "ALL"));
System.out.println("Upload Traffic Range: " +
(minUploadTraffic != null ? minUploadTraffic : "MIN") + " ~ " +
(maxUploadTraffic != null ? maxUploadTraffic : "MAX"));
System.out.println("Download Traffic Range: " +
(minDownloadTraffic != null ? minDownloadTraffic : "MIN") + " ~ " +
(maxDownloadTraffic != null ? maxDownloadTraffic : "MAX"));
System.out.println("Start Date: " + (startDate != null ? startDate : "ALL"));
System.out.println("End Date: " + (endDate != null ? endDate : "ALL"));
System.out.println("Total phones: " + result.size());
for (com.bigdata.dto.PhoneTrafficRatioDTO dto : result) {
System.out.println("Phone: " + dto.getPhoneModel() +
", OS: " + dto.getOs() +
", OS Version: " + dto.getOsVersion() +
", Operator: " + dto.getOperator() +
", Total Traffic: " + dto.getTotalTraffic() +
", Ratio: " + dto.getTrafficRatio() + "%" +
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
return result;
}
/**
* 统计各操作系统流量占比,支持按运营商、网络制式、流量范围和日期范围筛选
* @param request 查询请求参数,所有字段均为可选
* @return 操作系统流量占比统计列表,按总流量降序排列
*/
@PostMapping("/appTraffic/osTrafficRatio")
public List<com.bigdata.dto.OsTrafficRatioDTO> getOsTrafficRatio(
@RequestBody(required = false) AppTrafficQueryRequest request) {
// 如果请求体为空,创建默认请求对象
if (request == null) {
request = new AppTrafficQueryRequest();
}
String operator = null;
String networkType = null;
Double minUploadTraffic = null;
Double maxUploadTraffic = null;
Double minDownloadTraffic = null;
Double maxDownloadTraffic = null;
String startDate = null;
String endDate = null;
// 处理运营商参数ALL 或不传表示查询所有
if (request.getOperator() != null && !request.getOperator().trim().isEmpty()) {
String op = request.getOperator().trim().toUpperCase();
if (!"ALL".equals(op)) {
operator = op;
}
}
// 处理网络制式
if (request.getNetworkType() != null && !request.getNetworkType().trim().isEmpty()) {
networkType = request.getNetworkType().trim();
}
// 处理流量范围
if (request.getMinUploadTraffic() != null) {
minUploadTraffic = request.getMinUploadTraffic();
}
if (request.getMaxUploadTraffic() != null) {
maxUploadTraffic = request.getMaxUploadTraffic();
}
if (request.getMinDownloadTraffic() != null) {
minDownloadTraffic = request.getMinDownloadTraffic();
}
if (request.getMaxDownloadTraffic() != null) {
maxDownloadTraffic = request.getMaxDownloadTraffic();
}
// 处理日期范围:将 yyyy-MM-dd 格式转换为 yyyyMMdd
if (request.getStartDate() != null && !request.getStartDate().trim().isEmpty()) {
startDate = request.getStartDate().trim().replace("-", "");
}
if (request.getEndDate() != null && !request.getEndDate().trim().isEmpty()) {
endDate = request.getEndDate().trim().replace("-", "");
}
// 查询操作系统流量占比统计
List<com.bigdata.dto.OsTrafficRatioDTO> result =
appTrafficService.getOsTrafficRatio(
operator, networkType,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
// 打印到控制台
System.out.println("====== app_traffic os traffic ratio statistics ======");
System.out.println("Operator: " + (operator != null ? operator : "ALL"));
System.out.println("Network Type: " + (networkType != null ? networkType : "ALL"));
System.out.println("Upload Traffic Range: " +
(minUploadTraffic != null ? minUploadTraffic : "MIN") + " ~ " +
(maxUploadTraffic != null ? maxUploadTraffic : "MAX"));
System.out.println("Download Traffic Range: " +
(minDownloadTraffic != null ? minDownloadTraffic : "MIN") + " ~ " +
(maxDownloadTraffic != null ? maxDownloadTraffic : "MAX"));
System.out.println("Start Date: " + (startDate != null ? startDate : "ALL"));
System.out.println("End Date: " + (endDate != null ? endDate : "ALL"));
System.out.println("Total OS: " + result.size());
for (com.bigdata.dto.OsTrafficRatioDTO dto : result) {
System.out.println("OS: " + dto.getOsName() +
", OS: " + dto.getOs() +
", OS Version: " + dto.getOsVersion() +
", Operator: " + dto.getOperator() +
", Total Traffic: " + dto.getTotalTraffic() +
", Ratio: " + dto.getTrafficRatio() + "%" +
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
return result;
}
/**
* 统计可视区域内每个区域的流量top1 热门手机
* 将可视区域划分为300个矩形20x15返回每个区域的top1 热门手机
* @param request 查询请求参数,包含运营商、网络制式、流量范围、日期范围、可视区域范围等
* @return 各区域的top1 热门手机统计列表
*/
@PostMapping("/appTraffic/phoneRegionTop")
public List<com.bigdata.dto.PhoneTrafficRegionTopDTO> getPhoneRegionTop(
@RequestBody(required = false) com.bigdata.dto.PhoneTrafficRegionTopRequest request) {
// 如果请求体为空,创建默认请求对象
if (request == null) {
request = new com.bigdata.dto.PhoneTrafficRegionTopRequest();
}
// 查询区域top1 热门手机
List<com.bigdata.dto.PhoneTrafficRegionTopDTO> result = appTrafficService.getPhoneRegionTop(request);
// 打印到控制台
System.out.println("====== app_traffic phone region top1 statistics ======");
System.out.println("Operator: " + (request.getOperator() != null ? request.getOperator() : "ALL"));
System.out.println("Network Type: " + (request.getNetworkType() != null ? request.getNetworkType() : "ALL"));
System.out.println("Start Date: " + (request.getStartDate() != null ? request.getStartDate() : "ALL"));
System.out.println("End Date: " + (request.getEndDate() != null ? request.getEndDate() : "ALL"));
System.out.println("Grid: " + request.getGridRows() + "x" + request.getGridCols() + " = " +
(request.getGridRows() * request.getGridCols()) + " regions");
System.out.println("Total regions with data: " + result.size());
for (com.bigdata.dto.PhoneTrafficRegionTopDTO dto : result) {
System.out.println("Region [" + dto.getRowIndex() + "," + dto.getColIndex() +
"] (" + dto.getCenterLat() + "," + dto.getCenterLon() +
") Top1: " + dto.getPhoneModel() +
" (OS: " + dto.getOs() + ", Version: " + dto.getOsVersion() + ")" +
", Traffic: " + dto.getTotalTraffic() +
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
return result;
}
/**
* 统计可视区域内每个区域的流量top1 手机OS
* 将可视区域划分为300个矩形20x15返回每个区域的top1 手机OS
* @param request 查询请求参数,包含运营商、网络制式、流量范围、日期范围、可视区域范围等
* @return 各区域的top1 手机OS统计列表
*/
@PostMapping("/appTraffic/osRegionTop")
public List<com.bigdata.dto.OsTrafficRegionTopDTO> getOsRegionTop(
@RequestBody(required = false) com.bigdata.dto.OsTrafficRegionTopRequest request) {
// 如果请求体为空,创建默认请求对象
if (request == null) {
request = new com.bigdata.dto.OsTrafficRegionTopRequest();
}
// 查询区域top1 手机OS
List<com.bigdata.dto.OsTrafficRegionTopDTO> result = appTrafficService.getOsRegionTop(request);
// 打印到控制台
System.out.println("====== app_traffic OS region top1 statistics ======");
System.out.println("Operator: " + (request.getOperator() != null ? request.getOperator() : "ALL"));
System.out.println("Network Type: " + (request.getNetworkType() != null ? request.getNetworkType() : "ALL"));
System.out.println("Start Date: " + (request.getStartDate() != null ? request.getStartDate() : "ALL"));
System.out.println("End Date: " + (request.getEndDate() != null ? request.getEndDate() : "ALL"));
System.out.println("Grid: " + request.getGridRows() + "x" + request.getGridCols() + " = " +
(request.getGridRows() * request.getGridCols()) + " regions");
System.out.println("Total regions with data: " + result.size());
for (com.bigdata.dto.OsTrafficRegionTopDTO dto : result) {
System.out.println("Region [" + dto.getRowIndex() + "," + dto.getColIndex() +
"] (" + dto.getCenterLat() + "," + dto.getCenterLon() +
") Top1: " + dto.getOsName() +
", Traffic: " + dto.getTotalTraffic() +
", Records: " + dto.getRecordCount());
}
System.out.println("================================================");
return result;
}
}

View File

@@ -20,14 +20,14 @@ public class AppTrafficServiceImpl implements AppTrafficService {
@Override
public List<AppTraffic> getByCondition(String operator,
String networkType,
String appName,
Double minUploadTraffic,
Double maxUploadTraffic,
Double minDownloadTraffic,
Double maxDownloadTraffic,
String startDate,
String endDate) {
String networkType,
String appName,
Double minUploadTraffic,
Double maxUploadTraffic,
Double minDownloadTraffic,
Double maxDownloadTraffic,
String startDate,
String endDate) {
return appTrafficMapper.selectByCondition(operator, networkType, appName,
minUploadTraffic, maxUploadTraffic, minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
@@ -36,12 +36,12 @@ public class AppTrafficServiceImpl implements AppTrafficService {
@Override
public List<AppTrafficRatioDTO> getAppTrafficRatio(String operator, String startDate, String endDate) {
List<AppTrafficRatioDTO> result = appTrafficMapper.selectAppTrafficRatio(operator, startDate, endDate);
// 计算总流量,用于计算占比
double totalTrafficSum = result.stream()
.mapToDouble(dto -> dto.getTotalTraffic() != null ? dto.getTotalTraffic() : 0.0)
.sum();
// 计算每个APP的流量占比
if (totalTrafficSum > 0) {
for (AppTrafficRatioDTO dto : result) {
@@ -53,7 +53,7 @@ public class AppTrafficServiceImpl implements AppTrafficService {
}
}
}
return result;
}
@@ -68,15 +68,15 @@ public class AppTrafficServiceImpl implements AppTrafficService {
String timeGranularity,
String startDate,
String endDate) {
// 查询时间序列数据按appName聚合不区分packageName
List<com.bigdata.dto.AppTrafficTimeSeriesDTO> result =
List<com.bigdata.dto.AppTrafficTimeSeriesDTO> result =
appTrafficMapper.selectAppTrafficTimeSeries(
operator, networkType,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
timeGranularity, startDate, endDate);
// 先计算每个APP的总流量跨所有时间粒度
java.util.Map<String, Double> appTotalTrafficMap = new java.util.HashMap<>();
for (com.bigdata.dto.AppTrafficTimeSeriesDTO dto : result) {
@@ -85,30 +85,30 @@ public class AppTrafficServiceImpl implements AppTrafficService {
Double dtoTotal = dto.getTotalTraffic() != null ? dto.getTotalTraffic() : 0.0;
appTotalTrafficMap.put(key, currentTotal + dtoTotal);
}
// 按APP总流量降序排序然后按时间粒度排序
result.sort((a, b) -> {
String keyA = a.getAppName() + "|" + a.getOperator();
String keyB = b.getAppName() + "|" + b.getOperator();
Double totalA = appTotalTrafficMap.getOrDefault(keyA, 0.0);
Double totalB = appTotalTrafficMap.getOrDefault(keyB, 0.0);
// 先按APP总流量降序排序
int compare = totalB.compareTo(totalA);
if (compare != 0) {
return compare;
}
// 如果总流量相同按APP名称排序
int nameCompare = a.getAppName().compareTo(b.getAppName());
if (nameCompare != 0) {
return nameCompare;
}
// 如果APP名称也相同按时间粒度排序
return a.getTimeGranularity().compareTo(b.getTimeGranularity());
});
return result;
}
@@ -219,6 +219,95 @@ public class AppTrafficServiceImpl implements AppTrafficService {
return result;
}
@Override
public List<com.bigdata.dto.PhoneQualityUsageDTO> getPhoneQualityUsage(
String operator,
String networkType,
Double minUploadTraffic,
Double maxUploadTraffic,
Double minDownloadTraffic,
Double maxDownloadTraffic,
String startDate,
String endDate) {
return appTrafficMapper.selectPhoneQualityUsage(
operator, networkType,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
}
@Override
public List<com.bigdata.dto.PhoneTrafficRatioDTO> getPhoneTrafficRatio(
String operator,
String networkType,
Double minUploadTraffic,
Double maxUploadTraffic,
Double minDownloadTraffic,
Double maxDownloadTraffic,
String startDate,
String endDate) {
List<com.bigdata.dto.PhoneTrafficRatioDTO> result = appTrafficMapper.selectPhoneTrafficRatio(
operator, networkType,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
// 计算总流量,用于计算占比
double totalTrafficSum = result.stream()
.mapToDouble(dto -> dto.getTotalTraffic() != null ? dto.getTotalTraffic() : 0.0)
.sum();
// 计算每个手机的流量占比
if (totalTrafficSum > 0) {
for (com.bigdata.dto.PhoneTrafficRatioDTO dto : result) {
if (dto.getTotalTraffic() != null && dto.getTotalTraffic() > 0) {
double ratio = (dto.getTotalTraffic() / totalTrafficSum) * 100.0;
dto.setTrafficRatio(Math.round(ratio * 100.0) / 100.0); // 保留2位小数
} else {
dto.setTrafficRatio(0.0);
}
}
}
return result;
}
@Override
public List<com.bigdata.dto.OsTrafficRatioDTO> getOsTrafficRatio(
String operator,
String networkType,
Double minUploadTraffic,
Double maxUploadTraffic,
Double minDownloadTraffic,
Double maxDownloadTraffic,
String startDate,
String endDate) {
List<com.bigdata.dto.OsTrafficRatioDTO> result = appTrafficMapper.selectOsTrafficRatio(
operator, networkType,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
// 计算总流量,用于计算占比
double totalTrafficSum = result.stream()
.mapToDouble(dto -> dto.getTotalTraffic() != null ? dto.getTotalTraffic() : 0.0)
.sum();
// 计算每个操作系统的流量占比
if (totalTrafficSum > 0) {
for (com.bigdata.dto.OsTrafficRatioDTO dto : result) {
if (dto.getTotalTraffic() != null && dto.getTotalTraffic() > 0) {
double ratio = (dto.getTotalTraffic() / totalTrafficSum) * 100.0;
dto.setTrafficRatio(Math.round(ratio * 100.0) / 100.0); // 保留2位小数
} else {
dto.setTrafficRatio(0.0);
}
}
}
return result;
}
@Override
public List<AppTrafficRegionTopDTO> getRegionTopApp(AppTrafficRegionTopRequest request) {
// 1. 准备查询参数
@@ -226,13 +315,13 @@ public class AppTrafficServiceImpl implements AppTrafficService {
if (request.getOperator() != null && !request.getOperator().trim().isEmpty() && !"ALL".equals(request.getOperator().trim().toUpperCase())) {
operator = request.getOperator().trim().toUpperCase();
}
String networkType = request.getNetworkType();
Double minTraffic = request.getMinTraffic();
Double maxTraffic = request.getMaxTraffic();
String startDate = request.getStartDate() != null ? request.getStartDate().replace("-", "") : null;
String endDate = request.getEndDate() != null ? request.getEndDate().replace("-", "") : null;
// 计算流量范围(总流量 = 上传 + 下载)
Double minUploadTraffic = null;
Double maxUploadTraffic = null;
@@ -246,29 +335,29 @@ public class AppTrafficServiceImpl implements AppTrafficService {
maxUploadTraffic = maxTraffic / 2.0;
maxDownloadTraffic = maxTraffic / 2.0;
}
// 2. 查询数据
List<AppTraffic> dataList = appTrafficMapper.selectByCondition(
operator, networkType, null,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
if (dataList == null || dataList.isEmpty()) {
return new ArrayList<>();
}
// 3. 确定可视区域范围
Double minLon = request.getMinLon();
Double maxLon = request.getMaxLon();
Double minLat = request.getMinLat();
Double maxLat = request.getMaxLat();
if (minLon == null || maxLon == null || minLat == null || maxLat == null) {
// 如果没有指定范围,从数据中计算
List<Double> validLons = new ArrayList<>();
List<Double> validLats = new ArrayList<>();
for (AppTraffic traffic : dataList) {
try {
if (traffic.getUserLon() != null && !traffic.getUserLon().trim().isEmpty()) {
@@ -281,17 +370,17 @@ public class AppTrafficServiceImpl implements AppTrafficService {
// 忽略无效的经纬度数据
}
}
// 如果没有有效的经纬度数据,返回空列表
if (validLons.isEmpty() || validLats.isEmpty()) {
return new ArrayList<>();
}
minLon = validLons.stream().mapToDouble(Double::doubleValue).min().orElse(116.0);
maxLon = validLons.stream().mapToDouble(Double::doubleValue).max().orElse(117.0);
minLat = validLats.stream().mapToDouble(Double::doubleValue).min().orElse(39.0);
maxLat = validLats.stream().mapToDouble(Double::doubleValue).max().orElse(40.0);
// 如果范围太小,扩展一点
if (maxLon - minLon < 0.001) {
double centerLon = (minLon + maxLon) / 2.0;
@@ -304,92 +393,92 @@ public class AppTrafficServiceImpl implements AppTrafficService {
maxLat = centerLat + 0.01;
}
}
// 4. 网格参数
int gridRows = request.getGridRows() != null ? request.getGridRows() : 20;
int gridCols = request.getGridCols() != null ? request.getGridCols() : 15;
// 确保范围有效
if (maxLon <= minLon || maxLat <= minLat) {
return new ArrayList<>();
}
double lonStep = (maxLon - minLon) / gridCols;
double latStep = (maxLat - minLat) / gridRows;
// 确保步长不为0
if (lonStep <= 0 || latStep <= 0) {
return new ArrayList<>();
}
// 5. 按区域分组统计
Map<String, Map<String, Double>> regionAppTrafficMap = new HashMap<>();
Map<String, Long> regionRecordCountMap = new HashMap<>();
for (AppTraffic traffic : dataList) {
if (traffic.getUserLon() == null || traffic.getUserLon().trim().isEmpty() ||
traffic.getUserLat() == null || traffic.getUserLat().trim().isEmpty()) {
traffic.getUserLat() == null || traffic.getUserLat().trim().isEmpty()) {
continue;
}
try {
double lon = Double.parseDouble(traffic.getUserLon());
double lat = Double.parseDouble(traffic.getUserLat());
// 检查是否在可视区域内
if (lon < minLon || lon > maxLon || lat < minLat || lat > maxLat) {
continue;
}
// 计算所属区域
int colIndex = Math.min((int) ((lon - minLon) / lonStep), gridCols - 1);
int rowIndex = Math.min((int) ((lat - minLat) / latStep), gridRows - 1);
String regionKey = rowIndex + "_" + colIndex;
String appKey = (traffic.getAppName() != null ? traffic.getAppName() : "Unknown") +
"|" + (traffic.getPackageName() != null ? traffic.getPackageName() : "");
String appKey = (traffic.getAppName() != null ? traffic.getAppName() : "Unknown") +
"|" + (traffic.getPackageName() != null ? traffic.getPackageName() : "");
// 计算总流量
double totalTraffic = (traffic.getUploadTraffic() != null ? traffic.getUploadTraffic() : 0.0) +
(traffic.getDownloadTraffic() != null ? traffic.getDownloadTraffic() : 0.0);
(traffic.getDownloadTraffic() != null ? traffic.getDownloadTraffic() : 0.0);
// 累计流量
regionAppTrafficMap.computeIfAbsent(regionKey, k -> new HashMap<>())
.merge(appKey, totalTraffic, Double::sum);
regionRecordCountMap.merge(regionKey, 1L, Long::sum);
} catch (NumberFormatException e) {
// 忽略无效的经纬度数据
continue;
}
}
// 6. 找出每个区域的top1 APP
List<AppTrafficRegionTopDTO> result = new ArrayList<>();
for (int row = 0; row < gridRows; row++) {
for (int col = 0; col < gridCols; col++) {
String regionKey = row + "_" + col;
Map<String, Double> appTrafficMap = regionAppTrafficMap.get(regionKey);
if (appTrafficMap == null || appTrafficMap.isEmpty()) {
continue; // 该区域没有数据,跳过
}
// 找出流量最大的APP
Map.Entry<String, Double> topApp = appTrafficMap.entrySet().stream()
.max(Map.Entry.comparingByValue())
.orElse(null);
if (topApp != null) {
String[] appInfo = topApp.getKey().split("\\|");
String appName = appInfo[0];
String packageName = appInfo.length > 1 ? appInfo[1] : "";
// 计算区域中心点
double centerLon = minLon + (col + 0.5) * lonStep;
double centerLat = minLat + (row + 0.5) * latStep;
AppTrafficRegionTopDTO dto = new AppTrafficRegionTopDTO();
dto.setRowIndex(row);
dto.setColIndex(col);
@@ -399,7 +488,386 @@ public class AppTrafficServiceImpl implements AppTrafficService {
dto.setPackageName(packageName);
dto.setTotalTraffic(topApp.getValue());
dto.setRecordCount(regionRecordCountMap.getOrDefault(regionKey, 0L));
result.add(dto);
}
}
}
return result;
}
@Override
public List<com.bigdata.dto.PhoneTrafficRegionTopDTO> getPhoneRegionTop(com.bigdata.dto.PhoneTrafficRegionTopRequest request) {
// 1. 准备查询参数
String operator = null;
if (request.getOperator() != null && !request.getOperator().trim().isEmpty() && !"ALL".equals(request.getOperator().trim().toUpperCase())) {
operator = request.getOperator().trim().toUpperCase();
}
String networkType = request.getNetworkType();
Double minUploadTraffic = request.getMinUploadTraffic();
Double maxUploadTraffic = request.getMaxUploadTraffic();
Double minDownloadTraffic = request.getMinDownloadTraffic();
Double maxDownloadTraffic = request.getMaxDownloadTraffic();
String startDate = request.getStartDate() != null ? request.getStartDate().replace("-", "") : null;
String endDate = request.getEndDate() != null ? request.getEndDate().replace("-", "") : null;
// 2. 查询数据
List<AppTraffic> dataList = appTrafficMapper.selectByCondition(
operator, networkType, null,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
if (dataList == null || dataList.isEmpty()) {
return new ArrayList<>();
}
// 3. 确定可视区域范围
Double minLon = request.getMinLon();
Double maxLon = request.getMaxLon();
Double minLat = request.getMinLat();
Double maxLat = request.getMaxLat();
if (minLon == null || maxLon == null || minLat == null || maxLat == null) {
// 如果没有指定范围,从数据中计算
List<Double> validLons = new ArrayList<>();
List<Double> validLats = new ArrayList<>();
for (AppTraffic traffic : dataList) {
try {
if (traffic.getUserLon() != null && !traffic.getUserLon().trim().isEmpty()) {
validLons.add(Double.parseDouble(traffic.getUserLon()));
}
if (traffic.getUserLat() != null && !traffic.getUserLat().trim().isEmpty()) {
validLats.add(Double.parseDouble(traffic.getUserLat()));
}
} catch (NumberFormatException e) {
// 忽略无效的经纬度数据
}
}
// 如果没有有效的经纬度数据,返回空列表
if (validLons.isEmpty() || validLats.isEmpty()) {
return new ArrayList<>();
}
minLon = validLons.stream().mapToDouble(Double::doubleValue).min().orElse(116.0);
maxLon = validLons.stream().mapToDouble(Double::doubleValue).max().orElse(117.0);
minLat = validLats.stream().mapToDouble(Double::doubleValue).min().orElse(39.0);
maxLat = validLats.stream().mapToDouble(Double::doubleValue).max().orElse(40.0);
// 如果范围太小,扩展一点
if (maxLon - minLon < 0.001) {
double centerLon = (minLon + maxLon) / 2.0;
minLon = centerLon - 0.01;
maxLon = centerLon + 0.01;
}
if (maxLat - minLat < 0.001) {
double centerLat = (minLat + maxLat) / 2.0;
minLat = centerLat - 0.01;
maxLat = centerLat + 0.01;
}
}
// 4. 网格参数
int gridRows = request.getGridRows() != null ? request.getGridRows() : 20;
int gridCols = request.getGridCols() != null ? request.getGridCols() : 15;
// 确保范围有效
if (maxLon <= minLon || maxLat <= minLat) {
return new ArrayList<>();
}
double lonStep = (maxLon - minLon) / gridCols;
double latStep = (maxLat - minLat) / gridRows;
// 确保步长不为0
if (lonStep <= 0 || latStep <= 0) {
return new ArrayList<>();
}
// 5. 按区域分组统计(按手机型号分组)
Map<String, Map<String, Double>> regionPhoneTrafficMap = new HashMap<>();
Map<String, Long> regionRecordCountMap = new HashMap<>();
Map<String, String> phoneOsMap = new HashMap<>(); // 存储手机型号对应的OS
Map<String, String> phoneOsVersionMap = new HashMap<>(); // 存储手机型号对应的OS_ANDVERSION
for (AppTraffic traffic : dataList) {
if (traffic.getUserLon() == null || traffic.getUserLon().trim().isEmpty() ||
traffic.getUserLat() == null || traffic.getUserLat().trim().isEmpty()) {
continue;
}
try {
double lon = Double.parseDouble(traffic.getUserLon());
double lat = Double.parseDouble(traffic.getUserLat());
// 检查是否在可视区域内
if (lon < minLon || lon > maxLon || lat < minLat || lat > maxLat) {
continue;
}
// 计算所属区域
int colIndex = Math.min((int) ((lon - minLon) / lonStep), gridCols - 1);
int rowIndex = Math.min((int) ((lat - minLat) / latStep), gridRows - 1);
String regionKey = rowIndex + "_" + colIndex;
// 构建手机型号keyOS + OS_ANDVERSION
// 注意实体类中osVersion字段对应数据库的OS_ANDVERSION列
String os = traffic.getOs() != null ? traffic.getOs() : "";
String osAndVersion = traffic.getOsVersion() != null ? traffic.getOsVersion() : "";
String phoneKey = (os.toLowerCase() + osAndVersion).trim();
if (phoneKey.isEmpty()) {
continue; // 跳过没有OS信息的记录
}
// 计算总流量
double totalTraffic = (traffic.getUploadTraffic() != null ? traffic.getUploadTraffic() : 0.0) +
(traffic.getDownloadTraffic() != null ? traffic.getDownloadTraffic() : 0.0);
// 累计流量
regionPhoneTrafficMap.computeIfAbsent(regionKey, k -> new HashMap<>())
.merge(phoneKey, totalTraffic, Double::sum);
regionRecordCountMap.merge(regionKey, 1L, Long::sum);
// 保存手机型号对应的OS和OS_ANDVERSION
phoneOsMap.put(phoneKey, os);
phoneOsVersionMap.put(phoneKey, osAndVersion);
} catch (NumberFormatException e) {
// 忽略无效的经纬度数据
continue;
}
}
// 6. 找出每个区域的top1 热门手机
List<com.bigdata.dto.PhoneTrafficRegionTopDTO> result = new ArrayList<>();
for (int row = 0; row < gridRows; row++) {
for (int col = 0; col < gridCols; col++) {
String regionKey = row + "_" + col;
Map<String, Double> phoneTrafficMap = regionPhoneTrafficMap.get(regionKey);
if (phoneTrafficMap == null || phoneTrafficMap.isEmpty()) {
continue; // 该区域没有数据,跳过
}
// 找出流量最大的手机
Map.Entry<String, Double> topPhone = phoneTrafficMap.entrySet().stream()
.max(Map.Entry.comparingByValue())
.orElse(null);
if (topPhone != null) {
String phoneKey = topPhone.getKey();
String os = phoneOsMap.getOrDefault(phoneKey, "");
String osVersion = phoneOsVersionMap.getOrDefault(phoneKey, "");
String phoneModel = (os.toLowerCase() + osVersion).trim();
// 计算区域中心点
double centerLon = minLon + (col + 0.5) * lonStep;
double centerLat = minLat + (row + 0.5) * latStep;
com.bigdata.dto.PhoneTrafficRegionTopDTO dto = new com.bigdata.dto.PhoneTrafficRegionTopDTO();
dto.setRowIndex(row);
dto.setColIndex(col);
dto.setCenterLon(centerLon);
dto.setCenterLat(centerLat);
dto.setPhoneModel(phoneModel);
dto.setOs(os);
dto.setOsVersion(osVersion);
dto.setTotalTraffic(topPhone.getValue());
dto.setRecordCount(regionRecordCountMap.getOrDefault(regionKey, 0L));
result.add(dto);
}
}
}
return result;
}
@Override
public List<com.bigdata.dto.OsTrafficRegionTopDTO> getOsRegionTop(com.bigdata.dto.OsTrafficRegionTopRequest request) {
// 1. 准备查询参数
String operator = null;
if (request.getOperator() != null && !request.getOperator().trim().isEmpty() && !"ALL".equals(request.getOperator().trim().toUpperCase())) {
operator = request.getOperator().trim().toUpperCase();
}
String networkType = request.getNetworkType();
Double minUploadTraffic = request.getMinUploadTraffic();
Double maxUploadTraffic = request.getMaxUploadTraffic();
Double minDownloadTraffic = request.getMinDownloadTraffic();
Double maxDownloadTraffic = request.getMaxDownloadTraffic();
String startDate = request.getStartDate() != null ? request.getStartDate().replace("-", "") : null;
String endDate = request.getEndDate() != null ? request.getEndDate().replace("-", "") : null;
// 2. 查询数据
List<AppTraffic> dataList = appTrafficMapper.selectByCondition(
operator, networkType, null,
minUploadTraffic, maxUploadTraffic,
minDownloadTraffic, maxDownloadTraffic,
startDate, endDate);
if (dataList == null || dataList.isEmpty()) {
return new ArrayList<>();
}
// 3. 确定可视区域范围
Double minLon = request.getMinLon();
Double maxLon = request.getMaxLon();
Double minLat = request.getMinLat();
Double maxLat = request.getMaxLat();
if (minLon == null || maxLon == null || minLat == null || maxLat == null) {
// 如果没有指定范围,从数据中计算
List<Double> validLons = new ArrayList<>();
List<Double> validLats = new ArrayList<>();
for (AppTraffic traffic : dataList) {
try {
if (traffic.getUserLon() != null && !traffic.getUserLon().trim().isEmpty()) {
validLons.add(Double.parseDouble(traffic.getUserLon()));
}
if (traffic.getUserLat() != null && !traffic.getUserLat().trim().isEmpty()) {
validLats.add(Double.parseDouble(traffic.getUserLat()));
}
} catch (NumberFormatException e) {
// 忽略无效的经纬度数据
}
}
// 如果没有有效的经纬度数据,返回空列表
if (validLons.isEmpty() || validLats.isEmpty()) {
return new ArrayList<>();
}
minLon = validLons.stream().mapToDouble(Double::doubleValue).min().orElse(116.0);
maxLon = validLons.stream().mapToDouble(Double::doubleValue).max().orElse(117.0);
minLat = validLats.stream().mapToDouble(Double::doubleValue).min().orElse(39.0);
maxLat = validLats.stream().mapToDouble(Double::doubleValue).max().orElse(40.0);
// 如果范围太小,扩展一点
if (maxLon - minLon < 0.001) {
double centerLon = (minLon + maxLon) / 2.0;
minLon = centerLon - 0.01;
maxLon = centerLon + 0.01;
}
if (maxLat - minLat < 0.001) {
double centerLat = (minLat + maxLat) / 2.0;
minLat = centerLat - 0.01;
maxLat = centerLat + 0.01;
}
}
// 4. 网格参数
int gridRows = request.getGridRows() != null ? request.getGridRows() : 20;
int gridCols = request.getGridCols() != null ? request.getGridCols() : 15;
// 确保范围有效
if (maxLon <= minLon || maxLat <= minLat) {
return new ArrayList<>();
}
double lonStep = (maxLon - minLon) / gridCols;
double latStep = (maxLat - minLat) / gridRows;
// 确保步长不为0
if (lonStep <= 0 || latStep <= 0) {
return new ArrayList<>();
}
// 5. 按区域分组统计按OS分组
Map<String, Map<String, Double>> regionOsTrafficMap = new HashMap<>();
Map<String, Long> regionRecordCountMap = new HashMap<>();
Map<String, String> osNameMap = new HashMap<>(); // 存储OS key对应的OS名称
for (AppTraffic traffic : dataList) {
if (traffic.getUserLon() == null || traffic.getUserLon().trim().isEmpty() ||
traffic.getUserLat() == null || traffic.getUserLat().trim().isEmpty()) {
continue;
}
try {
double lon = Double.parseDouble(traffic.getUserLon());
double lat = Double.parseDouble(traffic.getUserLat());
// 检查是否在可视区域内
if (lon < minLon || lon > maxLon || lat < minLat || lat > maxLat) {
continue;
}
// 计算所属区域
int colIndex = Math.min((int) ((lon - minLon) / lonStep), gridCols - 1);
int rowIndex = Math.min((int) ((lat - minLat) / latStep), gridRows - 1);
String regionKey = rowIndex + "_" + colIndex;
// 构建OS key只按OS分组不包含版本号
String os = traffic.getOs() != null ? traffic.getOs() : "";
String osKey = os.toLowerCase().trim();
if (osKey.isEmpty()) {
continue; // 跳过没有OS信息的记录
}
// 计算总流量
double totalTraffic = (traffic.getUploadTraffic() != null ? traffic.getUploadTraffic() : 0.0) +
(traffic.getDownloadTraffic() != null ? traffic.getDownloadTraffic() : 0.0);
// 累计流量
regionOsTrafficMap.computeIfAbsent(regionKey, k -> new HashMap<>())
.merge(osKey, totalTraffic, Double::sum);
regionRecordCountMap.merge(regionKey, 1L, Long::sum);
// 保存OS key对应的OS名称保留原始大小写
osNameMap.put(osKey, os);
} catch (NumberFormatException e) {
// 忽略无效的经纬度数据
continue;
}
}
// 6. 找出每个区域的top1 手机OS
List<com.bigdata.dto.OsTrafficRegionTopDTO> result = new ArrayList<>();
for (int row = 0; row < gridRows; row++) {
for (int col = 0; col < gridCols; col++) {
String regionKey = row + "_" + col;
Map<String, Double> osTrafficMap = regionOsTrafficMap.get(regionKey);
if (osTrafficMap == null || osTrafficMap.isEmpty()) {
continue; // 该区域没有数据,跳过
}
// 找出流量最大的OS
Map.Entry<String, Double> topOs = osTrafficMap.entrySet().stream()
.max(Map.Entry.comparingByValue())
.orElse(null);
if (topOs != null) {
String osKey = topOs.getKey();
String osName = osNameMap.getOrDefault(osKey, osKey);
// 计算区域中心点
double centerLon = minLon + (col + 0.5) * lonStep;
double centerLat = minLat + (row + 0.5) * latStep;
com.bigdata.dto.OsTrafficRegionTopDTO dto = new com.bigdata.dto.OsTrafficRegionTopDTO();
dto.setRowIndex(row);
dto.setColIndex(col);
dto.setCenterLon(centerLon);
dto.setCenterLat(centerLat);
dto.setOsName(osName);
dto.setOs(osName);
dto.setTotalTraffic(topOs.getValue());
dto.setRecordCount(regionRecordCountMap.getOrDefault(regionKey, 0L));
result.add(dto);
}
}
@@ -783,7 +1251,7 @@ public class AppTrafficServiceImpl implements AppTrafficService {
}
}
}
return result;
}
}

View File

@@ -5,19 +5,19 @@
<!-- 按条件查询应用流量数据 -->
<select id="selectByCondition" resultType="com.bigdata.entity.AppTraffic">
SELECT
"ID" AS id,
"USER_LON" AS userLon,
"USER_LAT" AS userLat,
"UPLOAD_TRAFFIC" AS uploadTraffic,
"DOWNLOAD_TRAFFIC" AS downloadTraffic,
"PACKAGE_NAME" AS packageName,
"NETWORK_NAME" AS networkName,
"APP_NAME" AS appName,
"OS" AS os,
"OS_ANDVERSION" AS osVersion,
"COMPANY" AS company,
"START_TIME" AS startTime,
"END_TIME" AS endTime
"ID" AS id,
"USER_LON" AS userLon,
"USER_LAT" AS userLat,
"UPLOAD_TRAFFIC" AS uploadTraffic,
"DOWNLOAD_TRAFFIC" AS downloadTraffic,
"PACKAGE_NAME" AS packageName,
"NETWORK_NAME" AS networkName,
"APP_NAME" AS appName,
"OS" AS os,
"OS_ANDVERSION" AS osVersion,
"COMPANY" AS company,
"START_TIME" AS startTime,
"END_TIME" AS endTime
FROM "APP_TRAFFIC"
<where>
<!-- 运营商筛选ALL 或不传表示查询所有,否则查询指定运营商 -->
@@ -60,14 +60,14 @@
<!-- 统计各APP流量占比 -->
<select id="selectAppTrafficRatio" resultType="com.bigdata.dto.AppTrafficRatioDTO">
SELECT
"APP_NAME" AS appName,
"PACKAGE_NAME" AS packageName,
"NETWORK_NAME" AS operator,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(0.0 AS DOUBLE) AS trafficRatio,
CAST(COUNT(*) AS BIGINT) AS recordCount
"APP_NAME" AS appName,
"PACKAGE_NAME" AS packageName,
"NETWORK_NAME" AS operator,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(0.0 AS DOUBLE) AS trafficRatio,
CAST(COUNT(*) AS BIGINT) AS recordCount
FROM "APP_TRAFFIC"
<where>
<!-- 运营商筛选ALL 或不传表示查询所有,否则查询指定运营商 -->
@@ -89,35 +89,35 @@
<!-- 统计APP在时间粒度维度上的流量情况按appName聚合 -->
<select id="selectAppTrafficTimeSeries" resultType="com.bigdata.dto.AppTrafficTimeSeriesDTO">
SELECT
"APP_NAME" AS appName,
CAST(NULL AS VARCHAR) AS packageName,
"NETWORK_NAME" AS operator,
<choose>
<!-- 按小时粒度yyyyMMddHH -->
<when test="timeGranularity == 'HOUR'">
SUBSTR("START_TIME", 1, 10) AS timeGranularity,
</when>
<!-- 按天粒度yyyyMMdd -->
<when test="timeGranularity == 'DAY'">
SUBSTR("START_TIME", 1, 8) AS timeGranularity,
</when>
<!-- 按周粒度yyyyMM周的开始日期所在月份 -->
<when test="timeGranularity == 'WEEK'">
SUBSTR("START_TIME", 1, 6) AS timeGranularity,
</when>
<!-- 按月粒度yyyyMM -->
<when test="timeGranularity == 'MONTH'">
SUBSTR("START_TIME", 1, 6) AS timeGranularity,
</when>
<!-- 默认按天 -->
<otherwise>
SUBSTR("START_TIME", 1, 8) AS timeGranularity,
</otherwise>
</choose>
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(COUNT(*) AS BIGINT) AS recordCount
"APP_NAME" AS appName,
CAST(NULL AS VARCHAR) AS packageName,
"NETWORK_NAME" AS operator,
<choose>
<!-- 按小时粒度yyyyMMddHH -->
<when test="timeGranularity == 'HOUR'">
SUBSTR("START_TIME", 1, 10) AS timeGranularity,
</when>
<!-- 按天粒度yyyyMMdd -->
<when test="timeGranularity == 'DAY'">
SUBSTR("START_TIME", 1, 8) AS timeGranularity,
</when>
<!-- 按周粒度yyyyMM周的开始日期所在月份 -->
<when test="timeGranularity == 'WEEK'">
SUBSTR("START_TIME", 1, 6) AS timeGranularity,
</when>
<!-- 按月粒度yyyyMM -->
<when test="timeGranularity == 'MONTH'">
SUBSTR("START_TIME", 1, 6) AS timeGranularity,
</when>
<!-- 默认按天 -->
<otherwise>
SUBSTR("START_TIME", 1, 8) AS timeGranularity,
</otherwise>
</choose>
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(COUNT(*) AS BIGINT) AS recordCount
FROM "APP_TRAFFIC"
<where>
<!-- 运营商筛选ALL 或不传表示查询所有,否则查询指定运营商 -->
@@ -150,41 +150,41 @@
AND TO_NUMBER(SUBSTR("START_TIME", 1, 8)) &lt;= TO_NUMBER(#{endDate})
</if>
</where>
GROUP BY
"APP_NAME",
"NETWORK_NAME",
<choose>
<when test="timeGranularity == 'HOUR'">
SUBSTR("START_TIME", 1, 10)
</when>
<when test="timeGranularity == 'DAY'">
SUBSTR("START_TIME", 1, 8)
</when>
<when test="timeGranularity == 'WEEK'">
SUBSTR("START_TIME", 1, 6)
</when>
<when test="timeGranularity == 'MONTH'">
SUBSTR("START_TIME", 1, 6)
</when>
<otherwise>
SUBSTR("START_TIME", 1, 8)
</otherwise>
</choose>
GROUP BY
"APP_NAME",
"NETWORK_NAME",
<choose>
<when test="timeGranularity == 'HOUR'">
SUBSTR("START_TIME", 1, 10)
</when>
<when test="timeGranularity == 'DAY'">
SUBSTR("START_TIME", 1, 8)
</when>
<when test="timeGranularity == 'WEEK'">
SUBSTR("START_TIME", 1, 6)
</when>
<when test="timeGranularity == 'MONTH'">
SUBSTR("START_TIME", 1, 6)
</when>
<otherwise>
SUBSTR("START_TIME", 1, 8)
</otherwise>
</choose>
ORDER BY totalTraffic DESC, "APP_NAME", timeGranularity
</select>
<!-- 统计各APP流量使用情况 -->
<select id="selectAppTrafficUsage" resultType="com.bigdata.dto.AppTrafficUsageDTO">
SELECT
"APP_NAME" AS appName,
"PACKAGE_NAME" AS packageName,
"NETWORK_NAME" AS operator,
"OS" AS networkType,
"LANDMARK" AS landmark,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(COUNT(*) AS BIGINT) AS recordCount
"APP_NAME" AS appName,
"PACKAGE_NAME" AS packageName,
"NETWORK_NAME" AS operator,
"OS" AS networkType,
"LANDMARK" AS landmark,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(COUNT(*) AS BIGINT) AS recordCount
FROM "APP_TRAFFIC"
<where>
<!-- 运营商筛选ALL 或不传表示查询所有,否则查询指定运营商 -->
@@ -228,14 +228,14 @@
<!-- 统计各手机网络质量使用情况 -->
<select id="selectPhoneQualityUsage" resultType="com.bigdata.dto.PhoneQualityUsageDTO">
SELECT
"COMPANYMODEL" AS phoneModel,
"OS" AS os,
"NETWORK_NAME" AS operator,
"NETWORK_TYPE" AS networkType,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(COUNT(*) AS BIGINT) AS recordCount
"COMPANYMODEL" AS phoneModel,
"OS" AS os,
"NETWORK_NAME" AS operator,
"NETWORK_TYPE" AS networkType,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(COUNT(*) AS BIGINT) AS recordCount
FROM "APP_TRAFFIC"
<where>
<!-- 过滤掉无效的手机型号 -->
@@ -276,15 +276,15 @@
ORDER BY totalTraffic DESC, "COMPANYMODEL"
</select>
<!-- 统计各手机型号流量占比 -->
<!-- 统计各手机型号流量占比 -->
<select id="selectPhoneTrafficRatio" resultType="com.bigdata.dto.PhoneTrafficRatioDTO">
SELECT
"COMPANYMODEL" AS phoneModel,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC") + SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(0.0 AS DOUBLE) AS trafficRatio,
CAST(COUNT(*) AS BIGINT) AS recordCount
"COMPANYMODEL" AS phoneModel,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC") + SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(0.0 AS DOUBLE) AS trafficRatio,
CAST(COUNT(*) AS BIGINT) AS recordCount
FROM "APP_TRAFFIC"
<where>
<!-- 排除 COMPANYMODEL 为 NULL 或空字符串的记录 -->
@@ -326,18 +326,18 @@
</select>
<!-- 统计各操作系统流量占比 -->
<select id="selectOsTrafficRatio" resultType="com.bigdata.dto.OsTrafficRatioDTO">
<select id="selectOsTrafficRatio" resultType="com.bigdata.dto.OsTrafficRatioDTO">
SELECT
("OS" || CASE WHEN "OS_ANDVERSION" != 'NULL' AND "OS_ANDVERSION" != '' THEN ' ' || "OS_ANDVERSION" ELSE '' END) AS osName,
"OS" AS os,
CASE WHEN "OS_ANDVERSION" != 'NULL' THEN "OS_ANDVERSION" ELSE '' END AS osVersion,
"NETWORK_NAME" AS operator,
"OS" AS networkType,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(0.0 AS DOUBLE) AS trafficRatio,
CAST(COUNT(*) AS BIGINT) AS recordCount
("OS" || CASE WHEN "OS_ANDVERSION" != 'NULL' AND "OS_ANDVERSION" != '' THEN ' ' || "OS_ANDVERSION" ELSE '' END) AS osName,
"OS" AS os,
CASE WHEN "OS_ANDVERSION" != 'NULL' THEN "OS_ANDVERSION" ELSE '' END AS osVersion,
"NETWORK_NAME" AS operator,
"OS" AS networkType,
CAST(SUM("UPLOAD_TRAFFIC") AS DOUBLE) AS totalUploadTraffic,
CAST(SUM("DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalDownloadTraffic,
CAST(SUM("UPLOAD_TRAFFIC" + "DOWNLOAD_TRAFFIC") AS DOUBLE) AS totalTraffic,
CAST(0.0 AS DOUBLE) AS trafficRatio,
CAST(COUNT(*) AS BIGINT) AS recordCount
FROM "APP_TRAFFIC"
<where>
<!-- 运营商筛选ALL 或不传表示查询所有,否则查询指定运营商 -->