raylu 3 недель назад
Родитель
Сommit
b337bfddd0
5 измененных файлов с 46 добавлено и 16 удалено
  1. 2 2
      roi.py
  2. 27 6
      ts/roi.ts
  3. 2 2
      www/buy.html
  4. 8 3
      www/roi.html
  5. 7 3
      www/style.css

+ 2 - 2
roi.py

@@ -70,7 +70,7 @@ def calc_profit(recipe: Recipe, buildings: typing.Mapping[str, Building], hab_ar
 		materials[output['Ticker']]['Volume'] * output['Amount'],
 	) * runs_per_day / area
 	return Profit(output['Ticker'], recipe['RecipeName'],
-			expertise=building['Expertise'].replace('_', ' ').lower(),
+			expertise=building['Expertise'],
 			profit_per_day=(profit_per_run * runs_per_day - worker_consumable_daily_cost),
 			area=area,
 			capex=capex,
@@ -80,7 +80,7 @@ def calc_profit(recipe: Recipe, buildings: typing.Mapping[str, Building], hab_ar
 			average_traded_7d=output_price.average_traded_7d)
 
 def building_construction_cost(building: Building, prices: typing.Mapping[str, Price]) -> float:
-	return sum(bc['Amount'] * prices[bc['CommodityTicker']].vwap_7d for bc in building['BuildingCosts'])
+	return sum(bc['Amount'] * prices[bc['CommodityTicker']].vwap_7d for bc in building['BuildingCosts']) # pyright: ignore[reportOperatorIssue]
 
 def building_daily_cost(building: Building, prices: typing.Mapping[str, Price]) -> float:
 	consumption = {

+ 27 - 6
ts/roi.ts

@@ -1,13 +1,32 @@
 import {setupPopover} from './popover';
 
 const roi: Promise<{lastModified: Date, profits: Profit[]}> = (async function () {
-	const response = await fetch('https://prun.raylu.net/roi.json');
+	const response = await fetch('/roi.json');
 	const lastModified = new Date(response.headers.get('last-modified')!);
 	const profits = await response.json();
 	return {lastModified, profits};
 })();
 
-const lowVolume = document.querySelector('#low-volume') as HTMLInputElement;
+const lowVolume = document.querySelector('input#low-volume') as HTMLInputElement;
+
+const expertise = {
+	AGRICULTURE: 'agri',
+	CHEMISTRY: 'chem',
+	CONSTRUCTION: 'const',
+	ELECTRONICS: 'elec',
+	FOOD_INDUSTRIES: 'food ind',
+	FUEL_REFINING: 'fuel',
+	MANUFACTURING: 'mfg',
+	METALLURGY: 'metal',
+	RESOURCE_EXTRACTION: 'res ext',
+} as const;
+const expertiseSelect = document.querySelector('select#expertise') as HTMLSelectElement;
+for (const key of Object.keys(expertise)) {
+	const option = document.createElement('option');
+	option.value = key;
+	option.textContent = key.replace('_', ' ').toLowerCase();
+	expertiseSelect.appendChild(option);
+}
 
 async function render() {
 	const formatDecimal = new Intl.NumberFormat(undefined,
@@ -19,15 +38,16 @@ async function render() {
 	const {lastModified, profits} = await roi;
 	for (const p of profits) {
 		const volumeRatio = p.output_per_day / p.average_traded_7d;
-		if (!lowVolume.checked && volumeRatio > 0.05) {
+		if (!lowVolume.checked && volumeRatio > 0.05)
+			continue;
+		if (expertiseSelect.value !== '' && p.expertise !== expertiseSelect.value)
 			continue;
-		}
 		const tr = document.createElement('tr');
 		const profit_per_area = p.profit_per_day / p.area;
 		const break_even = p.profit_per_day > 0 ? p.capex / p.profit_per_day : Infinity;
 		tr.innerHTML = `
 			<td>${p.output}</td>
-			<td>${p.expertise}</td>
+			<td>${expertise[p.expertise]}</td>
 			<td style="color: ${color(profit_per_area, 0, 250)}">${formatDecimal(profit_per_area)}</td>
 			<td><span style="color: ${color(break_even, 30, 3)}">${formatDecimal(break_even)}</span>d</td>
 			<td style="color: ${color(p.capex, 300_000, 40_000)}">${formatWhole(p.capex)}</td>
@@ -54,12 +74,13 @@ function color(n: number, low: number, high: number): string {
 
 setupPopover();
 lowVolume.addEventListener('change', render);
+expertiseSelect.addEventListener('change', render);
 render();
 
 interface Profit {
 	output: string
 	recipe: string
-	expertise: string
+	expertise: keyof typeof expertise
 	profit_per_day: number
 	area: number
 	capex: number

+ 2 - 2
www/buy.html

@@ -10,7 +10,7 @@
 </head>
 <body>
 	<a href="/">← back</a>
-	<main>
+	<main class="buy">
 		<form>
 			<label>FIO username: <input type="text" id="username"></label>
 			<label>FIO API key: <input type="password" size="30" id="api-key"></label>
@@ -23,7 +23,7 @@
 			</select></label>
 			<input type="button" value="fetch" id="fetch">
 		</form>
-		<table class="buy">
+		<table>
 			<thead>
 				<tr>
 					<th>mat</th>

+ 8 - 3
www/roi.html

@@ -10,9 +10,14 @@
 </head>
 <body>
 	<a href="/">← back</a>
-	<main>
-        <label><input type="checkbox" id="low-volume">show low volume</label>
-		<table class="roi">
+	<main class="roi">
+		<form>
+			<label><input type="checkbox" id="low-volume">show low volume</label>
+			<label>expertise <select id="expertise">
+				<option value="">(all)</option>
+			</select></label>
+		</form>
+		<table>
 			<thead>
 				<tr>
 					<th>wrought<br>product</th>

+ 7 - 3
www/style.css

@@ -23,12 +23,16 @@ a:hover {
 	color: #5ad;
 }
 
-form {
+main.buy form {
 	display: flex;
 	flex-direction: column;
 	align-items: flex-start;
 	line-height: 2;
 }
+main.roi form {
+	display: flex;
+	justify-content: space-evenly;
+}
 input, select {
 	background-color: #171120;
 	color: inherit;
@@ -67,7 +71,7 @@ table {
 		border-top: 1px solid #222;
 	}
 }
-table.buy {
+main.buy table {
 	td:nth-child(1) {
 		font-family: inherit;
 		text-align: inherit;
@@ -76,7 +80,7 @@ table.buy {
 		color: #c66;
 	}
 }
-table.roi {
+main.roi table {
 	td:nth-child(1),
 	td:nth-child(2) {
 		font-family: inherit;