CODEBASE: Refactor Player.applyForJob (#1947)

This commit is contained in:
catloversg
2025-02-03 00:29:18 +07:00
committed by GitHub
parent 72d2528e9a
commit de6b202341
4 changed files with 133 additions and 37 deletions

View File

@@ -9,6 +9,7 @@ import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
import { JobSummary } from "./JobSummary";
import { Requirement } from "../../ui/Components/Requirement";
import { getJobRequirements } from "../GetJobRequirements";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
interface ApplyToJobProps {
company: Company;
@@ -47,7 +48,10 @@ export function ApplyToJobButton({ company, position, qualified }: ApplyToJobPro
);
function applyForJob(): void {
Player.applyForJob(company, position);
const result = Player.applyForJob(company, position);
if (result.message) {
dialogBoxCreate(result.message);
}
}
return (

View File

@@ -714,13 +714,17 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
const company = Companies[companyName];
const entryPos = CompanyPositions[JobTracks[field][0]];
const jobName = Player.applyForJob(company, entryPos, true);
if (jobName) {
helpers.log(ctx, () => `You were offered a new job at '${companyName}' with position '${jobName}'`);
} else {
helpers.log(ctx, () => `You failed to get a new job/promotion at '${companyName}' in the '${field}' field.`);
const result = Player.applyForJob(company, entryPos);
if (!result.success) {
helpers.log(
ctx,
() =>
`You failed to get a new job/promotion at '${companyName}' in the '${field}' field. Reason: ${result.message}`,
);
return null;
}
return jobName;
helpers.log(ctx, () => `You were offered a new job at '${companyName}' with position '${result.jobName}'.`);
return result.jobName;
},
quitJob: (ctx) => (_companyName) => {
helpers.checkSingularityAccess(ctx);

View File

@@ -53,6 +53,7 @@ import { canAccessBitNodeFeature } from "../../BitNode/BitNodeUtils";
import { AlertEvents } from "../../ui/React/AlertManager";
import { Augmentations } from "../../Augmentation/Augmentations";
import { PlayerEventType, PlayerEvents } from "./PlayerEvents";
import { Result } from "../../types";
export function init(this: PlayerObject): void {
/* Initialize Player's home computer */
@@ -288,22 +289,25 @@ export function applyForJob(
this: PlayerObject,
company: Company,
position: CompanyPosition,
sing = false,
): JobName | null {
if (!company) return null;
): Result<{ jobName: JobName }> {
if (!company) {
return { success: false, message: `Invalid company: ${company}.` };
}
// Start searching the job track from the provided point (which may not be the entry position)
let pos = position;
if (!this.isQualified(company, pos)) {
if (!sing) {
dialogBoxCreate(`Unfortunately, you do not qualify for this position.\n${getJobRequirementText(company, pos)}`);
}
return null;
return {
success: false,
message: `Unfortunately, you do not qualify for this position.\n${getJobRequirementText(company, pos)}`,
};
}
if (!company.hasPosition(pos)) {
console.error(`Company ${company.name} does not have position ${pos.name}. Player.applyToCompany() failed.`);
return null;
return {
success: false,
message: `Company ${company.name} does not have position ${pos.name}.`,
};
}
let nextPos = getNextCompanyPositionHelper(pos);
@@ -312,31 +316,27 @@ export function applyForJob(
nextPos = getNextCompanyPositionHelper(pos);
}
//Check if player already has the assigned job
// Check if player already has the assigned job
if (this.jobs[company.name] === pos.name) {
if (!sing) {
const nextPos = getNextCompanyPositionHelper(pos);
if (nextPos == null) {
dialogBoxCreate(`You are already ${pos.name}! No promotion available`);
} else if (!company.hasPosition(nextPos)) {
dialogBoxCreate(
`You already have the highest ${pos.field} position available at ${company.name}! No promotion available`,
);
} else {
dialogBoxCreate(
`Unfortunately, you do not qualify for a promotion.\n${getJobRequirementText(company, nextPos)}`,
);
}
let errorMessage;
const nextPos = getNextCompanyPositionHelper(pos);
if (nextPos === null) {
errorMessage = `You are already ${pos.name}! No promotion available.`;
} else if (!company.hasPosition(nextPos)) {
errorMessage = `You already have the highest ${pos.field} position available at ${company.name}! No promotion available.`;
} else {
errorMessage = `Unfortunately, you do not qualify for a promotion.\n${getJobRequirementText(company, nextPos)}`;
}
return null;
return { success: false, message: errorMessage };
}
this.jobs[company.name] = pos.name;
if (!sing) {
dialogBoxCreate(`${pos.hiredText} at ${company.name}!`);
}
return pos.name;
return {
success: true,
message: `${pos.hiredText} at ${company.name}!`,
jobName: pos.name,
};
}
/**

View File

@@ -1,6 +1,6 @@
import { installAugmentations } from "../../../src/Augmentation/AugmentationHelpers";
import { blackOpsArray } from "../../../src/Bladeburner/data/BlackOperations";
import { AugmentationName, FactionName } from "@enums";
import { AugmentationName, CompanyName, FactionName, JobField, JobName } from "@enums";
import { Player } from "@player";
import { prestigeSourceFile } from "../../../src/Prestige";
import { GetServerOrThrow } from "../../../src/Server/AllServers";
@@ -10,6 +10,10 @@ import { PlayerOwnedAugmentation } from "../../../src/Augmentation/PlayerOwnedAu
import { getNS, initGameEnvironment, setupBasicTestingEnvironment } from "./Utilities";
import { Terminal } from "../../../src/Terminal";
import type { NSFull } from "../../../src/NetscriptFunctions";
import { Companies } from "../../../src/Company/Companies";
import { CompanyPositions } from "../../../src/Company/CompanyPositions";
const nextBN = 3;
function setNumBlackOpsComplete(value: number): void {
if (!Player.bladeburner) {
@@ -18,7 +22,25 @@ function setNumBlackOpsComplete(value: number): void {
Player.bladeburner.numBlackOpsComplete = value;
}
const nextBN = 3;
function gainTonsOfExp() {
Player.exp.hacking = 1e100;
Player.exp.strength = 1e100;
Player.exp.defense = 1e100;
Player.exp.dexterity = 1e100;
Player.exp.agility = 1e100;
Player.exp.charisma = 1e100;
Player.updateSkillLevels();
}
function resetExp() {
Player.exp.hacking = 0;
Player.exp.strength = 0;
Player.exp.defense = 0;
Player.exp.dexterity = 0;
Player.exp.agility = 0;
Player.exp.charisma = 0;
Player.updateSkillLevels();
}
beforeAll(() => {
initGameEnvironment();
@@ -358,3 +380,69 @@ describe("connect", () => {
});
});
});
describe("applyToCompany", () => {
beforeEach(() => {
setupBasicTestingEnvironment();
prestigeSourceFile(true);
gainTonsOfExp();
});
describe("Success", () => {
test("Apply to entry position", () => {
const ns = getNS();
Companies[CompanyName.MegaCorp].playerReputation = 0;
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(JobName.software0);
});
test("Apply and be promoted to next position", () => {
const ns = getNS();
const nextPosition = CompanyPositions["Junior Software Engineer"];
Companies[CompanyName.MegaCorp].playerReputation = nextPosition.requiredReputation;
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(JobName.software1);
});
test("Apply and be promoted to highest position", () => {
const ns = getNS();
Companies[CompanyName.MegaCorp].playerReputation = 1e10;
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(JobName.software7);
});
test("Apply then apply again to be promoted to highest position", () => {
const ns = getNS();
Companies[CompanyName.MegaCorp].playerReputation = 0;
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(JobName.software0);
Companies[CompanyName.MegaCorp].playerReputation = 1e10;
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(JobName.software7);
});
});
describe("Failure", () => {
test("Not qualified", () => {
resetExp();
const ns = getNS();
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(null);
});
test("Invalid field", () => {
const ns = getNS();
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.agent)).toStrictEqual(null);
});
test("Already at highest position", () => {
const ns = getNS();
Companies[CompanyName.MegaCorp].playerReputation = 1e10;
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(JobName.software7);
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(null);
});
test("Already at highest available position", () => {
const ns = getNS();
Companies[CompanyName.WatchdogSecurity].playerReputation = 1e10;
// Watchdog Security only offers up to software5 (Head of Engineering).
expect(ns.singularity.applyToCompany(CompanyName.WatchdogSecurity, JobField.software)).toStrictEqual(
JobName.software5,
);
expect(ns.singularity.applyToCompany(CompanyName.WatchdogSecurity, JobField.software)).toStrictEqual(null);
});
test("Not qualified for promotion", () => {
const ns = getNS();
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(JobName.software0);
expect(ns.singularity.applyToCompany(CompanyName.MegaCorp, JobField.software)).toStrictEqual(null);
});
});
});