尚未检测到更新。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.