diff --git a/scripts/seed-demo.ts b/scripts/seed-demo.ts index 6463690..d1b3c76 100644 --- a/scripts/seed-demo.ts +++ b/scripts/seed-demo.ts @@ -21,6 +21,28 @@ type GeoNode = { synced_at: string } +type DemoHub = GeoNode & { + _key: string + latitude: number + longitude: number +} + +type DemoProduct = { + uuid: string + name: string + unit: string +} + +type DemoSupplier = { + uuid: string + name: string + latitude: number + longitude: number + country: string + country_code: string + hubKey: string +} + async function upsertNode(doc: GeoNode) { const { _key, ...patch } = doc await getDb().query(aql` @@ -46,7 +68,25 @@ await ensureGraph() const now = new Date().toISOString() -const hubs: GeoNode[] = [ +const products: DemoProduct[] = [ + { + uuid: '55555555-1111-4111-8111-111111111111', + name: 'Copper cathode', + unit: 'ton', + }, + { + uuid: '55555555-1111-4111-8111-222222222222', + name: 'Aluminum ingot', + unit: 'ton', + }, + { + uuid: '55555555-1111-4111-8111-333333333333', + name: 'Wheat', + unit: 'ton', + }, +] + +const hubs: DemoHub[] = [ { _key: 'logistics-demo-hub-1', node_type: 'logistics', @@ -82,86 +122,163 @@ const hubs: GeoNode[] = [ }, ] -const offers: GeoNode[] = Array.from({ length: 24 }, (_, index) => ({ - _key: `geo-demo-offer-${index + 1}`, - node_type: 'offer', - name: `Demo offer ${index + 1}`, - latitude: 43.238949 + (index % 6) * 0.12, - longitude: 76.889709 + Math.floor(index / 6) * 0.18, - country: index % 3 === 0 ? 'Kazakhstan' : index % 3 === 1 ? 'China' : 'Russia', - country_code: index % 3 === 0 ? 'KZ' : index % 3 === 1 ? 'CN' : 'RU', - product_uuid: ['55555555-1111-4111-8111-111111111111', '55555555-1111-4111-8111-222222222222', '55555555-1111-4111-8111-333333333333'][index % 3], - product_name: ['Copper cathode', 'Aluminum ingot', 'Wheat'][index % 3], - supplier_uuid: ['66666666-2222-4111-8111-111111111111', '66666666-2222-4111-8111-222222222222', '66666666-2222-4111-8111-333333333333'][index % 3], - supplier_name: ['Demo Supplier Almaty', 'Demo Supplier Urumqi', 'Demo Supplier Moscow'][index % 3], - price_per_unit: String(900 + (index % 8) * 55), - currency: 'USD', - quantity: String(500 + index * 25), - unit: 'ton', - synced_at: now, -})) - -const suppliers: GeoNode[] = [ +const suppliers: DemoSupplier[] = [ { - _key: 'geo-demo-supplier-1', - node_type: 'supplier', + uuid: '66666666-2222-4111-8111-111111111111', name: 'Demo Supplier Almaty', latitude: 43.25667, longitude: 76.92861, country: 'Kazakhstan', country_code: 'KZ', - synced_at: now, + hubKey: 'logistics-demo-hub-1', }, { - _key: 'geo-demo-supplier-2', - node_type: 'supplier', + uuid: '66666666-2222-4111-8111-222222222222', name: 'Demo Supplier Urumqi', latitude: 43.825592, longitude: 87.616848, country: 'China', country_code: 'CN', - synced_at: now, + hubKey: 'logistics-demo-hub-3', }, { - _key: 'geo-demo-supplier-3', - node_type: 'supplier', + uuid: '66666666-2222-4111-8111-333333333333', name: 'Demo Supplier Moscow', latitude: 55.755826, longitude: 37.6173, country: 'Russia', country_code: 'RU', - synced_at: now, + hubKey: 'logistics-demo-hub-2', }, ] -for (const node of [...hubs, ...offers, ...suppliers]) { +function quoteUuid(index: number) { + return `77777777-3333-4${String(index).padStart(3, '0')}-8${String(index).padStart(3, '0')}-777777${String(index).padStart(6, '0')}` +} + +function hubByKey(key: string) { + const hub = hubs.find(item => item._key === key) + if (!hub) throw new Error(`Unknown demo hub: ${key}`) + return hub +} + +const supplierNodes: GeoNode[] = suppliers.map(supplier => ({ + _key: supplier.uuid, + node_type: 'supplier', + name: supplier.name, + latitude: supplier.latitude, + longitude: supplier.longitude, + country: supplier.country, + country_code: supplier.country_code, + synced_at: now, +})) + +const offers: GeoNode[] = Array.from({ length: 24 }, (_, index) => { + const product = products[index % products.length] + const supplier = suppliers[Math.floor(index / products.length) % suppliers.length] + const localIndex = Math.floor(index / suppliers.length) + const latitudeOffset = ((localIndex % 3) - 1) * 0.08 + const longitudeOffset = (Math.floor(localIndex / 3) - 1) * 0.1 + + return { + _key: quoteUuid(index), + node_type: 'offer', + name: `${supplier.name} ${product.name}`, + latitude: supplier.latitude + latitudeOffset, + longitude: supplier.longitude + longitudeOffset, + country: supplier.country, + country_code: supplier.country_code, + product_uuid: product.uuid, + product_name: product.name, + supplier_uuid: supplier.uuid, + supplier_name: supplier.name, + price_per_unit: String(900 + (index % 8) * 55), + currency: 'USD', + quantity: String(500 + index * 25), + unit: product.unit, + synced_at: now, + } +}) + +for (const node of [...hubs, ...offers, ...supplierNodes]) { await upsertNode(node) } -await upsertEdge({ - _key: 'geo-demo-edge-1', - _from: 'nodes/logistics-demo-hub-1', - _to: 'nodes/logistics-demo-hub-2', - to_uuid: 'logistics-demo-hub-2', - to_name: 'Demo Moscow Hub', - to_latitude: 55.755826, - to_longitude: 37.6173, - distance_km: 3950, - travel_time_seconds: 864000, - transport_type: 'rail', -}) +const hubLinks = [ + { + from: 'logistics-demo-hub-1', + to: 'logistics-demo-hub-2', + distanceKm: 3950, + travelTimeSeconds: 864000, + transportType: 'rail', + }, + { + from: 'logistics-demo-hub-2', + to: 'logistics-demo-hub-1', + distanceKm: 3950, + travelTimeSeconds: 864000, + transportType: 'rail', + }, + { + from: 'logistics-demo-hub-1', + to: 'logistics-demo-hub-3', + distanceKm: 1050, + travelTimeSeconds: 172800, + transportType: 'auto', + }, + { + from: 'logistics-demo-hub-3', + to: 'logistics-demo-hub-1', + distanceKm: 1050, + travelTimeSeconds: 172800, + transportType: 'auto', + }, + { + from: 'logistics-demo-hub-3', + to: 'logistics-demo-hub-2', + distanceKm: 4650, + travelTimeSeconds: 950400, + transportType: 'rail', + }, + { + from: 'logistics-demo-hub-2', + to: 'logistics-demo-hub-3', + distanceKm: 4650, + travelTimeSeconds: 950400, + transportType: 'rail', + }, +] -await upsertEdge({ - _key: 'geo-demo-edge-2', - _from: 'nodes/logistics-demo-hub-1', - _to: 'nodes/logistics-demo-hub-3', - to_uuid: 'logistics-demo-hub-3', - to_name: 'Demo Urumqi Hub', - to_latitude: 43.825592, - to_longitude: 87.616848, - distance_km: 1050, - travel_time_seconds: 172800, - transport_type: 'auto', -}) +for (const [index, link] of hubLinks.entries()) { + const toHub = hubByKey(link.to) + await upsertEdge({ + _key: `geo-demo-hub-edge-${index + 1}`, + _from: `nodes/${link.from}`, + _to: `nodes/${link.to}`, + to_uuid: link.to, + to_name: toHub.name, + to_latitude: toHub.latitude, + to_longitude: toHub.longitude, + distance_km: link.distanceKm, + travel_time_seconds: link.travelTimeSeconds, + transport_type: link.transportType, + }) +} -console.log(`Seeded geo demo data: hubs ${hubs.length}, offers ${offers.length}, suppliers ${suppliers.length}`) +for (const [index, offer] of offers.entries()) { + const supplier = suppliers[Math.floor(index / products.length) % suppliers.length] + await upsertEdge({ + _key: `geo-demo-offer-edge-${index + 1}`, + _from: `nodes/${supplier.hubKey}`, + _to: `nodes/${offer._key}`, + to_uuid: offer._key, + to_name: offer.name, + to_latitude: offer.latitude, + to_longitude: offer.longitude, + distance_km: Math.max(1, Math.round(Math.hypot((offer.latitude - supplier.latitude) * 111, (offer.longitude - supplier.longitude) * 75))), + travel_time_seconds: 3600 + index * 120, + transport_type: 'offer', + }) +} + +console.log(`Seeded geo demo data: hubs ${hubs.length}, offers ${offers.length}, suppliers ${suppliers.length}, edges ${hubLinks.length + offers.length}`)