尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Seeded synthetic warehouse data with velocity-based SKU slotting, validation, labelled edge cases and a browser UI. Cuts pick distance 46.6% in simulation. Zero dependencies.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗
| 🚚 -47.3% | 📦 +14.8% | ✅ 0 | 🎯 50 / 50 | 🔁 100% |
|---|---|---|---|---|
| pick distance | lines per labor hour | validation failures | injected issues found | same-seed reproducible |
Full scale: 20 warehouses, 10,000 locations, 5,000 SKUs, 100,000 order lines, seed 20261022. The live page is available once GitHub Pages is enabled (main, folder /).
Requires Node 18+. No install step, no dependencies.
git clone https://github.com/Punitpritam788/warehouse-slotting && cd warehouse-slotting
node gen.js # starter: 4 warehouses, 800 locations, 400 SKUs, 4,000 order lines (<1 s)
node gen.js --large # 40 warehouses, 20,000 locations, 10,000 SKUs, 400,000 lines (~1.1M rows, ~17 s)
node gen.js --full # 20 warehouses, 10,000 locations, 5,000 SKUs, 100,000 order lines (~6 s)
node gen.js --full --seed 7 --out /tmp/x --sql --json # other seed, other folder, extra formats
| Flag | Meaning |
|---|---|
--full / --large / --starter | scale preset (default starter) |
--seed N | PRNG seed (default 20261022) |
--warehouses --locations --skus --lines --inject N | override any scale parameter |
--out DIR | output folder (default data/<scale>) |
--sql / --json | also write seed.sql (DDL + inserts) / all.json |
The command prints counts, validation failures, anomaly detection vs ground truth and the reproducibility check, and exits non-zero if anything fails. That exit code is the one-line way to verify the solution.
Web UI: open index.html, pick a scale and click Generate. Use the Modern / Classic switch in the top bar to change layout (remembered in your browser, or add ?view=classic to the URL). Scales: starter, full and a 400k-line large stress test. It runs the same engine in the browser, twice, and shows byte-for-byte equality, the baseline vs optimized comparison, every validation check and the injected edge cases. It can also download each table as CSV and the SQL seed.
Full scale, seed 20261022 (from data/full/manifest.json). Both layouts are replayed against the same 100,000 order lines.
| Metric | Baseline (random compatible fit) | Optimized (velocity ranked, nearest fit) | Change |
|---|---|---|---|
| Total pick distance (m) | 4,892,814 | 2,578,170 | -47.3% |
| Avg distance per line (m) | 48.93 | 25.78 | -47.3% |
| Avg distance, class-A SKUs (m) | 49.18 | 22.00 | -55.3% |
| Replenishment tasks | 39,471 | 40,445 | +2.5% |
| Replenishment labor (min) | 271,860 | 253,739 | -6.7% |
| Peak-day replen labor / capacity | 1.11 | 1.31 | |
| Lines per labor hour | 15.39 | 17.67 | +14.8% |
Reading it: putting fast movers near the dock cuts walking by almost half and lifts throughput by about 15%. Replenishment task count barely moves (slot capacity, not location, drives it) and total labor drops a little. The peak-day ratio is the least stable number: capacity is calibrated on the actual timeline (baseline until Jun 30, optimized after), so a replay of one layout over the whole year can land above or below 1.0 depending on the seed (here 1.11 baseline vs 1.31 optimized). Treat it as indicative, not as a result. Throughput assumes walking 1.2 m/s, 30 s handling per line, round trip to the dock.
| Check | Result |
|---|---|
| Rows (full) | Warehouse 20 · Zone 80 · Location 10,000 · SKU 5,000 · SKUProfile 5,000 · Order 33,505 · OrderLine 100,000 · PickEvent 100,000 · Replenishment 39,122 · SlotAssignment 10,030 · AisleBlock 70 · ground truth 50 |
| Validation failures (clean data and after injection) | 0 |
| Detector rows on clean data | 0 |
| Injected edge cases vs detector | 50 expected, 50 found, 0 false positives, 0 false negatives |
| Two runs, same seed | identical in every table |
flowchart LR
D[dict.js<br/>data dictionary + FKs] --> G
D --> V
G[engine.js gen] -->|clean tables| V[validate]
G --> DET[detect]
G -->|inject labelled rows| I[edge cases]
I --> V
I --> DET
I -->|answer key| GT[ground_truth.csv]
DET -. compared with .-> GT
G --> M[metrics: both layouts]
CLI[gen.js CLI] --> G
UI[index.html] --> G
CLI --> OUT[(data/ CSV, SQL, JSON, manifest)]
dict.js is the single source of truth: field types, units, enums and rules, plus foreign keys. It produces DATA_DICTIONARY.md and the SQL DDL, and it drives validation, so documentation and checks cannot drift apart.engine.js holds the generator, validator, detector and exporters. It has no dependencies and runs unchanged in Node and in the browser.erDiagram
Warehouse ||--o{ Zone : has
Zone ||--o{ Location : has
Warehouse ||--o{ SKU : "home of"
SKU ||--|| SKUProfile : describes
Warehouse ||--o{ Order : receives
Order ||--|{ OrderLine : contains
SKU ||--o{ OrderLine : ordered
OrderLine ||--|| PickEvent : "picked as"
Location ||--o{ PickEvent : "picked from"
SKU ||--o{ SlotAssignment : slotted
Location ||--o{ SlotAssignment : holds
SKU ||--o{ Replenishment : refilled
Location ||--o{ Replenishment : at
Warehouse ||--o{ AisleBlock : blocks
The ten entities from the brief plus AisleBlock (needed to model "pick path uses blocked aisle"). Full field list with types, units, allowed values and rules: DATA_DICTIONARY.md.
SlotAssignment, which has effective dates.WH-001, LOC-<zone-id>-000001, SKU-000001, ORD-2026-000001, PICK-<order-id>-001, SLOT-2026-000001. Added: REPL-2026-000001, BLK-2026-000001. Counters are zero padded and IDs are never reused.ACTIVE while it has no end date and becomes SUPERSEDED when the end date is set. Baseline slots run 2026-01-01 to 2026-06-30, optimized slots start 2026-07-01.Order of creation: Warehouse, Zone, Location, SKU, Order and OrderLine, SKUProfile, SlotAssignment, PickEvent, Replenishment, AisleBlock, then injected edge cases. Child rows only reference parents that already exist.
| Step | Rule |
|---|---|
| Layout | each warehouse has 4 zones (60% AMBIENT, 12% COLD, 10% HAZMAT, 18% BULK); 60 locations per aisle (20 bays x 3 levels); location size and weight limit depend on zone and level |
| SKU mix | 5% oversized, 8% hazard (flammable or corrosive), 10% cold chain, rest ambient; about 10% of ambient SKUs are bulky and 5% heavy so fit matters |
| Demand | Zipf-like popularity per warehouse; two peak windows (Mar 1-15, Sep 15 - Oct 11) at 3x order volume, with 10% "seasonal" SKUs at 6x during peaks |
| Velocity class | derived from realised order lines: A until 80% of lines, B until 95%, C after |
| Compatibility | oversized only in BULK, hazard only in HAZMAT, cold only in COLD, other goods in AMBIENT; the SKU must also fit the location (length, width, height, weight, no rotation) |
| Baseline slotting | velocity-blind: random compatible free location |
| Optimized slotting | hottest SKU first, nearest compatible free location to the dock |
| Pick | PickEvent.location_id is the slot in force on picked_at; travel distance is 2 x dock distance |
| Replenishment | when stock falls to 25% of slot capacity, refill to capacity; labor = 5 + 0.1 x qty + 0.05 x dock metres (minutes) |
| Labor capacity | per warehouse, 115% of its busiest replenishment day |
| Derived values | order totals, picks_total, velocity class, volumes, distances and labor are computed from source rows, never drawn independently |
Clean data is generated and validated first. Edge cases are then added as new labelled rows and never by editing valid rows. Ten per type at full scale (two at starter scale).
issue_type | How it is injected | Detector rule |
|---|---|---|
SKU_EXCEEDS_LOCATION_CAPACITY | extra slot in a free location the SKU does not fit | dimension or weight check |
INCOMPATIBLE_COLOCATED | hazard or cold SKU slotted in the wrong zone type | SKU class vs zone type |
DUPLICATE_ACTIVE_LOCATION | second SKU on a location that is already active | overlapping slot dates on one location, later slot flagged |
PICK_USES_BLOCKED_AISLE | an AisleBlock over a day on which exactly one pick used that aisle | pick date inside a block window |
REPLEN_EXCEEDS_LABOR_CAPACITY | extra replenishment tasks until one warehouse-day passes capacity | daily labor sum above capacity |
ground_truth.csv lists issue_id, issue_type, entity_type, entity_id, note, where the note states the expected decision (reject, re-route, rebalance). Each injected case is built so that only its own rule fires; the comparison reports true positives, false positives and false negatives.
engine.js > validate runs 60+ checks, all driven by dict.js:
picks_total vs lines, velocity class recomputed, pick distance, replenishment laborACTIVE if and only if no end date; every pick and replenishment location equals a slot in force on that dateBusiness-rule violations (the five edge-case types) are deliberately not structural errors, so they pass validation and are found by the detector instead.
One PRNG (mulberry32) seeded with 20261022, no Math.random, no wall-clock dates. gen.js generates the data twice in the same run and compares every table, and the manifest stores a SHA-256 and an FNV-1a checksum per table. Re-running with the same seed on the same Node version gives identical files.
This project was built with an LLM (Claude). The prompts are in PROMPTS.md together with what the AI produced and what I reviewed and verified. Verification: node gen.js and node gen.js --full pass all checks, and index.html was loaded in headless Chromium with the same results.
index.html modern web UI (loads dict.js + engine.js)
session.js generation session shared by the Web Worker and the main-thread fallback
worker.js Web Worker entry (keeps the page responsive on big runs)
engine.js generator, validator, detector, exporters
dict.js data dictionary, foreign keys, DDL and markdown generators
gen.js CLI: generate, validate, write files, check reproducibility
DATA_DICTIONARY.md generated field reference
PROMPTS.md prompt history and AI disclosure
PROMPT.md one detailed prompt that reproduces this repo (written afterwards)
data/starter/ all outputs for the starter scale
data/full/ CSV + ground_truth.csv + manifest.json for the full scale
All data is generated by this code; no third-party datasets were used. Add a LICENSE file of your choice before sharing widely.
worker.js), so the page stays responsive. If workers are unavailable (for example opening the file directly from disk), it falls back to the main thread.