Choose your marketSelected market: United States
Deloitte Virtual Internship / Task 04
An original Ape Intern practical · Task 04Service performance disparity review
Control for service mix and sample size before setting hub review priorities.
Start with the completed outputs, then use the materials to deliver your own work.
Read complete output firstMaterials
learner/checkpoints/order-review.csv Read the full file
Download file| order_id | hub | service | route | created_at | due_at | cohort | late_minutes | overdue_minutes |
|---|---|---|---|---|---|---|---|---|
| O0001 | Harbour | standard | R11 | 2026-09-01T06:00:00Z | 2026-09-02T06:00:00Z | cancelled | 0 | 0 |
| O0002 | Harbour | standard | R12 | 2026-09-02T07:00:00Z | 2026-09-03T07:00:00Z | delivered_late | 50 | 0 |
| O0003 | Harbour | standard | R11 | 2026-09-03T08:00:00Z | 2026-09-04T08:00:00Z | on_time | 0 | 0 |
| O0004 | Harbour | standard | R12 | 2026-09-04T09:00:00Z | 2026-09-05T09:00:00Z | on_time | 0 | 0 |
| O0005 | Harbour | standard | R11 | 2026-09-05T10:00:00Z | 2026-09-06T10:00:00Z | delivered_late | 50 | 0 |
| O0006 | Harbour | standard | R12 | 2026-09-06T11:00:00Z | 2026-09-07T11:00:00Z | on_time | 0 | 0 |
| O0007 | Harbour | standard | R11 | 2026-09-07T12:00:00Z | 2026-09-08T12:00:00Z | on_time | 0 | 0 |
| O0008 | Harbour | standard | R12 | 2026-09-08T13:00:00Z | 2026-09-09T13:00:00Z | delivered_late | 50 | 0 |
| O0009 | Harbour | standard | R11 | 2026-09-09T06:00:00Z | 2026-09-10T06:00:00Z | on_time | 0 | 0 |
| O0010 | Harbour | standard | R12 | 2026-09-10T07:00:00Z | 2026-09-11T07:00:00Z | on_time | 0 | 0 |
| O0011 | Harbour | standard | R11 | 2026-09-11T08:00:00Z | 2026-09-12T08:00:00Z | delivered_late | 50 | 0 |
| O0012 | Harbour | standard | R12 | 2026-09-12T09:00:00Z | 2026-09-13T09:00:00Z | on_time | 0 | 0 |
| O0013 | Harbour | standard | R11 | 2026-09-13T10:00:00Z | 2026-09-14T10:00:00Z | on_time | 0 | 0 |
| O0014 | Harbour | standard | R12 | 2026-09-01T11:00:00Z | 2026-09-02T11:00:00Z | delivered_late | 50 | 0 |
| O0015 | Harbour | standard | R11 | 2026-09-02T12:00:00Z | 2026-09-03T12:00:00Z | on_time | 0 | 0 |
| O0016 | Harbour | standard | R12 | 2026-09-03T13:00:00Z | 2026-09-04T13:00:00Z | on_time | 0 | 0 |
| O0017 | Harbour | standard | R11 | 2026-09-04T06:00:00Z | 2026-09-05T06:00:00Z | delivered_late | 50 | 0 |
| O0018 | Harbour | standard | R12 | 2026-09-05T07:00:00Z | 2026-09-06T07:00:00Z | overdue_open | 0 | 12540 |
| O0019 | Harbour | standard | R11 | 2026-09-06T08:00:00Z | 2026-09-07T08:00:00Z | on_time | 0 | 0 |
| O0020 | Harbour | standard | R12 | 2026-09-07T09:00:00Z | 2026-09-08T09:00:00Z | delivered_late | 50 | 0 |
| O0021 | Harbour | standard | R11 | 2026-09-08T10:00:00Z | 2026-09-09T10:00:00Z | on_time | 0 | 0 |
| O0022 | Harbour | standard | R12 | 2026-09-09T11:00:00Z | 2026-09-10T11:00:00Z | on_time | 0 | 0 |
| O0023 | Harbour | standard | R11 | 2026-09-10T12:00:00Z | 2026-09-11T12:00:00Z | delivered_late | 50 | 0 |
| O0024 | Harbour | standard | R12 | 2026-09-11T13:00:00Z | 2026-09-12T13:00:00Z | on_time | 0 | 0 |
| O0025 | Harbour | standard | R11 | 2026-09-12T06:00:00Z | 2026-09-13T06:00:00Z | on_time | 0 | 0 |
| O0026 | Harbour | standard | R12 | 2026-09-13T07:00:00Z | 2026-09-14T07:00:00Z | delivered_late | 50 | 0 |
| O0027 | Harbour | standard | R11 | 2026-09-01T08:00:00Z | 2026-09-02T08:00:00Z | on_time | 0 | 0 |
| O0028 | Harbour | standard | R12 | 2026-09-02T09:00:00Z | 2026-09-03T09:00:00Z | on_time | 0 | 0 |
| O0029 | Harbour | standard | R11 | 2026-09-03T10:00:00Z | 2026-09-04T10:00:00Z | delivered_late | 50 | 0 |
| O0030 | Harbour | standard | R12 | 2026-09-04T11:00:00Z | 2026-09-05T11:00:00Z | cancelled | 0 | 0 |
| O0031 | Harbour | standard | R11 | 2026-09-05T12:00:00Z | 2026-09-06T12:00:00Z | on_time | 0 | 0 |
| O0032 | Harbour | standard | R12 | 2026-09-06T13:00:00Z | 2026-09-07T13:00:00Z | delivered_late | 50 | 0 |
| O0033 | Harbour | standard | R11 | 2026-09-07T06:00:00Z | 2026-09-08T06:00:00Z | on_time | 0 | 0 |
| O0034 | Harbour | standard | R12 | 2026-09-08T07:00:00Z | 2026-09-09T07:00:00Z | on_time | 0 | 0 |
| O0035 | Harbour | standard | R11 | 2026-09-09T08:00:00Z | 2026-09-10T08:00:00Z | overdue_open | 0 | 6720 |
| O0036 | Harbour | standard | R12 | 2026-09-10T09:00:00Z | 2026-09-11T09:00:00Z | on_time | 0 | 0 |
| O0037 | Harbour | standard | R11 | 2026-09-11T10:00:00Z | 2026-09-12T10:00:00Z | on_time | 0 | 0 |
| O0038 | Harbour | standard | R12 | 2026-09-12T11:00:00Z | 2026-09-13T11:00:00Z | delivered_late | 50 | 0 |
| O0039 | Harbour | standard | R11 | 2026-09-13T12:00:00Z | 2026-09-14T12:00:00Z | on_time | 0 | 0 |
| O0040 | Harbour | standard | R12 | 2026-09-14T21:00:00Z | 2026-09-15T21:00:00Z | not_mature | 0 | 0 |
| O0041 | Harbour | express | R11 | 2026-09-01T06:00:00Z | 2026-09-01T14:00:00Z | cancelled | 0 | 0 |
| O0042 | Harbour | express | R12 | 2026-09-02T07:00:00Z | 2026-09-02T15:00:00Z | delivered_late | 50 | 0 |
| O0043 | Harbour | express | R11 | 2026-09-03T08:00:00Z | 2026-09-03T16:00:00Z | delivered_late | 50 | 0 |
| O0044 | Harbour | express | R12 | 2026-09-04T09:00:00Z | 2026-09-04T17:00:00Z | delivered_late | 50 | 0 |
| O0045 | Harbour | express | R11 | 2026-09-05T10:00:00Z | 2026-09-05T18:00:00Z | delivered_late | 50 | 0 |
| O0046 | Harbour | express | R12 | 2026-09-06T11:00:00Z | 2026-09-06T19:00:00Z | delivered_late | 50 | 0 |
| O0047 | Harbour | express | R11 | 2026-09-07T12:00:00Z | 2026-09-07T20:00:00Z | delivered_late | 50 | 0 |
| O0048 | Harbour | express | R12 | 2026-09-08T13:00:00Z | 2026-09-08T21:00:00Z | delivered_late | 50 | 0 |
| O0049 | Harbour | express | R11 | 2026-09-09T06:00:00Z | 2026-09-09T14:00:00Z | delivered_late | 50 | 0 |
| O0050 | Harbour | express | R12 | 2026-09-10T07:00:00Z | 2026-09-10T15:00:00Z | delivered_late | 50 | 0 |
| O0051 | Harbour | express | R11 | 2026-09-11T08:00:00Z | 2026-09-11T16:00:00Z | delivered_late | 50 | 0 |
| O0052 | Harbour | express | R12 | 2026-09-12T09:00:00Z | 2026-09-12T17:00:00Z | delivered_late | 50 | 0 |
| O0053 | Harbour | express | R11 | 2026-09-13T10:00:00Z | 2026-09-13T18:00:00Z | delivered_late | 50 | 0 |
| O0054 | Harbour | express | R12 | 2026-09-01T11:00:00Z | 2026-09-01T19:00:00Z | delivered_late | 50 | 0 |
| O0055 | Harbour | express | R11 | 2026-09-02T12:00:00Z | 2026-09-02T20:00:00Z | delivered_late | 50 | 0 |
| O0056 | Harbour | express | R12 | 2026-09-03T13:00:00Z | 2026-09-03T21:00:00Z | delivered_late | 50 | 0 |
| O0057 | Harbour | express | R11 | 2026-09-04T06:00:00Z | 2026-09-04T14:00:00Z | delivered_late | 50 | 0 |
| O0058 | Harbour | express | R12 | 2026-09-05T07:00:00Z | 2026-09-05T15:00:00Z | overdue_open | 0 | 13500 |
| O0059 | Harbour | express | R11 | 2026-09-06T08:00:00Z | 2026-09-06T16:00:00Z | delivered_late | 50 | 0 |
| O0060 | Harbour | express | R12 | 2026-09-14T21:00:00Z | 2026-09-15T05:00:00Z | not_mature | 0 | 0 |
| O0061 | Eastgate | standard | R21 | 2026-09-01T06:00:00Z | 2026-09-02T06:00:00Z | cancelled | 0 | 0 |
| O0062 | Eastgate | standard | R22 | 2026-09-02T07:00:00Z | 2026-09-03T07:00:00Z | delivered_late | 70 | 0 |
| O0063 | Eastgate | standard | R21 | 2026-09-03T08:00:00Z | 2026-09-04T08:00:00Z | on_time | 0 | 0 |
| O0064 | Eastgate | standard | R22 | 2026-09-04T09:00:00Z | 2026-09-05T09:00:00Z | on_time | 0 | 0 |
| O0065 | Eastgate | standard | R21 | 2026-09-05T10:00:00Z | 2026-09-06T10:00:00Z | on_time | 0 | 0 |
| O0066 | Eastgate | standard | R22 | 2026-09-06T11:00:00Z | 2026-09-07T11:00:00Z | delivered_late | 70 | 0 |
| O0067 | Eastgate | standard | R21 | 2026-09-07T12:00:00Z | 2026-09-08T12:00:00Z | on_time | 0 | 0 |
| O0068 | Eastgate | standard | R22 | 2026-09-08T13:00:00Z | 2026-09-09T13:00:00Z | on_time | 0 | 0 |
| O0069 | Eastgate | standard | R21 | 2026-09-09T06:00:00Z | 2026-09-10T06:00:00Z | on_time | 0 | 0 |
| O0070 | Eastgate | standard | R22 | 2026-09-10T07:00:00Z | 2026-09-11T07:00:00Z | delivered_late | 70 | 0 |
| O0071 | Eastgate | standard | R21 | 2026-09-11T08:00:00Z | 2026-09-12T08:00:00Z | on_time | 0 | 0 |
| O0072 | Eastgate | standard | R22 | 2026-09-12T09:00:00Z | 2026-09-13T09:00:00Z | on_time | 0 | 0 |
| O0073 | Eastgate | standard | R21 | 2026-09-13T10:00:00Z | 2026-09-14T10:00:00Z | on_time | 0 | 0 |
| O0074 | Eastgate | standard | R22 | 2026-09-01T11:00:00Z | 2026-09-02T11:00:00Z | delivered_late | 70 | 0 |
| O0075 | Eastgate | standard | R21 | 2026-09-02T12:00:00Z | 2026-09-03T12:00:00Z | on_time | 0 | 0 |
| O0076 | Eastgate | standard | R22 | 2026-09-03T13:00:00Z | 2026-09-04T13:00:00Z | on_time | 0 | 0 |
| O0077 | Eastgate | standard | R21 | 2026-09-04T06:00:00Z | 2026-09-05T06:00:00Z | on_time | 0 | 0 |
| O0078 | Eastgate | standard | R22 | 2026-09-05T07:00:00Z | 2026-09-06T07:00:00Z | overdue_open | 0 | 12540 |
| O0079 | Eastgate | standard | R21 | 2026-09-06T08:00:00Z | 2026-09-07T08:00:00Z | on_time | 0 | 0 |
| O0080 | Eastgate | standard | R22 | 2026-09-14T21:00:00Z | 2026-09-15T21:00:00Z | not_mature | 0 | 0 |
| O0081 | Eastgate | express | R21 | 2026-09-01T06:00:00Z | 2026-09-01T14:00:00Z | cancelled | 0 | 0 |
| O0082 | Eastgate | express | R22 | 2026-09-02T07:00:00Z | 2026-09-02T15:00:00Z | delivered_late | 70 | 0 |
| O0083 | Eastgate | express | R21 | 2026-09-03T08:00:00Z | 2026-09-03T16:00:00Z | on_time | 0 | 0 |
| O0084 | Eastgate | express | R22 | 2026-09-04T09:00:00Z | 2026-09-04T17:00:00Z | delivered_late | 70 | 0 |
| O0085 | Eastgate | express | R21 | 2026-09-05T10:00:00Z | 2026-09-05T18:00:00Z | delivered_late | 70 | 0 |
| O0086 | Eastgate | express | R22 | 2026-09-06T11:00:00Z | 2026-09-06T19:00:00Z | on_time | 0 | 0 |
| O0087 | Eastgate | express | R21 | 2026-09-07T12:00:00Z | 2026-09-07T20:00:00Z | delivered_late | 70 | 0 |
| O0088 | Eastgate | express | R22 | 2026-09-08T13:00:00Z | 2026-09-08T21:00:00Z | delivered_late | 70 | 0 |
| O0089 | Eastgate | express | R21 | 2026-09-09T06:00:00Z | 2026-09-09T14:00:00Z | on_time | 0 | 0 |
| O0090 | Eastgate | express | R22 | 2026-09-10T07:00:00Z | 2026-09-10T15:00:00Z | delivered_late | 70 | 0 |
| O0091 | Eastgate | express | R21 | 2026-09-11T08:00:00Z | 2026-09-11T16:00:00Z | delivered_late | 70 | 0 |
| O0092 | Eastgate | express | R22 | 2026-09-12T09:00:00Z | 2026-09-12T17:00:00Z | on_time | 0 | 0 |
| O0093 | Eastgate | express | R21 | 2026-09-13T10:00:00Z | 2026-09-13T18:00:00Z | delivered_late | 70 | 0 |
| O0094 | Eastgate | express | R22 | 2026-09-01T11:00:00Z | 2026-09-01T19:00:00Z | delivered_late | 70 | 0 |
| O0095 | Eastgate | express | R21 | 2026-09-02T12:00:00Z | 2026-09-02T20:00:00Z | on_time | 0 | 0 |
| O0096 | Eastgate | express | R22 | 2026-09-03T13:00:00Z | 2026-09-03T21:00:00Z | delivered_late | 70 | 0 |
| O0097 | Eastgate | express | R21 | 2026-09-04T06:00:00Z | 2026-09-04T14:00:00Z | delivered_late | 70 | 0 |
| O0098 | Eastgate | express | R22 | 2026-09-05T07:00:00Z | 2026-09-05T15:00:00Z | overdue_open | 0 | 13500 |
| O0099 | Eastgate | express | R21 | 2026-09-06T08:00:00Z | 2026-09-06T16:00:00Z | delivered_late | 70 | 0 |
| O0100 | Eastgate | express | R22 | 2026-09-07T09:00:00Z | 2026-09-07T17:00:00Z | delivered_late | 70 | 0 |
| O0101 | Eastgate | express | R21 | 2026-09-08T10:00:00Z | 2026-09-08T18:00:00Z | on_time | 0 | 0 |
| O0102 | Eastgate | express | R22 | 2026-09-09T11:00:00Z | 2026-09-09T19:00:00Z | delivered_late | 70 | 0 |
| O0103 | Eastgate | express | R21 | 2026-09-10T12:00:00Z | 2026-09-10T20:00:00Z | delivered_late | 70 | 0 |
| O0104 | Eastgate | express | R22 | 2026-09-11T13:00:00Z | 2026-09-11T21:00:00Z | on_time | 0 | 0 |
| O0105 | Eastgate | express | R21 | 2026-09-12T06:00:00Z | 2026-09-12T14:00:00Z | delivered_late | 70 | 0 |
| O0106 | Eastgate | express | R22 | 2026-09-13T07:00:00Z | 2026-09-13T15:00:00Z | delivered_late | 70 | 0 |
| O0107 | Eastgate | express | R21 | 2026-09-01T08:00:00Z | 2026-09-01T16:00:00Z | on_time | 0 | 0 |
| O0108 | Eastgate | express | R22 | 2026-09-02T09:00:00Z | 2026-09-02T17:00:00Z | delivered_late | 70 | 0 |
| O0109 | Eastgate | express | R21 | 2026-09-03T10:00:00Z | 2026-09-03T18:00:00Z | delivered_late | 70 | 0 |
| O0110 | Eastgate | express | R22 | 2026-09-04T11:00:00Z | 2026-09-04T19:00:00Z | cancelled | 0 | 0 |
| O0111 | Eastgate | express | R21 | 2026-09-05T12:00:00Z | 2026-09-05T20:00:00Z | delivered_late | 70 | 0 |
| O0112 | Eastgate | express | R22 | 2026-09-06T13:00:00Z | 2026-09-06T21:00:00Z | delivered_late | 70 | 0 |
| O0113 | Eastgate | express | R21 | 2026-09-07T06:00:00Z | 2026-09-07T14:00:00Z | on_time | 0 | 0 |
| O0114 | Eastgate | express | R22 | 2026-09-08T07:00:00Z | 2026-09-08T15:00:00Z | delivered_late | 70 | 0 |
| O0115 | Eastgate | express | R21 | 2026-09-09T08:00:00Z | 2026-09-09T16:00:00Z | overdue_open | 0 | 7680 |
| O0116 | Eastgate | express | R22 | 2026-09-10T09:00:00Z | 2026-09-10T17:00:00Z | on_time | 0 | 0 |
| O0117 | Eastgate | express | R21 | 2026-09-11T10:00:00Z | 2026-09-11T18:00:00Z | delivered_late | 70 | 0 |
| O0118 | Eastgate | express | R22 | 2026-09-12T11:00:00Z | 2026-09-12T19:00:00Z | delivered_late | 70 | 0 |
| O0119 | Eastgate | express | R21 | 2026-09-13T12:00:00Z | 2026-09-13T20:00:00Z | on_time | 0 | 0 |
| O0120 | Eastgate | express | R22 | 2026-09-14T21:00:00Z | 2026-09-15T05:00:00Z | not_mature | 0 | 0 |
| O0121 | Westhill | standard | R31 | 2026-09-01T06:00:00Z | 2026-09-02T06:00:00Z | cancelled | 0 | 0 |
| O0122 | Westhill | standard | R32 | 2026-09-02T07:00:00Z | 2026-09-03T07:00:00Z | delivered_late | 90 | 0 |
| O0123 | Westhill | standard | R31 | 2026-09-03T08:00:00Z | 2026-09-04T08:00:00Z | on_time | 0 | 0 |
| O0124 | Westhill | standard | R32 | 2026-09-04T09:00:00Z | 2026-09-05T09:00:00Z | on_time | 0 | 0 |
| O0125 | Westhill | standard | R31 | 2026-09-05T10:00:00Z | 2026-09-06T10:00:00Z | on_time | 0 | 0 |
| O0126 | Westhill | standard | R32 | 2026-09-06T11:00:00Z | 2026-09-07T11:00:00Z | on_time | 0 | 0 |
| O0127 | Westhill | standard | R31 | 2026-09-07T12:00:00Z | 2026-09-08T12:00:00Z | delivered_late | 90 | 0 |
| O0128 | Westhill | standard | R32 | 2026-09-08T13:00:00Z | 2026-09-09T13:00:00Z | on_time | 0 | 0 |
| O0129 | Westhill | standard | R31 | 2026-09-09T06:00:00Z | 2026-09-10T06:00:00Z | on_time | 0 | 0 |
| O0130 | Westhill | standard | R32 | 2026-09-10T07:00:00Z | 2026-09-11T07:00:00Z | on_time | 0 | 0 |
| O0131 | Westhill | standard | R31 | 2026-09-11T08:00:00Z | 2026-09-12T08:00:00Z | on_time | 0 | 0 |
| O0132 | Westhill | standard | R32 | 2026-09-12T09:00:00Z | 2026-09-13T09:00:00Z | delivered_late | 90 | 0 |
| O0133 | Westhill | standard | R31 | 2026-09-13T10:00:00Z | 2026-09-14T10:00:00Z | on_time | 0 | 0 |
| O0134 | Westhill | standard | R32 | 2026-09-01T11:00:00Z | 2026-09-02T11:00:00Z | on_time | 0 | 0 |
| O0135 | Westhill | standard | R31 | 2026-09-02T12:00:00Z | 2026-09-03T12:00:00Z | on_time | 0 | 0 |
| O0136 | Westhill | standard | R32 | 2026-09-03T13:00:00Z | 2026-09-04T13:00:00Z | on_time | 0 | 0 |
| O0137 | Westhill | standard | R31 | 2026-09-04T06:00:00Z | 2026-09-05T06:00:00Z | delivered_late | 90 | 0 |
| O0138 | Westhill | standard | R32 | 2026-09-05T07:00:00Z | 2026-09-06T07:00:00Z | overdue_open | 0 | 12540 |
| O0139 | Westhill | standard | R31 | 2026-09-06T08:00:00Z | 2026-09-07T08:00:00Z | on_time | 0 | 0 |
| O0140 | Westhill | standard | R32 | 2026-09-07T09:00:00Z | 2026-09-08T09:00:00Z | on_time | 0 | 0 |
| O0141 | Westhill | standard | R31 | 2026-09-08T10:00:00Z | 2026-09-09T10:00:00Z | on_time | 0 | 0 |
| O0142 | Westhill | standard | R32 | 2026-09-09T11:00:00Z | 2026-09-10T11:00:00Z | delivered_late | 90 | 0 |
| O0143 | Westhill | standard | R31 | 2026-09-10T12:00:00Z | 2026-09-11T12:00:00Z | on_time | 0 | 0 |
| O0144 | Westhill | standard | R32 | 2026-09-11T13:00:00Z | 2026-09-12T13:00:00Z | on_time | 0 | 0 |
| O0145 | Westhill | standard | R31 | 2026-09-12T06:00:00Z | 2026-09-13T06:00:00Z | on_time | 0 | 0 |
| O0146 | Westhill | standard | R32 | 2026-09-13T07:00:00Z | 2026-09-14T07:00:00Z | on_time | 0 | 0 |
| O0147 | Westhill | standard | R31 | 2026-09-01T08:00:00Z | 2026-09-02T08:00:00Z | delivered_late | 90 | 0 |
| O0148 | Westhill | standard | R32 | 2026-09-02T09:00:00Z | 2026-09-03T09:00:00Z | on_time | 0 | 0 |
| O0149 | Westhill | standard | R31 | 2026-09-03T10:00:00Z | 2026-09-04T10:00:00Z | on_time | 0 | 0 |
| O0150 | Westhill | standard | R32 | 2026-09-04T11:00:00Z | 2026-09-05T11:00:00Z | cancelled | 0 | 0 |
| O0151 | Westhill | standard | R31 | 2026-09-05T12:00:00Z | 2026-09-06T12:00:00Z | on_time | 0 | 0 |
| O0152 | Westhill | standard | R32 | 2026-09-06T13:00:00Z | 2026-09-07T13:00:00Z | delivered_late | 90 | 0 |
| O0153 | Westhill | standard | R31 | 2026-09-07T06:00:00Z | 2026-09-08T06:00:00Z | on_time | 0 | 0 |
| O0154 | Westhill | standard | R32 | 2026-09-08T07:00:00Z | 2026-09-09T07:00:00Z | on_time | 0 | 0 |
| O0155 | Westhill | standard | R31 | 2026-09-09T08:00:00Z | 2026-09-10T08:00:00Z | overdue_open | 0 | 6720 |
| O0156 | Westhill | standard | R32 | 2026-09-14T21:00:00Z | 2026-09-15T21:00:00Z | not_mature | 0 | 0 |
| O0157 | Westhill | express | R31 | 2026-09-01T06:00:00Z | 2026-09-01T14:00:00Z | cancelled | 0 | 0 |
| O0158 | Westhill | express | R32 | 2026-09-02T07:00:00Z | 2026-09-02T15:00:00Z | delivered_late | 90 | 0 |
| O0159 | Westhill | express | R31 | 2026-09-03T08:00:00Z | 2026-09-03T16:00:00Z | on_time | 0 | 0 |
| O0160 | Westhill | express | R32 | 2026-09-04T09:00:00Z | 2026-09-04T17:00:00Z | on_time | 0 | 0 |
| O0161 | Westhill | express | R31 | 2026-09-05T10:00:00Z | 2026-09-05T18:00:00Z | delivered_late | 90 | 0 |
| O0162 | Westhill | express | R32 | 2026-09-06T11:00:00Z | 2026-09-06T19:00:00Z | delivered_late | 90 | 0 |
| O0163 | Westhill | express | R31 | 2026-09-07T12:00:00Z | 2026-09-07T20:00:00Z | on_time | 0 | 0 |
| O0164 | Westhill | express | R32 | 2026-09-08T13:00:00Z | 2026-09-08T21:00:00Z | on_time | 0 | 0 |
| O0165 | Westhill | express | R31 | 2026-09-09T06:00:00Z | 2026-09-09T14:00:00Z | delivered_late | 90 | 0 |
| O0166 | Westhill | express | R32 | 2026-09-10T07:00:00Z | 2026-09-10T15:00:00Z | delivered_late | 90 | 0 |
| O0167 | Westhill | express | R31 | 2026-09-11T08:00:00Z | 2026-09-11T16:00:00Z | on_time | 0 | 0 |
| O0168 | Westhill | express | R32 | 2026-09-12T09:00:00Z | 2026-09-12T17:00:00Z | on_time | 0 | 0 |
| O0169 | Westhill | express | R31 | 2026-09-13T10:00:00Z | 2026-09-13T18:00:00Z | delivered_late | 90 | 0 |
| O0170 | Westhill | express | R32 | 2026-09-01T11:00:00Z | 2026-09-01T19:00:00Z | delivered_late | 90 | 0 |
| O0171 | Westhill | express | R31 | 2026-09-02T12:00:00Z | 2026-09-02T20:00:00Z | on_time | 0 | 0 |
| O0172 | Westhill | express | R32 | 2026-09-03T13:00:00Z | 2026-09-03T21:00:00Z | on_time | 0 | 0 |
| O0173 | Westhill | express | R31 | 2026-09-04T06:00:00Z | 2026-09-04T14:00:00Z | delivered_late | 90 | 0 |
| O0174 | Westhill | express | R32 | 2026-09-05T07:00:00Z | 2026-09-05T15:00:00Z | overdue_open | 0 | 13500 |
| O0175 | Westhill | express | R31 | 2026-09-06T08:00:00Z | 2026-09-06T16:00:00Z | on_time | 0 | 0 |
| O0176 | Westhill | express | R32 | 2026-09-07T09:00:00Z | 2026-09-07T17:00:00Z | on_time | 0 | 0 |
| O0177 | Westhill | express | R31 | 2026-09-08T10:00:00Z | 2026-09-08T18:00:00Z | delivered_late | 90 | 0 |
| O0178 | Westhill | express | R32 | 2026-09-09T11:00:00Z | 2026-09-09T19:00:00Z | delivered_late | 90 | 0 |
| O0179 | Westhill | express | R31 | 2026-09-10T12:00:00Z | 2026-09-10T20:00:00Z | on_time | 0 | 0 |
| O0180 | Westhill | express | R32 | 2026-09-14T21:00:00Z | 2026-09-15T05:00:00Z | not_mature | 0 | 0 |
| O0181 | Southbay | standard | R41 | 2026-09-01T06:00:00Z | 2026-09-02T06:00:00Z | cancelled | 0 | 0 |
| O0182 | Southbay | standard | R42 | 2026-09-02T07:00:00Z | 2026-09-03T07:00:00Z | delivered_late | 110 | 0 |
| O0183 | Southbay | standard | R41 | 2026-09-03T08:00:00Z | 2026-09-04T08:00:00Z | on_time | 0 | 0 |
| O0184 | Southbay | standard | R42 | 2026-09-04T09:00:00Z | 2026-09-05T09:00:00Z | on_time | 0 | 0 |
| O0185 | Southbay | standard | R41 | 2026-09-05T10:00:00Z | 2026-09-06T10:00:00Z | on_time | 0 | 0 |
| O0186 | Southbay | standard | R42 | 2026-09-06T11:00:00Z | 2026-09-07T11:00:00Z | on_time | 0 | 0 |
| O0187 | Southbay | standard | R41 | 2026-09-07T12:00:00Z | 2026-09-08T12:00:00Z | on_time | 0 | 0 |
| O0188 | Southbay | standard | R42 | 2026-09-08T13:00:00Z | 2026-09-09T13:00:00Z | delivered_late | 110 | 0 |
| O0189 | Southbay | standard | R41 | 2026-09-09T06:00:00Z | 2026-09-10T06:00:00Z | on_time | 0 | 0 |
| O0190 | Southbay | standard | R42 | 2026-09-10T07:00:00Z | 2026-09-11T07:00:00Z | on_time | 0 | 0 |
| O0191 | Southbay | standard | R41 | 2026-09-11T08:00:00Z | 2026-09-12T08:00:00Z | on_time | 0 | 0 |
| O0192 | Southbay | standard | R42 | 2026-09-12T09:00:00Z | 2026-09-13T09:00:00Z | on_time | 0 | 0 |
| O0193 | Southbay | standard | R41 | 2026-09-13T10:00:00Z | 2026-09-14T10:00:00Z | on_time | 0 | 0 |
| O0194 | Southbay | standard | R42 | 2026-09-01T11:00:00Z | 2026-09-02T11:00:00Z | delivered_late | 110 | 0 |
| O0195 | Southbay | standard | R41 | 2026-09-02T12:00:00Z | 2026-09-03T12:00:00Z | on_time | 0 | 0 |
| O0196 | Southbay | standard | R42 | 2026-09-03T13:00:00Z | 2026-09-04T13:00:00Z | on_time | 0 | 0 |
| O0197 | Southbay | standard | R41 | 2026-09-04T06:00:00Z | 2026-09-05T06:00:00Z | on_time | 0 | 0 |
| O0198 | Southbay | standard | R42 | 2026-09-05T07:00:00Z | 2026-09-06T07:00:00Z | overdue_open | 0 | 12540 |
| O0199 | Southbay | standard | R41 | 2026-09-06T08:00:00Z | 2026-09-07T08:00:00Z | on_time | 0 | 0 |
| O0200 | Southbay | standard | R42 | 2026-09-07T09:00:00Z | 2026-09-08T09:00:00Z | delivered_late | 110 | 0 |
| O0201 | Southbay | standard | R41 | 2026-09-08T10:00:00Z | 2026-09-09T10:00:00Z | on_time | 0 | 0 |
| O0202 | Southbay | standard | R42 | 2026-09-09T11:00:00Z | 2026-09-10T11:00:00Z | on_time | 0 | 0 |
| O0203 | Southbay | standard | R41 | 2026-09-10T12:00:00Z | 2026-09-11T12:00:00Z | on_time | 0 | 0 |
| O0204 | Southbay | standard | R42 | 2026-09-11T13:00:00Z | 2026-09-12T13:00:00Z | on_time | 0 | 0 |
| O0205 | Southbay | standard | R41 | 2026-09-12T06:00:00Z | 2026-09-13T06:00:00Z | on_time | 0 | 0 |
| O0206 | Southbay | standard | R42 | 2026-09-13T07:00:00Z | 2026-09-14T07:00:00Z | delivered_late | 110 | 0 |
| O0207 | Southbay | standard | R41 | 2026-09-01T08:00:00Z | 2026-09-02T08:00:00Z | on_time | 0 | 0 |
| O0208 | Southbay | standard | R42 | 2026-09-02T09:00:00Z | 2026-09-03T09:00:00Z | on_time | 0 | 0 |
| O0209 | Southbay | standard | R41 | 2026-09-03T10:00:00Z | 2026-09-04T10:00:00Z | on_time | 0 | 0 |
| O0210 | Southbay | standard | R42 | 2026-09-14T21:00:00Z | 2026-09-15T21:00:00Z | cancelled | 0 | 0 |
| O0211 | Southbay | express | R41 | 2026-09-01T06:00:00Z | 2026-09-01T14:00:00Z | cancelled | 0 | 0 |
| O0212 | Southbay | express | R42 | 2026-09-02T07:00:00Z | 2026-09-02T15:00:00Z | delivered_late | 110 | 0 |
| O0213 | Southbay | express | R41 | 2026-09-03T08:00:00Z | 2026-09-03T16:00:00Z | on_time | 0 | 0 |
| O0214 | Southbay | express | R42 | 2026-09-04T09:00:00Z | 2026-09-04T17:00:00Z | on_time | 0 | 0 |
| O0215 | Southbay | express | R41 | 2026-09-05T10:00:00Z | 2026-09-05T18:00:00Z | on_time | 0 | 0 |
| O0216 | Southbay | express | R42 | 2026-09-14T21:00:00Z | 2026-09-15T05:00:00Z | not_mature | 0 | 0 |
learner/materials/rules.json Read the full file
Download file{
"cutoff": "2026-09-15T00:00:00Z",
"late_target": 0.1,
"min_sample": 15,
"review_gap_pp": 5,
"priority_gap_pp": 15,
"standard_weight": 0.5,
"express_weight": 0.5
}learner/materials/data-dictionary.md Read the full file
Download fileData dictionary and decision rules
Assignment brief
You join the cold-chain fulfilment operations team. The operations lead needs to decide which orders and hubs to review first, where export controls failed, and what the next operations workbench must deliver. The four hubs are Harbour, Eastgate, Westhill and Southbay. Standard service promises delivery within 24 hours and express within 8 hours. Use the actual due_at value in orders.csv for each order.
The review cutoff is 2026-09-15T00:00:00Z, defined in rules.json. Convert every business timestamp to UTC. Records can contain events after the cutoff so that you can test whether a historical review accidentally uses future information.
Orders
One row in orders.csv is one order. order_id is a unique text identifier; keep its leading zeros. hub is the operating hub, service is standard or express, and route identifies the route. created_at and due_at are timezone-aware ISO 8601 timestamps. Counting event rows is not a valid way to count orders.
Event feeds and canonical schema
Feed A maps event_id to event_id, order_ref to order_id, hub to hub, service to service, event to kind, and event_time to happened_at.
Feed B maps id to event_id, shipment.number to order_id, shipment.station to hub, shipment.product to service, and at_ms to happened_at. at_ms is an integer Unix timestamp in milliseconds. Map OPEN, COLLECT, DROP and VOID to created, picked_up, delivered and cancelled respectively.
The canonical event contains event_id, order_id, hub, service, kind and happened_at. happened_at is UTC ISO 8601 with a Z suffix. Validate required fields, action names and dimensions. Reject timezone-free timestamps and non-integer epochs. Do not change the raw inputs.
Identical canonical content under the same event_id is an exact replay: retain one event and list every removed replay. Different content under one immutable event_id is a conflict: quarantine the entire group. Never accept the first arrival and silently overwrite it later. Keep the source filename, 1-based line number and reason for every rejected record or replay. Reconcile raw records = canonical events + quarantined records + removed replays.
Historical fulfilment cohort
Group events by order_id and retain only events with happened_at <= cutoff. A visible cancellation takes precedence and is excluded from the mature denominator. A non-cancelled order with due_at > cutoff is not_mature. Otherwise, no visible delivery means overdue_open; the first visible delivery after due_at means delivered_late; delivery at or before due_at means on_time. Exactly at the due timestamp is mature, and delivery exactly at that timestamp is on time.
Eligible mature orders = on_time + delivered_late + overdue_open. Late orders = delivered_late + overdue_open. Never classify cancellation or an order not yet due as successful delivery. Keep delivered lateness minutes (delivery minus due_at) separate from open overdue minutes (cutoff minus due_at). The inputs do not contain actual refunds, damaged-goods values or costs, so do not calculate those amounts.
Service review
The fixed late-rate target is 10%, and the minimum mature sample is 15 per hub/service cell. gap_pp = (late_rate - 0.10) * 100, measured in percentage points. Apply sample size first: below 15 is More data needed. A gap above 15 points is Priority review; above 5 and at most 15 is Review needed; at most 5 is Within threshold. These are operational triage rules, not a statistical finding of unfair treatment.
For a comparable service mix, give standard and express equal 50% weights. Calculate a hub's standardized late rate only when both service cells meet the minimum sample. Otherwise retain a missing value and state which cell is insufficient. Do not impute an overall mean or rank a small sample as the best hub. Separate observations, possible explanations and causal claims.
Access logs and policy
One access-log.csv row is one request. request_id is unique; at is UTC. user, session and role are gateway request context. method and path identify the resource; status is the response code; rows and bytes are gateway response counts. These counts do not prove unique customers, file retention or subsequent use.
access-policy.json defines the baseline. An operator can read only the assigned hub and cannot export. A supervisor or approved service role can export. A session lasts 30 minutes after a successful login: exactly 30 minutes is valid, and later requests must be rejected. Failed logins do not renew sessions. A 401 is a denied attempt, not confirmed disclosure. svc-archive is approved, so a frequent large export is not automatically suspicious. The IP ranges are documentation addresses; the logs cannot establish geography, a natural person's identity or the actual access path. Endpoint and VPN evidence would be needed.
Steps
- Group the order-level review by hub and service. Calculate mature and late counts from orders, using a pivot table or Python; do not reconstruct counts from rounded percentages.
- Calculate late/eligible and gap_pp against 10%. Apply the minimum sample first, then the >15 and >5 point boundaries. Test values exactly at 5 and 15.
- Write service-review.csv with count, rate, target, gap and recommendation for every cell.
- Use a 50/50 standard/express mix for each hub. If either cell has fewer than 15 mature orders, leave the standardized hub value missing and mark More data needed.
- Compare raw and standardized rates side by side. Explain Eastgate's larger express share. Standardization alone does not establish cause.
- Write review-memo.md naming the insufficient Southbay cell and the number of additional mature orders needed, plus a review action and conclusions the data cannot support.
Complete outputs
Service performance review memorandum
Priority
Review Harbour express (18/18) and Harbour standard (14/37) first, along with Eastgate express (26/37). Southbay express has only four mature orders and one late order. Collect more data before treating its 25% rate as stable.
| Hub | Raw late rate | Standardized late rate |
|---|---|---|
| Eastgate | 56.36% | 49.02% |
| Southbay | 21.88% | More data needed |
| Harbour | 58.18% | 68.92% |
| Westhill | 36.36% | 38.64% |
Method
For each hub/service cell, late_rate = late/eligible and gap_pp = (late_rate - 0.10) * 100. Apply the sample check before thresholds. A gap exactly at 15 points is Review needed, not Priority review. A gap exactly at 5 points is Within threshold.
Standardized rate = 0.5 * standard rate + 0.5 * express rate. Eastgate express accounts for 37/55 mature orders. Its raw 56.36% rate becomes 49.02% at equal weights. Harbour express accounts for only 18/55, so its standardized rate rises from 58.18% to 68.92%. Overall differences partly reflect service mix and should not be attributed entirely to hub performance.
Next evidence
Southbay express needs at least 11 more mature orders to reach the operational threshold of 15; the added observations can change its rate. Hold the observation period and cohort rules consistent, retaining cancelled and not-mature records. Fifteen is a review threshold, not proof of statistical significance.
Weather, route distance, customer appointments and shift schedules are absent. This comparison does not establish individual responsibility, unfair treatment or an improvement forecast. Inspect Harbour express handovers and departures, then compare like routes, services and time periods before designing a process experiment.
Download fileReference answers
instructor/answers/service-review.csv Read the full file
Download file| hub | service | eligible | late | late_rate | target | gap_pp | review |
|---|---|---|---|---|---|---|---|
| Eastgate | express | 37 | 26 | 0.702703 | 0.1 | 60.27 | Priority review |
| Eastgate | standard | 18 | 5 | 0.277778 | 0.1 | 17.778 | Priority review |
| Harbour | express | 18 | 18 | 1.0 | 0.1 | 90.0 | Priority review |
| Harbour | standard | 37 | 14 | 0.378378 | 0.1 | 27.838 | Priority review |
| Southbay | express | 4 | 1 | 0.25 | 0.1 | 15.0 | More data needed |
| Southbay | standard | 28 | 6 | 0.214286 | 0.1 | 11.429 | Review needed |
| Westhill | express | 22 | 11 | 0.5 | 0.1 | 40.0 | Priority review |
| Westhill | standard | 33 | 9 | 0.272727 | 0.1 | 17.273 | Priority review |
instructor/answers/standardized-comparison.csv Read the full file
Download file| hub | standardized_late_rate | status |
|---|---|---|
| Eastgate | 0.49024 | Comparable |
| Harbour | 0.689189 | Comparable |
| Southbay | More data needed | |
| Westhill | 0.386363 | Comparable |
Complete reference implementation Read the full file
Download file"""Reference implementation for the Ape Intern cold-chain operations lab."""
import csv,json
from collections import defaultdict,Counter
from datetime import datetime,timezone
from pathlib import Path
from urllib.parse import urlparse,parse_qs
UTC=timezone.utc
KINDS={'OPEN':'created','COLLECT':'picked_up','DROP':'delivered','VOID':'cancelled'}
HUBS={'Harbour','Eastgate','Westhill','Southbay'}
def parse_time(value):
t=datetime.fromisoformat(value.replace('Z','+00:00'))
if t.tzinfo is None:raise ValueError('timezone_required')
return t.astimezone(UTC)
def iso(t):return t.isoformat(timespec='seconds').replace('+00:00','Z')
def readcsv(p):
with Path(p).open(encoding='utf-8-sig',newline='') as f:return list(csv.DictReader(f))
def writecsv(p,rows,fields=None):
rows=list(rows)
with Path(p).open('w',encoding='utf-8-sig',newline='') as f:
w=csv.DictWriter(f,fieldnames=fields or list(rows[0]));w.writeheader();w.writerows(rows)
def dump(p,value):Path(p).write_text(json.dumps(value,ensure_ascii=False,indent=2)+'\n')
def _normalize(record,source):
if source=='A':
e=dict(event_id=record['event_id'],order_id=record['order_ref'],hub=record['hub'],service=record['service'],kind=record['event'],happened_at=iso(parse_time(record['event_time'])))
else:
ms=record['at_ms']
if type(ms) is not int:raise ValueError('epoch_must_be_integer')
e=dict(event_id=record['id'],order_id=record['shipment']['number'],hub=record['shipment']['station'],service=record['shipment']['product'],kind=KINDS[record['action']],happened_at=iso(datetime.fromtimestamp(ms/1000,UTC)))
if e['kind'] not in KINDS.values():raise ValueError('unsupported_event')
if e['hub'] not in HUBS or e['service'] not in {'standard','express'}:raise ValueError('unknown_dimension')
if not e['event_id'] or not e['order_id']:raise ValueError('empty_key')
return e
def normalize(record,source):
try:return _normalize(record,source)
except (KeyError,TypeError,OverflowError) as error:raise ValueError(str(error).strip("'")) from error
def ingest(data):
grouped=defaultdict(list);rejected=[];duplicates=[]
for source,name in [('A','dispatch-a.jsonl'),('B','courier-b.jsonl')]:
for line,text in enumerate((data/name).read_text().splitlines(),1):
loc={'source':name,'line':line}
try:
event=normalize(json.loads(text),source);grouped[event['event_id']].append((event,loc))
except (ValueError,KeyError,TypeError,OverflowError) as ex:
rejected.append(dict(loc,reason=str(ex).strip("'")))
accepted=[]
for eid,items in grouped.items():
distinct={json.dumps(e,sort_keys=True,ensure_ascii=False) for e,loc in items}
if len(distinct)>1:
rejected.extend(dict(loc,reason='immutable_id_conflict') for e,loc in items);continue
accepted.append(items[0][0])
duplicates.extend(dict(loc,event_id=eid,reason='exact_replay') for e,loc in items[1:])
accepted.sort(key=lambda e:(e['happened_at'],e['event_id']))
return accepted,rejected,duplicates
def classify_order(order,events,cutoff):
# Only facts available at cutoff can influence a retrospective result.
visible=[e for e in events if parse_time(e['happened_at'])<=cutoff]
visible.sort(key=lambda e:parse_time(e['happened_at']))
delivered=[parse_time(e['happened_at']) for e in visible if e['kind']=='delivered']
cancelled=any(e['kind']=='cancelled' for e in visible)
due=parse_time(order['due_at'])
if cancelled:state='cancelled'
elif due>cutoff:state='not_mature'
elif not delivered:state='overdue_open'
elif min(delivered)>due:state='delivered_late'
else:state='on_time'
delay=round((min(delivered)-due).total_seconds()/60) if state=='delivered_late' else 0
overdue=round((cutoff-due).total_seconds()/60) if state=='overdue_open' else 0
return dict(order,cohort=state,late_minutes=delay,overdue_minutes=overdue)
def aggregate(rows,keys):
groups=defaultdict(list)
for row in rows:groups[tuple(row[k] for k in keys)].append(row)
result=[]
for dims,records in sorted(groups.items()):
counts=Counter(r['cohort'] for r in records)
eligible=sum(counts[x] for x in ['on_time','delivered_late','overdue_open'])
late=counts['delivered_late']+counts['overdue_open']
result.append(dict(zip(keys,dims),total=len(records),eligible=eligible,late=late,late_rate=round(late/eligible,6) if eligible else None,on_time=counts['on_time'],delivered_late=counts['delivered_late'],overdue_open=counts['overdue_open'],cancelled=counts['cancelled'],not_mature=counts['not_mature'],delivered_late_minutes=sum(r['late_minutes'] for r in records),open_overdue_minutes=sum(r['overdue_minutes'] for r in records)))
return result
def service_band(rate,n,rules):
if n<rules['min_sample']:return 'More data needed'
gap=(rate-rules['late_target'])*100
if gap>rules['priority_gap_pp']:return 'Priority review'
if gap>rules['review_gap_pp']:return 'Review needed'
return 'Within threshold'
def fairness(hub_tiers,rules):
rows=[]
for x in hub_tiers:
rate=x['late_rate'];rows.append(dict(hub=x['hub'],service=x['service'],eligible=x['eligible'],late=x['late'],late_rate=rate,target=rules['late_target'],gap_pp=round((rate-rules['late_target'])*100,3) if rate is not None else None,review=service_band(rate,x['eligible'],rules)))
standardized=[]
for hub in sorted(HUBS):
parts=[r for r in rows if r['hub']==hub]
enough=len(parts)==2 and all(r['eligible']>=rules['min_sample'] for r in parts)
value=sum(r['late_rate']*rules[r['service']+'_weight'] for r in parts) if enough else None
standardized.append(dict(hub=hub,standardized_late_rate=round(value,6) if value is not None else None,status='Comparable' if enough else 'More data needed'))
return rows,standardized
def investigate(logs,policy):
logins={};findings=[]
for row in sorted(logs,key=lambda r:(r['at'],r['request_id'])):
t=parse_time(row['at']);status=int(row['status']);route=urlparse(row['path']);query=parse_qs(route.query)
if route.path=='/login' and status==200:logins[(row['user'],row['session'])]=t;continue
if status!=200:continue
types=[]
if route.path=='/export' and row['role'] not in policy['export_roles']:types.append('unauthorised_export')
hub=query.get('hub',[''])[0]
if row['role']=='operator' and hub and hub!=policy['operator_hub'].get(row['user']):types.append('hub_scope_violation')
login=logins.get((row['user'],row['session']))
if login is None or (t-login).total_seconds()>policy['session_ttl_minutes']*60:types.append('expired_or_missing_session')
if types:findings.append(dict(request_id=row['request_id'],at=row['at'],user=row['user'],session=row['session'],finding=';'.join(types),status=status,rows=int(row['rows']),bytes=int(row['bytes'])))
return findings
def solve(data,out):
data=Path(data);out=Path(out);out.mkdir(parents=True,exist_ok=True)
events,rejects,dups=ingest(data)
(out/'canonical-events.jsonl').write_text(''.join(json.dumps(e,ensure_ascii=False)+'\n' for e in events))
writecsv(out/'rejected.csv',rejects);writecsv(out/'duplicates.csv',dups)
rules=json.loads((data/'rules.json').read_text());cutoff=parse_time(rules['cutoff'])
by_order=defaultdict(list)
for e in events:by_order[e['order_id']].append(e)
orders=readcsv(data/'orders.csv')
records=[classify_order(o,by_order[o['order_id']],cutoff) for o in orders]
writecsv(out/'order-review.csv',records)
hubs=aggregate(records,['hub']);tiers=aggregate(records,['hub','service']);routes=aggregate(records,['route'])
writecsv(out/'hub-metrics.csv',hubs);writecsv(out/'route-metrics.csv',routes)
bands,std=fairness(tiers,rules)
writecsv(out/'service-review.csv',bands);writecsv(out/'standardized-comparison.csv',std)
findings=investigate(readcsv(data/'access-log.csv'),json.loads((data/'access-policy.json').read_text()))
writecsv(out/'security-findings.csv',findings)
summary=dict(orders=len(orders),accepted_events=len(events),rejected=len(rejects),duplicates=len(dups),cohorts=dict(Counter(r['cohort'] for r in records)),hubs=hubs,service_review=bands,standardized=std,security=dict(flagged_requests=len(findings),potential_export_rows=sum(f['rows'] for f in findings if 'unauthorised_export' in f['finding']),potential_export_bytes=sum(f['bytes'] for f in findings if 'unauthorised_export' in f['finding']),findings=findings))
dump(out/'results.json',summary)
return summary
if __name__=='__main__':
import sys
print(json.dumps(solve(sys.argv[1],sys.argv[2]),ensure_ascii=False,indent=2))
Each task is worth 20 points. Reach at least 14 and correct all critical rule errors before the next review. Editing raw inputs, silently dropping records, including not-yet-due orders in the denominator, counting 401 attempts as disclosure, ranking an insufficient sample or treating a UI filter as authorization requires correction and re-testing.
- Stratified denominator and target: 6
- Threshold boundaries and sample precedence: 5
- Standardization and missing values: 5
- Explanation and follow-up sampling: 4