jsts corporation

This commit is contained in:
Olivier Gagnon 2021-08-31 03:07:20 -04:00
parent 67be13c6d6
commit 1ae17677c0
18 changed files with 160 additions and 277 deletions

@ -1,47 +1,26 @@
import { AllCorporationStates, import { CorporationState } from "./CorporationState";
CorporationState } from "./CorporationState";
import { import {
CorporationUnlockUpgrade, CorporationUnlockUpgrade,
CorporationUnlockUpgrades } from "./data/CorporationUnlockUpgrades"; CorporationUnlockUpgrades } from "./data/CorporationUnlockUpgrades";
import { CorporationUpgrade, CorporationUpgrades } from "./data/CorporationUpgrades"; import { CorporationUpgrade, CorporationUpgrades } from "./data/CorporationUpgrades";
import { EmployeePositions } from "./EmployeePositions";
import { Industries,
IndustryStartingCosts,
IndustryResearchTrees } from "./IndustryData";
import { IndustryUpgrades } from "./IndustryUpgrades";
import { Material } from "./Material";
import { MaterialSizes } from "./MaterialSizes";
import { Product } from "./Product";
import { ResearchMap } from "./ResearchMap";
import { Warehouse } from "./Warehouse"; import { Warehouse } from "./Warehouse";
import { OfficeSpace } from "./OfficeSpace";
import { CorporationConstants } from "./data/Constants"; import { CorporationConstants } from "./data/Constants";
import { Industry } from "./Industry"; import { Industry } from "./Industry";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { showLiterature } from "../Literature/LiteratureHelpers"; import { showLiterature } from "../Literature/LiteratureHelpers";
import { LiteratureNames } from "../Literature/data/LiteratureNames"; import { LiteratureNames } from "../Literature/data/LiteratureNames";
import { CityName } from "../Locations/data/CityNames";
import { IPlayer } from "../PersonObjects/IPlayer"; import { IPlayer } from "../PersonObjects/IPlayer";
import { numeralWrapper } from "../ui/numeralFormat";
import { Page, routing } from "../ui/navigationTracking"; import { Page, routing } from "../ui/navigationTracking";
import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { dialogBoxCreate } from "../../utils/DialogBox";
import { Reviver, import { Reviver,
Generic_toJSON, Generic_toJSON,
Generic_fromJSON } from "../../utils/JSONReviver"; Generic_fromJSON } from "../../utils/JSONReviver";
import { appendLineBreaks } from "../../utils/uiHelpers/appendLineBreaks";
import { createElement } from "../../utils/uiHelpers/createElement"; import { createElement } from "../../utils/uiHelpers/createElement";
import { createPopup } from "../../utils/uiHelpers/createPopup";
import { createPopupCloseButton } from "../../utils/uiHelpers/createPopupCloseButton";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { isString } from "../../utils/helpers/isString"; import { isString } from "../../utils/helpers/isString";
import { KEY } from "../../utils/helpers/keyCodes";
import { removeElement } from "../../utils/uiHelpers/removeElement";
import { removeElementById } from "../../utils/uiHelpers/removeElementById"; import { removeElementById } from "../../utils/uiHelpers/removeElementById";
// UI Related Imports // UI Related Imports
@ -52,16 +31,6 @@ import { CorporationRouting } from "./ui/Routing";
import Decimal from "decimal.js"; import Decimal from "decimal.js";
/* Constants */
export const INITIALSHARES = 1e9; //Total number of shares you have at your company
export const SHARESPERPRICEUPDATE = 1e6; //When selling large number of shares, price is dynamically updated for every batch of this amount
export const CyclesPerMarketCycle = 50;
export const CyclesPerIndustryStateCycle = CyclesPerMarketCycle / AllCorporationStates.length;
export const SecsPerMarketCycle = CyclesPerMarketCycle / 5;
export const DividendMaxPercentage = 50;
interface IParams { interface IParams {
name?: string; name?: string;
} }
@ -107,7 +76,7 @@ export class Corporation {
this.upgradeMultipliers = Array(numUpgrades).fill(1); this.upgradeMultipliers = Array(numUpgrades).fill(1);
} }
addFunds(amt: number) { addFunds(amt: number): void {
if(!isFinite(amt)) { if(!isFinite(amt)) {
console.error('Trying to add invalid amount of funds. Report to a developper.'); console.error('Trying to add invalid amount of funds. Report to a developper.');
return; return;
@ -123,11 +92,11 @@ export class Corporation {
this.storedCycles += numCycles; this.storedCycles += numCycles;
} }
process(player: IPlayer) { process(player: IPlayer): void {
if (this.storedCycles >= CyclesPerIndustryStateCycle) { if (this.storedCycles >= CorporationConstants.CyclesPerIndustryStateCycle) {
const state = this.getState(); const state = this.getState();
const marketCycles = 1; const marketCycles = 1;
const gameCycles = (marketCycles * CyclesPerIndustryStateCycle); const gameCycles = (marketCycles * CorporationConstants.CyclesPerIndustryStateCycle);
this.storedCycles -= gameCycles; this.storedCycles -= gameCycles;
this.divisions.forEach((ind) => { this.divisions.forEach((ind) => {
@ -152,8 +121,8 @@ export class Corporation {
this.revenue = this.revenue.plus(ind.lastCycleRevenue); this.revenue = this.revenue.plus(ind.lastCycleRevenue);
this.expenses = this.expenses.plus(ind.lastCycleExpenses); this.expenses = this.expenses.plus(ind.lastCycleExpenses);
}); });
var profit = this.revenue.minus(this.expenses); const profit = this.revenue.minus(this.expenses);
const cycleProfit = profit.times(marketCycles * SecsPerMarketCycle); const cycleProfit = profit.times(marketCycles * CorporationConstants.SecsPerMarketCycle);
if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) { if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) {
dialogBoxCreate("There was an error calculating your Corporations funds and they got reset to 0. " + dialogBoxCreate("There was an error calculating your Corporations funds and they got reset to 0. " +
"This is a bug. Please report to game developer.<br><br>" + "This is a bug. Please report to game developer.<br><br>" +
@ -164,7 +133,7 @@ export class Corporation {
// Process dividends // Process dividends
if (this.dividendPercentage > 0 && cycleProfit > 0) { if (this.dividendPercentage > 0 && cycleProfit > 0) {
// Validate input again, just to be safe // Validate input again, just to be safe
if (isNaN(this.dividendPercentage) || this.dividendPercentage < 0 || this.dividendPercentage > DividendMaxPercentage) { if (isNaN(this.dividendPercentage) || this.dividendPercentage < 0 || this.dividendPercentage > CorporationConstants.DividendMaxPercentage) {
console.error(`Invalid Corporation dividend percentage: ${this.dividendPercentage}`); console.error(`Invalid Corporation dividend percentage: ${this.dividendPercentage}`);
} else { } else {
const totalDividends = (this.dividendPercentage / 100) * cycleProfit; const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
@ -188,8 +157,8 @@ export class Corporation {
} }
} }
determineValuation() { determineValuation(): number {
var val, profit = (this.revenue.minus(this.expenses)).toNumber(); let val, profit = (this.revenue.minus(this.expenses)).toNumber();
if (this.public) { if (this.public) {
// Account for dividends // Account for dividends
if (this.dividendPercentage > 0) { if (this.dividendPercentage > 0) {
@ -212,13 +181,13 @@ export class Corporation {
return val * BitNodeMultipliers.CorporationValuation; return val * BitNodeMultipliers.CorporationValuation;
} }
getTargetSharePrice() { getTargetSharePrice(): number {
// Note: totalShares - numShares is not the same as issuedShares because // Note: totalShares - numShares is not the same as issuedShares because
// issuedShares does not account for private investors // issuedShares does not account for private investors
return this.determineValuation() / (2 * (this.totalShares - this.numShares) + 1); return this.determineValuation() / (2 * (this.totalShares - this.numShares) + 1);
} }
updateSharePrice() { updateSharePrice(): void {
const targetPrice = this.getTargetSharePrice(); const targetPrice = this.getTargetSharePrice();
if (this.sharePrice <= targetPrice) { if (this.sharePrice <= targetPrice) {
this.sharePrice *= (1 + (Math.random() * 0.01)); this.sharePrice *= (1 + (Math.random() * 0.01));
@ -228,7 +197,7 @@ export class Corporation {
if (this.sharePrice <= 0.01) {this.sharePrice = 0.01;} if (this.sharePrice <= 0.01) {this.sharePrice = 0.01;}
} }
immediatelyUpdateSharePrice() { immediatelyUpdateSharePrice(): void {
this.sharePrice = this.getTargetSharePrice(); this.sharePrice = this.getTargetSharePrice();
} }
@ -242,7 +211,7 @@ export class Corporation {
let sharesSold = 0; let sharesSold = 0;
let profit = 0; let profit = 0;
const maxIterations = Math.ceil(numShares / SHARESPERPRICEUPDATE); const maxIterations = Math.ceil(numShares / CorporationConstants.SHARESPERPRICEUPDATE);
if (isNaN(maxIterations) || maxIterations > 10e6) { if (isNaN(maxIterations) || maxIterations > 10e6) {
console.error(`Something went wrong or unexpected when calculating share sale. Maxiterations calculated to be ${maxIterations}`); console.error(`Something went wrong or unexpected when calculating share sale. Maxiterations calculated to be ${maxIterations}`);
return [0, 0, 0]; return [0, 0, 0];
@ -255,7 +224,7 @@ export class Corporation {
break; break;
} else { } else {
profit += (sharePrice * sharesUntilUpdate); profit += (sharePrice * sharesUntilUpdate);
sharesUntilUpdate = SHARESPERPRICEUPDATE; sharesUntilUpdate = CorporationConstants.SHARESPERPRICEUPDATE;
sharesTracker -= sharesUntilUpdate; sharesTracker -= sharesUntilUpdate;
sharesSold += sharesUntilUpdate; sharesSold += sharesUntilUpdate;
@ -267,7 +236,7 @@ export class Corporation {
return [profit, sharePrice, sharesUntilUpdate]; return [profit, sharePrice, sharesUntilUpdate];
} }
convertCooldownToString(cd: number) { convertCooldownToString(cd: number): string {
// The cooldown value is based on game cycles. Convert to a simple string // The cooldown value is based on game cycles. Convert to a simple string
const seconds = cd / 5; const seconds = cd / 5;
@ -306,11 +275,11 @@ export class Corporation {
//Levelable upgrades //Levelable upgrades
upgrade(upgrade: CorporationUpgrade): void { upgrade(upgrade: CorporationUpgrade): void {
var upgN = upgrade[0], basePrice = upgrade[1], priceMult = upgrade[2], const upgN = upgrade[0], basePrice = upgrade[1], priceMult = upgrade[2],
upgradeAmt = upgrade[3]; //Amount by which the upgrade multiplier gets increased (additive) upgradeAmt = upgrade[3]; //Amount by which the upgrade multiplier gets increased (additive)
while (this.upgrades.length <= upgN) {this.upgrades.push(0);} while (this.upgrades.length <= upgN) {this.upgrades.push(0);}
while (this.upgradeMultipliers.length <= upgN) {this.upgradeMultipliers.push(1);} while (this.upgradeMultipliers.length <= upgN) {this.upgradeMultipliers.push(1);}
var totalCost = basePrice * Math.pow(priceMult, this.upgrades[upgN]); const totalCost = basePrice * Math.pow(priceMult, this.upgrades[upgN]);
if (this.funds.lt(totalCost)) { if (this.funds.lt(totalCost)) {
dialogBoxCreate("You don't have enough funds to purchase this!"); dialogBoxCreate("You don't have enough funds to purchase this!");
return; return;
@ -323,9 +292,9 @@ export class Corporation {
//If storage size is being updated, update values in Warehouse objects //If storage size is being updated, update values in Warehouse objects
if (upgN === 1) { if (upgN === 1) {
for (var i = 0; i < this.divisions.length; ++i) { for (let i = 0; i < this.divisions.length; ++i) {
var industry = this.divisions[i]; const industry = this.divisions[i];
for (var city in industry.warehouses) { for (const city in industry.warehouses) {
if (industry.warehouses.hasOwnProperty(city) && industry.warehouses[city] instanceof Warehouse) { if (industry.warehouses.hasOwnProperty(city) && industry.warehouses[city] instanceof Warehouse) {
industry.warehouses[city].updateSize(this, industry); industry.warehouses[city].updateSize(this, industry);
} }
@ -334,64 +303,64 @@ export class Corporation {
} }
} }
getProductionMultiplier() { getProductionMultiplier(): number {
var mult = this.upgradeMultipliers[0]; const mult = this.upgradeMultipliers[0];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
getStorageMultiplier() { getStorageMultiplier(): number {
var mult = this.upgradeMultipliers[1]; const mult = this.upgradeMultipliers[1];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
getDreamSenseGain() { getDreamSenseGain(): number {
var gain = this.upgradeMultipliers[2] - 1; const gain = this.upgradeMultipliers[2] - 1;
return gain <= 0 ? 0 : gain; return gain <= 0 ? 0 : gain;
} }
getAdvertisingMultiplier() { getAdvertisingMultiplier(): number {
var mult = this.upgradeMultipliers[3]; const mult = this.upgradeMultipliers[3];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
getEmployeeCreMultiplier() { getEmployeeCreMultiplier(): number {
var mult = this.upgradeMultipliers[4]; const mult = this.upgradeMultipliers[4];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
getEmployeeChaMultiplier() { getEmployeeChaMultiplier(): number {
var mult = this.upgradeMultipliers[5]; const mult = this.upgradeMultipliers[5];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
getEmployeeIntMultiplier() { getEmployeeIntMultiplier(): number {
var mult = this.upgradeMultipliers[6]; const mult = this.upgradeMultipliers[6];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
getEmployeeEffMultiplier() { getEmployeeEffMultiplier(): number {
var mult = this.upgradeMultipliers[7]; const mult = this.upgradeMultipliers[7];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
getSalesMultiplier() { getSalesMultiplier(): number {
var mult = this.upgradeMultipliers[8]; const mult = this.upgradeMultipliers[8];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
getScientificResearchMultiplier() { getScientificResearchMultiplier(): number {
var mult = this.upgradeMultipliers[9]; const mult = this.upgradeMultipliers[9];
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;} if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
} }
// Adds the Corporation Handbook (Starter Guide) to the player's home computer. // Adds the Corporation Handbook (Starter Guide) to the player's home computer.
// This is a lit file that gives introductory info to the player // This is a lit file that gives introductory info to the player
// This occurs when the player clicks the "Getting Started Guide" button on the overview panel // This occurs when the player clicks the "Getting Started Guide" button on the overview panel
getStarterGuide(player: IPlayer) { getStarterGuide(player: IPlayer): void {
// Check if player already has Corporation Handbook // Check if player already has Corporation Handbook
let homeComp = player.getHomeComputer(), const homeComp = player.getHomeComputer();
hasHandbook = false, let hasHandbook = false;
handbookFn = LiteratureNames.CorporationManagementHandbook; const handbookFn = LiteratureNames.CorporationManagementHandbook;
for (let i = 0; i < homeComp.messages.length; ++i) { for (let i = 0; i < homeComp.messages.length; ++i) {
if (isString(homeComp.messages[i]) && homeComp.messages[i] === handbookFn) { if (isString(homeComp.messages[i]) && homeComp.messages[i] === handbookFn) {
hasHandbook = true; hasHandbook = true;
@ -401,10 +370,10 @@ export class Corporation {
if (!hasHandbook) { homeComp.messages.push(handbookFn); } if (!hasHandbook) { homeComp.messages.push(handbookFn); }
showLiterature(handbookFn); showLiterature(handbookFn);
return false; return;
} }
createUI(player: IPlayer) { createUI(player: IPlayer): void {
companyManagementDiv = createElement("div", { companyManagementDiv = createElement("div", {
id:"cmpy-mgmt-container", id:"cmpy-mgmt-container",
position:"fixed", position:"fixed",
@ -419,7 +388,7 @@ export class Corporation {
this.rerender(player); this.rerender(player);
} }
rerender(player: IPlayer) { rerender(player: IPlayer): void {
if (companyManagementDiv == null || corpRouting == null) { if (companyManagementDiv == null || corpRouting == null) {
console.warn(`Corporation.rerender() called when companyManagementDiv, corpRouting, or eventHandler is null`); console.warn(`Corporation.rerender() called when companyManagementDiv, corpRouting, or eventHandler is null`);
return; return;
@ -433,7 +402,7 @@ export class Corporation {
/>, companyManagementDiv); />, companyManagementDiv);
} }
clearUI() { clearUI(): void {
if (companyManagementDiv instanceof HTMLElement) { if (companyManagementDiv instanceof HTMLElement) {
ReactDOM.unmountComponentAtNode(companyManagementDiv); ReactDOM.unmountComponentAtNode(companyManagementDiv);
removeElementById(companyManagementDiv.id); removeElementById(companyManagementDiv.id);

@ -120,7 +120,7 @@ export class Industry {
this.init(); this.init();
} }
init() { init(): void {
//Set the unique properties of an industry (how much its affected by real estate/scientific research, etc.) //Set the unique properties of an industry (how much its affected by real estate/scientific research, etc.)
const startingCost = IndustryStartingCosts[this.type]; const startingCost = IndustryStartingCosts[this.type];
if(startingCost === undefined) if(startingCost === undefined)
@ -323,8 +323,8 @@ export class Industry {
} }
} }
getProductDescriptionText() { getProductDescriptionText(): string {
if (!this.makesProducts) {return;} if (!this.makesProducts) return '';
switch (this.type) { switch (this.type) {
case Industries.Food: case Industries.Food:
return "create and manage restaurants"; return "create and manage restaurants";
@ -349,7 +349,7 @@ export class Industry {
} }
} }
getMaximumNumberProducts() { getMaximumNumberProducts(): number {
if (!this.makesProducts) return 0; if (!this.makesProducts) return 0;
// Calculate additional number of allowed Products from Research/Upgrades // Calculate additional number of allowed Products from Research/Upgrades
@ -360,24 +360,24 @@ export class Industry {
return CorporationConstants.BaseMaxProducts + additional; return CorporationConstants.BaseMaxProducts + additional;
} }
hasMaximumNumberProducts() { hasMaximumNumberProducts(): boolean {
return (Object.keys(this.products).length >= this.getMaximumNumberProducts()); return (Object.keys(this.products).length >= this.getMaximumNumberProducts());
} }
//Calculates the values that factor into the production and properties of //Calculates the values that factor into the production and properties of
//materials/products (such as quality, etc.) //materials/products (such as quality, etc.)
calculateProductionFactors() { calculateProductionFactors(): void {
var multSum = 0; let multSum = 0;
for (var i = 0; i < CorporationConstants.Cities.length; ++i) { for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
var city = CorporationConstants.Cities[i]; const city = CorporationConstants.Cities[i];
var warehouse = this.warehouses[city]; const warehouse = this.warehouses[city];
if (!(warehouse instanceof Warehouse)) { if (!(warehouse instanceof Warehouse)) {
continue; continue;
} }
var materials = warehouse.materials; const materials = warehouse.materials;
var cityMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) * const cityMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) *
Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) * Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) *
Math.pow(0.002 * materials.Robots.qty+1, this.robFac) * Math.pow(0.002 * materials.Robots.qty+1, this.robFac) *
Math.pow(0.002 * materials.AICores.qty+1, this.aiFac); Math.pow(0.002 * materials.AICores.qty+1, this.aiFac);
@ -390,9 +390,9 @@ export class Industry {
updateWarehouseSizeUsed(warehouse: Warehouse): void { updateWarehouseSizeUsed(warehouse: Warehouse): void {
warehouse.updateMaterialSizeUsed(); warehouse.updateMaterialSizeUsed();
for (var prodName in this.products) { for (const prodName in this.products) {
if (this.products.hasOwnProperty(prodName)) { if (this.products.hasOwnProperty(prodName)) {
var prod = this.products[prodName]; const prod = this.products[prodName];
warehouse.sizeUsed += (prod.data[warehouse.loc][0] * prod.siz); warehouse.sizeUsed += (prod.data[warehouse.loc][0] * prod.siz);
if (prod.data[warehouse.loc][0] > 0) { if (prod.data[warehouse.loc][0] > 0) {
warehouse.breakdown += (prodName + ": " + formatNumber(prod.data[warehouse.loc][0] * prod.siz, 0) + "<br>"); warehouse.breakdown += (prodName + ": " + formatNumber(prod.data[warehouse.loc][0] * prod.siz, 0) + "<br>");
@ -401,7 +401,7 @@ export class Industry {
} }
} }
process(marketCycles=1, state: string, company: any) { process(marketCycles=1, state: string, company: any): void {
this.state = state; this.state = state;
//At the start of a cycle, store and reset revenue/expenses //At the start of a cycle, store and reset revenue/expenses
@ -423,8 +423,8 @@ export class Industry {
if (this.lastCycleRevenue.gt(0)) {this.newInd = false;} if (this.lastCycleRevenue.gt(0)) {this.newInd = false;}
// Process offices (and the employees in them) // Process offices (and the employees in them)
var employeeSalary = 0; let employeeSalary = 0;
for (var officeLoc in this.offices) { for (const officeLoc in this.offices) {
if (this.offices[officeLoc] instanceof OfficeSpace) { if (this.offices[officeLoc] instanceof OfficeSpace) {
employeeSalary += this.offices[officeLoc].process(marketCycles, {industry:this, corporation:company}); employeeSalary += this.offices[officeLoc].process(marketCycles, {industry:this, corporation:company});
} }
@ -432,7 +432,7 @@ export class Industry {
this.thisCycleExpenses = this.thisCycleExpenses.plus(employeeSalary); this.thisCycleExpenses = this.thisCycleExpenses.plus(employeeSalary);
// Process change in demand/competition of materials/products // Process change in demand/competition of materials/products
this.processMaterialMarket(marketCycles); this.processMaterialMarket();
this.processProductMarket(marketCycles); this.processProductMarket(marketCycles);
// Process loss of popularity // Process loss of popularity
@ -440,7 +440,7 @@ export class Industry {
this.popularity = Math.max(0, this.popularity); this.popularity = Math.max(0, this.popularity);
// Process Dreamsense gains // Process Dreamsense gains
var popularityGain = company.getDreamSenseGain(), awarenessGain = popularityGain * 4; const popularityGain = company.getDreamSenseGain(), awarenessGain = popularityGain * 4;
if (popularityGain > 0) { if (popularityGain > 0) {
this.popularity += (popularityGain * marketCycles); this.popularity += (popularityGain * marketCycles);
this.awareness += (awarenessGain * marketCycles); this.awareness += (awarenessGain * marketCycles);
@ -465,24 +465,24 @@ export class Industry {
} }
// Process change in demand and competition for this industry's materials // Process change in demand and competition for this industry's materials
processMaterialMarket(marketCycles=1) { processMaterialMarket(): void {
//References to prodMats and reqMats //References to prodMats and reqMats
var reqMats = this.reqMats, prodMats = this.prodMats; const reqMats = this.reqMats, prodMats = this.prodMats;
//Only 'process the market' for materials that this industry deals with //Only 'process the market' for materials that this industry deals with
for (var i = 0; i < CorporationConstants.Cities.length; ++i) { for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
//If this industry has a warehouse in this city, process the market //If this industry has a warehouse in this city, process the market
//for every material this industry requires or produces //for every material this industry requires or produces
if (this.warehouses[CorporationConstants.Cities[i]] instanceof Warehouse) { if (this.warehouses[CorporationConstants.Cities[i]] instanceof Warehouse) {
var wh = this.warehouses[CorporationConstants.Cities[i]]; const wh = this.warehouses[CorporationConstants.Cities[i]];
for (var name in reqMats) { for (const name in reqMats) {
if (reqMats.hasOwnProperty(name)) { if (reqMats.hasOwnProperty(name)) {
wh.materials[name].processMarket(); wh.materials[name].processMarket();
} }
} }
//Produced materials are stored in an array //Produced materials are stored in an array
for (var foo = 0; foo < prodMats.length; ++foo) { for (let foo = 0; foo < prodMats.length; ++foo) {
wh.materials[prodMats[foo]].processMarket(); wh.materials[prodMats[foo]].processMarket();
} }
@ -496,13 +496,13 @@ export class Industry {
} }
// Process change in demand and competition for this industry's products // Process change in demand and competition for this industry's products
processProductMarket(marketCycles=1) { processProductMarket(marketCycles=1): void {
// Demand gradually decreases, and competition gradually increases // Demand gradually decreases, and competition gradually increases
for (const name in this.products) { for (const name in this.products) {
if (this.products.hasOwnProperty(name)) { if (this.products.hasOwnProperty(name)) {
const product = this.products[name]; const product = this.products[name];
let change = getRandomInt(0, 3) * 0.0004; let change = getRandomInt(0, 3) * 0.0004;
if (change === 0) { continue; } if (change === 0) continue;
if (this.type === Industries.Pharmaceutical || this.type === Industries.Software || if (this.type === Industries.Pharmaceutical || this.type === Industries.Software ||
this.type === Industries.Robotics) { this.type === Industries.Robotics) {
@ -519,20 +519,20 @@ export class Industry {
//Process production, purchase, and import/export of materials //Process production, purchase, and import/export of materials
processMaterials(marketCycles=1, company: any): [number, number] { processMaterials(marketCycles=1, company: any): [number, number] {
var revenue = 0, expenses = 0; let revenue = 0, expenses = 0;
this.calculateProductionFactors(); this.calculateProductionFactors();
//At the start of the export state, set the imports of everything to 0 //At the start of the export state, set the imports of everything to 0
if (this.state === "EXPORT") { if (this.state === "EXPORT") {
for (let i = 0; i < CorporationConstants.Cities.length; ++i) { for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
var city = CorporationConstants.Cities[i], office = this.offices[city]; const city = CorporationConstants.Cities[i];
if (!(this.warehouses[city] instanceof Warehouse)) { if (!(this.warehouses[city] instanceof Warehouse)) {
continue; continue;
} }
var warehouse = this.warehouses[city]; const warehouse = this.warehouses[city];
for (var matName in warehouse.materials) { for (const matName in warehouse.materials) {
if (warehouse.materials.hasOwnProperty(matName)) { if (warehouse.materials.hasOwnProperty(matName)) {
var mat = warehouse.materials[matName]; const mat = warehouse.materials[matName];
mat.imp = 0; mat.imp = 0;
} }
} }
@ -540,20 +540,20 @@ export class Industry {
} }
for (let i = 0; i < CorporationConstants.Cities.length; ++i) { for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
var city = CorporationConstants.Cities[i], office = this.offices[city]; const city = CorporationConstants.Cities[i], office = this.offices[city];
if (this.warehouses[city] instanceof Warehouse) { if (this.warehouses[city] instanceof Warehouse) {
var warehouse = this.warehouses[city]; const warehouse = this.warehouses[city];
switch(this.state) { switch(this.state) {
case "PURCHASE": case "PURCHASE":
/* Process purchase of materials */ /* Process purchase of materials */
for (var matName in warehouse.materials) { for (const matName in warehouse.materials) {
if (warehouse.materials.hasOwnProperty(matName)) { if (warehouse.materials.hasOwnProperty(matName)) {
(function(matName, ind) { (function(matName, ind) {
var mat = warehouse.materials[matName]; const mat = warehouse.materials[matName];
var buyAmt, maxAmt; let buyAmt, maxAmt;
if (warehouse.smartSupplyEnabled && Object.keys(ind.reqMats).includes(matName)) { if (warehouse.smartSupplyEnabled && Object.keys(ind.reqMats).includes(matName)) {
//Smart supply tracker is stored as per second rate //Smart supply tracker is stored as per second rate
mat.buy = ind.reqMats[matName] * warehouse.smartSupplyStore; mat.buy = ind.reqMats[matName] * warehouse.smartSupplyStore;
@ -583,10 +583,10 @@ export class Industry {
/* Process production of materials */ /* Process production of materials */
if (this.prodMats.length > 0) { if (this.prodMats.length > 0) {
var mat = warehouse.materials[this.prodMats[0]]; const mat = warehouse.materials[this.prodMats[0]];
//Calculate the maximum production of this material based //Calculate the maximum production of this material based
//on the office's productivity //on the office's productivity
var maxProd = this.getOfficeProductivity(office) const maxProd = this.getOfficeProductivity(office)
* this.prodMult // Multiplier from materials * this.prodMult // Multiplier from materials
* company.getProductionMultiplier() * company.getProductionMultiplier()
* this.getProductionMultiplier(); // Multiplier from Research * this.getProductionMultiplier(); // Multiplier from Research
@ -601,17 +601,17 @@ export class Industry {
prod *= (CorporationConstants.SecsPerMarketCycle * marketCycles); //Convert production from per second to per market cycle prod *= (CorporationConstants.SecsPerMarketCycle * marketCycles); //Convert production from per second to per market cycle
// Calculate net change in warehouse storage making the produced materials will cost // Calculate net change in warehouse storage making the produced materials will cost
var totalMatSize = 0; let totalMatSize = 0;
for (let tmp = 0; tmp < this.prodMats.length; ++tmp) { for (let tmp = 0; tmp < this.prodMats.length; ++tmp) {
totalMatSize += (MaterialSizes[this.prodMats[tmp]]); totalMatSize += (MaterialSizes[this.prodMats[tmp]]);
} }
for (const reqMatName in this.reqMats) { for (const reqMatName in this.reqMats) {
var normQty = this.reqMats[reqMatName]; const normQty = this.reqMats[reqMatName];
totalMatSize -= (MaterialSizes[reqMatName] * normQty); totalMatSize -= (MaterialSizes[reqMatName] * normQty);
} }
// If not enough space in warehouse, limit the amount of produced materials // If not enough space in warehouse, limit the amount of produced materials
if (totalMatSize > 0) { if (totalMatSize > 0) {
var maxAmt = Math.floor((warehouse.size - warehouse.sizeUsed) / totalMatSize); const maxAmt = Math.floor((warehouse.size - warehouse.sizeUsed) / totalMatSize);
prod = Math.min(maxAmt, prod); prod = Math.min(maxAmt, prod);
} }
@ -621,10 +621,10 @@ export class Industry {
warehouse.smartSupplyStore += (prod / (CorporationConstants.SecsPerMarketCycle * marketCycles)); warehouse.smartSupplyStore += (prod / (CorporationConstants.SecsPerMarketCycle * marketCycles));
// Make sure we have enough resource to make our materials // Make sure we have enough resource to make our materials
var producableFrac = 1; let producableFrac = 1;
for (var reqMatName in this.reqMats) { for (const reqMatName in this.reqMats) {
if (this.reqMats.hasOwnProperty(reqMatName)) { if (this.reqMats.hasOwnProperty(reqMatName)) {
var req = this.reqMats[reqMatName] * prod; const req = this.reqMats[reqMatName] * prod;
if (warehouse.materials[reqMatName].qty < req) { if (warehouse.materials[reqMatName].qty < req) {
producableFrac = Math.min(producableFrac, warehouse.materials[reqMatName].qty / req); producableFrac = Math.min(producableFrac, warehouse.materials[reqMatName].qty / req);
} }
@ -635,7 +635,7 @@ export class Industry {
// Make our materials if they are producable // Make our materials if they are producable
if (producableFrac > 0 && prod > 0) { if (producableFrac > 0 && prod > 0) {
for (const reqMatName in this.reqMats) { for (const reqMatName in this.reqMats) {
var reqMatQtyNeeded = (this.reqMats[reqMatName] * prod * producableFrac); const reqMatQtyNeeded = (this.reqMats[reqMatName] * prod * producableFrac);
warehouse.materials[reqMatName].qty -= reqMatQtyNeeded; warehouse.materials[reqMatName].qty -= reqMatQtyNeeded;
warehouse.materials[reqMatName].prd = 0; warehouse.materials[reqMatName].prd = 0;
warehouse.materials[reqMatName].prd -= reqMatQtyNeeded / (CorporationConstants.SecsPerMarketCycle * marketCycles); warehouse.materials[reqMatName].prd -= reqMatQtyNeeded / (CorporationConstants.SecsPerMarketCycle * marketCycles);
@ -672,9 +672,9 @@ export class Industry {
case "SALE": case "SALE":
/* Process sale of materials */ /* Process sale of materials */
for (var matName in warehouse.materials) { for (const matName in warehouse.materials) {
if (warehouse.materials.hasOwnProperty(matName)) { if (warehouse.materials.hasOwnProperty(matName)) {
var mat = warehouse.materials[matName]; const mat = warehouse.materials[matName];
if (mat.sCost < 0 || mat.sllman[0] === false) { if (mat.sCost < 0 || mat.sllman[0] === false) {
mat.sll = 0; mat.sll = 0;
continue; continue;
@ -687,7 +687,7 @@ export class Industry {
// Determine the cost that the material will be sold at // Determine the cost that the material will be sold at
const markupLimit = mat.getMarkupLimit(); const markupLimit = mat.getMarkupLimit();
var sCost; let sCost;
if (mat.marketTa2) { if (mat.marketTa2) {
const prod = mat.prd; const prod = mat.prd;
@ -746,17 +746,17 @@ export class Industry {
} }
} }
var maxSell = (mat.qlt + .001) const maxSell = (mat.qlt + .001)
* marketFactor * marketFactor
* markup * markup
* businessFactor * businessFactor
* company.getSalesMultiplier() * company.getSalesMultiplier()
* advertisingFactor * advertisingFactor
* this.getSalesMultiplier(); * this.getSalesMultiplier();
var sellAmt; let sellAmt;
if (isString(mat.sllman[1])) { if (isString(mat.sllman[1])) {
//Dynamically evaluated //Dynamically evaluated
var tmp = mat.sllman[1].replace(/MAX/g, maxSell); let tmp = mat.sllman[1].replace(/MAX/g, maxSell);
tmp = tmp.replace(/PROD/g, mat.prd); tmp = tmp.replace(/PROD/g, mat.prd);
try { try {
sellAmt = eval(tmp); sellAmt = eval(tmp);
@ -794,13 +794,13 @@ export class Industry {
break; break;
case "EXPORT": case "EXPORT":
for (var matName in warehouse.materials) { for (const matName in warehouse.materials) {
if (warehouse.materials.hasOwnProperty(matName)) { if (warehouse.materials.hasOwnProperty(matName)) {
var mat = warehouse.materials[matName]; const mat = warehouse.materials[matName];
mat.totalExp = 0; //Reset export mat.totalExp = 0; //Reset export
for (var expI = 0; expI < mat.exp.length; ++expI) { for (let expI = 0; expI < mat.exp.length; ++expI) {
var exp = mat.exp[expI]; const exp = mat.exp[expI];
var amt = exp.amt.replace(/MAX/g, mat.qty / (CorporationConstants.SecsPerMarketCycle * marketCycles)); let amt = exp.amt.replace(/MAX/g, mat.qty / (CorporationConstants.SecsPerMarketCycle * marketCycles));
try { try {
amt = eval(amt); amt = eval(amt);
} catch(e) { } catch(e) {
@ -822,10 +822,10 @@ export class Industry {
if (amt === 0) { if (amt === 0) {
break; //None left break; //None left
} }
for (var foo = 0; foo < company.divisions.length; ++foo) { for (let foo = 0; foo < company.divisions.length; ++foo) {
if (company.divisions[foo].name === exp.ind) { if (company.divisions[foo].name === exp.ind) {
var expIndustry = company.divisions[foo]; const expIndustry = company.divisions[foo];
var expWarehouse = expIndustry.warehouses[exp.city]; const expWarehouse = expIndustry.warehouses[exp.city];
if (!(expWarehouse instanceof Warehouse)) { if (!(expWarehouse instanceof Warehouse)) {
console.error(`Invalid export! ${expIndustry.name} ${exp.city}`); console.error(`Invalid export! ${expIndustry.name} ${exp.city}`);
break; break;
@ -837,7 +837,7 @@ export class Industry {
// affect revenue so just return 0's // affect revenue so just return 0's
return [0, 0]; return [0, 0];
} else { } else {
var maxAmt = Math.floor((expWarehouse.size - expWarehouse.sizeUsed) / MaterialSizes[matName]); const maxAmt = Math.floor((expWarehouse.size - expWarehouse.sizeUsed) / MaterialSizes[matName]);
amt = Math.min(maxAmt, amt); amt = Math.min(maxAmt, amt);
} }
expWarehouse.materials[matName].imp += (amt / (CorporationConstants.SecsPerMarketCycle * marketCycles)); expWarehouse.materials[matName].imp += (amt / (CorporationConstants.SecsPerMarketCycle * marketCycles));
@ -881,7 +881,8 @@ export class Industry {
//Process production & sale of this industry's FINISHED products (including all of their stats) //Process production & sale of this industry's FINISHED products (including all of their stats)
processProducts(marketCycles=1, corporation: any): [number, number] { processProducts(marketCycles=1, corporation: any): [number, number] {
var revenue = 0, expenses = 0; let revenue = 0;
const expenses = 0;
//Create products //Create products
if (this.state === "PRODUCTION") { if (this.state === "PRODUCTION") {
@ -913,9 +914,9 @@ export class Industry {
} }
//Produce Products //Produce Products
for (var prodName in this.products) { for (const prodName in this.products) {
if (this.products.hasOwnProperty(prodName)) { if (this.products.hasOwnProperty(prodName)) {
var prod = this.products[prodName]; const prod = this.products[prodName];
if (prod instanceof Product && prod.fin) { if (prod instanceof Product && prod.fin) {
revenue += this.processProduct(marketCycles, prod, corporation); revenue += this.processProduct(marketCycles, prod, corporation);
} }
@ -928,14 +929,14 @@ export class Industry {
processProduct(marketCycles=1, product: Product, corporation: any): number { processProduct(marketCycles=1, product: Product, corporation: any): number {
let totalProfit = 0; let totalProfit = 0;
for (let i = 0; i < CorporationConstants.Cities.length; ++i) { for (let i = 0; i < CorporationConstants.Cities.length; ++i) {
let city = CorporationConstants.Cities[i], office = this.offices[city], warehouse = this.warehouses[city]; const city = CorporationConstants.Cities[i], office = this.offices[city], warehouse = this.warehouses[city];
if (warehouse instanceof Warehouse) { if (warehouse instanceof Warehouse) {
switch(this.state) { switch(this.state) {
case "PRODUCTION": { case "PRODUCTION": {
//Calculate the maximum production of this material based //Calculate the maximum production of this material based
//on the office's productivity //on the office's productivity
var maxProd = this.getOfficeProductivity(office, {forProduct:true}) const maxProd = this.getOfficeProductivity(office, {forProduct:true})
* corporation.getProductionMultiplier() * corporation.getProductionMultiplier()
* this.prodMult // Multiplier from materials * this.prodMult // Multiplier from materials
* this.getProductionMultiplier() // Multiplier from research * this.getProductionMultiplier() // Multiplier from research
@ -951,27 +952,27 @@ export class Industry {
prod *= (CorporationConstants.SecsPerMarketCycle * marketCycles); prod *= (CorporationConstants.SecsPerMarketCycle * marketCycles);
//Calculate net change in warehouse storage making the Products will cost //Calculate net change in warehouse storage making the Products will cost
var netStorageSize = product.siz; let netStorageSize = product.siz;
for (var reqMatName in product.reqMats) { for (const reqMatName in product.reqMats) {
if (product.reqMats.hasOwnProperty(reqMatName)) { if (product.reqMats.hasOwnProperty(reqMatName)) {
var normQty = product.reqMats[reqMatName]; const normQty = product.reqMats[reqMatName];
netStorageSize -= (MaterialSizes[reqMatName] * normQty); netStorageSize -= (MaterialSizes[reqMatName] * normQty);
} }
} }
//If there's not enough space in warehouse, limit the amount of Product //If there's not enough space in warehouse, limit the amount of Product
if (netStorageSize > 0) { if (netStorageSize > 0) {
var maxAmt = Math.floor((warehouse.size - warehouse.sizeUsed) / netStorageSize); const maxAmt = Math.floor((warehouse.size - warehouse.sizeUsed) / netStorageSize);
prod = Math.min(maxAmt, prod); prod = Math.min(maxAmt, prod);
} }
warehouse.smartSupplyStore += (prod / (CorporationConstants.SecsPerMarketCycle * marketCycles)); warehouse.smartSupplyStore += (prod / (CorporationConstants.SecsPerMarketCycle * marketCycles));
//Make sure we have enough resources to make our Products //Make sure we have enough resources to make our Products
var producableFrac = 1; let producableFrac = 1;
for (var reqMatName in product.reqMats) { for (const reqMatName in product.reqMats) {
if (product.reqMats.hasOwnProperty(reqMatName)) { if (product.reqMats.hasOwnProperty(reqMatName)) {
var req = product.reqMats[reqMatName] * prod; const req = product.reqMats[reqMatName] * prod;
if (warehouse.materials[reqMatName].qty < req) { if (warehouse.materials[reqMatName].qty < req) {
producableFrac = Math.min(producableFrac, warehouse.materials[reqMatName].qty / req); producableFrac = Math.min(producableFrac, warehouse.materials[reqMatName].qty / req);
} }
@ -980,9 +981,9 @@ export class Industry {
//Make our Products if they are producable //Make our Products if they are producable
if (producableFrac > 0 && prod > 0) { if (producableFrac > 0 && prod > 0) {
for (var reqMatName in product.reqMats) { for (const reqMatName in product.reqMats) {
if (product.reqMats.hasOwnProperty(reqMatName)) { if (product.reqMats.hasOwnProperty(reqMatName)) {
var reqMatQtyNeeded = (product.reqMats[reqMatName] * prod * producableFrac); const reqMatQtyNeeded = (product.reqMats[reqMatName] * prod * producableFrac);
warehouse.materials[reqMatName].qty -= reqMatQtyNeeded; warehouse.materials[reqMatName].qty -= reqMatQtyNeeded;
warehouse.materials[reqMatName].prd -= reqMatQtyNeeded / (CorporationConstants.SecsPerMarketCycle * marketCycles); warehouse.materials[reqMatName].prd -= reqMatQtyNeeded / (CorporationConstants.SecsPerMarketCycle * marketCycles);
} }
@ -998,7 +999,7 @@ export class Industry {
case "SALE": { case "SALE": {
//Process sale of Products //Process sale of Products
product.pCost = 0; //Estimated production cost product.pCost = 0; //Estimated production cost
for (var reqMatName in product.reqMats) { for (const reqMatName in product.reqMats) {
if (product.reqMats.hasOwnProperty(reqMatName)) { if (product.reqMats.hasOwnProperty(reqMatName)) {
product.pCost += (product.reqMats[reqMatName] * warehouse.materials[reqMatName].bCost); product.pCost += (product.reqMats[reqMatName] * warehouse.materials[reqMatName].bCost);
} }
@ -1014,7 +1015,7 @@ export class Industry {
// Calculate Sale Cost (sCost), which could be dynamically evaluated // Calculate Sale Cost (sCost), which could be dynamically evaluated
const markupLimit = product.rat / product.mku; const markupLimit = product.rat / product.mku;
var sCost; let sCost;
if (product.marketTa2) { if (product.marketTa2) {
const prod = product.data[city][1]; const prod = product.data[city][1];
@ -1062,14 +1063,14 @@ export class Industry {
sCost = product.sCost; sCost = product.sCost;
} }
var markup = 1; let markup = 1;
if (sCost > product.pCost) { if (sCost > product.pCost) {
if ((sCost - product.pCost) > markupLimit) { if ((sCost - product.pCost) > markupLimit) {
markup = markupLimit / (sCost - product.pCost); markup = markupLimit / (sCost - product.pCost);
} }
} }
var maxSell = 0.5 const maxSell = 0.5
* Math.pow(product.rat, 0.65) * Math.pow(product.rat, 0.65)
* marketFactor * marketFactor
* corporation.getSalesMultiplier() * corporation.getSalesMultiplier()
@ -1077,10 +1078,10 @@ export class Industry {
* businessFactor * businessFactor
* advertisingFactor * advertisingFactor
* this.getSalesMultiplier(); * this.getSalesMultiplier();
var sellAmt; let sellAmt;
if (product.sllman[city][0] && isString(product.sllman[city][1])) { if (product.sllman[city][0] && isString(product.sllman[city][1])) {
//Sell amount is dynamically evaluated //Sell amount is dynamically evaluated
var tmp = product.sllman[city][1].replace(/MAX/g, maxSell); let tmp = product.sllman[city][1].replace(/MAX/g, maxSell);
tmp = tmp.replace(/PROD/g, product.data[city][1]); tmp = tmp.replace(/PROD/g, product.data[city][1]);
try { try {
tmp = eval(tmp); tmp = eval(tmp);
@ -1124,7 +1125,7 @@ export class Industry {
} }
discontinueProduct(product: Product): void { discontinueProduct(product: Product): void {
for (var productName in this.products) { for (const productName in this.products) {
if (this.products.hasOwnProperty(productName)) { if (this.products.hasOwnProperty(productName)) {
if (product === this.products[productName]) { if (product === this.products[productName]) {
delete this.products[productName]; delete this.products[productName];
@ -1133,7 +1134,7 @@ export class Industry {
} }
} }
upgrade(upgrade: IndustryUpgrade, refs: {corporation: any, office: OfficeSpace}): void { upgrade(upgrade: IndustryUpgrade, refs: {corporation: any; office: OfficeSpace}): void {
const corporation = refs.corporation; const corporation = refs.corporation;
const office = refs.office; const office = refs.office;
const upgN = upgrade[0]; const upgN = upgrade[0];
@ -1141,23 +1142,26 @@ export class Industry {
++this.upgrades[upgN]; ++this.upgrades[upgN];
switch (upgN) { switch (upgN) {
case 0: //Coffee, 5% energy per employee case 0: { //Coffee, 5% energy per employee
for (let i = 0; i < office.employees.length; ++i) { for (let i = 0; i < office.employees.length; ++i) {
office.employees[i].ene = Math.min(office.employees[i].ene * 1.05, office.maxEne); office.employees[i].ene = Math.min(office.employees[i].ene * 1.05, office.maxEne);
} }
break; break;
case 1: //AdVert.Inc, }
case 1: { //AdVert.Inc,
const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier(); const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier();
this.awareness += (3 * advMult); this.awareness += (3 * advMult);
this.popularity += (1 * advMult); this.popularity += (1 * advMult);
this.awareness *= (1.01 * advMult); this.awareness *= (1.01 * advMult);
this.popularity *= ((1 + getRandomInt(1, 3) / 100) * advMult); this.popularity *= ((1 + getRandomInt(1, 3) / 100) * advMult);
break; break;
default: }
default: {
console.error(`Un-implemented function index: ${upgN}`); console.error(`Un-implemented function index: ${upgN}`);
break; break;
} }
} }
}
// Returns how much of a material can be produced based of office productivity (employee stats) // Returns how much of a material can be produced based of office productivity (employee stats)
getOfficeProductivity(office: OfficeSpace, params: any = {}): number { getOfficeProductivity(office: OfficeSpace, params: any = {}): number {
@ -1205,7 +1209,7 @@ export class Industry {
} }
//Returns a multiplier based on a materials demand and competition that affects sales //Returns a multiplier based on a materials demand and competition that affects sales
getMarketFactor(mat: {dmd: number, cmp: number}): number { getMarketFactor(mat: {dmd: number; cmp: number}): number {
return Math.max(0.1, mat.dmd * (100 - mat.cmp) / 100); return Math.max(0.1, mat.dmd * (100 - mat.cmp) / 100);
} }

@ -2,8 +2,6 @@ import React from 'react';
import { ResearchTree } from "./ResearchTree"; import { ResearchTree } from "./ResearchTree";
import { getBaseResearchTreeCopy, import { getBaseResearchTreeCopy,
getProductIndustryResearchTreeCopy } from "./data/BaseResearchTree"; getProductIndustryResearchTreeCopy } from "./data/BaseResearchTree";
import { numeralWrapper } from "../ui/numeralFormat";
import { Money } from "../ui/React/Money"; import { Money } from "../ui/React/Money";
interface IIndustryMap<T> { interface IIndustryMap<T> {

@ -1,12 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
interface IProps { interface IProps {
mat: any; mat: any;
@ -90,8 +84,7 @@ amount to 'MAX' to export all of the materials in this warehouse.
</p> </p>
<select className="dropdown" onChange={onIndustryChange} defaultValue={industry}> <select className="dropdown" onChange={onIndustryChange} defaultValue={industry}>
{ {
props.corp.divisions.map((division: any) => props.corp.divisions.map((division: any) => <option key={division.name} value={division.name}>{division.name}</option>)
<option key={division.name} value={division.name}>{division.name}</option>)
} }
</select> </select>
<select className="dropdown" onChange={onCityChange} defaultValue={city}> <select className="dropdown" onChange={onCityChange} defaultValue={city}>
@ -109,8 +102,7 @@ Below is a list of all current exports of this material from this warehouse.
Clicking on one of the exports below will REMOVE that export. Clicking on one of the exports below will REMOVE that export.
</p> </p>
{ {
props.mat.exp.map((exp: any, index: number) => props.mat.exp.map((exp: any, index: number) => <div key={index} className="cmpy-mgmt-existing-export" onClick={() => removeExport(exp)}>
<div key={index} className="cmpy-mgmt-existing-export" onClick={() => removeExport(exp)}>
Industry: {exp.ind}<br /> Industry: {exp.ind}<br />
City: {exp.city}<br /> City: {exp.city}<br />
Amount/s: {exp.amt} Amount/s: {exp.amt}

@ -1,12 +1,5 @@
import React, { useState } from 'react'; import React from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { CorporationConstants } from "../data/Constants"; import { CorporationConstants } from "../data/Constants";

@ -1,14 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { CorporationConstants } from "../data/Constants";
interface IProps { interface IProps {
corp: any; corp: any;

@ -79,7 +79,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
display: "inline-block", display: "inline-block",
} }
function openMakeProductPopup() { function openMakeProductPopup(): void {
const popupId = "cmpy-mgmt-create-product-popup"; const popupId = "cmpy-mgmt-create-product-popup";
createPopup(popupId, MakeProductPopup, { createPopup(popupId, MakeProductPopup, {
popupText: createProductPopupText, popupText: createProductPopupText,

@ -260,7 +260,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
const purchaseButtonText = `Buy (${numeralWrapper.format(mat.buy, nfB)})`; const purchaseButtonText = `Buy (${numeralWrapper.format(mat.buy, nfB)})`;
const purchaseButtonClass = tutorial ? "std-button flashing-button tooltip" : "std-button"; const purchaseButtonClass = tutorial ? "std-button flashing-button tooltip" : "std-button";
function openPurchaseMaterialPopup() { function openPurchaseMaterialPopup(): void {
const popupId = "cmpy-mgmt-material-purchase-popup"; const popupId = "cmpy-mgmt-material-purchase-popup";
createPopup(popupId, PurchaseMaterialPopup, { createPopup(popupId, PurchaseMaterialPopup, {
mat: mat, mat: mat,
@ -271,7 +271,7 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
}); });
} }
function openExportPopup() { function openExportPopup(): void {
const popupId = "cmpy-mgmt-export-popup"; const popupId = "cmpy-mgmt-export-popup";
createPopup(popupId, ExportPopup, { createPopup(popupId, ExportPopup, {
mat: mat, mat: mat,

@ -1,5 +1,4 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { createElement } from "../../../utils/uiHelpers/createElement";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";

@ -1,13 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
interface IProps { interface IProps {
product: any; product: any;
@ -25,7 +18,7 @@ export function LimitProductProductionPopup(props: IProps): React.ReactElement {
removePopup(props.popupId); removePopup(props.popupId);
return; return;
} }
var qty = limit; const qty = limit;
if (isNaN(qty)) { if (isNaN(qty)) {
dialogBoxCreate("Invalid value entered"); dialogBoxCreate("Invalid value entered");
return; return;

@ -1,12 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { Industries } from "../IndustryData"; import { Industries } from "../IndustryData";
import { Product } from "../Product"; import { Product } from "../Product";
@ -29,9 +23,9 @@ function productPlaceholder(tpe: string): string {
} }
// Create a popup that lets the player create a product for their current industry // Create a popup that lets the player create a product for their current industry
export function MakeProductPopup(props: IProps) { export function MakeProductPopup(props: IProps): React.ReactElement {
const allCities = Object.keys(props.division.offices). const allCities = Object.keys(props.division.offices)
filter((cityName: string) => props.division.offices[cityName] !== 0); .filter((cityName: string) => props.division.offices[cityName] !== 0);
const [city, setCity] = useState(allCities.length > 0 ? allCities[0] : ''); const [city, setCity] = useState(allCities.length > 0 ? allCities[0] : '');
const [name, setName] = useState(''); const [name, setName] = useState('');
const [design, setDesign] = useState<number | null>(null); const [design, setDesign] = useState<number | null>(null);
@ -94,8 +88,7 @@ export function MakeProductPopup(props: IProps) {
<p dangerouslySetInnerHTML={{__html: props.popupText}} /> <p dangerouslySetInnerHTML={{__html: props.popupText}} />
<select className="dropdown" style={{margin: "5px"}} onChange={onCityChange} defaultValue={city}> <select className="dropdown" style={{margin: "5px"}} onChange={onCityChange} defaultValue={city}>
{ {
allCities.map((cityName: string) => allCities.map((cityName: string) => <option key={cityName} value={cityName}>{cityName}</option>)
<option key={cityName} value={cityName}>{cityName}</option>)
} }
</select> </select>
<input onChange={onProductNameChange} className="text-input" style={{margin:"5px"}} placeholder={productPlaceholder(props.division.type)} /> <input onChange={onProductNameChange} className="text-input" style={{margin:"5px"}} placeholder={productPlaceholder(props.division.type)} />

@ -1,12 +1,4 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
interface IMarketTA2Props { interface IMarketTA2Props {

@ -1,12 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { import {
Industries, Industries,
IndustryStartingCosts, IndustryStartingCosts,
@ -22,9 +16,7 @@ interface IProps {
// This is created when the player clicks the "Expand into new Industry" header tab // This is created when the player clicks the "Expand into new Industry" header tab
export function NewIndustryPopup(props: IProps): React.ReactElement { export function NewIndustryPopup(props: IProps): React.ReactElement {
const allIndustries = Object.keys(Industries).sort(); const allIndustries = Object.keys(Industries).sort();
const possibleIndustries = allIndustries.filter((industryType: string) => const possibleIndustries = allIndustries.filter((industryType: string) => props.corp.divisions.find((division: any) => division.type === industryType) === undefined).sort();
props.corp.divisions.find((division: any) =>
division.type === industryType) === undefined).sort();
const [industry, setIndustry] = useState(possibleIndustries.length > 0 ? possibleIndustries[0] : ''); const [industry, setIndustry] = useState(possibleIndustries.length > 0 ? possibleIndustries[0] : '');
const [name, setName] = useState(''); const [name, setName] = useState('');
@ -74,8 +66,7 @@ export function NewIndustryPopup(props: IProps): React.ReactElement {
<p>Create a new division to expand into a new industry:</p> <p>Create a new division to expand into a new industry:</p>
<select className="dropdown" defaultValue={industry} onChange={onIndustryChange}> <select className="dropdown" defaultValue={industry} onChange={onIndustryChange}>
{ {
possibleIndustries.map((industry: string) => possibleIndustries.map((industry: string) => <option key={industry} value={industry}>{industry}</option>)
<option key={industry} value={industry}>{industry}</option>)
} }
</select> </select>
<p>{IndustryDescriptions[industry]}</p> <p>{IndustryDescriptions[industry]}</p>

@ -1,12 +1,4 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
interface IProps { interface IProps {

@ -1,12 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { MaterialSizes } from "../MaterialSizes"; import { MaterialSizes } from "../MaterialSizes";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
@ -85,7 +79,7 @@ function BulkPurchase(props: IProps): React.ReactElement {
(all at once). (all at once).
</p> </p>
<BulkPurchaseText warehouse={props.warehouse} mat={props.mat} amount={buyAmt} /> <BulkPurchaseText warehouse={props.warehouse} mat={props.mat} amount={buyAmt} />
<input onChange={onChange} type="number" placeholder="Bulk Purchase amount" style={{margin: "5px"}} /> <input onChange={onChange} type="number" placeholder="Bulk Purchase amount" style={{margin: "5px"}} onKeyDown={onKeyDown} />
<button className="std-button">Confirm Bulk Purchase</button> <button className="std-button">Confirm Bulk Purchase</button>
</>); </>);
} }

@ -1,18 +1,10 @@
import React, { useState, useEffect } from 'react'; import React, { useEffect } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement"; import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { MaterialSizes } from "../MaterialSizes";
import { numeralWrapper } from "../../ui/numeralFormat";
import { IndustryResearchTrees } from "../IndustryData"; import { IndustryResearchTrees } from "../IndustryData";
import { CorporationConstants } from "../data/Constants"; import { CorporationConstants } from "../data/Constants";
import { ResearchMap } from "../ResearchMap"; import { ResearchMap } from "../ResearchMap";
import { ResearchTree } from "../ResearchTree";
import { Treant } from 'treant-js'; import { Treant } from 'treant-js';
interface IProps { interface IProps {

@ -1,12 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
function initialPrice(mat: any): string { function initialPrice(mat: any): string {
let val = mat.sCost ? mat.sCost : ''; let val = mat.sCost ? mat.sCost : '';

@ -1,12 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Warehouse } from "../Warehouse";
import { dialogBoxCreate } from "../../../utils/DialogBox"; import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createElement } from "../../../utils/uiHelpers/createElement";
import { removePopup } from "../../ui/React/createPopup"; import { removePopup } from "../../ui/React/createPopup";
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
import { getSelectText,
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
import { Cities } from "../../Locations/Cities"; import { Cities } from "../../Locations/Cities";
function initialPrice(product: any): string { function initialPrice(product: any): string {
@ -40,9 +34,9 @@ export function SellProductPopup(props: IProps): React.ReactElement {
if (px.includes("MP")) { if (px.includes("MP")) {
//Dynamically evaluated quantity. First test to make sure its valid //Dynamically evaluated quantity. First test to make sure its valid
//Sanitize input, then replace dynamic variables with arbitrary numbers //Sanitize input, then replace dynamic variables with arbitrary numbers
var price = px.replace(/\s+/g, ''); let price = px.replace(/\s+/g, '');
price = price.replace(/[^-()\d/*+.MP]/g, ''); price = price.replace(/[^-()\d/*+.MP]/g, '');
var temp = price.replace(/MP/g, '1'); let temp = price.replace(/MP/g, '1');
try { try {
temp = eval(temp); temp = eval(temp);
} catch(e) { } catch(e) {
@ -55,7 +49,7 @@ export function SellProductPopup(props: IProps): React.ReactElement {
} }
props.product.sCost = price; //Use sanitized price props.product.sCost = price; //Use sanitized price
} else { } else {
var cost = parseFloat(px); const cost = parseFloat(px);
if (isNaN(cost)) { if (isNaN(cost)) {
dialogBoxCreate("Invalid value for sell price field"); dialogBoxCreate("Invalid value for sell price field");
return; return;
@ -69,9 +63,9 @@ export function SellProductPopup(props: IProps): React.ReactElement {
// Parse quantity // Parse quantity
if (iQty.includes("MAX") || iQty.includes("PROD")) { if (iQty.includes("MAX") || iQty.includes("PROD")) {
//Dynamically evaluated quantity. First test to make sure its valid //Dynamically evaluated quantity. First test to make sure its valid
var qty = iQty.replace(/\s+/g, ''); let qty = iQty.replace(/\s+/g, '');
qty = qty.replace(/[^-()\d/*+.MAXPROD]/g, ''); qty = qty.replace(/[^-()\d/*+.MAXPROD]/g, '');
var temp = qty.replace(/MAX/g, '1'); let temp = qty.replace(/MAX/g, '1');
temp = temp.replace(/PROD/g, '1'); temp = temp.replace(/PROD/g, '1');
try { try {
temp = eval(temp); temp = eval(temp);