xyc
昨天 2b1af100a2402e65b44a929489754949198a19df
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package com.trafficaudit.holiday.service;
 
import com.trafficaudit.holiday.HolidayConstants;
import com.trafficaudit.holiday.HolidayNumberUtils;
import com.trafficaudit.holiday.entity.HolidayCalendar;
import com.trafficaudit.holiday.entity.HolidayPassengerFlow;
import com.trafficaudit.holiday.entity.HolidayVehicleFlow;
import com.trafficaudit.holiday.mapper.HolidayPassengerFlowMapper;
import com.trafficaudit.holiday.mapper.HolidayVehicleFlowMapper;
import org.junit.jupiter.api.Test;
 
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
 
/**
 * The Excel comparison base column (C) is an operator backup value only: it must never change the
 * national/provincial ring ratio. This locks in that behaviour.
 */
class HolidayComparisonBaseTest {
 
    @Test
    void ringRatioUsesPreviousDayEvenWhenComparisonBaseIsStored() throws Exception {
        HolidayConfigService configService = mock(HolidayConfigService.class);
        HolidayPassengerFlowMapper passengerMapper = mock(HolidayPassengerFlowMapper.class);
        HolidayVehicleFlowMapper vehicleMapper = mock(HolidayVehicleFlowMapper.class);
 
        when(configService.coefficientOf(2026, HolidayConstants.CATEGORY_HOLIDAY)).thenReturn(new BigDecimal("2.4"));
        when(passengerMapper.selectList(any())).thenReturn(new ArrayList<HolidayPassengerFlow>());
        when(vehicleMapper.selectList(any())).thenReturn(vehicleRows());
 
        HolidayStatService service = new HolidayStatService();
        inject(service, "configService", configService);
        inject(service, "passengerFlowMapper", passengerMapper);
        inject(service, "vehicleFlowMapper", vehicleMapper);
 
        List<Map<String, Object>> rows = service.buildOverviewRows(2026, HolidayConstants.TYPE_NATIONAL_DAY, calendar());
 
        BigDecimal ringRatio = (BigDecimal) rows.get(3).get("nationalProvincialRingRatio");
        assertEquals(ratio(new BigDecimal("322.7695"), new BigDecimal("323.7837")), ringRatio);
        assertNotEquals(ratio(new BigDecimal("322.7695"), new BigDecimal("320.2418")), ringRatio);
        assertEquals(new BigDecimal("320.2418"), rows.get(2).get("comparisonBase"));
    }
 
    @Test
    void exportFormulaComparesPreviousRowInsteadOfComparisonBaseColumn() {
        assertEquals("=(D6-D5)/D5", HolidayWorkbookService.ringRatioFormula(6, 5));
    }
 
    private static BigDecimal ratio(BigDecimal current, BigDecimal base) {
        return HolidayNumberUtils.normalize(HolidayNumberUtils.divide(current, base).subtract(BigDecimal.ONE));
    }
 
    private static List<HolidayVehicleFlow> vehicleRows() {
        List<HolidayVehicleFlow> rows = new ArrayList<>();
        rows.add(vehicle("2026-10-03", "323.7837", "320.2418"));
        rows.add(vehicle("2026-10-04", "322.7695", null));
        return rows;
    }
 
    private static HolidayVehicleFlow vehicle(String date, String value, String base) {
        HolidayVehicleFlow row = new HolidayVehicleFlow();
        row.setYear(2026);
        row.setFlowDate(LocalDate.parse(date));
        row.setRoadCategory(HolidayConstants.ROAD_NATIONAL_PROVINCIAL);
        row.setVehicleType(HolidayConstants.VEHICLE_MEDIUM_SMALL_PASSENGER);
        row.setVehicleCount(new BigDecimal(value));
        row.setComparisonBase(base == null ? null : new BigDecimal(base));
        return row;
    }
 
    private static List<HolidayCalendar> calendar() {
        List<HolidayCalendar> days = new ArrayList<>();
        for (int i = 1; i <= 4; i++) {
            HolidayCalendar day = new HolidayCalendar();
            day.setYear(2026);
            day.setHolidayType(HolidayConstants.TYPE_NATIONAL_DAY);
            day.setDayIndex(i);
            day.setHolidayDate(LocalDate.of(2026, 10, i));
            days.add(day);
        }
        return days;
    }
 
    private static void inject(Object target, String field, Object value) throws Exception {
        Field declared = target.getClass().getDeclaredField(field);
        declared.setAccessible(true);
        declared.set(target, value);
    }
}