A fintech super-app serves 20M+ mobile DAUs through an in-app webview. To reduce latency and battery drain, the frontend batches calls to mobile-specific web APIs (e.g., Geolocation, DeviceOrientation, Vibration) and ships them to an on-device aggregator before sending a compact payload to the backend.
However, the aggregator must deduplicate events that are effectively the same (e.g., multiple geolocation reads within a few seconds) while preserving the order in which distinct user actions occurred. Your task is to implement the core merge logic.
You are given a list of API event records in chronological order:
events[i] = [t_i, api_i, payload_i]
t_i is an integer timestamp in milliseconds (non-decreasing)api_i is a string (e.g., "geo", "orient", "vibrate")payload_i is a string (opaque; treat as exact-match)You are also given an integer window_ms.
Two events A and B are considered mergeable if:
A.api == B.apiA.payload == B.payloadB.t - A.t <= window_msWhen events are mergeable, they should be merged into a single output record:
[start_t, end_t, api, payload, count]
start_t = timestamp of the first event in the merged groupend_t = timestamp of the last event in the merged groupcount = number of merged eventsMerging is only allowed for contiguous runs in the input. If a different event appears in between, you must not merge across it even if timestamps and fields match.
Return the merged list.
Input:
events = [[1000,"geo","A"],[1200,"geo","A"],[2000,"orient","x"],[2100,"geo","A"]]window_ms = 500Output:
[[1000,1200,"geo","A",2],[2000,2000,"orient","x",1],[2100,2100,"geo","A",1]]Explanation:
The first two geo/A events are contiguous and within 500ms, so they merge. The final geo/A cannot merge with them because an orient/x event breaks contiguity.
Input:
events = [[0,"vibrate","50"],[400,"vibrate","50"],[1200,"vibrate","50"],[1300,"vibrate","60"]]window_ms = 500Output:
[[0,400,"vibrate","50",2],[1200,1200,"vibrate","50",1],[1300,1300,"vibrate","60",1]]Explanation: The first two merge (400ms apart). The third is 800ms after the first, so it starts a new group. Different payloads never merge.
t_i non-decreasing).payload as an opaque string; no parsing.