Răsfoiți Sursa

roi: selectable CX

raylu 1 săptămână în urmă
părinte
comite
1c2d69216f
4 a modificat fișierele cu 28 adăugiri și 8 ștergeri
  1. 1 0
      .gitignore
  2. 9 3
      roi.py
  3. 11 4
      ts/roi.ts
  4. 7 1
      www/roi.html

+ 1 - 0
.gitignore

@@ -5,3 +5,4 @@ node_modules/
 uv.lock
 www/buy.js*
 www/roi.js*
+www/roi_*.json

+ 9 - 3
roi.py

@@ -11,9 +11,16 @@ def main() -> None:
 	buildings: dict[str, Building] = {m['Ticker']: m for m in cache.get('https://api.prunplanner.org/data/buildings')}
 	materials: dict[str, Material] = {m['Ticker']: m for m in cache.get('https://api.prunplanner.org/data/materials')}
 	raw_prices: list[RawPrice] = cache.get('https://refined-prun.github.io/refined-prices/all.json')
+	for cx in ['AI1', 'CI1', 'IC1', 'NC1']:
+		profits = calc_for_cx(cx, recipes, buildings, materials, raw_prices)
+		with open(f'www/roi_{cx.lower()}.json', 'w') as f:
+			json.dump([dataclasses.asdict(p) for p in profits], f, indent='\t')
+
+def calc_for_cx(cx: str, recipes: typing.Collection[Recipe], buildings: typing.Mapping[str, Building],
+		materials: typing.Mapping[str, Material], raw_prices: typing.Collection[RawPrice]) -> typing.Sequence[Profit]:
 	prices: dict[str, Price] = {
 		p['MaterialTicker']: Price(p['VWAP7D'], p['AverageTraded7D'], p['VWAP30D']) for p in raw_prices # pyright: ignore[reportArgumentType]
-		if p['ExchangeCode'] == 'IC1'
+		if p['ExchangeCode'] == cx
 	}
 	habitation: typing.Mapping[Worker, str] = {
 		'Pioneers': 'HB1',
@@ -33,8 +40,7 @@ def main() -> None:
 		if profit := calc_profit(recipe, buildings, hab_area_cost, hab_capex, materials, prices):
 			profits.append(profit)
 	profits.sort()
-	with open('www/roi.json', 'w') as f:
-		json.dump([dataclasses.asdict(p) for p in profits], f, indent='\t')
+	return profits
 
 def calc_profit(recipe: Recipe, buildings: typing.Mapping[str, Building], hab_area_cost: typing.Mapping[Worker, float],
 		hab_capex: typing.Mapping[Worker, float], materials: typing.Mapping[str, Material],

+ 11 - 4
ts/roi.ts

@@ -1,11 +1,12 @@
 import {setupPopover} from './popover';
 
-const roi: Promise<{lastModified: Date, profits: Profit[]}> = (async function () {
-	const response = await fetch('/roi.json');
+const roiCache: Record<string, Promise<{lastModified: Date, profits: Profit[]}>> = {};
+async function getROI(cx: string) {
+	const response = await fetch(`/roi_${cx.toLowerCase()}.json`);
 	const lastModified = new Date(response.headers.get('last-modified')!);
 	const profits = await response.json();
 	return {lastModified, profits};
-})();
+}
 
 const lowVolume = document.querySelector('input#low-volume') as HTMLInputElement;
 
@@ -27,6 +28,7 @@ for (const key of Object.keys(expertise)) {
 	option.textContent = key.replace('_', ' ').toLowerCase();
 	expertiseSelect.appendChild(option);
 }
+const cxSelect = document.querySelector('select#cx') as HTMLSelectElement;
 
 const formatDecimal = new Intl.NumberFormat(undefined,
 		{maximumFractionDigits: 2, maximumSignificantDigits: 6, roundingPriority: 'lessPrecision'}).format;
@@ -36,7 +38,11 @@ async function render() {
 	const tbody = document.querySelector('tbody')!;
 	tbody.innerHTML = '';
 
-	const {lastModified, profits} = await roi;
+	const cx = cxSelect.value;
+	if (!roiCache[cx])
+		roiCache[cx] = getROI(cx);
+	const {lastModified, profits} = await roiCache[cx];
+
 	for (const p of profits) {
 		const volumeRatio = p.output_per_day / p.average_traded_7d;
 		if (!lowVolume.checked && volumeRatio > 0.05)
@@ -93,6 +99,7 @@ function formatMatPrices(matPrices: MatPrice[]): string {
 setupPopover();
 lowVolume.addEventListener('change', render);
 expertiseSelect.addEventListener('change', render);
+cxSelect.addEventListener('change', render);
 render();
 
 interface Profit {

+ 7 - 1
www/roi.html

@@ -12,6 +12,12 @@
 	<a href="/">← back</a>
 	<main class="roi">
 		<form>
+			<label>CX <select id="cx">
+				<option value="AI1">AI1/ANT</option>
+				<option value="CI1">CI1/BEN</option>
+				<option value="IC1" selected>IC1/HRT</option>
+				<option value="NC1">NC1/MOR</option>
+			</select></label>
 			<label><input type="checkbox" id="low-volume">show low volume</label>
 			<label>expertise <select id="expertise">
 				<option value="">(all)</option>
@@ -35,7 +41,7 @@
 	</main>
 	<footer>
 		<time id="last-updated"></time>
-		<br>prices and traded volume are IC1/HRT from refined-price's 7-day volume-weighted average
+		<br>prices and traded volume are from refined-price's 7-day volume-weighted average
 		<br>FRM and ORC use 112.12% fertility (promitor's)
 	</footer>
 	<div id="popover" popover="hint"></div>