소스 검색

gov: migration

raylu 1 주 전
부모
커밋
e0316e2bdb
1개의 변경된 파일43개의 추가작업 그리고 18개의 파일을 삭제
  1. 43 18
      ts/gov.ts

+ 43 - 18
ts/gov.ts

@@ -70,6 +70,13 @@ async function _render(planetName: string, pop: Pop) {
 	const lastPOPRts = Math.floor(new Date(lastPOPR.ReportTimestamp).getTime() / 1000);
 	const nextPOPRts = lastPOPRts + 7 * 24 * 60 * 60;
 
+	let currentPop = 0;
+	if (pop == 'pio') currentPop = lastPOPR.NextPopulationPioneer;
+	else if (pop == 'set') currentPop = lastPOPR.NextPopulationSettler;
+	else if (pop == 'tec') currentPop = lastPOPR.NextPopulationTechnician;
+	else if (pop == 'eng') currentPop = lastPOPR.NextPopulationEngineer;
+	else if (pop == 'sci') currentPop = lastPOPR.NextPopulationScientist;
+
 	const siteCount = siteCounts[0].Count;
 
 	const totalNeeds: Record<Need, number> = {
@@ -151,7 +158,7 @@ async function _render(planetName: string, pop: Pop) {
 		</tr>
 	</table>
 
-	<h2>POPI</h2>
+	<h2>current POPI</h2>
 	<table>
 		<tr>
 			${infras.map((infra) => {
@@ -165,17 +172,28 @@ async function _render(planetName: string, pop: Pop) {
 			}).join('')}
 		</tr>
 	</table>
+	current projected ${pop.toUpperCase()} happiness:
+	${formatPct(projectedHappiness(pop, totalNeeds, siteCount, currentPOPIFilled))}
 
 	<h2>options</h2>
-	current projected ${pop} happiness: ${formatPct(projectedHappiness(pop, totalNeeds, siteCount, currentPOPIFilled))}
 	<table class="options">
-	${paretoFront(pop, totalNeeds, siteCount, currentPOPIFilled, prices).map((result) => {
-		return `<tr>
-			<td>${[...result.config.entries()].map(([building, fill]) => `${building}: ${fill.numMats}`).join(', ')}</td>
-			<td>${formatPct(result.happiness)}</td>
-			<td>${formatNum(result.cost)}/day</td>
-		</tr>`;
-	}).join('')}
+		<tr>
+			<th>config</th>
+			<th>projected migration</th>
+			<th>cost/day</th>
+			<th>unit cost</th>
+		</tr>
+		${paretoFront(pop, totalNeeds, siteCount, currentPOPIFilled, currentPop, prices).map((result) => {
+			let unitCost = '';
+			if (result.cost > 0)
+				unitCost = formatNum(result.cost / result.migration);
+			return `<tr>
+				<td>${[...result.config.entries()].map(([building, fill]) => `${building}: ${fill.numMats}`).join(', ')}</td>
+				<td>${formatDelta(result.migration)}</td>
+				<td>${formatNum(result.cost)}</td>
+				<td>${unitCost}</td>
+			</tr>`;
+		}).join('')}
 	</table>
 	`;
 }
@@ -185,9 +203,9 @@ const formatPct = new Intl.NumberFormat(undefined, {style: 'percent', maximumFra
 
 function formatDelta(n: number, withPlus: boolean = true): string {
 	if (n > 0)
-		return `<span class="positive">${withPlus ? '+' : ''}${n}</span>`;
+		return `<span class="positive">${withPlus ? '+' : ''}${formatNum(n)}</span>`;
 	else if (n < 0)
-		return `<span class="negative">${n}</span>`;
+		return `<span class="negative">${formatNum(n)}</span>`;
 	else
 		return n.toString();
 }
@@ -230,21 +248,28 @@ function calcPOPIFilled(infra: Infrastructure): number | null {
 }
 
 function paretoFront(pop: Pop, totalNeeds: Record<Need, number>, siteCount: number, currentPOPIFilled: POPIFill,
-		prices: Map<string, number>): {config: POPIFill, happiness: number, cost: number}[] {
-	const results: {config: POPIFill, happiness: number, cost: number}[] = [];
+		currentPop: number, prices: Map<string, number>): {config: POPIFill, migration: number, cost: number}[] {
+	const results: {config: POPIFill, migration: number, cost: number}[] = [];
 	for (const config of popiFillCombinations(currentPOPIFilled)) {
 		const happiness = projectedHappiness(pop, totalNeeds, siteCount, config);
+		let migration = 0;
+		if (happiness > 0.7)
+			migration = currentPop * (happiness - 0.7);
+		else if (happiness < 0.5)
+			migration = 0.8 * currentPop * (happiness - 0.5);
+		// TODO: education
+
 		let cost = calcCost(config, prices);
 		// is any result better than this one?
-		if (results.some((result) => (result.happiness >= happiness && result.cost < cost) ||
-				(result.happiness > happiness && result.cost <= cost)))
+		if (results.some((result) => (result.migration >= migration && result.cost < cost) ||
+				(result.migration > migration && result.cost <= cost)))
 			continue;
 		// are any results worse than this one?
 		for (let i = results.length - 1; i >= 0; i--)
-			if ((results[i].happiness <= happiness && results[i].cost > cost) ||
-					(results[i].happiness < happiness && results[i].cost >= cost))
+			if ((results[i].migration <= migration && results[i].cost > cost) ||
+					(results[i].migration < migration && results[i].cost >= cost))
 				results.splice(i, 1);
-		results.push({config, happiness, cost});
+		results.push({config, migration, cost});
 	}
 	return results;
 }