package com.reyun.report; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.*; import com.reyun.model.ReportListResult; import com.reyun.util.DateUtil; import com.reyun.util.ViewColumnDependUtil; import org.json.JSONException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.ion.Decimal; import java.lang.reflect.Array; import java.math.BigDecimal; import java.text.DecimalFormat; import java.util.*; import java.util.stream.Collector; import java.util.stream.Collectors; /** * Created by nolan on 18/01/2017. * description: */ public abstract class AbstractNoDivideReportParse extends AbstractReportParse { private static final Logger logger = LoggerFactory.getLogger(AbstractNoDivideReportParse.class); private static final List<String> RP_CHANNEL = ImmutableList.of("channelinfo_bychannel", "h5_channel_detail_list", "channelinfo_order_bychannel"); private static final List<String> RP_CAMPAIGN = ImmutableList.of("delay_click_bycampaign", "delay_install_bycampaign", "recycle_dashboard_campaign", "recycle_analysis_bycampaign"); private static final List<String> RP_CAMPAIGN_GROUP = ImmutableList.of(""); /** * 解析报表串 * * @param reportResult * @param isSearchText * @param searchIds * @return */ public abstract ReportListResult parse(ReportListResult reportResult, Long app, Long account, List<String> viewColumns, String reportName, boolean isSearchText, List<String> searchIds) throws JSONException; public abstract ReportListResult parse(ReportListResult reportResult, Long app, Long account, List<String> viewColumns, String reportName, boolean isSearchText, List<String> searchIds,Map<String, String> conditions); public abstract ReportListResult parse(ReportListResult reportResult, Long app, Long account, List<String> viewColumns, String reportName, boolean isSearchText, List<String> searchIds, Long cid, Map<String, String> conditions) throws JSONException; public abstract ReportListResult parse(ReportListResult reportResult, Long app, Long account, List<String> viewColumns, String reportName, boolean isSearchText, List<String> searchIds, Long cid) throws JSONException; protected boolean isReplaceLableKey(String name) { return RP_CHANNEL.contains(name) || RP_CAMPAIGN.contains(name); } protected boolean isRPCampaign(String name) { return RP_CAMPAIGN.contains(name); } protected boolean isRPChannel(String name) { return RP_CHANNEL.contains(name); } protected boolean isRPCampaignGroup(String name) { return RP_CAMPAIGN_GROUP.contains(name); } protected List<Map<String, Object>> calFirstTotalRow(ReportListResult reportResult, List<String> viewColumns) { List<Map<String, Object>> sourceResult = reportResult.getVal(); Map<String, Object> totalRowMap = Maps.newHashMap(); if (sourceResult == null || sourceResult.size() == 0) { for (String fieldcode : viewColumns) { Object tmp = null; if (isRateFields(fieldcode)) { tmp = 0.0; } else { tmp = 0l; } totalRowMap.put(fieldcode, tmp); } totalRowMap.put("isall0", false); totalRowMap.put("istotal", true); totalRowMap.put(firstTotalRowNeedReplaceId(), "汇总"); totalRowMap.put("amt_perticket", 0); totalRowMap.put("amt_pay_perticket", 0); totalRowMap.put("rate_pay_order", 0); totalRowMap.put("amt_time", 0); return ImmutableList.of(totalRowMap); } Map<String, Integer> viewColumnsMap = viewColumns.stream().collect(Collectors.toMap(v -> v, v -> 0, (v1, v2) -> v1)); List<String> viewColumnsFull = new ArrayList<>(); for (String fieldcode : viewColumns) { Collection<String> linkfields = ViewColumnDependUtil.getRateDependFields(fieldcode); if (linkfields != null && linkfields.size() > 0) { String fieldNext = (String) new ArrayList(linkfields).get(1); if (!viewColumnsMap.containsKey(fieldNext)) { viewColumnsFull.add(fieldNext); } } } viewColumnsFull.addAll(viewColumns); //分列 计算 留存指标等 ListMultimap<String, Object> attributeMapList = ArrayListMultimap.create(); for (int i = 0, n = sourceResult.size(); i < n; i++) { Map<String, Object> sourceItem = sourceResult.get(i); boolean isall0 = true; for (String fieldcode : viewColumnsFull) { Object v = sourceItem.get(fieldcode); boolean isRateFields = isRateFields(fieldcode); if (v == null) { if (isRateFields) { v = 0.0; } else { v = 0l; } sourceItem.put(fieldcode, v); attributeMapList.put(fieldcode, v); } else { Object linkfieldVal = null; String[] linkfield = null; Collection<String> linkfields = ViewColumnDependUtil.getRateDependFields(fieldcode); if (linkfields != null && linkfields.size() > 0) { linkfield = new String[linkfields.size()]; linkfield = linkfields.toArray(linkfield); final Object f1 = sourceItem.get(linkfield[0]); linkfieldVal = sourceItem.get(linkfield[1]); if (linkfieldVal == null) { linkfieldVal = "0"; } Object rateValue; boolean isDouble = f1.getClass().isAssignableFrom(Double.class) ? true : false; if (fieldcode.startsWith("amt_ltv")) { //非百分比计算 rateValue = divideTwoValue(f1, linkfieldVal, 100, isDouble, false); } else { rateValue = divideTwoValue(f1, linkfieldVal, 1, isDouble, true); } if (isall0) { //isall0 有一个是 false 则不再判断 isall0 = (Double) rateValue > 0 ? false : true; } sourceItem.put(fieldcode, rateValue); } else if (sourceItem.get(fieldcode) != null && sourceItem.get(fieldcode).getClass().isAssignableFrom(Long.class) && fieldcode.toLowerCase().equals("duration")) { sourceItem.put(fieldcode, DateUtil.formatCaseTime(Long.valueOf(sourceItem.get(fieldcode) == null ? "0" : sourceItem.get(fieldcode).toString()))); } attributeMapList.put(fieldcode, v); if (isall0) { //isall0 有一个是 false 则不再判断 if (v.getClass().isAssignableFrom(Long.class) && (Long) v > 0) { isall0 = false; } else if (v.getClass().isAssignableFrom(Double.class) && (Double) v > 0) { isall0 = false; } } } } sourceItem.put("isall0", isall0); } boolean isall0 = true; //计算汇总行 for (String fieldcode : viewColumnsFull) { List<Object> listbyAttribute = attributeMapList.get(fieldcode); if (listbyAttribute == null || listbyAttribute.size() == 0) { continue; } Object calVal = null; Object[] obj = listbyAttribute.toArray(); int line_number = 0; try { if (obj[0] instanceof Long) { Long[] f2 = new Long[obj.length]; for (int i = 0; i < obj.length; i++) { line_number = i; String obValue = obj[i] == null ? "0" : obj[i].toString(); if (obValue.equals("0.0")) { obValue = "0"; } f2[i] = Long.valueOf(obValue); } calVal = plus(f2); } else if (obj[0] instanceof Double) { Double[] f2 = new Double[obj.length]; for (int i = 0; i < obj.length; i++) { line_number = i; f2[i] = Double.valueOf(String.valueOf(obj[i])); } calVal = plus(f2); } } catch (ArrayStoreException e) { String valueAsString = ""; try { valueAsString = new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(obj); } catch (JsonProcessingException e1) { logger.error("解析汇总数据错误", valueAsString, e1); } logger.error("汇总数据复制数据错误", valueAsString, e); } catch (Exception e) { logger.error("解析汇总数数据时发生错误, 第{}行, colum:{} ", line_number, fieldcode, e); } totalRowMap.put(fieldcode, calVal); if (!firstTotalRowNeedReplaceId().equals(fieldcode) && isall0) { if (calVal != null && Double.valueOf(String.valueOf(calVal)) > 0) { isall0 = false; } } } //根据依赖字段计算比率值 for (String fieldcode : viewColumns) { if (fieldcode.toLowerCase().equals("duration")) { totalRowMap.put(fieldcode, DateUtil.formatCaseTime(Long.valueOf(totalRowMap.get(fieldcode) == null ? "0" : totalRowMap.get(fieldcode).toString()))); } Collection<String> linkfields = ViewColumnDependUtil.getRateDependFields(fieldcode); if (linkfields == null || linkfields.size() == 0) { continue; } String[] linkfield = new String[linkfields.size()]; linkfield = linkfields.toArray(linkfield); final Object f1 = totalRowMap.get(linkfield[0]); if (f1 == null) { totalRowMap.put(fieldcode, 0); continue; } Object calVal = null; Object linkFieldValue2 = totalRowMap.get(linkfield[1]); if (linkFieldValue2 != null) { if (f1.getClass().isAssignableFrom(Long.class)) { if (fieldcode.startsWith("amt_ltv")) { calVal = divideAmt(((Long) f1) / 100, (Long) linkFieldValue2); } else if (fieldcode.startsWith("rate_retentiond")) { calVal = divide(((Long) f1), (Long) linkFieldValue2); } else if (fieldcode.startsWith("avg_time")) { calVal = divideAvgTime(((Long) f1), (Long) linkFieldValue2); } else if (fieldcode.equals("amt_use_freq")) { calVal = divideAmt(((Long) f1) / 100.0, Long.valueOf(String.valueOf(linkFieldValue2)) * 1.0); } else { if (linkFieldValue2 == null) { linkFieldValue2 = "0"; } calVal = divide((Long) f1, Long.parseLong(linkFieldValue2.toString())); } } else if (f1.getClass().isAssignableFrom(Double.class)) { if (fieldcode.startsWith("amt_ltv")) { calVal = divideAmt(((Double) f1) / 100, Double.valueOf(String.valueOf(linkFieldValue2))); } else if (fieldcode.startsWith("rate_retentiond")) { calVal = divide(((Double) f1), Double.valueOf(String.valueOf(linkFieldValue2))); } else if (fieldcode.startsWith("amt_arp") && fieldcode.endsWith("_new")) { calVal = divideAmt(((Double) f1) / 100, Double.valueOf(String.valueOf(linkFieldValue2))); } else if (fieldcode.startsWith("amt_arp")) { calVal = divide(((Double) f1) / 100, Double.valueOf(String.valueOf(linkFieldValue2))); } else if (fieldcode.equals("amt_pay_perticket") || fieldcode.equals("amt_perticket")) { calVal = divide(((Double) f1) / 100, Double.valueOf(String.valueOf(linkFieldValue2))); } else if (fieldcode.equals("amt_time")) { calVal = divideAmt(((Double) f1) / 100, Double.valueOf(String.valueOf(linkFieldValue2))); } else { calVal = divide((Double) f1, Double.valueOf(String.valueOf( getNewRateInstallData(fieldcode, totalRowMap, linkFieldValue2)))); } } } else { calVal = 0.0d; } totalRowMap.put(fieldcode, calVal); } totalRowMap.put("isall0", false); totalRowMap.put("istotal", true); totalRowMap.put(firstTotalRowNeedReplaceId(), "汇总"); List<Map<String, Object>> newResult = Lists.newArrayList(); newResult.add(totalRowMap); newResult.addAll(sourceResult); return newResult; } protected String firstTotalRowNeedReplaceId() { return ""; } protected void setDefaultValue(ReportListResult reportListResult, List<String> searchIds) { if (searchIds != null && reportListResult.getKey() != null) { List<String> diffList = Lists.newArrayList(Sets.difference(Sets.newHashSet(searchIds), Sets.newHashSet(reportListResult.getKey()))); reportListResult.getKey().addAll(diffList); for (String diffid : diffList) { Map<String, Object> apdItem = Maps.newHashMap(); for (Object key : reportListResult.getColumnkey()) { final String column = String.valueOf(key); if (isRateFields(column)) { apdItem.put(column, 0.0); } else { apdItem.put(column, 0l); } if (column.contains("rate_retentiond3") && !apdItem.containsKey("num_d3_install")) { apdItem.put("num_d3_install", 0l); } if (column.contains("rate_retentiond7") && !apdItem.containsKey("num_d7_install")) { apdItem.put("num_d7_install", 0l); } if (column.contains("rate_retentiond30") && !apdItem.containsKey("num_d30_install")) { apdItem.put("num_d30_install", 0l); } } apdItem.put(firstTotalRowNeedReplaceId(), diffid); apdItem.put("isall0", true); reportListResult.getVal().add(apdItem); } } } protected ReportListResult getMapTotalData(ReportListResult reportResult, String totalName, Map nameMap) { return getMapTotalData(reportResult, totalName, nameMap, null); } protected ReportListResult getMapTotalData(ReportListResult reportResult, String totalName, Map nameMap, Map<String, String> rateCuloms) { List<Object> columnkeys = reportResult.getColumnkey(); Map<String, Object> totalMap = new HashMap<>(); List<String> reteNames = new ArrayList<>(); for (Object colum : columnkeys) { if (colum != null && !colum.toString().startsWith("rate_")) { totalMap.put(colum.toString(), 0L); } else { reteNames.add(colum.toString()); } } List<Map<String, Object>> res = new LinkedList<>(); List<Map<String, Object>> valList = reportResult.getVal(); Set<String> keys = totalMap.keySet(); String reportName = reportResult.getReportname().get(0); boolean isMttiReport = reportName.startsWith("black_top5_list_mtti_"); for (Map<String, Object> data : valList) { for (String kname : keys) { if (!totalName.equals(kname)) { totalMap.put(kname, Long.parseLong(totalMap.get(kname).toString()) + Long.parseLong(data.get(kname).toString())); if (isMttiReport && !kname.equals("sum_install")) { getRateTotal(data, "rate_" + kname, kname, "sum_install"); data.remove(kname); } } else { if (nameMap != null) { Object nameshow = nameMap.get(data.get(totalName).toString()); if (nameshow != null) { data.put(totalName, nameshow); } } } } res.add(data); } totalMap.put(totalName, "汇总"); if (rateCuloms != null) { for (String name : reteNames) { if (rateCuloms.get(name) != null) { this.getRateTotal(totalMap, name, rateCuloms.get(name).split(",")); } } } else { this.getRateTotal(totalMap, "rate_click", "num_black", "num_click"); this.getRateTotal(totalMap, "rate_install", "num_total_install_black", "num_install"); } res.add(0, totalMap); reportResult.setVal(res); return reportResult; } private void getRateTotal(Map<String, Object> totalMap, String rateName, String... keys) { long valueA = Long.parseLong(totalMap.get(keys[0]).toString()); long valueB = Long.parseLong(totalMap.get(keys[1]).toString()); if (valueB != 0 && valueA != 0) { double v = valueA * 100.0 / valueB; DecimalFormat df = new DecimalFormat("#0.00"); totalMap.put(rateName, df.format(v)); } else { totalMap.put(rateName, "0.00"); } } protected List<Map<String, Object>> calFirstTotalRowSimple(ReportListResult reportResult, List<String> viewColumns, List<String> specilColums, String reportName, String totalKey) { List<Map<String, Object>> mapValue = reportResult.getVal(); if (mapValue == null) { return mapValue; } List<String> formatKeys = Arrays.asList("cpc_num", "cpm_num"); Map total_all_ = new HashMap(); int[] isall0 = new int[mapValue.size()]; List<String> totalColums = specilColums == null ? viewColumns : specilColums; for (String colm : totalColums) { if (totalKey.equals(colm)) { total_all_.put(colm, "汇总"); continue; } Double total_double = 0.0; Long total_long = 0L; boolean isLongdata = true; for (int i = 0, j = mapValue.size(); i < j; i++) { Map<String, Object> dataItem = mapValue.get(i); dataItem.put("isall0", true); if (i > 0 && isall0[i - 1] == 1) { mapValue.get(i - 1).put("isall0", false); } Object value = dataItem.get(colm); if (value == null) { continue; } if (value instanceof Long) { total_long += (Long) value; if (isall0[i] == 0 && (Long) value > 0) { isall0[i] = 1; } } else if (value instanceof Double) { isLongdata = false; total_double += (Double) value; if (isall0[i] == 0 && (Double) value > 0) { isall0[i] = 1; } // // //格式化小数 } if (colm.equals(totalColums.get(0))) { //格式化小数 for (String keyc : formatKeys) { Object dataCpm = dataItem.get(keyc); if (dataCpm != null && dataCpm instanceof Double) { dataItem.put(keyc, new BigDecimal((double) dataItem.get(keyc)).setScale(2, Decimal.ROUND_HALF_UP).doubleValue()); } } } } if (isall0[isall0.length - 1] == 1) { mapValue.get(isall0.length - 1).put("isall0", false); } if (isLongdata) { total_all_.put(colm, total_long); } else { total_all_.put(colm, new BigDecimal(total_double).setScale(2, Decimal.ROUND_HALF_UP).doubleValue()); } } total_all_.put("isall0", false); if (specilColums != null && specilColums.size() > 0) { for (String viewColumn : viewColumns) { if (!specilColums.contains(viewColumn)) { total_all_.put(viewColumn, "-"); } } } mapValue.add(0, total_all_); return mapValue; } protected void createColumByReplace(ReportListResult reportResult) { List<Object> keys = reportResult.getColumnkey(); if (firstTotalRowNeedReplaceId().equals(keys.get(0)) || "".equals(firstTotalRowNeedReplaceId())) { return; } keys.remove(0); keys.add(0, firstTotalRowNeedReplaceId()); } }