feat: add sorter simulation dashboard MVP

This commit is contained in:
deploy
2026-07-04 00:26:08 +02:00
parent 482be98b49
commit 9395d25332
33 changed files with 3141 additions and 0 deletions

102
src/data/items.ts Normal file
View File

@@ -0,0 +1,102 @@
import type { Item } from '../domain/types';
export const ITEMS: Item[] = [
{
id: 'SKU-001',
name: 'Box 300x200x200',
dimensionsMm: { width: 300, depth: 200, height: 200 },
roundness: 0.12,
confidence: 0.94,
shape: 'box',
expectedCategory: 'B',
},
{
id: 'SKU-002',
name: 'Lunchbox 201x152x62',
dimensionsMm: { width: 201, depth: 152, height: 62 },
roundness: 0.22,
confidence: 0.91,
shape: 'rectangular prism',
expectedCategory: 'B',
},
{
id: 'SKU-003',
name: 'Detergent 259x179x278',
dimensionsMm: { width: 259, depth: 179, height: 278 },
roundness: 0.38,
confidence: 0.88,
shape: 'bottle box',
expectedCategory: 'B',
},
{
id: 'SKU-004',
name: 'Oversized box 401x300x400',
dimensionsMm: { width: 401, depth: 300, height: 400 },
roundness: 0.18,
confidence: 0.9,
shape: 'oversized box',
expectedCategory: 'C',
},
{
id: 'SKU-005',
name: 'Pouf 489x264x489',
dimensionsMm: { width: 489, depth: 264, height: 489 },
roundness: 0.74,
confidence: 0.86,
shape: 'soft bulky item',
expectedCategory: 'C',
},
{
id: 'SKU-006',
name: 'Plate 210x209x27',
dimensionsMm: { width: 210, depth: 209, height: 27 },
roundness: 0.95,
confidence: 0.89,
shape: 'round plate',
expectedCategory: 'D',
},
{
id: 'SKU-007',
name: 'Bottle 91x91x305',
dimensionsMm: { width: 91, depth: 91, height: 305 },
roundness: 0.92,
confidence: 0.93,
shape: 'cylinder bottle',
expectedCategory: 'D',
},
{
id: 'SKU-008',
name: 'Cylinder 435x50x43',
dimensionsMm: { width: 435, depth: 50, height: 43 },
roundness: 0.88,
confidence: 0.87,
shape: 'long cylinder',
expectedCategory: 'D',
},
{
id: 'SKU-009',
name: 'Pen 9x13x148',
dimensionsMm: { width: 9, depth: 13, height: 148 },
roundness: 0.66,
confidence: 0.84,
shape: 'thin item',
expectedCategory: 'C',
},
{
id: 'SKU-010',
name: 'Boundary box 450x320x320',
dimensionsMm: { width: 450, depth: 320, height: 320 },
roundness: 0.2,
confidence: 0.9,
shape: 'boundary box',
expectedCategory: 'B',
},
];
export function getItem(id: string): Item {
const item = ITEMS.find((candidate) => candidate.id === id);
if (!item) {
throw new Error(`Unknown item id: ${id}`);
}
return item;
}

60
src/data/scenarios.ts Normal file
View File

@@ -0,0 +1,60 @@
import { getItem } from './items';
import type { Scenario } from '../domain/types';
export const SCENARIOS: Scenario[] = [
{
id: 'normal_flow',
name: 'Normal flow',
description: 'Обычный поток из нескольких товаров B/C/D с полным циклом сортировки.',
items: ['SKU-001', 'SKU-006', 'SKU-004', 'SKU-003', 'SKU-007'].map(getItem),
},
{
id: 'oversized_item',
name: 'Oversized item',
description: 'Товар выходит за max dimensions и должен попасть в roll-cage C.',
items: ['SKU-004', 'SKU-005'].map(getItem),
},
{
id: 'round_object',
name: 'Round object',
description: 'Габариты проходят, но roundness >= 0.8, маршрут в D.',
items: ['SKU-006', 'SKU-007', 'SKU-008'].map(getItem),
},
{
id: 'boundary_dimensions',
name: 'Boundary dimensions',
description: 'Товары около min/max границ показывают устойчивость правил.',
items: ['SKU-010', 'SKU-009', 'SKU-002'].map(getItem),
},
{
id: 'close_items',
name: 'Close items',
description: 'Два товара близко друг к другу: warning queue/spacing и последовательная обработка.',
items: ['SKU-001', 'SKU-002', 'SKU-006'].map(getItem),
},
{
id: 'low_confidence',
name: 'Low confidence',
description: 'CV confidence ниже 0.65, система предупреждает и принимает rule-based решение.',
items: [
{ ...getItem('SKU-003'), id: 'SKU-003-LC', confidence: 0.58 },
{ ...getItem('SKU-006'), id: 'SKU-006-LC', confidence: 0.61 },
],
},
{
id: 'jam',
name: 'Jam at gate',
description: 'Застревание у stop-gate переводит систему в FAULT и останавливает конвейер.',
items: ['SKU-004'].map(getItem),
},
{
id: 'emergency_stop',
name: 'Emergency stop',
description: 'Аварийная остановка переводит систему в EMERGENCY_STOP, движение остановлено.',
items: ['SKU-001', 'SKU-006'].map(getItem),
},
];
export function getScenario(id: string): Scenario {
return SCENARIOS.find((scenario) => scenario.id === id) ?? SCENARIOS[0];
}