|
|
@@ -118,8 +118,6 @@ async function _render(planetName: string, pop: Pop) {
|
|
|
prices.set(price.ticker, price.vwap_30d);
|
|
|
|
|
|
const results = paretoFront(pop, totalNeeds, siteCount, currentPOPIFilled, currentPop, lowerPop, totalPop, prices);
|
|
|
- const maxPop = Math.max(...results.map((result) => result.change));
|
|
|
- const bestUnitCost = Math.min(...results.filter((result) => result.change > 0).map((result) => result.cost / result.change));
|
|
|
|
|
|
renderTarget.innerHTML = `last POPR: ${lastPOPR.ReportTimestamp} (${lastPOPRts})
|
|
|
<br>next POPR: ${new Date(nextPOPRts * 1000).toISOString()} (${nextPOPRts})
|
|
|
@@ -152,7 +150,6 @@ async function _render(planetName: string, pop: Pop) {
|
|
|
</table>
|
|
|
|
|
|
<h2>needs</h2>
|
|
|
- ${siteCount} bases
|
|
|
<table>
|
|
|
<tr>
|
|
|
<th></th>
|
|
|
@@ -181,6 +178,7 @@ async function _render(planetName: string, pop: Pop) {
|
|
|
</table>
|
|
|
|
|
|
<h2>current POPI</h2>
|
|
|
+ ${siteCount} bases
|
|
|
<table>
|
|
|
<tr>
|
|
|
${infras.map((infra) => {
|
|
|
@@ -198,6 +196,24 @@ async function _render(planetName: string, pop: Pop) {
|
|
|
${formatPct(projectedHappiness(pop, totalNeeds, siteCount, currentPOPIFilled, null))}
|
|
|
|
|
|
<h2>options</h2>
|
|
|
+ <select id="gov_program">
|
|
|
+ <option value="">(all)</option>
|
|
|
+ ${[...new Set(results.map((result) => result.govProgram))].map(
|
|
|
+ (program) => `<option value="${program ?? 'no program'}">${program ?? 'no program'}</option>`).join('')}
|
|
|
+ </select>
|
|
|
+ ${renderOptions(results, currentPOPIFilled, '')}
|
|
|
+ `;
|
|
|
+
|
|
|
+ const govProgramSelect = renderTarget.querySelector('#gov_program') as HTMLSelectElement;
|
|
|
+ govProgramSelect.addEventListener('change', (event) => {
|
|
|
+ renderTarget.querySelector('.options')!.outerHTML = renderOptions(results, currentPOPIFilled, govProgramSelect.value);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function renderOptions(results: ConfigResult[], currentPOPIFilled: POPIFill, govProgramFilter: string): string {
|
|
|
+ const maxPop = Math.max(...results.map((result) => result.change));
|
|
|
+ const bestUnitCost = Math.min(...results.filter((result) => result.change > 0).map((result) => result.cost / result.change));
|
|
|
+ return `
|
|
|
<table class="options">
|
|
|
<tr>
|
|
|
<th>config</th>
|
|
|
@@ -206,7 +222,7 @@ async function _render(planetName: string, pop: Pop) {
|
|
|
<th>cost/day</th>
|
|
|
<th>unit cost</th>
|
|
|
</tr>
|
|
|
- ${results.map((result) => {
|
|
|
+ ${results.filter((result) => govProgramFilter === '' || govProgramFilter === (result.govProgram ?? 'no program')).map((result) => {
|
|
|
let unitCost = '';
|
|
|
if (result.change !== 0)
|
|
|
unitCost = formatNum(result.cost / result.change);
|
|
|
@@ -248,7 +264,6 @@ function formatDelta(n: number, withPlus: boolean = true): string {
|
|
|
function color(n: number, low: number, high: number): string {
|
|
|
// scale n from low..high to 0..1 clamped
|
|
|
const scale = Math.min(Math.max((n - low) / (high - low), 0), 1);
|
|
|
- console.log(n, low, high, scale)
|
|
|
return `color-mix(in xyz, #0aa ${scale * 100}%, #f80)`;
|
|
|
}
|
|
|
|
|
|
@@ -290,9 +305,8 @@ function calcPOPIFilled(infra: Infrastructure): number | null {
|
|
|
}
|
|
|
|
|
|
function paretoFront(pop: Pop, totalNeeds: Record<Need, number>, siteCount: number, currentPOPIFilled: POPIFill,
|
|
|
- currentPop: number, lowerPop: number, totalPop: number, prices: Map<string, number>):
|
|
|
- {config: POPIFill, govProgram: GovProgram | null, happiness: number, change: number, cost: number}[] {
|
|
|
- const results: {config: POPIFill, govProgram: GovProgram | null, happiness: number, change: number, cost: number}[] = [];
|
|
|
+ currentPop: number, lowerPop: number, totalPop: number, prices: Map<string, number>): ConfigResult[] {
|
|
|
+ const results: ConfigResult[] = [];
|
|
|
let education = 0;
|
|
|
if (pop !== 'pio') {
|
|
|
education = EDUCATION[pop];
|
|
|
@@ -521,6 +535,7 @@ type POPIBuilding = 'SAFETY_STATION' | 'SECURITY_DRONE_POST' | 'EMERGENCY_CENTER
|
|
|
type POPIFill = Map<POPIBuilding, {tier: number, numMats: number}>;
|
|
|
type GovProgram = 'festivities I' | 'festivities II' | 'festivities III' | 'education I' | 'education II' | 'education III' |
|
|
|
'pio immigration' | 'set immigration' | 'tec immigration' | 'eng immigration' | 'sci immigration';
|
|
|
+type ConfigResult = {config: POPIFill, govProgram: GovProgram | null, happiness: number, change: number, cost: number};
|
|
|
|
|
|
interface Planet {
|
|
|
PopulationReports: POPR[]
|