feat: add shared unstable listing classifier

This commit is contained in:
2026-04-22 17:56:26 -04:00
parent f8975fa91d
commit 8141de5b4b
4 changed files with 140 additions and 0 deletions

View File

@@ -41,3 +41,4 @@ export * from "./utils/cookies";
export * from "./utils/delay";
export * from "./utils/format";
export * from "./utils/http";
export * from "./utils/unstable";

View File

@@ -18,3 +18,12 @@ export interface ListingDetails {
address?: string | null;
creationDate?: string;
}
export interface UnstableListingBuckets<T> {
results: T[];
unstableResults: T[];
}
export interface UnstableListingModeOptions {
hideUnstableResults?: boolean;
}

View File

@@ -0,0 +1,46 @@
import type { ListingDetails, UnstableListingBuckets } from "../types/common";
function getMedian(values: number[]): number {
const middleIndex = Math.floor(values.length / 2);
if (values.length % 2 === 0) {
return (values[middleIndex - 1] + values[middleIndex]) / 2;
}
return values[middleIndex];
}
export function classifyUnstableListings<T extends ListingDetails>(
listings: T[],
): UnstableListingBuckets<T> {
const validPrices = listings
.map((listing) => listing.listingPrice.cents)
.filter((price) => Number.isFinite(price) && price > 0)
.sort((left, right) => left - right);
if (validPrices.length < 2) {
return {
results: [...listings],
unstableResults: [],
};
}
const threshold = getMedian(validPrices) * 0.8;
const buckets: UnstableListingBuckets<T> = {
results: [],
unstableResults: [],
};
for (const listing of listings) {
const price = listing.listingPrice.cents;
if (Number.isFinite(price) && price > 0 && price < threshold) {
buckets.unstableResults.push(listing);
continue;
}
buckets.results.push(listing);
}
return buckets;
}