BUGFIX: Coding contract UI does not handle error properly when answer format is invalid (#2171)

This commit is contained in:
catloversg
2025-06-02 16:33:57 +07:00
committed by GitHub
parent 67017c5782
commit 856ce9a5c9
4 changed files with 132 additions and 61 deletions
+46 -27
View File
@@ -1,5 +1,5 @@
import { Player } from "@player";
import { CodingContract } from "../CodingContract/Contract";
import { CodingContract, CodingContractResult } from "../CodingContract/Contract";
import { CodingContractObject, CodingContract as ICodingContract } from "@nsdefs";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { helpers } from "../Netscript/NetscriptHelpers";
@@ -7,6 +7,7 @@ import { CodingContractName } from "@enums";
import { generateDummyContract } from "../CodingContract/ContractGenerator";
import { isCodingContractName } from "../CodingContract/ContractTypes";
import { type BaseServer } from "../Server/BaseServer";
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
const getCodingContract = function (ctx: NetscriptContext, hostname: string, filename: string): CodingContract {
@@ -25,26 +26,51 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
contract: CodingContract,
answer: unknown,
): string {
if (contract.isSolution(answer)) {
const reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty());
helpers.log(ctx, () => `Successfully completed Coding Contract '${contract.fn}'. Reward: ${reward}`);
server.removeContract(contract.fn);
return reward;
const validationResult = contract.isValid(answer);
if (!validationResult.success) {
throw helpers.errorMessage(ctx, validationResult.message);
}
if (++contract.tries >= contract.getMaxNumTries()) {
helpers.log(ctx, () => `Coding Contract attempt '${contract.fn}' failed. Contract is now self-destructing`);
server.removeContract(contract.fn);
} else {
helpers.log(
ctx,
() =>
`Coding Contract attempt '${contract.fn}' failed. ${
contract.getMaxNumTries() - contract.tries
} attempt(s) remaining.`,
);
const resultOfCheckingSolution = contract.isSolution(answer);
switch (resultOfCheckingSolution.result) {
case CodingContractResult.Success: {
const reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty());
helpers.log(ctx, () => `Successfully completed Coding Contract '${contract.fn}'. Reward: ${reward}`);
server.removeContract(contract.fn);
return reward;
}
/**
* This should never happen. If the answer format is invalid, it should already be handled by the call to
* contract.isValid() above.
*/
case CodingContractResult.InvalidFormat: {
exceptionAlert(
new Error(
`contract.isSolution() returns unexpected InvalidFormat result. Type: ${contract.type}. Answer: ${answer}`,
),
true,
);
return "";
}
case CodingContractResult.Failure: {
if (++contract.tries >= contract.getMaxNumTries()) {
helpers.log(ctx, () => `Coding Contract attempt '${contract.fn}' failed. Contract is now self-destructing`);
server.removeContract(contract.fn);
} else {
helpers.log(
ctx,
() =>
`Coding Contract attempt '${contract.fn}' failed. ${
contract.getMaxNumTries() - contract.tries
} attempt(s) remaining.`,
);
}
return "";
}
default: {
const __: never = resultOfCheckingSolution.result;
}
}
return "";
}
@@ -53,15 +79,8 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
const filename = helpers.string(ctx, "filename", _filename);
const host = _host ? helpers.string(ctx, "host", _host) : ctx.workerScript.hostname;
const contract = getCodingContract(ctx, host, filename);
if (!contract.isValid(answer))
throw helpers.errorMessage(
ctx,
`Answer is not in the right format for contract '${contract.type}'. Got: ${answer}`,
);
const serv = helpers.getServer(ctx, host);
return attemptContract(ctx, serv, contract, answer);
const server = helpers.getServer(ctx, host);
return attemptContract(ctx, server, contract, answer);
},
getContractType: (ctx) => (_filename, _host?) => {
const filename = helpers.string(ctx, "filename", _filename);