CORPORATION: Rename setAutoJobAssignment API to setJobAssignment (#2146)

This commit is contained in:
catloversg
2025-05-23 02:42:16 +07:00
committed by GitHub
parent 47153bd31c
commit 4e5044124c
8 changed files with 63 additions and 29 deletions

View File

@@ -30,7 +30,7 @@ Requires the Office API upgrade from your corporation.
| [hireAdVert(divisionName)](./bitburner.officeapi.hireadvert.md) | Hire AdVert. |
| [hireEmployee(divisionName, city, employeePosition)](./bitburner.officeapi.hireemployee.md) | Hire an employee. |
| [research(divisionName, researchName)](./bitburner.officeapi.research.md) | Purchase a research. |
| [setAutoJobAssignment(divisionName, city, job, amount)](./bitburner.officeapi.setautojobassignment.md) | Set the job assignment for a job. |
| [setJobAssignment(divisionName, city, job, amount)](./bitburner.officeapi.setjobassignment.md) | Set the job assignment for a job. |
| [throwParty(divisionName, city, costPerEmployee)](./bitburner.officeapi.throwparty.md) | Throw a party for your employees. |
| [upgradeOfficeSize(divisionName, city, size)](./bitburner.officeapi.upgradeofficesize.md) | Upgrade office size. |

View File

@@ -1,15 +1,20 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [OfficeAPI](./bitburner.officeapi.md) &gt; [setAutoJobAssignment](./bitburner.officeapi.setautojobassignment.md)
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [OfficeAPI](./bitburner.officeapi.md) &gt; [setJobAssignment](./bitburner.officeapi.setjobassignment.md)
## OfficeAPI.setAutoJobAssignment() method
## OfficeAPI.setJobAssignment() method
Set the job assignment for a job.
**Signature:**
```typescript
setAutoJobAssignment(divisionName: string, city: CityName, job: string, amount: number): boolean;
setJobAssignment(
divisionName: string,
city: CityName,
job: Exclude<CorpEmployeePosition, "Unassigned">,
amount: number,
): boolean;
```
## Parameters
@@ -18,7 +23,7 @@ setAutoJobAssignment(divisionName: string, city: CityName, job: string, amount:
| --- | --- | --- |
| divisionName | string | Name of the division |
| city | [CityName](./bitburner.cityname.md) | Name of the city |
| job | string | Name of the job |
| job | Exclude&lt;[CorpEmployeePosition](./bitburner.corpemployeeposition.md)<!-- -->, "Unassigned"&gt; | Name of the job. Passing "Unassigned" will cause this API to not do anything and just return false. |
| amount | number | Number of employees to assign to that job |
**Returns:**

View File

@@ -127,7 +127,7 @@ Check the optimizer in this [section](./boost-material.md).
API (`upgradeOfficeSize`) gives you granular control over office size. You cannot do that through UI.
#### Why does setAutoJobAssignment not take effect immediately?
#### Why does `setJobAssignment` not take effect immediately?
It only takes effect in the next cycle's START state.

View File

@@ -2,7 +2,7 @@
## Basic information
Employee's stats are kept track as average value. There are 6 average values: `AvgEnergy`, `AvgMorale`, `AvgIntelligence`, `AvgCharisma`, `AvgCreativity`, `AvgEfficiency`. Every time you hire a new employee, these average values are recalculated, they are modified by a randomized number from 50 to 100:
Employee stats are kept track of as average values. There are 6 average values: `AvgEnergy`, `AvgMorale`, `AvgIntelligence`, `AvgCharisma`, `AvgCreativity`, `AvgEfficiency`. Every time you hire a new employee, these average values are recalculated. They are modified by a randomized number from 50 to 100:
```typescript
this.avgMorale =
@@ -11,19 +11,19 @@ this.avgMorale =
Job assignment:
- Each office has 2 records: `employeeJobs` and `employeeNextJobs`. Data in `employeeJobs` (number of employees in each job) is used for calculations of other relevant data like `EmployeeProductionByJob`, `AvgEnergy`, `AvgMorale`, `TotalExperience`. When you call `setAutoJobAssignment`, its parameter is calculated and assigned to `employeeNextJobs`. In next cycle's START state, data in `employeeNextJobs` will be copied to `employeeJobs`.
- Behavior of `setAutoJobAssignment` may be confused at first glance. Let's say you call it like this: `ns.corporation.setAutoJobAssignment("Agriculture","Sector-12","Operations", 5)`
- Each office has 2 records: `employeeJobs` and `employeeNextJobs`. Data in `employeeJobs` (number of employees in each job) is used for calculations of other relevant data like `EmployeeProductionByJob`, `AvgEnergy`, `AvgMorale`, `TotalExperience`. When you call `setJobAssignment`, its parameter is calculated and assigned to `employeeNextJobs`. In the next cycle's START state, data in `employeeNextJobs` will be copied to `employeeJobs`.
- Behavior of `setJobAssignment` may be confused at first glance. Let's say you call it like this: `ns.corporation.setJobAssignment("Agriculture","Sector-12","Operations", 5)`
- If you have 5 \"Operations\" employees, it does nothing.
- If you have 7 \"Operations\" employees, it reduces number of \"Operations\" employees to 5, and set \"Unassigned\" employees to 2.
- If you have 2 \"Operations\" employees, it checks if you have at least 3 \"Unassigned\" employees. If yes, it changes \"Operations\" employees to 5 and reduces \"Unassigned\" employees by 3. If not, it throws error. Essentially, it tries to move employees from \"Unassigned\" to \"Operations\".
- This means the proper way to use `setAutoJobAssignment` is:
- This means the proper way to use `setJobAssignment` is:
- Use it to set all jobs to 0.
- Use it to set all jobs to your requirements.
Total experience is increased in these cases:
- Hire new employee. Each new employee increases total experience by `getRandomInt(50, 100)`.
- In START state. Gain per cycle:
- Hire a new employee. Each new employee increases total experience by `getRandomInt(50, 100)`.
- In the START state. Gain per cycle:
$$TotalExperienceGain = 0.0015\ast(TotalEmployees - UnassignedEmployees + InternEmployees\ast 9)$$
@@ -65,7 +65,7 @@ $$MaxSize = 3\ast\log_{1.09}\left( MaxCost\ast\frac{0.09}{BasePrice} + {1.09}^{\
## Energy and morale
They are calculated in START state.
They are calculated in the START state.
They start dropping when your office's number of employees is greater than or equal to 9. The minimum value is 10.
@@ -83,9 +83,9 @@ When throwing party, `PartyMult` is calculated. It's used in the calculation of
$$PartyMult = 1 + \frac{PartyCostPerEmployee}{10^{7}}$$
`PartyMult` is not affected by number of employees. Therefore, you can throw a "big party" (high `PartyCostPerEmployee`) when you have 1 employee at low total cost (due to having only 1 employee), then hire the rest of employees later.
`PartyMult` is not affected by the number of employees. Therefore, you can throw a "big party" (high `PartyCostPerEmployee`) when you have 1 employee at low total cost (due to having only 1 employee), then hire the rest of the employees later.
There is a flat randomized reduction of energy/morale per cycle. It's capped at 0.002 per cycle. This is tiny so it's not a problem.
There is a flat randomized reduction of energy/morale per cycle. It's capped at 0.002 per cycle. This is tiny, so it's not a problem.
There is a flat increase of morale if `PartyMult` is greater than 1. `PartyMult` is based on `PartyCostPerEmployee`, so this increase is based on `PartyCostPerEmployee`.
@@ -104,11 +104,11 @@ this.avgMorale = ((this.avgMorale - reduction * Math.random()) * perfMult + incr
There are 3 ways to counter the drop of energy/morale:
- Buy tea and throw party. You should always use this option. Writing script to automate them is very easy.
- Buy tea and throw party. You should always use this option. Writing a script to automate them is very easy.
- Assign Intern. Many people throw around the ratio 1/9 as the way to counter the drop of energy/morale. You can only use that ratio when your corporation/division works fine. If it does not, there is a penalty multiplier (0.001). In this case, you need to use 1/6.
- Buy 2 research upgrades: AutoBrew and AutoPartyManager. They keep energy/morale at maximum value. However, you should never buy them. It's always better to spend your RP on other useful research upgrades or just stock up on RP.
`AvgEnergy` and `AvgMorale` are increased by a randomized amount when we hire new employee.
`AvgEnergy` and `AvgMorale` are increased by a randomized amount when we hire a new employee.
```typescript
this.avgMorale = (this.avgMorale * this.numEmployees + getRandomInt(50, 100)) / (this.numEmployees + 1);
@@ -146,7 +146,7 @@ $$x_{2} = 500000\ast\left( \sqrt{(a\ast k - 10)^{2} + 40\ast b} - a\ast k - 10 \
One big party is less cost-effective than multiple small parties. For example: throwing 1 big party for 70→100 morale costs more than throwing 3 small parties: 70→80, 80→90, 90→100.
Don't be a cheapskate when it comes to tea/party. Energy and morale are vital to efficient office. Check the next part for the formulas.
Don't be a cheapskate when it comes to tea/party. Energy and morale are vital to an efficient office. Check the next part for the formulas.
- It's fine to spend 500e3 per employee when throwing party. You can spend more if you want.
- Try to maintain maximum energy/morale at all times. Personally, I always buy tea / throw party when energy/morale decreases to 99.5 (109.5, if I bought the relevant research upgrades).
@@ -154,7 +154,7 @@ Don't be a cheapskate when it comes to tea/party. Energy and morale are vital to
## Employee production by job
In each cycle's START state, all stats are used for calculating "production" values, these values are saved in `office.employeeProductionByJob`. These values can be used later for calculating:
In each cycle's START state, all stats are used for calculating "production" values. These values are saved in `office.employeeProductionByJob` and used later for calculating:
- RP.
- Material's quality.
@@ -164,7 +164,7 @@ In each cycle's START state, all stats are used for calculating "production" val
Formulas:
- Calculate multipliers of Intelligence, Charisma, Creativity, and Efficiency. They are the product of average value, upgrade benefit and research benefit.
- Calculate multipliers of Intelligence, Charisma, Creativity, and Efficiency. They are the product of average values, upgrade benefit and research benefit.
- Production base:
$$ProductionBase = AvgMorale\ast AvgEnergy\ast 10^{-4}$$
@@ -188,4 +188,4 @@ $$EmployeeProductionByJob = EmployeesJobCount\ast ProductionMultiplier\ast Produ
4 stats `AvgIntelligence`, `AvgCharisma`, `AvgCreativity`, `AvgEfficiency` are inaccessible through NS API.
We can calculate them by using the formulas from previous part and [Ceres Solver](./miscellany.md). In 5 jobs Operations, Engineer, Business, Management, Research & Development, we need at least 4 jobs having 1 employee at the minimum to use this solution.
We can calculate them by using the formulas from the previous part and [Ceres Solver](./miscellany.md). In 5 jobs (i.e., Operations, Engineer, Business, Management, and Research & Development), we need at least 4 jobs having 1 employee at the minimum to use this solution.

View File

@@ -484,7 +484,7 @@ const corporation = {
getHireAdVertCount: RamCostConstants.CorporationInfo,
getResearchCost: RamCostConstants.CorporationInfo,
hasResearched: RamCostConstants.CorporationInfo,
setAutoJobAssignment: RamCostConstants.CorporationAction,
setJobAssignment: RamCostConstants.CorporationAction,
getOfficeSizeUpgradeCost: RamCostConstants.CorporationInfo,
} as const;

View File

@@ -487,29 +487,37 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
const office = getOffice(divisionName, cityName);
return calculateOfficeSizeUpgradeCost(office.size, increase);
},
setAutoJobAssignment: (ctx) => (_divisionName, _cityName, _job, _amount) => {
setJobAssignment: (ctx) => (_divisionName, _cityName, _job, _amount) => {
checkAccess(ctx, CorpUnlockName.OfficeAPI);
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
const cityName = getEnumHelper("CityName").nsGetMember(ctx, _cityName);
const amount = helpers.number(ctx, "amount", _amount);
const job = getEnumHelper("CorpEmployeeJob").nsGetMember(ctx, _job, "job");
if (job === CorpEmployeeJob.Unassigned) return false;
if (amount < 0 || !Number.isInteger(amount))
if (job === CorpEmployeeJob.Unassigned) {
helpers.log(
ctx,
() => `This API will not do anything and just return false if you pass "Unassigned" to the "job" parameter.`,
);
return false;
}
if (amount < 0 || !Number.isInteger(amount)) {
throw helpers.errorMessage(
ctx,
`Invalid value for amount! Must be an integer and greater than or be 0". Amount:'${amount}'`,
);
}
const office = getOffice(divisionName, cityName);
const totalNewEmployees = amount - office.employeeNextJobs[job];
if (office.employeeNextJobs[CorpEmployeeJob.Unassigned] < totalNewEmployees)
if (office.employeeNextJobs[CorpEmployeeJob.Unassigned] < totalNewEmployees) {
throw helpers.errorMessage(
ctx,
`Unable to bring '${job} employees to ${amount}. Requires ${totalNewEmployees} unassigned employees`,
);
}
return office.autoAssignJob(job, amount);
},
hireEmployee: (ctx) => (_divisionName, _cityName, _position) => {
@@ -797,7 +805,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
setRemovedFunctions(corpFunctions, {
assignJob: {
version: "2.2.0",
replacement: "Removed due to employees no longer being objects. Use ns.corporation.setAutoJobAssignment instead.",
replacement: "Removed due to employees no longer being objects. Use ns.corporation.setJobAssignment instead.",
replaceMsg: true,
},
getEmployee: {
@@ -813,6 +821,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
getResearchNames: { version: "2.2.0", replacement: "corporation.getConstants().researchNames" },
getUnlockables: { version: "2.2.0", replacement: "corporation.getConstants().unlockNames" },
getUpgradeNames: { version: "2.2.0", replacement: "corporation.getConstants().upgradeNames" },
setAutoJobAssignment: { version: "3.0.0", replacement: "corporation.setJobAssignment()" },
});
return corpFunctions;
}

View File

@@ -8906,11 +8906,16 @@ export interface OfficeAPI {
*
* @param divisionName - Name of the division
* @param city - Name of the city
* @param job - Name of the job
* @param job - Name of the job. Passing "Unassigned" will cause this API to not do anything and just return false.
* @param amount - Number of employees to assign to that job
* @returns true if the employee count reached the target amount, false if not
*/
setAutoJobAssignment(divisionName: string, city: CityName, job: string, amount: number): boolean;
setJobAssignment(
divisionName: string,
city: CityName,
job: Exclude<CorpEmployeePosition, "Unassigned">,
amount: number,
): boolean;
/**
* Get the cost to upgrade an office.

View File

@@ -94,4 +94,19 @@ export const breakInfos300: APIBreakInfo[] = [
'It has been automatically replaced with "ns.ui.setTailTitle()".\n\n',
showPopUp: false,
},
{
brokenAPIs: [
{
name: "ns.corporation.setAutoJobAssignment",
migration: {
searchValue: "setAutoJobAssignment",
replaceValue: "setJobAssignment",
},
},
],
info:
"ns.corporation.setAutoJobAssignment() was removed.\n" +
'It has been automatically replaced with "ns.corporation.setJobAssignment()".\n\n',
showPopUp: false,
},
];