bitburner-src/src/Corporation/OfficeSpace.ts

290 lines
8.1 KiB
TypeScript
Raw Normal View History

2021-08-28 08:50:06 +02:00
import { EmployeePositions } from "./EmployeePositions";
import { CorporationConstants } from "./data/Constants";
2021-09-25 20:42:57 +02:00
import { getRandomInt } from "../utils/helpers/getRandomInt";
import { generateRandomString } from "../utils/StringHelperFunctions";
2022-07-15 01:00:10 +02:00
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
2021-08-28 08:50:06 +02:00
import { Employee } from "./Employee";
2022-09-20 12:47:54 +02:00
import { Industry } from "./Industry";
import { Corporation } from "./Corporation";
2021-08-28 08:50:06 +02:00
interface IParams {
2021-09-05 01:09:30 +02:00
loc?: string;
size?: number;
2021-08-28 08:50:06 +02:00
}
export class OfficeSpace {
2021-09-05 01:09:30 +02:00
loc: string;
size: number;
2021-09-05 01:09:30 +02:00
minEne = 0;
minHap = 0;
minMor = 0;
maxEne = 100;
2021-09-05 01:09:30 +02:00
maxHap = 100;
maxMor = 100;
autoCoffee = false;
autoParty = false;
coffeeMult = 0;
partyMult = 0;
coffeeEmployees = 0;
partyEmployees = 0;
2021-09-05 01:09:30 +02:00
employees: Employee[] = [];
employeeProd: { [key: string]: number } = {
[EmployeePositions.Operations]: 0,
[EmployeePositions.Engineer]: 0,
[EmployeePositions.Business]: 0,
[EmployeePositions.Management]: 0,
[EmployeePositions.RandD]: 0,
total: 0,
};
employeeJobs: { [key: string]: number } = {
[EmployeePositions.Operations]: 0,
[EmployeePositions.Engineer]: 0,
[EmployeePositions.Business]: 0,
[EmployeePositions.Management]: 0,
[EmployeePositions.RandD]: 0,
2022-04-01 07:44:53 +02:00
[EmployeePositions.Training]: 0,
[EmployeePositions.Unassigned]: 0,
};
employeeNextJobs: { [key: string]: number } = {
[EmployeePositions.Operations]: 0,
[EmployeePositions.Engineer]: 0,
[EmployeePositions.Business]: 0,
[EmployeePositions.Management]: 0,
[EmployeePositions.RandD]: 0,
[EmployeePositions.Training]: 0,
[EmployeePositions.Unassigned]: 0,
};
2021-09-05 01:09:30 +02:00
constructor(params: IParams = {}) {
this.loc = params.loc ? params.loc : "";
this.size = params.size ? params.size : 1;
}
atCapacity(): boolean {
return this.employees.length >= this.size;
}
2022-09-20 12:47:54 +02:00
process(marketCycles = 1, corporation: Corporation, industry: Industry): number {
2021-09-05 01:09:30 +02:00
// 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;
}
2021-08-28 08:50:06 +02:00
}
// Update employee jobs and job counts
for (const employee of this.employees) {
employee.pos = employee.nextPos;
}
2022-04-12 02:59:37 +02:00
this.calculateTotalEmployees();
this.calculateNextEmployees();
2021-09-05 01:09:30 +02:00
// Process Office properties
this.maxEne = 100;
this.maxHap = 100;
this.maxMor = 100;
2021-09-05 01:09:30 +02:00
if (industry.hasResearch("Go-Juice")) {
this.maxEne += 10;
2021-08-28 08:50:06 +02:00
}
2021-09-05 01:09:30 +02:00
if (industry.hasResearch("JoyWire")) {
this.maxHap += 10;
2021-08-28 08:50:06 +02:00
}
2021-09-05 01:09:30 +02:00
if (industry.hasResearch("Sti.mu")) {
this.maxMor += 10;
2021-08-28 08:50:06 +02:00
}
if (industry.hasResearch("AutoBrew")) {
this.autoCoffee = true;
}
if (industry.hasResearch("AutoPartyManager")) {
this.autoParty = true;
}
2021-08-28 08:50:06 +02:00
2021-09-05 01:09:30 +02:00
// 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);
2021-08-28 08:50:06 +02:00
}
let totalSalary = 0;
for (const employee of this.employees) {
const salary = employee.process(marketCycles);
totalSalary += salary;
2021-09-05 01:09:30 +02:00
if (this.autoCoffee) {
employee.ene = this.maxEne;
} else if (this.coffeeMult > 1) {
const mult = 1 + ((this.coffeeMult - 1) * this.employees.length) / this.coffeeEmployees;
employee.ene *= mult;
2021-09-05 01:09:30 +02:00
} else {
employee.ene *= perfMult;
2021-09-05 01:09:30 +02:00
}
if (this.autoParty) {
employee.mor = this.maxMor;
employee.hap = this.maxHap;
} else if (this.partyMult > 1) {
const mult = 1 + ((this.partyMult - 1) * this.employees.length) / this.partyEmployees;
employee.mor *= mult;
employee.hap *= mult;
2021-09-05 01:09:30 +02:00
} else {
employee.mor *= perfMult;
employee.hap *= perfMult;
2021-09-05 01:09:30 +02:00
}
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);
2021-08-28 08:50:06 +02:00
}
this.coffeeMult = 0;
this.partyMult = 0;
this.coffeeEmployees = 0;
this.partyEmployees = 0;
2021-09-05 01:09:30 +02:00
this.calculateEmployeeProductivity(corporation, industry);
return totalSalary;
2021-09-05 01:09:30 +02:00
}
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]++;
}
2021-09-05 01:09:30 +02:00
}
2022-04-12 02:59:37 +02:00
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]++;
}
}
2022-09-20 12:47:54 +02:00
calculateEmployeeProductivity(corporation: Corporation, industry: Industry): void {
2021-09-05 01:09:30 +02:00
//Reset
2022-01-16 01:45:03 +01:00
for (const name of Object.keys(this.employeeProd)) {
2021-09-05 01:09:30 +02:00
this.employeeProd[name] = 0;
2021-08-28 08:50:06 +02:00
}
2021-09-05 01:09:30 +02:00
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;
2021-08-28 08:50:06 +02:00
}
2021-09-05 01:09:30 +02:00
this.employeeProd.total = total;
}
hireRandomEmployee(): Employee | undefined {
if (this.atCapacity()) return;
2021-09-09 05:47:34 +02:00
if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) return;
2021-09-05 01:09:30 +02:00
//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),
2021-09-09 05:47:34 +02:00
sal = CorporationConstants.EmployeeSalaryMultiplier * (int + cha + exp + cre + eff);
2021-09-05 01:09:30 +02:00
const emp = new Employee({
2021-09-30 01:05:25 +02:00
intelligence: int,
charisma: cha,
experience: exp,
creativity: cre,
efficiency: eff,
salary: sal,
2021-09-05 01:09:30 +02:00
});
const name = generateRandomString(7);
for (let i = 0; i < this.employees.length; ++i) {
if (this.employees[i].name === name) {
return this.hireRandomEmployee();
}
2021-08-28 08:50:06 +02:00
}
2021-09-05 01:09:30 +02:00
emp.name = name;
this.employees.push(emp);
this.calculateTotalEmployees();
this.calculateNextEmployees();
2021-09-05 01:09:30 +02:00
return emp;
}
assignSingleJob(employee: Employee, job: string): void {
employee.nextPos = job;
this.calculateNextEmployees();
2021-09-05 01:09:30 +02:00
}
autoAssignJob(job: string, target: number): boolean {
let count = this.employeeNextJobs[job];
2022-02-13 10:57:13 +01:00
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--;
2021-09-05 01:09:30 +02:00
}
}
this.calculateNextEmployees();
return count === target;
2021-09-05 01:09:30 +02:00
}
getCoffeeCost(): number {
return 500e3 * this.employees.length;
}
setCoffee(mult = 1.05): boolean {
if (mult > 1 && this.coffeeMult === 0 && !this.autoCoffee && this.employees.length > 0) {
this.coffeeMult = mult;
this.coffeeEmployees = this.employees.length;
return true;
2021-09-05 01:09:30 +02:00
}
2021-09-05 01:09:30 +02:00
return false;
}
setParty(mult: number): boolean {
if (mult > 1 && this.partyMult === 0 && !this.autoParty && this.employees.length > 0) {
this.partyMult = mult;
this.partyEmployees = this.employees.length;
return true;
}
return false;
}
2022-07-15 01:00:10 +02:00
toJSON(): IReviverValue {
2021-09-05 01:09:30 +02:00
return Generic_toJSON("OfficeSpace", this);
}
2022-07-15 01:00:10 +02:00
static fromJSON(value: IReviverValue): OfficeSpace {
2021-09-05 01:09:30 +02:00
return Generic_fromJSON(OfficeSpace, value.data);
}
2021-08-28 08:50:06 +02:00
}
2021-09-05 01:09:30 +02:00
Reviver.constructors.OfficeSpace = OfficeSpace;