Refactoring: Body.

This commit is contained in:
marley 2023-05-17 17:29:09 -07:00
parent 87779e88ab
commit 5f374f0657
2 changed files with 126 additions and 122 deletions

View file

@ -1,4 +1,4 @@
import type {valuableBody} from '../@types/edsmResponses'; import type { valuableBody } from '../@types/edsmResponses';
import type { import type {
asteroidScan, asteroidScan,
autoScan, autoScan,
@ -7,17 +7,19 @@ import type {
starScan, starScan,
} from '../@types/journalLines'; } from '../@types/journalLines';
import {BodyCodes} from '../data/BodyCodes'; import { BodyCodes } from '../data/BodyCodes';
export interface Body extends starScan<'AutoScan' | 'DetailedScan'>, asteroidScan<'AutoScan' | 'DetailedScan'>, planetScan<'AutoScan' | 'DetailedScan'> {} export interface Body extends starScan<'AutoScan'|'DetailedScan'>,
asteroidScan<'AutoScan'|'DetailedScan'>,
planetScan<'AutoScan'|'DetailedScan'> {}
export class Body { export class Body {
DSSDone: boolean; DSSDone: boolean;
mappedValue: number; mappedValue: number;
constructor( constructor(
journalLine: autoScan | detailedScan | valuableBody | null = null, journalLine: autoScan|detailedScan|valuableBody|null = null,
DSS: boolean = false, DSS: boolean = false,
) { ) {
this.DSSDone = DSS; this.DSSDone = DSS;
@ -28,25 +30,25 @@ export class Body {
this.mappedValue = this.#getValue(); this.mappedValue = this.#getValue();
} }
/* -------------------------------------------------------------------------- isAsteroid ---- */ /* ---------------------------------------------------------------------------- isAsteroid ---- */
isAsteroid(): boolean { isAsteroid(): boolean {
return this.BodyName?.includes('Belt'); return this.BodyName?.includes('Belt');
} }
/* ---------------------------------------------------------------------------- isPlanet ---- */ /* ------------------------------------------------------------------------------ isPlanet ---- */
isPlanet(): boolean { isPlanet(): boolean {
return !!this.PlanetClass; return !!this.PlanetClass;
} }
/* ------------------------------------------------------------------------------ isStar ---- */ /* -------------------------------------------------------------------------------- isStar ---- */
isStar(): boolean { isStar(): boolean {
return !!this.StarType; return !!this.StarType;
} }
/* ---------------------------------------------------------------------------- nameIcon ---- */ /* ------------------------------------------------------------------------------ nameIcon ---- */
nameIcon(): string { nameIcon(): string {
let nameIcon: string = ''; let nameIcon: string = '';
@ -62,13 +64,13 @@ export class Body {
return nameIcon; return nameIcon;
} }
/* -------------------------------------------------------------------------- simpleName ---- */ /* ---------------------------------------------------------------------------- simpleName ---- */
simpleName(): string { simpleName(): string {
return this.BodyName.replace(this.StarSystem, ''); return this.BodyName.replace(this.StarSystem, '');
} }
/* ---------------------------------------------------------------------------- typeIcon ---- */ /* ------------------------------------------------------------------------------ typeIcon ---- */
typeIcon(): string { typeIcon(): string {
let typeIcon: string = ''; let typeIcon: string = '';
@ -96,51 +98,58 @@ export class Body {
return typeIcon; return typeIcon;
} }
/* ---------------------------------------------------------------------------- getValue ---- */ /* ------------------------------------------------------------------------------ getValue ---- */
// https://forums.frontier.co.uk/threads/exploration-value-formulae.232000/ // https://forums.frontier.co.uk/threads/exploration-value-formulae.232000/
// https://github.com/EDSM-NET/Component/blob/master/Body/Value.php // https://github.com/EDSM-NET/Component/blob/master/Body/Value.php
#getValue(): number { #getValue(): number {
let bodyType: number | undefined = undefined; // Asteroids. const bodyType = this.#getNumericalBodyType();
const mass = 'MassEM' in this ? this.MassEM : 1;
if (this.isStar()) { let terraformState = this.#getNumericalTerraformState();
// Typescript feels so stupid sometimes.
bodyType = BodyCodes.starTypes[this.StarType as keyof typeof BodyCodes.starTypes];
} else if (this.isPlanet()) {
bodyType = BodyCodes.planetTypes[this.PlanetClass as keyof typeof BodyCodes.planetTypes];
}
// Asteroids don't have mass.
const mass = (
'MassEM' in this
) ? this.MassEM : 1;
let terraformState: number | undefined = undefined; // Asteroids & Stars.
if ('TerraformState' in this) {
terraformState =
BodyCodes.terraformStates[this.TerraformState as keyof typeof BodyCodes.terraformStates];
}
const firstDiscover = !this.WasDiscovered;
const firstMap = !this.WasMapped;
if (this.isStar()) { if (this.isStar()) {
return this.#appraiseStar(bodyType, mass); return this.#appraiseStar(bodyType, mass);
} else if (this.isPlanet() || this.isAsteroid()) { } else if (this.isPlanet() || this.isAsteroid()) {
// Asteroids are treated as planets for the purpose of value calculation. return this.#appraisePlanet(bodyType, mass, terraformState);
return this.#appraisePlanet(bodyType, mass, terraformState, firstDiscover, firstMap);
} else { } else {
return 0; return 0;
} }
} }
/* ----------------------------------------------------------------------- #appraiseStar ---- */ /* ----------------------------------------------------------------- #getNumericalBodyType ---- */
#appraiseStar(bodyType: number | undefined, mass: number): number { #getNumericalBodyType(): number|undefined {
let code: number|undefined;
if (this.isStar()) {
// Typescript feels so stupid sometimes.
code = BodyCodes.starTypes[this.StarType as keyof typeof BodyCodes.starTypes];
} else if (this.isPlanet()) {
code = BodyCodes.planetTypes[this.PlanetClass as keyof typeof BodyCodes.planetTypes];
}
return code;
}
/* ----------------------------------------------------------- #getNumericalTerraformState ---- */
#getNumericalTerraformState(): number|undefined {
let terraformState: number|undefined;
if ('TerraformState' in this) {
terraformState =
BodyCodes.terraformStates[this.TerraformState as keyof typeof BodyCodes.terraformStates];
}
return terraformState;
}
/* ------------------------------------------------------------------------- #appraiseStar ---- */
#appraiseStar(bodyType: number|undefined, mass: number): number {
let value: number = 1200; let value: number = 1200;
if (bodyType) { if (bodyType) {
@ -154,108 +163,104 @@ export class Body {
value = 22628; value = 22628;
} else if (BodyCodes.superMassiveBlackHole.includes(bodyType)) { } else if (BodyCodes.superMassiveBlackHole.includes(bodyType)) {
value = 33.5678; // Not confirmed in game. value = 33.5678;
} }
} }
return Math.round(value + ( return Math.round(value + (mass * value / 66.25));
mass * value / 66.25
));
} }
/* --------------------------------------------------------------------- #appraisePlanet ---- */ /* ----------------------------------------------------------------------- #appraisePlanet ---- */
#appraisePlanet( #appraisePlanet(
bodyType: number | undefined, bodyType: number|undefined,
mass: number, mass: number,
terraformState: number | undefined, terraformState: number|undefined,
firstDiscover: boolean,
firstMap: boolean,
): number { ): number {
let value: number = this.#calculatePlanetBaseValue(bodyType);
// Base value & terraform bonus calculation. let terraformBonus: number = this.#calculateTerraformBonus(bodyType, terraformState);
let value: number = 300; let mapMultiplier: number = this.#calculateMapMultiplier();
let terraformBonus: number = 0;
// Base terraform bonus.
if (terraformState && terraformState > 0) {
terraformBonus = 93328;
}
if (bodyType) {
// Metal-rich body.
if (BodyCodes.metalRich.includes(bodyType)) {
value = 21790;
if (terraformState && terraformState > 0) {
terraformBonus = 65631;
}
// Ammonia world.
} else if (BodyCodes.ammonia.includes(bodyType)) {
value = 96932;
// Class I gas giant.
} else if (BodyCodes.classIGiant.includes(bodyType)) {
value = 1656;
// High metal content & Class II gas giant.
} else if (
BodyCodes.highMetalContent.includes(bodyType)
|| BodyCodes.classIIGiant.includes(bodyType)
) {
value = 9654;
if (terraformState && terraformState > 0) {
terraformBonus = 100677;
}
// Earth-like world & water world.
} else if (
BodyCodes.earthLike.includes(bodyType)
|| BodyCodes.water.includes(bodyType)
) {
value = 64831;
if (terraformState && terraformState > 0) {
terraformBonus = 116295;
}
// Earth-like always gets a bonus.
if (BodyCodes.earthLike.includes(bodyType)) {
terraformBonus = 116295;
}
}
}
// Mapping multiplier.
let mapMultiplier: number = 3.3333333333;
if (firstDiscover && firstMap) {
mapMultiplier = 3.699622554;
} else if (!firstDiscover && firstMap) {
mapMultiplier = 8.0956;
}
// Efficiency bonus.
mapMultiplier *= 1.25;
// Final calculation. // Final calculation.
const q = 0.56591828; const q = 0.56591828;
value += terraformBonus; value += terraformBonus;
let finalValue = Math.max(( let finalValue = Math.max((value + (value * Math.pow(mass, 0.2) * q)) * mapMultiplier, 500);
value + (
value * Math.pow(mass, 0.2) * q
)
) * mapMultiplier, 500);
// First discovery bonus. // First discovery bonus.
if (firstDiscover) { if (!this.WasDiscovered) {
finalValue *= 2.6; finalValue *= 2.6;
} }
return Math.round(finalValue); return Math.round(finalValue);
} }
/* ------------------------------------------------------------- #calculatePlanetBaseValue ---- */
#calculatePlanetBaseValue(bodyType: number|undefined): number {
let value: number = 300;
if (bodyType) {
if (BodyCodes.metalRich.includes(bodyType)) {
value = 21790;
} else if (BodyCodes.ammonia.includes(bodyType)) {
value = 96932;
} else if (BodyCodes.classIGiant.includes(bodyType)) {
value = 1656;
} else if (
BodyCodes.highMetalContent.includes(bodyType)
|| BodyCodes.classIIGiant.includes(bodyType)
) {
value = 9654;
} else if (BodyCodes.earthLike.includes(bodyType) || BodyCodes.water.includes(bodyType)) {
value = 64831;
}
}
return value;
}
/* -------------------------------------------------------------- #calculateTerraformBonus ---- */
#calculateTerraformBonus(bodyType: number|undefined, terraformState: number|undefined): number {
let bonus: number = 0;
if (terraformState && terraformState > 0) {
bonus = 93328;
}
if (bodyType && (terraformState && terraformState > 0)) {
if (BodyCodes.metalRich.includes(bodyType)) {
bonus = 65631;
} else if (
BodyCodes.highMetalContent.includes(bodyType)
|| BodyCodes.classIIGiant.includes(bodyType)
) {
bonus = 100677;
} else if (BodyCodes.water.includes(bodyType)) {
bonus = 116295;
}
} else if (bodyType && BodyCodes.earthLike.includes(bodyType)) {
bonus = 116295;
}
return bonus;
}
/* --------------------------------------------------------------- #calculateMapMultiplier ---- */
#calculateMapMultiplier(): number {
let multiplier: number = 3.3333333333;
if (!this.WasDiscovered && !this.WasMapped) {
multiplier = 3.699622554;
} else if (this.WasDiscovered && !this.WasMapped) {
multiplier = 8.0956;
}
// Efficiency bonus.
multiplier *= 1.25;
return multiplier;
}
} }

View file

@ -8,7 +8,6 @@ const {statSync, writeFileSync, readFileSync} = require('fs');
const ini = require('ini'); const ini = require('ini');
const os = require('node:os'); const os = require('node:os');
const path = require('node:path'); const path = require('node:path');
const {setTimeout} = require('node:timers/promises');
const xmlJS = require('xml-js'); const xmlJS = require('xml-js');
import {Log} from './Log'; import {Log} from './Log';