diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3a252ac7d..e34c77fdb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ permissions: contents: read pages: write id-token: write - + concurrency: group: "pages" cancel-in-progress: true @@ -35,16 +35,16 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 - + - name: Use Node.js 16.13.1 uses: actions/setup-node@v2 with: node-version: 16.13.1 cache: "npm" - + - name: Install NPM dependencies run: npm ci - + - name: Build Production App if: ${{ github.event.inputs.buildApp == 'true' }} run: npm run build @@ -59,7 +59,7 @@ jobs: dist/vendor.bundle.js.map index.html expire-on: never - + - name: Build Documentation if: ${{ github.event.inputs.buildDoc == 'true' }} run: npm run doc diff --git a/src/Achievements/Achievements.ts b/src/Achievements/Achievements.ts index e7b54d202..1e8be562a 100644 --- a/src/Achievements/Achievements.ts +++ b/src/Achievements/Achievements.ts @@ -464,7 +464,7 @@ export const achievements: Record = { for (const d of Player.corporation.divisions) { for (const o of Object.values(d.offices)) { if (o === 0) continue; - if (o.employees.length >= 3000) return true; + if (o.totalEmployees >= 3000) return true; } } return false; diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index 74dd2f5f5..10bcee486 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -302,13 +302,6 @@ export function BuyBackShares(corporation: Corporation, numShares: number): bool return true; } -export function AssignJob(office: OfficeSpace, employeeName: string, job: string): void { - const employee = office.employees.find((e) => e.name === employeeName); - if (!employee) throw new Error(`Could not find employee '${name}'.`); - if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); - office.assignSingleJob(employee, job); -} - export function AutoAssignJob(office: OfficeSpace, job: string, count: number): boolean { if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); return office.autoAssignJob(job, count); @@ -344,7 +337,7 @@ export function BuyCoffee(corp: Corporation, office: OfficeSpace): boolean { export function ThrowParty(corp: Corporation, office: OfficeSpace, costPerEmployee: number): number { const mult = 1 + costPerEmployee / 10e6; - const cost = costPerEmployee * office.employees.length; + const cost = costPerEmployee * office.totalEmployees; if (corp.funds < cost) { return 0; } diff --git a/src/Corporation/Employee.ts b/src/Corporation/Employee.ts deleted file mode 100644 index 08287945a..000000000 --- a/src/Corporation/Employee.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { CorporationConstants } from "./data/Constants"; -import { getRandomInt } from "../utils/helpers/getRandomInt"; -import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; -import { EmployeePositions } from "./EmployeePositions"; -import { Corporation } from "./Corporation"; -import { Industry } from "./Industry"; - -interface IParams { - name?: string; - morale?: number; - happiness?: number; - energy?: number; - intelligence?: number; - charisma?: number; - experience?: number; - creativity?: number; - efficiency?: number; - salary?: number; - loc?: string; -} - -export class Employee { - name: string; - mor: number; - hap: number; - ene: number; - int: number; - cha: number; - exp: number; - cre: number; - eff: number; - sal: number; - cyclesUntilRaise = CorporationConstants.CyclesPerEmployeeRaise; - loc: string; - pos: string; - nextPos: string; - - constructor(params: IParams = {}) { - this.name = params.name ? params.name : "Bobby"; - - //Morale, happiness, and energy are 0-100 - this.mor = params.morale ? params.morale : getRandomInt(50, 100); - this.hap = params.happiness ? params.happiness : getRandomInt(50, 100); - this.ene = params.energy ? params.energy : getRandomInt(50, 100); - - this.int = params.intelligence ? params.intelligence : getRandomInt(10, 50); - this.cha = params.charisma ? params.charisma : getRandomInt(10, 50); - this.exp = params.experience ? params.experience : getRandomInt(10, 50); - this.cre = params.creativity ? params.creativity : getRandomInt(10, 50); - this.eff = params.efficiency ? params.efficiency : getRandomInt(10, 50); - this.sal = params.salary ? params.salary : getRandomInt(0.1, 5); - - this.loc = params.loc ? params.loc : ""; - this.pos = EmployeePositions.Unassigned; - this.nextPos = this.pos; - } - - //Returns the amount the employee needs to be paid - process(marketCycles = 1): number { - const gain = 0.003 * marketCycles; - const det = gain * Math.random(); - this.exp += gain; - - //Training - const trainingEff = gain * Math.random(); - if (this.pos === EmployeePositions.Training) { - //To increase creativity and intelligence special upgrades are needed - this.cha += trainingEff; - this.exp += trainingEff; - this.eff += trainingEff; - } - - this.ene -= det; - this.hap -= det; - - const salary = this.sal * marketCycles * CorporationConstants.SecsPerMarketCycle; - return salary; - } - - calculateProductivity(corporation: Corporation, industry: Industry): number { - const effCre = this.cre * corporation.getEmployeeCreMultiplier() * industry.getEmployeeCreMultiplier(), - effCha = this.cha * corporation.getEmployeeChaMultiplier() * industry.getEmployeeChaMultiplier(), - effInt = this.int * corporation.getEmployeeIntMultiplier() * industry.getEmployeeIntMultiplier(), - effEff = this.eff * corporation.getEmployeeEffMultiplier() * industry.getEmployeeEffMultiplier(); - const prodBase = this.mor * this.hap * this.ene * 1e-6; - let prodMult = 0; - switch (this.pos) { - //Calculate productivity based on position. This is multiplied by prodBase - //to get final value - case EmployeePositions.Operations: - prodMult = 0.6 * effInt + 0.1 * effCha + this.exp + 0.5 * effCre + effEff; - break; - case EmployeePositions.Engineer: - prodMult = effInt + 0.1 * effCha + 1.5 * this.exp + effEff; - break; - case EmployeePositions.Business: - prodMult = 0.4 * effInt + effCha + 0.5 * this.exp; - break; - case EmployeePositions.Management: - prodMult = 2 * effCha + this.exp + 0.2 * effCre + 0.7 * effEff; - break; - case EmployeePositions.RandD: - prodMult = 1.5 * effInt + 0.8 * this.exp + effCre + 0.5 * effEff; - break; - case EmployeePositions.Unassigned: - case EmployeePositions.Training: - prodMult = 0; - break; - default: - console.error(`Invalid employee position: ${this.pos}`); - break; - } - return prodBase * prodMult; - } - - toJSON(): IReviverValue { - return Generic_toJSON("Employee", this); - } - - static fromJSON(value: IReviverValue): Employee { - return Generic_fromJSON(Employee, value.data); - } -} - -Reviver.constructors.Employee = Employee; diff --git a/src/Corporation/OfficeSpace.ts b/src/Corporation/OfficeSpace.ts index eba259395..ed429c1ae 100644 --- a/src/Corporation/OfficeSpace.ts +++ b/src/Corporation/OfficeSpace.ts @@ -1,9 +1,6 @@ import { EmployeePositions } from "./EmployeePositions"; import { CorporationConstants } from "./data/Constants"; -import { getRandomInt } from "../utils/helpers/getRandomInt"; -import { generateRandomString } from "../utils/StringHelperFunctions"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; -import { Employee } from "./Employee"; import { Industry } from "./Industry"; import { Corporation } from "./Corporation"; @@ -24,6 +21,19 @@ export class OfficeSpace { maxHap = 100; maxMor = 100; + avgEne = 75; + avgHap = 75; + avgMor = 75; + + avgInt = 75; + avgCha = 75; + totalExp = 0; + avgCre = 75; + avgEff = 75; + + totalEmployees = 0; + totalSalary = 0; + autoCoffee = false; autoParty = false; coffeeMult = 0; @@ -31,16 +41,17 @@ export class OfficeSpace { coffeeEmployees = 0; partyEmployees = 0; - employees: Employee[] = []; - employeeProd: { [key: string]: number } = { + employeeProd: Record = { [EmployeePositions.Operations]: 0, [EmployeePositions.Engineer]: 0, [EmployeePositions.Business]: 0, [EmployeePositions.Management]: 0, [EmployeePositions.RandD]: 0, + [EmployeePositions.Training]: 0, + [EmployeePositions.Unassigned]: 0, total: 0, }; - employeeJobs: { [key: string]: number } = { + employeeJobs: Record = { [EmployeePositions.Operations]: 0, [EmployeePositions.Engineer]: 0, [EmployeePositions.Business]: 0, @@ -49,7 +60,7 @@ export class OfficeSpace { [EmployeePositions.Training]: 0, [EmployeePositions.Unassigned]: 0, }; - employeeNextJobs: { [key: string]: number } = { + employeeNextJobs: Record = { [EmployeePositions.Operations]: 0, [EmployeePositions.Engineer]: 0, [EmployeePositions.Business]: 0, @@ -65,24 +76,21 @@ export class OfficeSpace { } atCapacity(): boolean { - return this.employees.length >= this.size; + return this.totalEmployees >= this.size; } process(marketCycles = 1, corporation: Corporation, industry: Industry): number { // HRBuddy AutoRecruitment and training if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) { - const emp = this.hireRandomEmployee(); - if (industry.hasResearch("HRBuddy-Training") && emp !== undefined) { - emp.pos = EmployeePositions.Training; - } + this.hireRandomEmployee( + industry.hasResearch("HRBuddy-Training") ? EmployeePositions.Training : EmployeePositions.Unassigned, + ); } // Update employee jobs and job counts - for (const employee of this.employees) { - employee.pos = employee.nextPos; + for (const [pos, jobCount] of Object.entries(this.employeeNextJobs) as [EmployeePositions, number][]) { + this.employeeJobs[pos] = jobCount; } - this.calculateTotalEmployees(); - this.calculateNextEmployees(); // Process Office properties this.maxEne = 100; @@ -105,162 +113,149 @@ export class OfficeSpace { this.autoParty = true; } - // Calculate changes in Morale/Happiness/Energy for Employees - let perfMult = 1; //Multiplier for employee morale/happiness/energy based on company performance - if (corporation.funds < 0 && industry.lastCycleRevenue < 0) { - perfMult = Math.pow(0.99, marketCycles); - } else if (corporation.funds > 0 && industry.lastCycleRevenue > 0) { - perfMult = Math.pow(1.01, marketCycles); - } - - let totalSalary = 0; - for (const employee of this.employees) { - const salary = employee.process(marketCycles); - totalSalary += salary; + if (this.totalEmployees > 0) { + // Calculate changes in Morale/Happiness/Energy for Employees + let perfMult = 1; //Multiplier for employee morale/happiness/energy based on company performance + const reduction = 0.0015 * marketCycles; // Passive reduction every cycle + if (corporation.funds < 0 && industry.lastCycleRevenue < 0) { + perfMult = Math.pow(0.995, marketCycles); + } else if (corporation.funds > 0 && industry.lastCycleRevenue > 0) { + perfMult = Math.pow(1.005, marketCycles); + } if (this.autoCoffee) { - employee.ene = this.maxEne; + this.avgEne = this.maxEne; } else if (this.coffeeMult > 1) { - const mult = 1 + ((this.coffeeMult - 1) * this.employees.length) / this.coffeeEmployees; - employee.ene *= mult; + this.avgEne -= reduction; + this.avgEne *= (this.coffeeMult * this.coffeeEmployees) / this.totalEmployees; } else { - employee.ene *= perfMult; + this.avgEne -= reduction; + this.avgEne *= perfMult; } if (this.autoParty) { - employee.mor = this.maxMor; - employee.hap = this.maxHap; + this.avgMor = this.maxMor; + this.avgHap = this.maxHap; } else if (this.partyMult > 1) { - const mult = 1 + ((this.partyMult - 1) * this.employees.length) / this.partyEmployees; - employee.mor *= mult; - employee.hap *= mult; + this.avgHap -= reduction; + this.avgMor *= (this.partyMult * this.partyEmployees) / this.totalEmployees; + this.avgHap *= (this.partyMult * this.partyEmployees) / this.totalEmployees; } else { - employee.mor *= perfMult; - employee.hap *= perfMult; + this.avgHap -= reduction; + this.avgMor *= perfMult; + this.avgHap *= perfMult; } - employee.ene = Math.max(Math.min(employee.ene, this.maxEne), this.minEne); - employee.mor = Math.max(Math.min(employee.mor, this.maxMor), this.minMor); - employee.hap = Math.max(Math.min(employee.hap, this.maxHap), this.minHap); + this.avgEne = Math.max(Math.min(this.avgEne, this.maxEne), this.minEne); + this.avgMor = Math.max(Math.min(this.avgMor, this.maxMor), this.minMor); + this.avgHap = Math.max(Math.min(this.avgHap, this.maxHap), this.minHap); + + this.coffeeMult = 0; + this.partyMult = 0; + this.coffeeEmployees = 0; + this.partyEmployees = 0; } - this.coffeeMult = 0; - this.partyMult = 0; - this.coffeeEmployees = 0; - this.partyEmployees = 0; + // Get experience increase; unassigned employees do not contribute, employees in training contribute 5x + this.totalExp += + 0.0015 * + marketCycles * + (this.totalEmployees - + this.employeeJobs[EmployeePositions.Unassigned] + + this.employeeJobs[EmployeePositions.Training] * 4); this.calculateEmployeeProductivity(corporation, industry); - return totalSalary; - } - - calculateNextEmployees(): void { - //Reset - for (const name of Object.keys(this.employeeNextJobs)) { - this.employeeNextJobs[name] = 0; - } - - for (let i = 0; i < this.employees.length; ++i) { - const employee = this.employees[i]; - this.employeeNextJobs[employee.nextPos]++; - } - } - - calculateTotalEmployees(): void { - //Reset - for (const name of Object.keys(this.employeeJobs)) { - this.employeeJobs[name] = 0; - } - - for (let i = 0; i < this.employees.length; ++i) { - const employee = this.employees[i]; - this.employeeJobs[employee.pos]++; + if (this.totalEmployees === 0) { + this.totalSalary = 0; + } else { + this.totalSalary = + CorporationConstants.EmployeeSalaryMultiplier * + marketCycles * + this.totalEmployees * + (this.avgInt + this.avgCha + this.totalExp / this.totalEmployees + this.avgCre + this.avgEff); } + return this.totalSalary; } calculateEmployeeProductivity(corporation: Corporation, industry: Industry): void { - //Reset - for (const name of Object.keys(this.employeeProd)) { - this.employeeProd[name] = 0; - } + const effCre = this.avgCre * corporation.getEmployeeCreMultiplier() * industry.getEmployeeCreMultiplier(), + effCha = this.avgCha * corporation.getEmployeeChaMultiplier() * industry.getEmployeeChaMultiplier(), + effInt = this.avgInt * corporation.getEmployeeIntMultiplier() * industry.getEmployeeIntMultiplier(), + effEff = this.avgEff * corporation.getEmployeeEffMultiplier() * industry.getEmployeeEffMultiplier(); + const prodBase = this.avgMor * this.avgHap * this.avgEne * 1e-6; let total = 0; - for (let i = 0; i < this.employees.length; ++i) { - const employee = this.employees[i]; - const prod = employee.calculateProductivity(corporation, industry); - this.employeeProd[employee.pos] += prod; - total += prod; + const exp = this.totalExp / this.totalEmployees || 0; + for (const name of Object.keys(this.employeeProd) as (EmployeePositions | "total")[]) { + let prodMult = 0; + switch (name) { + case EmployeePositions.Operations: + prodMult = 0.6 * effInt + 0.1 * effCha + exp + 0.5 * effCre + effEff; + break; + case EmployeePositions.Engineer: + prodMult = effInt + 0.1 * effCha + 1.5 * exp + effEff; + break; + case EmployeePositions.Business: + prodMult = 0.4 * effInt + effCha + 0.5 * exp; + break; + case EmployeePositions.Management: + prodMult = 2 * effCha + exp + 0.2 * effCre + 0.7 * effEff; + break; + case EmployeePositions.RandD: + prodMult = 1.5 * effInt + 0.8 * exp + effCre + 0.5 * effEff; + break; + case EmployeePositions.Unassigned: + case EmployeePositions.Training: + case "total": + continue; + default: + console.error(`Invalid employee position: ${name}`); + break; + } + this.employeeProd[name] = this.employeeJobs[name] * prodMult * prodBase; + total += this.employeeProd[name]; } + this.employeeProd.total = total; } - hireRandomEmployee(): Employee | undefined { - if (this.atCapacity()) return; - if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) return; + hireRandomEmployee(position: EmployeePositions): boolean { + if (this.atCapacity()) return false; + if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) return false; - //Generate three random employees (meh, decent, amazing) - const int = getRandomInt(50, 100), - cha = getRandomInt(50, 100), - exp = getRandomInt(50, 100), - cre = getRandomInt(50, 100), - eff = getRandomInt(50, 100), - sal = CorporationConstants.EmployeeSalaryMultiplier * (int + cha + exp + cre + eff); + ++this.totalEmployees; + ++this.employeeJobs[position]; + ++this.employeeNextJobs[position]; - const emp = new Employee({ - intelligence: int, - charisma: cha, - experience: exp, - creativity: cre, - efficiency: eff, - salary: sal, - }); - - const name = generateRandomString(7); - - for (let i = 0; i < this.employees.length; ++i) { - if (this.employees[i].name === name) { - return this.hireRandomEmployee(); - } - } - emp.name = name; - this.employees.push(emp); - - this.calculateTotalEmployees(); - this.calculateNextEmployees(); - return emp; + this.totalExp += 75; + this.avgMor = (this.avgMor * this.totalEmployees + 75) / (this.totalEmployees + 1); + this.avgHap = (this.avgHap * this.totalEmployees + 75) / (this.totalEmployees + 1); + this.avgEne = (this.avgEne * this.totalEmployees + 75) / (this.totalEmployees + 1); + return true; } - assignSingleJob(employee: Employee, job: string): void { - employee.nextPos = job; - this.calculateNextEmployees(); - } + autoAssignJob(job: EmployeePositions, target: number): boolean { + const diff = target - this.employeeNextJobs[job]; - autoAssignJob(job: string, target: number): boolean { - let count = this.employeeNextJobs[job]; - - for (const employee of this.employees) { - if (count === target) { - break; - } else if (employee.nextPos === EmployeePositions.Unassigned && count <= target) { - employee.nextPos = job; - count++; - } else if (employee.nextPos === job && count >= target) { - employee.nextPos = EmployeePositions.Unassigned; - count--; - } + if (diff === 0) { + return true; + } else if (diff <= this.employeeNextJobs[EmployeePositions.Unassigned]) { + // This covers both a negative diff (reducing the amount of employees in position) and a positive (increasing and using up unassigned employees) + this.employeeNextJobs[EmployeePositions.Unassigned] -= diff; + this.employeeNextJobs[job] = target; + return true; } - - this.calculateNextEmployees(); - return count === target; + return false; } getCoffeeCost(): number { - return 500e3 * this.employees.length; + return 500e3 * this.totalEmployees; } setCoffee(mult = 1.05): boolean { - if (mult > 1 && this.coffeeMult === 0 && !this.autoCoffee && this.employees.length > 0) { + if (mult > 1 && this.coffeeMult === 0 && !this.autoCoffee && this.totalEmployees > 0) { this.coffeeMult = mult; - this.coffeeEmployees = this.employees.length; + this.coffeeEmployees = this.totalEmployees; return true; } @@ -268,9 +263,9 @@ export class OfficeSpace { } setParty(mult: number): boolean { - if (mult > 1 && this.partyMult === 0 && !this.autoParty && this.employees.length > 0) { + if (mult > 1 && this.partyMult === 0 && !this.autoParty && this.totalEmployees > 0) { this.partyMult = mult; - this.partyEmployees = this.employees.length; + this.partyEmployees = this.totalEmployees; return true; } @@ -282,6 +277,18 @@ export class OfficeSpace { } static fromJSON(value: IReviverValue): OfficeSpace { + // Convert employees from the old version + if (value.data.hasOwnProperty("employees")) { + const empCopy: [{ data: { hap: number; mor: number; ene: number; exp: number } }] = value.data.employees; + delete value.data.employees; + const ret = Generic_fromJSON(OfficeSpace, value.data); + ret.totalEmployees = empCopy.length; + ret.avgHap = empCopy.reduce((a, b) => a + b.data.hap, 0) / ret.totalEmployees || 75; + ret.avgMor = empCopy.reduce((a, b) => a + b.data.mor, 0) / ret.totalEmployees || 75; + ret.avgEne = empCopy.reduce((a, b) => a + b.data.ene, 0) / ret.totalEmployees || 75; + ret.totalExp = empCopy.reduce((a, b) => a + b.data.exp, 0); + return ret; + } return Generic_fromJSON(OfficeSpace, value.data); } } diff --git a/src/Corporation/ui/IndustryOffice.tsx b/src/Corporation/ui/IndustryOffice.tsx index fd294eb1c..fc4189767 100644 --- a/src/Corporation/ui/IndustryOffice.tsx +++ b/src/Corporation/ui/IndustryOffice.tsx @@ -3,7 +3,6 @@ import React, { useState } from "react"; import { OfficeSpace } from "../OfficeSpace"; -import { Employee } from "../Employee"; import { EmployeePositions } from "../EmployeePositions"; import { BuyCoffee } from "../Actions"; @@ -23,8 +22,6 @@ import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp"; import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; import Tooltip from "@mui/material/Tooltip"; -import MenuItem from "@mui/material/MenuItem"; -import Select, { SelectChangeEvent } from "@mui/material/Select"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableRow from "@mui/material/TableRow"; @@ -36,139 +33,9 @@ interface IProps { rerender: () => void; } -interface ISwitchProps { - manualMode: boolean; - switchMode: (f: (b: boolean) => boolean) => void; -} - -function SwitchButton(props: ISwitchProps): React.ReactElement { - if (props.manualMode) { - return ( - - Switch to Automatic Assignment Mode, which will automatically assign employees to your selected jobs. You - simply have to select the number of assignments for each job - - } - > - - - ); - } else { - return ( - - Switch to Manual Assignment Mode, which allows you to specify which employees should get which jobs - - } - > - - - ); - } -} - -function ManualManagement(props: IProps): React.ReactElement { - const corp = useCorporation(); - const division = useDivision(); - const [employee, setEmployee] = useState( - props.office.employees.length > 0 ? props.office.employees[0] : null, - ); - - // Employee Selector - const employees = []; - for (let i = 0; i < props.office.employees.length; ++i) { - employees.push( - - {props.office.employees[i].name} - , - ); - } - - function employeeSelectorOnChange(e: SelectChangeEvent): void { - const name = e.target.value; - for (let i = 0; i < props.office.employees.length; ++i) { - if (name === props.office.employees[i].name) { - setEmployee(props.office.employees[i]); - break; - } - } - - props.rerender(); - } - - // Employee Positions Selector - const emp = employee; - let employeePositionSelectorInitialValue = ""; - const employeePositions = []; - const positionNames = Object.values(EmployeePositions); - for (let i = 0; i < positionNames.length; ++i) { - employeePositions.push( - - {positionNames[i]} - , - ); - if (emp != null && emp.nextPos === positionNames[i]) { - employeePositionSelectorInitialValue = emp.nextPos; - } - } - - function employeePositionSelectorOnChange(e: SelectChangeEvent): void { - if (employee === null) return; - props.office.assignSingleJob(employee, e.target.value); - props.rerender(); - } - - // Numeral.js formatter - const nf = "0.000"; - - // Employee stats (after applying multipliers) - const effCre = emp ? emp.cre * corp.getEmployeeCreMultiplier() * division.getEmployeeCreMultiplier() : 0; - const effCha = emp ? emp.cha * corp.getEmployeeChaMultiplier() * division.getEmployeeChaMultiplier() : 0; - const effInt = emp ? emp.int * corp.getEmployeeIntMultiplier() * division.getEmployeeIntMultiplier() : 0; - const effEff = emp ? emp.eff * corp.getEmployeeEffMultiplier() * division.getEmployeeEffMultiplier() : 0; - - return ( - <> -
- - {employee != null && ( - - Morale: {numeralWrapper.format(employee.mor, nf)} -
- Happiness: {numeralWrapper.format(employee.hap, nf)} -
- Energy: {numeralWrapper.format(employee.ene, nf)} -
- Intelligence: {numeralWrapper.format(effInt, nf)} -
- Charisma: {numeralWrapper.format(effCha, nf)} -
- Experience: {numeralWrapper.format(employee.exp, nf)} -
- Creativity: {numeralWrapper.format(effCre, nf)} -
- Efficiency: {numeralWrapper.format(effEff, nf)} -
- Salary: -
- )} - {employee != null && ( - - )} - - ); -} - interface IAutoAssignProps { office: OfficeSpace; - job: string; + job: EmployeePositions; desc: string; rerender: () => void; } @@ -232,27 +99,6 @@ function AutoManagement(props: IProps): React.ReactElement { const division = useDivision(); const vechain = corp.unlockUpgrades[4] === 1; // Has Vechain upgrade - // Calculate average morale, happiness, energy, and salary. - let totalMorale = 0, - totalHappiness = 0, - totalEnergy = 0, - totalSalary = 0; - for (let i = 0; i < props.office.employees.length; ++i) { - totalMorale += props.office.employees[i].mor; - totalHappiness += props.office.employees[i].hap; - totalEnergy += props.office.employees[i].ene; - totalSalary += props.office.employees[i].sal; - } - - let avgMorale = 0, - avgHappiness = 0, - avgEnergy = 0; - if (props.office.employees.length > 0) { - avgMorale = totalMorale / props.office.employees.length; - avgHappiness = totalHappiness / props.office.employees.length; - avgEnergy = totalEnergy / props.office.employees.length; - } - const currUna = props.office.employeeJobs[EmployeePositions.Unassigned]; const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned]; @@ -272,7 +118,7 @@ function AutoManagement(props: IProps): React.ReactElement { Avg Employee Morale: - {numeralWrapper.format(avgMorale, "0.000")} + {numeralWrapper.format(props.office.avgMor, "0.000")} @@ -280,7 +126,7 @@ function AutoManagement(props: IProps): React.ReactElement { Avg Employee Happiness: - {numeralWrapper.format(avgHappiness, "0.000")} + {numeralWrapper.format(props.office.avgHap, "0.000")} @@ -288,7 +134,17 @@ function AutoManagement(props: IProps): React.ReactElement { Avg Employee Energy: - {numeralWrapper.format(avgEnergy, "0.000")} + {numeralWrapper.format(props.office.avgEne, "0.000")} + + + + + Avg Employee Experience: + + + + {numeralWrapper.format(props.office.totalExp / props.office.totalEmployees || 0, "0.000")} + @@ -297,7 +153,7 @@ function AutoManagement(props: IProps): React.ReactElement { - + @@ -419,11 +275,10 @@ export function IndustryOffice(props: IProps): React.ReactElement { const division = useDivision(); const [upgradeOfficeSizeOpen, setUpgradeOfficeSizeOpen] = useState(false); const [throwPartyOpen, setThrowPartyOpen] = useState(false); - const [employeeManualAssignMode, setEmployeeManualAssignMode] = useState(false); function autohireEmployeeButtonOnClick(): void { if (props.office.atCapacity()) return; - props.office.hireRandomEmployee(); + props.office.hireRandomEmployee(EmployeePositions.Unassigned); props.rerender(); } @@ -431,11 +286,11 @@ export function IndustryOffice(props: IProps): React.ReactElement { Office Space - Size: {props.office.employees.length} / {props.office.size} employees + Size: {props.office.totalEmployees} / {props.office.size} employees - Automatically hires an employee and gives him/her a random name}> + Hires an employee}>