You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
5.4 KiB
217 lines
5.4 KiB
/**
|
|
* Flock Direct 10 组样例探针
|
|
*
|
|
* 用法:
|
|
* FLOCK_QUOTE_MODE=direct npm run batch:flock-direct-10
|
|
*/
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { runFlockQuoteRpa } from "@/workers/rpa/flock/run-quote";
|
|
import type { FlockQuoteInput } from "@/workers/rpa/flock/types";
|
|
|
|
function tomorrowMmDdYyyy(offsetDays = 1): string {
|
|
const d = new Date();
|
|
d.setDate(d.getDate() + offsetDays);
|
|
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
const dd = String(d.getDate()).padStart(2, "0");
|
|
return `${mm}/${dd}/${d.getFullYear()}`;
|
|
}
|
|
|
|
/** 10 组差异化:跨区 ZIP + 不同托盘/总重/尺寸(硬限内) */
|
|
const CASES: Array<Omit<FlockQuoteInput, "pickupDate"> & { label: string }> = [
|
|
{
|
|
label: "LA→Dallas 6pl/10k",
|
|
pickupZip: "90001",
|
|
deliveryZip: "75201",
|
|
palletCount: 6,
|
|
totalWeightLb: 10_000,
|
|
lengthIn: 48,
|
|
widthIn: 40,
|
|
heightIn: 48,
|
|
},
|
|
{
|
|
label: "SF→Chicago 4pl/2.8k",
|
|
pickupZip: "94102",
|
|
deliveryZip: "60611",
|
|
palletCount: 4,
|
|
totalWeightLb: 2_800,
|
|
lengthIn: 48,
|
|
widthIn: 40,
|
|
heightIn: 48,
|
|
},
|
|
{
|
|
label: "Boston→Atlanta 8pl/9.2k",
|
|
pickupZip: "02109",
|
|
deliveryZip: "30326",
|
|
palletCount: 8,
|
|
totalWeightLb: 9_200,
|
|
lengthIn: 48,
|
|
widthIn: 40,
|
|
heightIn: 60,
|
|
},
|
|
{
|
|
label: "Austin→Philly 10pl/14k",
|
|
pickupZip: "78701",
|
|
deliveryZip: "19106",
|
|
palletCount: 10,
|
|
totalWeightLb: 14_000,
|
|
lengthIn: 48,
|
|
widthIn: 40,
|
|
heightIn: 72,
|
|
},
|
|
{
|
|
label: "Seattle→Miami 12pl/18.5k",
|
|
pickupZip: "98101",
|
|
deliveryZip: "33130",
|
|
palletCount: 12,
|
|
totalWeightLb: 18_500,
|
|
lengthIn: 48,
|
|
widthIn: 48,
|
|
heightIn: 96,
|
|
},
|
|
{
|
|
label: "Denver→NYC 5pl/6k",
|
|
pickupZip: "80202",
|
|
deliveryZip: "10001",
|
|
palletCount: 5,
|
|
totalWeightLb: 6_000,
|
|
lengthIn: 48,
|
|
widthIn: 40,
|
|
heightIn: 60,
|
|
},
|
|
{
|
|
label: "Phoenix→Houston 16pl/28k",
|
|
pickupZip: "85004",
|
|
deliveryZip: "77002",
|
|
palletCount: 16,
|
|
totalWeightLb: 28_000,
|
|
lengthIn: 48,
|
|
widthIn: 40,
|
|
heightIn: 96,
|
|
},
|
|
{
|
|
label: "Portland→Dallas 4pl/8k long",
|
|
pickupZip: "97201",
|
|
deliveryZip: "75201",
|
|
palletCount: 4,
|
|
totalWeightLb: 8_000,
|
|
lengthIn: 96,
|
|
widthIn: 48,
|
|
heightIn: 72,
|
|
},
|
|
{
|
|
label: "Detroit→LA 7pl/12k",
|
|
pickupZip: "48226",
|
|
deliveryZip: "90012",
|
|
palletCount: 7,
|
|
totalWeightLb: 12_000,
|
|
lengthIn: 48,
|
|
widthIn: 40,
|
|
heightIn: 84,
|
|
},
|
|
{
|
|
label: "Chicago→SF 20pl/38k",
|
|
pickupZip: "60611",
|
|
deliveryZip: "94102",
|
|
palletCount: 20,
|
|
totalWeightLb: 38_000,
|
|
lengthIn: 48,
|
|
widthIn: 40,
|
|
heightIn: 96,
|
|
},
|
|
];
|
|
|
|
type Row = {
|
|
index: number;
|
|
label: string;
|
|
ok: boolean;
|
|
ms: number;
|
|
reference: string | null;
|
|
prices: string | null;
|
|
error: string | null;
|
|
};
|
|
|
|
async function main(): Promise<void> {
|
|
process.env.RPA_MOCK_MODE = "false";
|
|
process.env.FLOCK_QUOTE_MODE ??= "direct";
|
|
process.env.FLOCK_MIN_QUOTES ??= "1";
|
|
|
|
const delayMs = Number(process.env.FLOCK_BATCH_DELAY_MS ?? "1500");
|
|
const outDir = path.join(process.cwd(), ".rpa", "flock-network-poc");
|
|
fs.mkdirSync(outDir, { recursive: true });
|
|
|
|
console.log(
|
|
`[flock-direct-10] mode=${process.env.FLOCK_QUOTE_MODE} cases=${CASES.length}`,
|
|
);
|
|
|
|
const rows: Row[] = [];
|
|
for (let i = 0; i < CASES.length; i += 1) {
|
|
const c = CASES[i]!;
|
|
const input: FlockQuoteInput = {
|
|
pickupDate: tomorrowMmDdYyyy(1 + (i % 3)),
|
|
pickupZip: c.pickupZip,
|
|
deliveryZip: c.deliveryZip,
|
|
palletCount: c.palletCount,
|
|
totalWeightLb: c.totalWeightLb,
|
|
lengthIn: c.lengthIn,
|
|
widthIn: c.widthIn,
|
|
heightIn: c.heightIn,
|
|
};
|
|
console.log(
|
|
`\n[${i + 1}/${CASES.length}] ${c.label} ` +
|
|
`${input.pickupZip}→${input.deliveryZip} ${input.palletCount}pl ${input.totalWeightLb}lb`,
|
|
);
|
|
const t0 = Date.now();
|
|
const result = await runFlockQuoteRpa(input);
|
|
const ms = Date.now() - t0;
|
|
const ok = result.ok && result.quotes.length >= 1;
|
|
const prices = ok
|
|
? result.quotes.map((q) => `${q.label}:$${q.totalUsd}`).join(", ")
|
|
: null;
|
|
rows.push({
|
|
index: i + 1,
|
|
label: c.label,
|
|
ok,
|
|
ms,
|
|
reference: result.reference ?? null,
|
|
prices,
|
|
error: ok ? null : (result.errorMessage ?? "unknown"),
|
|
});
|
|
if (ok) {
|
|
console.log(`[OK] ${ms}ms ref=${result.reference ?? "-"} ${prices}`);
|
|
} else {
|
|
console.error(`[FAIL] ${ms}ms ${result.errorMessage ?? "unknown"}`);
|
|
}
|
|
if (i < CASES.length - 1 && delayMs > 0) {
|
|
await new Promise((r) => setTimeout(r, delayMs));
|
|
}
|
|
}
|
|
|
|
const passed = rows.filter((r) => r.ok).length;
|
|
const summary = {
|
|
capturedAt: new Date().toISOString(),
|
|
mode: process.env.FLOCK_QUOTE_MODE,
|
|
passed,
|
|
total: rows.length,
|
|
rows,
|
|
};
|
|
const outPath = path.join(outDir, `direct-10-${Date.now()}.json`);
|
|
fs.writeFileSync(outPath, JSON.stringify(summary, null, 2), "utf8");
|
|
|
|
console.log(`\n========== 汇总 ${passed}/${rows.length} ==========`);
|
|
for (const r of rows) {
|
|
console.log(
|
|
r.ok
|
|
? ` ✓ #${r.index} ${r.label} (${r.ms}ms) ${r.prices}`
|
|
: ` ✗ #${r.index} ${r.label} (${r.ms}ms) ${r.error}`,
|
|
);
|
|
}
|
|
console.log(`结果文件: ${outPath}`);
|
|
if (passed < rows.length) process.exitCode = 1;
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error("[flock-direct-10] fatal:", error);
|
|
process.exit(1);
|
|
});
|