| | |
| | | import java.io.FileInputStream; |
| | | import java.io.InputStream; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.nio.file.Files; |
| | | import java.time.LocalDate; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.function.Function; |
| | | import java.util.zip.ZipEntry; |
| | | import java.util.zip.ZipInputStream; |
| | | import java.util.zip.ZipOutputStream; |
| | |
| | | if (table == null) { |
| | | throw new IllegalArgumentException("快报模板中找不到数据表"); |
| | | } |
| | | DailyMetrics previousYearCivilCumulative = comparableCumulative( |
| | | current, previousYear, DailyMetrics::getCivilAviation); |
| | | DailyMetrics twoYearsAgoCivilCumulative = comparableCumulative( |
| | | current, twoYearsAgo, DailyMetrics::getCivilAviation); |
| | | writeTableRow(table, 2, new String[]{ |
| | | number(current.getNonBusinessPersonFlow()), |
| | | ratio(current.getNonBusinessPersonFlow(), previousDay == null ? null : previousDay.getNonBusinessPersonFlow()), |
| | |
| | | previousYear == null ? null : previousYear.getCivilAviation(), |
| | | twoYearsAgo == null ? null : twoYearsAgo.getCivilAviation(), |
| | | currentCumulative.getCivilAviation(), |
| | | previousYearCumulative == null ? null : previousYearCumulative.getCivilAviation(), |
| | | twoYearsAgoCumulative == null ? null : twoYearsAgoCumulative.getCivilAviation())); |
| | | previousYearCivilCumulative == null ? null : previousYearCivilCumulative.getCivilAviation(), |
| | | twoYearsAgoCivilCumulative == null ? null : twoYearsAgoCivilCumulative.getCivilAviation())); |
| | | writeTableRow(table, 7, transportRow(current.getWater(), |
| | | previousDay == null ? null : previousDay.getWater(), |
| | | previousYear == null ? null : previousYear.getWater(), |
| | |
| | | Element pPr = firstChildElement(templateParagraph, "pPr"); |
| | | if (pPr != null) paragraph.appendChild(pPr.cloneNode(true)); |
| | | } |
| | | Element templateRun = templateParagraph == null ? null : firstChildElement(templateParagraph, "r"); |
| | | Element rPr = templateRun == null ? null : firstChildElement(templateRun, "rPr"); |
| | | Element run = createElement("r"); |
| | | if (rPr != null) run.appendChild(rPr.cloneNode(true)); |
| | | Element t = createElement("t"); |
| | | t.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:space", "preserve"); |
| | | t.setTextContent(text == null ? "" : text); |
| | |
| | | return (percent.signum() > 0 ? "增长" : "下降") + HolidayNumberUtils.format1(percent.abs()) + "%"; |
| | | } |
| | | |
| | | private DailyMetrics comparableCumulative(DailyMetrics current, DailyMetrics comparisonYear, |
| | | Function<DailyMetrics, BigDecimal> selector) { |
| | | if (current == null || comparisonYear == null) return null; |
| | | int coveredDay = 0; |
| | | for (int day = current.getDayIndex(); day >= 1; day--) { |
| | | DailyMetrics metrics = statService.dailyMetrics(current.getYear(), current.getHolidayType(), day); |
| | | if (metrics != null && selector.apply(metrics) != null) { |
| | | coveredDay = day; |
| | | break; |
| | | } |
| | | } |
| | | if (coveredDay == 0) return null; |
| | | return statService.cumulativeMetrics(comparisonYear.getYear(), current.getHolidayType(), coveredDay); |
| | | } |
| | | |
| | | private String ratio(BigDecimal current, BigDecimal base) { |
| | | if (current == null || base == null || base.abs().compareTo(EPSILON) < 0) return "—"; |
| | | return ratioPhrase(current, base); |
| | | BigDecimal ratio = HolidayNumberUtils.divide(current, base); |
| | | if (ratio == null) return "—"; |
| | | BigDecimal percent = HolidayNumberUtils.multiply(ratio.subtract(BigDecimal.ONE), BigDecimal.valueOf(100)); |
| | | if (percent == null) return "—"; |
| | | BigDecimal rounded = percent.setScale(1, RoundingMode.HALF_UP); |
| | | return rounded.signum() == 0 ? "0%" : rounded.toPlainString() + "%"; |
| | | } |
| | | |
| | | private String number(BigDecimal value) { |