Show ingredient tier/enchant + price age in haul advisor
All checks were successful
Deploy / deploy (push) Successful in 1m42s
All checks were successful
Deploy / deploy (push) Successful in 1m42s
- Opportunities breakdown now shows each ingredient's tier/enchant (e.g. T6.4) so enchant mismatches are visible at a glance. - Travel haul advisor now shows color-coded price-age badges (green fresh / yellow aging / red stale) for both buy and sell prices, like Opportunities already does. Note: the enchanted-ingredient pricing itself was already correct in code (T6_SHOES_PLATE_SET1@4); a deployed DB parsed before that fix must re-run Game Data -> Re-download to pick it up. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
38c7ff5e56
commit
7ed585d6a9
3 changed files with 31 additions and 2 deletions
|
|
@ -141,6 +141,8 @@ export interface HaulItem {
|
|||
weight: number;
|
||||
buyAt: number; // sell-order price in origin (you buy instantly)
|
||||
sellAt: number; // sell-order price in destination
|
||||
buyAgeHours: number | null; // how stale the origin price is
|
||||
sellAgeHours: number | null; // how stale the destination price is
|
||||
netPerUnit: number; // after taxes at destination
|
||||
unitsCarryable: number;
|
||||
tripProfit: number;
|
||||
|
|
@ -177,6 +179,8 @@ export async function haulAdvisor(from: string, to: string, maxWeight: number, m
|
|||
weight: it.weight,
|
||||
buyAt: buy.price,
|
||||
sellAt: sell.price,
|
||||
buyAgeHours: buy.ageHours,
|
||||
sellAgeHours: sell.ageHours,
|
||||
netPerUnit,
|
||||
unitsCarryable,
|
||||
tripProfit: netPerUnit * unitsCarryable,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,14 @@ const CITIES = ['Bridgewatch', 'Caerleon', 'Fort Sterling', 'Lymhurst', 'Martloc
|
|||
|
||||
const silver = (n: number) => Math.round(n).toLocaleString('en-US');
|
||||
|
||||
/** Derive a "T6.4" chip from an item id like "T6_SHOES_PLATE_SET1@4" (blank for non-tiered ids). */
|
||||
function tierEnchant(id: string): string {
|
||||
const t = id.match(/^T(\d)_/);
|
||||
if (!t) return '';
|
||||
const e = id.match(/@(\d)$/);
|
||||
return `T${t[1]}${e ? `.${e[1]}` : ''}`;
|
||||
}
|
||||
|
||||
function Age({ hours }: { hours: number | null }) {
|
||||
if (hours == null) return null;
|
||||
const label = hours < 1 ? `${Math.round(hours * 60)}m` : hours < 48 ? `${Math.round(hours)}h` : `${Math.round(hours / 24)}d`;
|
||||
|
|
@ -218,7 +226,12 @@ export default function OpportunitiesPage() {
|
|||
<tbody>
|
||||
{o.inputs.map((inp) => (
|
||||
<tr key={inp.item}>
|
||||
<td>{o.inputNames[inp.item] ?? inp.item}</td>
|
||||
<td>
|
||||
{o.inputNames[inp.item] ?? inp.item}
|
||||
{tierEnchant(inp.item) && (
|
||||
<span className="tag" title={inp.item}>{tierEnchant(inp.item)}</span>
|
||||
)}
|
||||
</td>
|
||||
<td>{inp.count}</td>
|
||||
<td>{inp.effectiveCount.toFixed(2)}</td>
|
||||
<td>{silver(inp.unitCost)}</td>
|
||||
|
|
|
|||
|
|
@ -26,12 +26,22 @@ interface HaulItem {
|
|||
weight: number;
|
||||
buyAt: number;
|
||||
sellAt: number;
|
||||
buyAgeHours: number | null;
|
||||
sellAgeHours: number | null;
|
||||
netPerUnit: number;
|
||||
unitsCarryable: number;
|
||||
tripProfit: number;
|
||||
profitPerWeight: number;
|
||||
}
|
||||
|
||||
/** Color-coded price-age badge: green fresh, yellow aging, red stale. */
|
||||
function PriceAge({ hours }: { hours: number | null }) {
|
||||
if (hours == null) return <span className="muted">—</span>;
|
||||
const label = hours < 1 ? `${Math.round(hours * 60)}m` : hours < 48 ? `${Math.round(hours)}h` : `${Math.round(hours / 24)}d`;
|
||||
const color = hours < 6 ? '#7fd18a' : hours < 24 ? '#e0c069' : '#e08869';
|
||||
return <span style={{ color, fontSize: 12 }}>{label}</span>;
|
||||
}
|
||||
|
||||
interface Status {
|
||||
zones: number;
|
||||
connections: number;
|
||||
|
|
@ -218,7 +228,7 @@ export default function TravelPage() {
|
|||
<table style={{ marginTop: 10 }}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Item</th><th>Buy at {from}</th><th>Sell at {to}</th><th>Net/unit</th><th>Units</th><th>Trip profit</th><th>Profit/kg</th>
|
||||
<th>Item</th><th>Buy at {from}</th><th>age</th><th>Sell at {to}</th><th>age</th><th>Net/unit</th><th>Units</th><th>Trip profit</th><th>Profit/kg</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -226,7 +236,9 @@ export default function TravelPage() {
|
|||
<tr key={h.item}>
|
||||
<td>{h.name ?? h.item} <span className="tag">T{h.tier}</span></td>
|
||||
<td>{silver(h.buyAt)}</td>
|
||||
<td><PriceAge hours={h.buyAgeHours} /></td>
|
||||
<td>{silver(h.sellAt)}</td>
|
||||
<td><PriceAge hours={h.sellAgeHours} /></td>
|
||||
<td>{silver(h.netPerUnit)}</td>
|
||||
<td>{h.unitsCarryable}</td>
|
||||
<td style={{ color: '#7fd18a', fontWeight: 600 }}>{silver(h.tripProfit)}</td>
|
||||
|
|
|
|||
Loading…
Reference in a new issue