# Productivity per cargo type — Steinweg Sohar **Retrieved 2026-10-13.** Nothing new was calculated or rebuilt here. This document only collects what already existed, with the figures pulled out of the files so you can read them without opening anything. Two separate things live side by side in this document: - **The norm** — the standard rates from the manager's `Productivity_Report_Rev.04.xlsm` workbook, hidden sheet `Prod_data`. 63 rows. This is what the planning app uses. - **The measurement** — what 1,442 real productivity reports (2024–2026) actually show. 16,591 crane-shift lines in `shifts.db`. --- ## 0. Read the units first Every rate in this document is **per net crane-hour, per single crane (one gang)**. It is *not* per vessel and *not* per gang-hour across multiple cranes. Two cranes on a hold means you plan with two times the rate. The unit of the number itself depends on the commodity group: | commodity group | unit of the rate | |---|---| | Drybulk | **MT per crane-hour** (tonnes) | | Breakbulk | **pieces/bundles per crane-hour** | | ProjectCargo | **pieces per crane-hour** | | RORO | **units (vehicles) per crane-hour** — RORO has no crane; the divisor is driver-hours | The norm sheet carries three rate columns for every cargo. They differ only in what counts as lost time: | column | what it divides by | meaning | |---|---|---| | **Tot CSO Prod** | shift time minus only the CSO-attributable delays | "what the terminal is accountable for". **This is the column the app actually calculates with** — `engine.js` `rateFor()` returns `totcso` and nothing else. | | Net Prod | net worked hours only (column R of the report) | best case, pure working speed with all delays removed. The highest of the three. | | Gross Prod | the whole shift, delays included | planning rate for wall-clock / berth occupancy. The lowest of the three. | Ordering is always Gross ≤ Tot CSO ≤ Net. If you plan with Net you will be late; if you plan with Gross you build in the delays you already have. One more number in the sheet: cell `L1` holds **Acceptance = 0.75**. In the Excel this discounted the norm to 75% for planning. **The app stores this value but never applies it** — worth deciding whether you want it back. --- ## 1. What exists and where | artefact | what it answers | live? | where | |---|---|---|---| | **Reports dashboard** | The whole 1,442-report corpus: netto %, delay pareto, per cargo, per shift, per month, per vessel | **Yes, open it now** | https://reports.leonsteer.com | | `dashboard.html` + `data.json` | Same dashboard, offline copy | Yes, double-click | `~/Projects/reportstats-tools/dashboard.html` | | `corporate_report.html` | The written management report on the corpus | Yes, double-click | `~/Projects/reportstats-tools/corporate_report.html` | | `Steinweg-Productivity-Report.pdf` | The same report as PDF, for sending on | Yes | `~/Projects/reportstats-tools/Steinweg-Productivity-Report.pdf` | | `shifts.db` | The raw corpus — 16,591 crane-shift lines, queryable | Yes, on the server | `root@91.98.64.82:/root/reportstats/shifts.db` | | `benchmarks.json` | The 63 norms, as read out of a real Rev.04 workbook on the server | Yes, data file | `root@91.98.64.82:/root/reportstats/benchmarks.json` | | **Productivity app** | Plan a vessel: cargo per hold → rate → hours and finish times per gang | Needs starting (`assemble.sh`, then `start-productivity.bat`) | `~/Projects/steinweg-productivity-app/` | | `Prod_data_cells.json` | The raw cell dump of the hidden `Prod_data` sheet — the source of truth for the norms | Data file | `~/Projects/steinweg-productivity-app/extracted/` | | `data.js` (`PROD_DATA.rates`) | The norm table ported 1:1 into the app, plus berths, cranes, grabs, delay categories | Data file | `~/Projects/steinweg-productivity-app/server/public/data.js` | | `rates.js` | A third copy of the norms, used by the Berthing Planner | Data file | `~/Projects/berthing-planner/www/rates.js` | | `compare_rates.js` | Script that diffs the norms against the measured rates | Needs `node` (**not installed on this Mac**) | `~/Projects/reportstats-tools/compare_rates.js` | | `export_dashboard_data.py` | Rebuilds `data.json` from `shifts.db` | Needs running | `~/Projects/reportstats-tools/` | | `extract_benchmarks.py` | Re-reads the norms from a Rev.04 workbook | Needs running | `~/Projects/reportstats-tools/` | | `templates-spec.md` | The verified column layout of all four report templates | Yes, read it | `~/Projects/reportstats-tools/templates-spec.md` | | EGA vessel files | Four EGA vessels, per shift, achieved vs standard | Data files | `~/Projects/ega-productivity/data/*.json` | | `supervisors.html` | Per-supervisor breakdown. **Contains real names**, private path. Exists; contents not reproduced here. | On a private path | `~/Projects/reportstats-tools/supervisors.html` | The corpus splits over four report templates: `rev04` 8,980 lines / 547 reports · `breakbulk` 3,886 / 217 · `bulk` 2,376 / 206 · `roro` 1,349 / 304. --- ## 2. The norm table per cargo type All 63 rows of `Prod_data`. **The bold column is the one the app calculates with.** Unit is per net crane-hour throughout — MT for Drybulk, pieces for Breakbulk/ProjectCargo, units for RORO. ### 2a. Main cargoes (the ones Sohar handles most) | cargo | commodity | imex | unit | **Tot CSO Prod** (used by app) | Net Prod | Gross Prod | |---|---|---|---|---|---|---| | ALUMINIUM | Breakbulk | Export | pcs/net crane-hr | 72.6 | 76.3 | 56.9 | | STEEL_COILS | Breakbulk | Import | pcs/net crane-hr | 12.9 | 13.1 | 11.6 | | STEEL_BILLETS | Breakbulk | Import | pcs/net crane-hr | 81.2 | 83.4 | 74.4 | | BIGBAGS | Breakbulk | Import | pcs/net crane-hr | 56.2 | 58.3 | 50.2 | | STEEL_PIPES | Breakbulk | Import | pcs/net crane-hr | 25.2 | 25.3 | 23.4 | | STEEL_PIPES_BNDLS | Breakbulk | Import | pcs/net crane-hr | 37.5 | 39.8 | 33.0 | | STEEL_PIPES_LOOSE | Breakbulk | Import | pcs/net crane-hr | 49.3 | 49.3 | 47.3 | | OIL_COUNTR_TUB_GOODS | Breakbulk | Import | pcs/net crane-hr | 45.8 | 46.5 | 41.7 | | LIMESTONE | Drybulk | Export | MT/net crane-hr | 804.0 | 829.4 | 677.9 | | CALCINED_PETCOKE | Drybulk | Export | MT/net crane-hr | 498.2 | 718.5 | 454.0 | | GREEN_PETCOKE_BB | Drybulk | Export | MT/net crane-hr | 312.1 | 336.5 | 265.3 | | GREEN_PETCOKE_DB | Drybulk | Import | MT/net crane-hr | 452.2 | 493.0 | 334.3 | | AGGREGATES | Drybulk | Export | MT/net crane-hr | 903.2 | 928.6 | 768.8 | ### 2b. Drybulk — remaining | cargo | commodity | imex | unit | **Tot CSO Prod** (used by app) | Net Prod | Gross Prod | |---|---|---|---|---|---|---| | Wadi_Gravel | Drybulk | Export | MT/net crane-hr | 1062.2 | 1140.2 | 865.8 | | DOLOMITE | Drybulk | Export | MT/net crane-hr | 680.2 | 703.6 | 577.3 | | FELDSPAR | Drybulk | Import | MT/net crane-hr | 607.0 | 607.0 | 485.0 | | COPPER_SLAG | Drybulk | Import | MT/net crane-hr | 582.6 | 586.0 | 444.4 | | COPPER_CONCENTRATE | Drybulk | Export | MT/net crane-hr | 534.2 | 589.2 | 247.9 | | MILL_SCALE | Drybulk | Import | MT/net crane-hr | 525.2 | 566.9 | 448.2 | | BARITE | Drybulk | Import | MT/net crane-hr | 499.3 | 508.7 | 373.3 | | HOT BRIQUETTED IRON ORE | Drybulk | Import | MT/net crane-hr | 499.1 | 517.1 | 413.1 | | ILMENITE_SANDS | Drybulk | Import | MT/net crane-hr | 495.3 | 495.3 | 295.3 | | BAUXITE | Drybulk | Import | MT/net crane-hr | 469.4 | 469.4 | 288.5 | | MANGANESE_ORE | Drybulk | Import | MT/net crane-hr | 455.9 | 455.9 | 278.4 | | CLAY_BALL | Drybulk | Import | MT/net crane-hr | 451.6 | 451.6 | 290.6 | | SALT | Drybulk | Import | MT/net crane-hr | 441.5 | 451.0 | 313.9 | | BENTONITE | Drybulk | Import | MT/net crane-hr | 409.4 | 418.1 | 333.6 | | IRON_ORE | Drybulk | Import | MT/net crane-hr | 375.3 | 419.4 | 286.4 | | WHEAT | Drybulk | Import | MT/net crane-hr | 337.5 | 383.2 | 286.1 | | MET_COKE | Drybulk | Import | MT/net crane-hr | 312.9 | 321.9 | 230.9 | | Clinker | Drybulk | Import | MT/net crane-hr | 285.3 | 285.3 | 233.2 | | SILICA | Drybulk | Import | MT/net crane-hr | 191.6 | 191.6 | 146.7 | | CEMENT | Drybulk | Import | MT/net crane-hr | 123.8 | 133.0 | 123.3 | ### 2c. Breakbulk — remaining | cargo | commodity | imex | unit | **Tot CSO Prod** (used by app) | Net Prod | Gross Prod | |---|---|---|---|---|---|---| | TIMBER | Breakbulk | Import | pcs/net crane-hr | 39.7 | 40.7 | 35.6 | | STEEL_CASING | Breakbulk | Import | pcs/net crane-hr | 38.7 | 40.6 | 35.0 | | FOREST_PRODUCTS | Breakbulk | Import | pcs/net crane-hr | 34.8 | 35.6 | 31.0 | | PLYWOOD | Breakbulk | Import | pcs/net crane-hr | 27.5 | 28.0 | 24.3 | | WIRE_ROD | Breakbulk | Import | pcs/net crane-hr | 24.4 | 24.6 | 21.9 | | WIRE_ROD_10.0MM | Breakbulk | Import | pcs/net crane-hr | 24.4 | 24.6 | 21.9 | | WIRE_ROD_5.5MM | Breakbulk | Import | pcs/net crane-hr | 24.4 | 24.6 | 21.9 | | WIRE_ROD_6.0MM | Breakbulk | Import | pcs/net crane-hr | 24.4 | 24.6 | 21.9 | | WIRE_ROD_6.5MM | Breakbulk | Import | pcs/net crane-hr | 24.4 | 24.6 | 21.9 | | WIRE_ROD_8.0MM | Breakbulk | Import | pcs/net crane-hr | 24.4 | 24.6 | 21.9 | | STEEL_SHEETS | Breakbulk | Import | pcs/net crane-hr | 20.0 | 20.1 | 17.7 | | STEEL_PLATES | Breakbulk | Import | pcs/net crane-hr | 16.4 | 16.8 | 14.5 | | STEEL_STRUCTURES | Breakbulk | Import | pcs/net crane-hr | 15.2 | 15.4 | 13.5 | | ISO CONTAINER | Breakbulk | Import | pcs/net crane-hr | 13.5 | 13.5 | 13.5 | | PROJECT_BB | Breakbulk | Import | pcs/net crane-hr | 5.0 | 5.3 | 3.9 | | PROJECT_PR | Breakbulk | Import | pcs/net crane-hr | 3.7 | 3.9 | 3.1 | | CONSTRUCTION_VEHICLES | Breakbulk | Import | pcs/net crane-hr | 2.7 | 2.9 | 1.7 | | TRUCKS_AND_TRAILERS | Breakbulk | Import | pcs/net crane-hr | 2.7 | 2.9 | 1.7 | ### 2d. RORO — remaining | cargo | commodity | imex | unit | **Tot CSO Prod** (used by app) | Net Prod | Gross Prod | |---|---|---|---|---|---|---| | PASSENGER_CARS | RORO | Import | units/net crane-hr | 86.8 | 87.4 | 82.5 | | PASSENGER_CARS | RORO | Export | units/net crane-hr | 56.7 | 56.9 | 53.8 | | HIGH_and_HEAVY | RORO | Import | units/net crane-hr | 26.0 | 29.2 | 24.5 | | STATIC_CARGO | RORO | Import | units/net crane-hr | 12.1 | 12.1 | 12.0 | | HIGH_and_HEAVY | RORO | Export | units/net crane-hr | 11.0 | 11.3 | 10.2 | | MAFI | RORO | Import | units/net crane-hr | 5.2 | 5.2 | 5.0 | | STATIC_CARGO | RORO | Export | units/net crane-hr | 2.6 | 2.6 | 2.6 | | MAFI | RORO | Export | units/net crane-hr | 2.2 | 2.2 | 2.2 | ### 2e. ProjectCargo — remaining | cargo | commodity | imex | unit | **Tot CSO Prod** (used by app) | Net Prod | Gross Prod | |---|---|---|---|---|---|---| | PROJECT_PR | ProjectCargo | Import | pcs/net crane-hr | 3.7 | 3.9 | 3.1 | | PROJECT_BB | ProjectCargo | Export | pcs/net crane-hr | 3.7 | 3.9 | 3.1 | | PROJECT_PR | ProjectCargo | Export | pcs/net crane-hr | 3.7 | 3.9 | 3.1 | | CONSTRUCTION_VEHICLES | ProjectCargo | Export | pcs/net crane-hr | 2.7 | 2.9 | 1.7 | --- ## 3. Measured rates per cargo type, next to the norm From `shifts.db`: all 16,591 crane-shift lines grouped by the cargo label in the report. 41 cargo types could be matched to a norm. **Read the `vessels` and `crane-shifts` columns before you believe any line** — a rate off three vessels is an anecdote, not a standard. `measured Net` = total production ÷ total net worked hours. Compare it with `norm Net Prod`. `measured Gross` = total production ÷ total shift hours. Compare it with `norm Gross Prod`. Where the norm shows a **range** (e.g. `56.9–87.4`), the workbook has a separate import and export norm for that cargo but **the reports do not record import/export**, so the measurement cannot be split. Those lines give a band, not a verdict. Evidence tiers: **strong** = 20+ vessels and 500+ net crane-hours · **usable** = 10+ vessels or 200+ net crane-hours · **thin** = below that, treat as indicative only. | cargo | unit | crane-shifts | vessels | net crane-hr | measured Net | norm Net Prod | gap | measured Gross | norm Gross Prod | gap | evidence | |---|---|---|---|---|---|---|---|---|---|---|---| | STEEL_BILLETS | pcs | 1178 | 51 | 5,554 | 76.3 | 83.4 | 91% | 68.7 | 74.4 | 92% | strong | | PROJECT_BB | pcs | 1958 | 208 | 4,675 | 5.2 | 3.9–5.3 | 98–133% | 3.9 | 3.1–3.9 | 100–126% | strong | | BIGBAGS | pcs | 973 | 37 | 4,615 | 59.3 | 58.3 | 102% | 52.7 | 50.2 | 105% | strong | | OIL_COUNTR_TUB_GOODS | pcs | 989 | 92 | 4,165 | 43.3 | 46.5 | 93% | 39.1 | 41.7 | 94% | strong | | STEEL_COILS | pcs | 1041 | 130 | 3,923 | 12.3 | 13.1 | 94% | 10.9 | 11.6 | 94% | strong | | AGGREGATES | MT | 624 | 37 | 2,736 | 998.0 | 928.6 | 107% | 801.4 | 768.8 | 104% | strong | | PASSENGER_CARS | units | 1068 | 451 | 2,536 | 82.3 | 56.9–87.4 | 94–145% | 78.1 | 53.8–82.5 | 95–145% | strong | | STEEL_STRUCTURES | pcs | 596 | 55 | 2,112 | 12.2 | 15.4 | 79% | 10.7 | 13.5 | 79% | strong | | GREEN_PETCOKE_DB | MT | 395 | 23 | 1,353 | 524.4 | 493.0 | 106% | 309.9 | 334.3 | 93% | strong | | ALUMINIUM | pcs | 293 | 4 | 1,333 | 39.1 | 76.3 | 51% | 32.1 | 56.9 | 56% | usable | | FOREST_PRODUCTS | pcs | 275 | 22 | 1,119 | 31.9 | 35.6 | 90% | 27.5 | 31.0 | 89% | strong | | CALCINED_PETCOKE | MT | 224 | 30 | 784 | 692.3 | 718.5 | 96% | 430.3 | 454.0 | 95% | strong | | LIMESTONE | MT | 145 | 9 | 722 | 782.7 | 829.4 | 94% | 636.5 | 677.9 | 94% | usable | | GREEN_PETCOKE_BB | MT | 123 | 6 | 618 | 356.9 | 336.5 | 106% | 275.2 | 265.3 | 104% | usable | | HIGH_and_HEAVY | units | 608 | 316 | 612 | 22.1 | 11.3–29.2 | 76–196% | 19.2 | 10.2–24.5 | 78–188% | strong | | STEEL_PIPES | pcs | 124 | 4 | 609 | 14.2 | 25.3 | 56% | 12.9 | 23.4 | 55% | usable | | STEEL_PLATES | pcs | 181 | 47 | 592 | 13.4 | 16.8 | 80% | 11.9 | 14.5 | 82% | strong | | WIRE_ROD | pcs | 127 | 17 | 335 | 39.1 | 24.6 | 159% | 34.4 | 21.9 | 157% | usable | | CONSTRUCTION_VEHICLES | units | 215 | 91 | 293 | 5.0 | 2.9 | 172% | 3.8 | 1.7 | 224% | usable | | SALT | MT | 61 | 4 | 232 | 482.9 | 451.0 | 107% | 308.2 | 313.9 | 98% | usable | | STEEL_SHEETS | pcs | 63 | 25 | 172 | 17.9 | 20.1 | 89% | 16.0 | 17.7 | 90% | usable | | TIMBER | pcs | 32 | 2 | 162 | 43.4 | 40.7 | 107% | 39.1 | 35.6 | 110% | thin | | COPPER_CONCENTRATE | MT | 57 | 10 | 138 | 609.2 | 589.2 | 103% | 261.9 | 247.9 | 106% | usable | | HOT BRIQUETTED IRON ORE | MT | 32 | 4 | 134 | 490.3 | 517.1 | 95% | 353.0 | 413.1 | 85% | thin | | PROJECT_PR | pcs | 49 | 8 | 125 | 5.4 | 3.9 | 138% | 3.5 | 3.1 | 113% | thin | | PLYWOOD | pcs | 31 | 3 | 107 | 23.4 | 28.0 | 84% | 20.6 | 24.3 | 85% | thin | | BENTONITE | MT | 26 | 1 | 93 | 539.5 | 418.1 | 129% | 334.3 | 333.6 | 100% | thin | | ISO CONTAINER | pcs | 58 | 19 | 88 | 5.2 | 13.5 | 39% | 3.8 | 13.5 | 28% | usable | | BARITE | MT | 20 | 3 | 88 | 532.5 | 508.7 | 105% | 370.0 | 373.3 | 99% | thin | | TRUCKS_AND_TRAILERS | units | 110 | 69 | 88 | 29.9 | 2.9 | 1031% | 25.7 | 1.7 | 1512% | usable | | MET_COKE | MT | 23 | 3 | 78 | 345.5 | 321.9 | 107% | 271.5 | 230.9 | 118% | thin | | STATIC_CARGO | units | 117 | 100 | 78 | 14.0 | 2.6–12.1 | 116–538% | 13.9 | 2.6–12.0 | 116–535% | usable | | MAFI | units | 117 | 77 | 64 | 6.2 | 2.2–5.2 | 119–282% | 5.7 | 2.2–5.0 | 114–259% | usable | | ILMENITE_SANDS | MT | 12 | 1 | 54 | 376.3 | 495.3 | 76% | 315.7 | 295.3 | 107% | thin | | COPPER_SLAG | MT | 12 | 1 | 47 | 767.9 | 586.0 | 131% | 488.4 | 444.4 | 110% | thin | | WIRE_ROD_5.5MM | pcs | 17 | 3 | 33 | 36.9 | 24.6 | 150% | 33.4 | 21.9 | 153% | thin | | FELDSPAR | MT | 10 | 1 | 31 | 490.5 | 607.0 | 81% | 309.8 | 485.0 | 64% | thin | | CLAY_BALL | MT | 6 | 1 | 16 | 604.9 | 451.6 | 134% | 402.7 | 290.6 | 139% | thin | | Copper Concentrate | MT | 5 | 1 | 14 | 723.6 | 589.2 | 123% | 336.1 | 247.9 | 136% | thin | | WIRE_ROD_10.0MM | pcs | 4 | 1 | 6 | 10.9 | 24.6 | 44% | 9.8 | 21.9 | 45% | thin | | ISO Container | pcs | 2 | 2 | 0 | 12.5 | 13.5 | 93% | 1.7 | 13.5 | 13% | thin | --- ## 4. Where norm and reality disagree most Split in two, because the two groups need different action. ### 4a. Norms that are broken on their face — fix the standard, not the gang These are not performance problems. The number in the workbook cannot be right. | cargo | norm (Tot CSO / Net) | measured Net | gap | evidence | what is wrong with the norm | |---|---|---|---|---|---| | **TRUCKS_AND_TRAILERS** | 2.7 / 2.9 units/crane-hr | **29.9** units/crane-hr | **10×** | 69 vessels, 110 crane-shifts, 88 net crane-hr | The norm triplet (1.74 / 2.94 / 2.73) is **byte-identical to CONSTRUCTION_VEHICLES**. It was copied across in the workbook. A truck drives off in minutes; 2.9 per hour is a heavy-lift rate. | | **ISO CONTAINER** | 13.5 / 13.5 units/crane-hr | **5.2** pcs/crane-hr | **38% of norm** | 19 vessels, 58 crane-shifts, 88 net crane-hr | Gross, Net and Tot CSO are **all exactly 13.5** — the only row in the sheet where the three are identical round numbers. That is a hand-typed placeholder, not a measured norm. | | **CONSTRUCTION_VEHICLES** | 2.7 / 2.9 units/crane-hr | **5.0** units/crane-hr | **171% of norm** | 91 vessels, 215 crane-shifts, 293 net crane-hr | Same shared row as TRUCKS_AND_TRAILERS. Even for genuine construction vehicles the norm is roughly half of what is being achieved, across 91 vessels. Soft norm — hides lost hours. | | **WIRE_ROD** (all diameters) | 24.4 / 24.6 pcs/crane-hr | **39.1** pcs/crane-hr | **159% of norm** | 17 vessels, 127 crane-shifts, 335 net crane-hr | One single value (24.43) is applied to **all five diameters** — 5.5, 6.0, 6.5, 8.0 and 10.0 mm carry the identical norm. The measurements disagree with each other across diameters (5.5 mm hits 36.9, 10.0 mm only 10.9), so a diameter-blind norm cannot be right in both directions. | ### 4b. Real gaps, with enough evidence to act on | cargo | norm Net | measured Net | gap | evidence | reading | |---|---|---|---|---|---| | **STEEL_STRUCTURES** | 15.4 pcs/crane-hr | **12.2** pcs/crane-hr | **79% of norm** | 55 vessels, 596 crane-shifts, 2,112 net crane-hr | The most trustworthy shortfall in the whole set. Caveat: `STEEL_STRUCTURES` is a catch-all — the reports also carry sub-labels like `STEEL_STRUCTURES PIPES`, `ROUND PIPE`, `channel/beam/angle/pipe`. If the mix under the label has shifted towards awkward pieces, part of the 21% is mix and not performance. | | **STEEL_PLATES** | 16.8 pcs/crane-hr | **13.4** pcs/crane-hr | **80% of norm** | 47 vessels, 181 crane-shifts, 592 net crane-hr | Consistent shortfall over a wide spread of vessels. Same on the gross side (82%), so it is not a delay artefact. | | **ALUMINIUM** | 76.3 pcs/crane-hr (Export) | **39.1** pcs/crane-hr | **51% of norm** | **only 4 vessels**, 293 crane-shifts, 1,333 net crane-hr | The biggest block of hours sitting under a badly-missed norm, but across just four vessels. **Do not act on this before checking the piece definition** — if the norm counts ingot bundles and the reports count sows (or the reverse), the whole gap is a counting difference. Also note the norm exists for **Export only** and the reports do not record import/export. | | **STEEL_PIPES** | 25.3 pcs/crane-hr | **14.2** pcs/crane-hr | **56% of norm** | **only 4 vessels**, 124 crane-shifts, 609 net crane-hr | Same warning. Three separate pipe norms exist (`STEEL_PIPES` 25.3, `STEEL_PIPES_BNDLS` 39.8, `STEEL_PIPES_LOOSE` 49.3) and the reports only ever use the bare label, so it is unclear which norm the cargo should have been held to. | | **STEEL_BILLETS** | 83.4 pcs/crane-hr | **76.3** pcs/crane-hr | **91% of norm** | 51 vessels, 1,178 crane-shifts, 5,554 net crane-hr | The single largest cargo by hours. A steady 9% under norm on the biggest volume you handle — small percentage, large absolute number of hours. | ### 4c. Where the norm is comfortably met or beaten For context, so the list above is not read as a general failure. `BIGBAGS` 102%, `AGGREGATES` 107%, `GREEN_PETCOKE_DB` 106%, `GREEN_PETCOKE_BB` 106%, `SALT` 107%, `COPPER_CONCENTRATE` 103%, `MET_COKE` 107%, `BARITE` 105% — all at or above the standard. `OIL_COUNTR_TUB_GOODS` 93%, `STEEL_COILS` 94%, `LIMESTONE` 94%, `CALCINED_PETCOKE` 96% and `FOREST_PRODUCTS` 90% sit just under it, which is what a healthy norm should look like. --- ## 5. What is missing or uncertain ### 5a. The three copies of the norm table — do they agree? There are three copies in circulation. `compare_rates.js` could not be run (`node` is not installed on this Mac), so they were diffed directly. | copy | rows | verdict | |---|---|---| | `extracted/Prod_data_cells.json` (raw cell dump) | 361 sheet rows, of which **63 real norms** | The source of truth. The "361 rows" is the extent of the sheet, not the number of norms. | | `server/public/data.js` → `PROD_DATA.rates` | **63** | Matches the cell dump exactly. This is what the app uses. | | `/root/reportstats/benchmarks.json` (server) | **59** | **Numerically identical on all 58 shared rows** — not a single figure differs by more than 0.05. Missing 4 rows the app has (`CONSTRUCTION_VEHICLES Export`, `PROJECT_BB Export`, `PROJECT_PR Export`) and calls the container row `CONTAINERS` where the app calls it `ISO CONTAINER`. Naming only. | | `~/Projects/berthing-planner/www/rates.js` | **53** | Rounded to 1 decimal and renamed to readable labels. Two real disagreements, below. | **The two real disagreements, both in `rates.js`:** 1. **RORO gross rates are overstated.** `rates.js` sets `gross = totcso` for all RORO rows, so Passenger Cars gross reads 86.8 instead of 82.5 (import) and 56.7 instead of 53.8 (export); Static Cargo 12.1 instead of 12.0; Mafi 5.2 instead of 5.0. The Berthing Planner uses `gross` for berth occupancy, so it plans RORO vessels roughly **5% faster than the workbook says**. 2. **Ten norm rows are absent** from `rates.js`: the five `WIRE_ROD` diameter variants, `TRUCKS_AND_TRAILERS`, and four `PROJECT_BB` / `PROJECT_PR` import/export duplicates. Its fallback is "any cargo with this name", so a wire-rod vessel still gets a rate — but `TRUCKS_AND_TRAILERS` gets nothing and falls through to zero hours. Everything else agrees. The norm table itself is consistent across copies. ### 5b. Cargo types with too little data to trust Of the 41 matched cargo types: **13 strong**, **13 usable**, **15 thin**. The thin ones — do not set a standard on these: `PROJECT_PR` (8 vessels), `HOT BRIQUETTED IRON ORE` (4), `TIMBER` (2), `BENTONITE` (1), `BARITE` (3), `PLYWOOD` (3), `MET_COKE` (3), `COPPER_SLAG` (1), `ILMENITE_SANDS` (1), `FELDSPAR` (1), `WIRE_ROD_5.5MM` (3), `WIRE_ROD_10.0MM` (1), `CLAY_BALL` (1), plus two duplicate labels (`Copper Concentrate`, `ISO Container`) that are just different spellings. Several of these show eye-catching numbers off a single vessel — `COPPER_SLAG` 131%, `CLAY_BALL` 134%, `BENTONITE` 129%, `FELDSPAR` 81%, `ILMENITE_SANDS` 76%. **One vessel is one vessel.** They are in the table in section 3 for completeness, not as evidence. ### 5c. Norms that exist but were never measured 16 norms have no matching cargo in 1,442 reports, so they are untested: `STEEL_CASING`, `STEEL_PIPES_BNDLS`, `STEEL_PIPES_LOOSE`, `WIRE_ROD_6.0MM`, `WIRE_ROD_6.5MM`, `WIRE_ROD_8.0MM`, `BAUXITE`, `CEMENT`, `Clinker`, `DOLOMITE`, `IRON_ORE`, `MANGANESE_ORE`, `MILL_SCALE`, `SILICA`, `Wadi_Gravel`, `WHEAT`. `Wadi_Gravel` carries the highest rate in the whole sheet (1,062 MT/crane-hr Tot CSO) and has never been measured once. If a gravel export is planned on that number, it is planned on an unverified figure. ### 5d. Cargo that was handled but has no norm at all 159 cargo labels in the reports match no norm — **9,328 crane-shift hours, 16% of all shift time**, planned against nothing. The largest: | cargo label in reports | unit | crane-shifts | vessels | net crane-hr | measured Net | |---|---|---|---|---|---| | ALUMINA | MT | 228 | 6 | 1,073 | 232.4 | | FOREST_PRODUCTS Timber | pcs | 149 | 7 | 684 | 45.1 | | FOREST_PRODUCTS MDF | pcs | 124 | 6 | 571 | 27.8 | | BIGBAGS Alumina | pcs | 97 | 1 | 441 | 61.5 | | FOREST_PRODUCTS Plywood | pcs | 86 | 11 | 322 | 21.3 | | FOREST_PRODUCTS TIMBER | pcs | 53 | 4 | 205 | 30.3 | | STEEL_STRUCTURES PIPES | pcs | 43 | 5 | 194 | 21.2 | | Alumina | MT | 27 | 1 | 123 | 246.9 | | CHROME ORE | MT | 30 | 3 | 149 | 388.0 | | PROJECT_BB Prj & structures | pcs | 32 | 1 | 146 | 5.1 | | STEEL_REBAR | pcs | 37 | 6 | 145 | 30.6 | | AGGREGATES 10mm | MT | 25 | 2 | 117 | 1029.3 | `ALUMINA` is the one that stands out: 1,564 crane-shift hours over 6 vessels, measured at 232 MT/net crane-hr, and **there is no alumina norm in the workbook**. For a cargo at that volume that is a genuine hole. Most of the rest of the long tail is not missing cargo but **messy labels** — `FOREST_PRODUCTS Timber`, `FOREST_PRODUCTS MDF`, `FOREST_PRODUCTS Plywood`, `BIGBAGS Alumina`, `AGGREGATES 10mm`, `STEEL_STRUCTURES ROUND PIPE`, `PASSENGER_CARS Import`. The supervisor typed a free-text suffix after the cargo code, so the line no longer matches its own norm. Tightening the cargo field in the report template would move most of these 9,328 hours back under a standard without any new analysis. ### 5e. What could not be verified - **Import/export cannot be separated in the measurements.** `shifts.db` has no imex column, but 10 norms differ by import and export — for `STATIC_CARGO` the export norm (2.6) is less than a quarter of the import norm (12.1), for `HIGH_and_HEAVY` 11.3 against 29.2, for `PASSENGER_CARS` 56.9 against 87.4. For those five cargo types marked with a range in section 3, no verdict is possible until the reports record direction. - **The `Tot CSO Prod` column — the one the app calculates with — could not be reproduced from the corpus.** Rebuilding it means knowing which delay buckets count as CSO-attributable, and that split differs per report template (the breakbulk, bulk and RoRo templates put different delays in the same lettered columns — see `templates-spec.md`). Rather than guess, section 3 compares against `Net Prod` and `Gross Prod`, which are unambiguous. `Tot CSO Prod` sits between the two, so the Net comparison is the stricter test and the Gross comparison the looser one. - **Which Rev.04 workbook the norms came from** is not recorded. The server copy was read from a file found under `/root/reportstats/data/`; the app copy came from `source_excel/`. They agree numerically, which is reassuring, but neither records a revision date — so **when** these norms were set, and from which period of data, is unknown. - **The reports do not say how the norms were derived.** The figures carry 13 decimal places, which means they were computed from data rather than negotiated. Which data, and over what period, is not in any file found. - **The EGA files** (`~/Projects/ega-productivity/data/*.json`) hold four vessels with achieved against standard per shift. They were not merged into section 3 — different scope (four vessels, one customer) and they would be drowned by the 1,442-report corpus. They are listed in section 1 as a separate artefact. --- ## In one line The norm table is internally consistent and mostly realistic: of the 26 cargo types with decent evidence, most land between 90% and 110% of standard. Four norms are demonstrably broken (`TRUCKS_AND_TRAILERS`, `ISO CONTAINER`, `CONSTRUCTION_VEHICLES`, `WIRE_ROD`) and should be reset before anyone is measured against them. Two shortfalls are real and worth a look (`STEEL_STRUCTURES` 79%, `STEEL_PLATES` 80%), and the biggest cargo you handle (`STEEL_BILLETS`, 5,554 net crane-hours) runs a steady 9% under norm. 16% of all shift hours are not covered by any norm at all, mostly because of free-text cargo labels.