mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 14:42:28 +01:00
Only switch employee jobs at the start of corp cycles
This commit is contained in:
parent
6f017bf4f6
commit
b9356ea782
@ -304,9 +304,19 @@ export function BuyBackShares(corporation: ICorporation, player: IPlayer, numSha
|
||||
return true;
|
||||
}
|
||||
|
||||
export function AssignJob(employee: Employee, job: string): void {
|
||||
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 (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
|
||||
employee.pos = job;
|
||||
|
||||
office.assignSingleJob(employee, job);
|
||||
}
|
||||
|
||||
export function AutoAssignJob(office: OfficeSpace, job: string, count: number): boolean {
|
||||
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
|
||||
|
||||
return office.autoAssignJob(job, count);
|
||||
}
|
||||
|
||||
export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size: number): void {
|
||||
|
@ -34,6 +34,7 @@ export class Employee {
|
||||
cyclesUntilRaise = CorporationConstants.CyclesPerEmployeeRaise;
|
||||
loc: string;
|
||||
pos: string;
|
||||
nextPos: string;
|
||||
|
||||
constructor(params: IParams = {}) {
|
||||
this.name = params.name ? params.name : "Bobby";
|
||||
@ -52,6 +53,7 @@ export class Employee {
|
||||
|
||||
this.loc = params.loc ? params.loc : "";
|
||||
this.pos = EmployeePositions.Unassigned;
|
||||
this.nextPos = this.pos;
|
||||
}
|
||||
|
||||
//Returns the amount the employee needs to be paid
|
||||
|
@ -37,7 +37,15 @@ export class OfficeSpace {
|
||||
[EmployeePositions.RandD]: 0,
|
||||
[EmployeePositions.Training]: 0,
|
||||
[EmployeePositions.Unassigned]: 0,
|
||||
total: 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,
|
||||
};
|
||||
|
||||
constructor(params: IParams = {}) {
|
||||
@ -58,7 +66,13 @@ export class OfficeSpace {
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.employees.length; ++i) {
|
||||
const emp = this.employees[i];
|
||||
emp.pos = emp.nextPos;
|
||||
}
|
||||
|
||||
this.calculateTotalEmployees();
|
||||
this.calculateNextEmployees();
|
||||
|
||||
// Process Office properties
|
||||
this.maxEne = 100;
|
||||
@ -113,6 +127,18 @@ export class OfficeSpace {
|
||||
return salaryPaid;
|
||||
}
|
||||
|
||||
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)) {
|
||||
@ -123,7 +149,6 @@ export class OfficeSpace {
|
||||
const employee = this.employees[i];
|
||||
this.employeeJobs[employee.pos]++;
|
||||
}
|
||||
this.employeeJobs.total = this.employees.length;
|
||||
}
|
||||
|
||||
calculateEmployeeProductivity(corporation: ICorporation, industry: IIndustry): void {
|
||||
@ -173,45 +198,33 @@ export class OfficeSpace {
|
||||
emp.name = name;
|
||||
this.employees.push(emp);
|
||||
|
||||
this.calculateTotalEmployees();
|
||||
this.calculateNextEmployees();
|
||||
return emp;
|
||||
}
|
||||
|
||||
//Finds the first unassigned employee and assigns its to the specified job
|
||||
assignEmployeeToJob(job: string): boolean {
|
||||
for (let i = 0; i < this.employees.length; ++i) {
|
||||
if (this.employees[i].pos === EmployeePositions.Unassigned) {
|
||||
this.employees[i].pos = job;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
assignSingleJob(employee: Employee, job: string): void {
|
||||
employee.nextPos = job;
|
||||
this.calculateNextEmployees();
|
||||
}
|
||||
|
||||
//Finds the first employee with the given job and unassigns it
|
||||
unassignEmployeeFromJob(job: string): boolean {
|
||||
for (let i = 0; i < this.employees.length; ++i) {
|
||||
if (this.employees[i].pos === job) {
|
||||
this.employees[i].pos = EmployeePositions.Unassigned;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
setEmployeeToJob(job: string, amount: number): boolean {
|
||||
let jobCount = this.employees.reduce((acc, employee) => (employee.pos === job ? acc + 1 : acc), 0);
|
||||
autoAssignJob(job: string, target: number): boolean {
|
||||
let count = this.employeeNextJobs[job];
|
||||
|
||||
for (const employee of this.employees) {
|
||||
if (jobCount == amount) return true;
|
||||
if (employee.pos === EmployeePositions.Unassigned && jobCount <= amount) {
|
||||
employee.pos = job;
|
||||
jobCount++;
|
||||
} else if (employee.pos === job && jobCount >= amount) {
|
||||
employee.pos = EmployeePositions.Unassigned;
|
||||
jobCount--;
|
||||
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--;
|
||||
}
|
||||
}
|
||||
return jobCount === amount;
|
||||
|
||||
this.calculateNextEmployees();
|
||||
return count === target;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
|
@ -115,14 +115,14 @@ function ManualManagement(props: IProps): React.ReactElement {
|
||||
{positionNames[i]}
|
||||
</MenuItem>,
|
||||
);
|
||||
if (emp != null && emp.pos === positionNames[i]) {
|
||||
employeePositionSelectorInitialValue = positionNames[i];
|
||||
if (emp != null && emp.nextPos === positionNames[i]) {
|
||||
employeePositionSelectorInitialValue = emp.nextPos;
|
||||
}
|
||||
}
|
||||
|
||||
function employeePositionSelectorOnChange(e: SelectChangeEvent<string>): void {
|
||||
if (employee === null) return;
|
||||
employee.pos = e.target.value;
|
||||
props.office.assignSingleJob(employee, e.target.value);
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
@ -181,38 +181,40 @@ interface IAutoAssignProps {
|
||||
function AutoAssignJob(props: IAutoAssignProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division = useDivision();
|
||||
const numJob = countEmployee(props.office.employees, props.job);
|
||||
const numUnassigned = countEmployee(props.office.employees, EmployeePositions.Unassigned);
|
||||
|
||||
const currJob = props.office.employeeJobs[props.job];
|
||||
const nextJob = props.office.employeeNextJobs[props.job];
|
||||
const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned];
|
||||
|
||||
function assignEmployee(): void {
|
||||
if (numUnassigned <= 0) {
|
||||
if (nextUna <= 0) {
|
||||
console.warn("Cannot assign employee. No unassigned employees available");
|
||||
return;
|
||||
}
|
||||
|
||||
props.office.assignEmployeeToJob(props.job);
|
||||
props.office.calculateEmployeeProductivity(corp, division);
|
||||
props.office.autoAssignJob(props.job, nextJob + 1);
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
function unassignEmployee(): void {
|
||||
props.office.unassignEmployeeFromJob(props.job);
|
||||
props.office.calculateEmployeeProductivity(corp, division);
|
||||
props.office.autoAssignJob(props.job, nextJob - 1);
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
return (
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Tooltip title={props.desc}>
|
||||
<Typography>
|
||||
{props.job} ({numJob})
|
||||
{props.job} ({(currJob == nextJob ? currJob : `${currJob} -> ${nextJob}`)})
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<IconButton disabled={numUnassigned === 0} onClick={assignEmployee}>
|
||||
<IconButton disabled={nextUna === 0} onClick={assignEmployee}>
|
||||
<ArrowDropUpIcon />
|
||||
</IconButton>
|
||||
<IconButton disabled={numJob === 0} onClick={unassignEmployee}>
|
||||
<IconButton disabled={nextJob === 0} onClick={unassignEmployee}>
|
||||
<ArrowDropDownIcon />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
@ -223,7 +225,6 @@ function AutoAssignJob(props: IAutoAssignProps): React.ReactElement {
|
||||
function AutoManagement(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division = useDivision();
|
||||
const numUnassigned = countEmployee(props.office.employees, EmployeePositions.Unassigned);
|
||||
const vechain = corp.unlockUpgrades[4] === 1; // Has Vechain upgrade
|
||||
|
||||
// Calculate average morale, happiness, energy, and salary.
|
||||
@ -247,6 +248,9 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
avgEnergy = totalEnergy / props.office.employees.length;
|
||||
}
|
||||
|
||||
const currUna = props.office.employeeJobs[EmployeePositions.Unassigned];
|
||||
const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table padding="none">
|
||||
@ -256,7 +260,7 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<Typography>Unassigned Employees:</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography>{numUnassigned}</Typography>
|
||||
<Typography>{(currUna == nextUna ? currUna : `${currUna} -> ${nextUna}`)}</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
|
@ -34,6 +34,7 @@ import {
|
||||
SetSmartSupply,
|
||||
BuyMaterial,
|
||||
AssignJob,
|
||||
AutoAssignJob,
|
||||
UpgradeOfficeSize,
|
||||
ThrowParty,
|
||||
PurchaseWarehouse,
|
||||
@ -685,20 +686,6 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
||||
const researchName = ctx.helper.string("researchName", _researchName);
|
||||
return hasResearched(getDivision(divisionName), researchName);
|
||||
},
|
||||
setAutoJobAssignment:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _job: unknown, _amount: unknown): Promise<boolean> => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const amount = ctx.helper.number("amount", _amount);
|
||||
const job = ctx.helper.string("job", _job);
|
||||
const office = getOffice(divisionName, cityName);
|
||||
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
|
||||
return netscriptDelay(1000, workerScript).then(function () {
|
||||
return Promise.resolve(office.setEmployeeToJob(job, amount));
|
||||
});
|
||||
},
|
||||
getOfficeSizeUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _size: unknown): number => {
|
||||
@ -724,10 +711,31 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const employeeName = ctx.helper.string("employeeName", _employeeName);
|
||||
const job = ctx.helper.string("job", _job);
|
||||
const employee = getEmployee(divisionName, cityName, employeeName);
|
||||
return netscriptDelay(["Training", "Unassigned"].includes(employee.pos) ? 0 : 1000, workerScript).then(function () {
|
||||
return Promise.resolve(AssignJob(employee, job));
|
||||
|
||||
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
|
||||
const office = getOffice(divisionName, cityName);
|
||||
|
||||
return netscriptDelay(0, workerScript).then(function () {
|
||||
return Promise.resolve(AssignJob(office, employeeName, job));
|
||||
});
|
||||
//return AssignJob(office, employeeName, job);
|
||||
},
|
||||
setAutoJobAssignment:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _job: unknown, _amount: unknown): Promise<boolean> => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const amount = ctx.helper.number("amount", _amount);
|
||||
const job = ctx.helper.string("job", _job);
|
||||
|
||||
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
|
||||
const office = getOffice(divisionName, cityName);
|
||||
|
||||
return netscriptDelay(0, workerScript).then(function () {
|
||||
return Promise.resolve(AutoAssignJob(office, job, amount));
|
||||
});
|
||||
//return AutoAssignJob(office, job, amount);
|
||||
},
|
||||
hireEmployee:
|
||||
(ctx: NetscriptContext) =>
|
||||
|
Loading…
Reference in New Issue
Block a user