Merge pull request #3954 from Snarling/contractFix

CONTRACTS: FIX #3755 change input handling for contract attempts
This commit is contained in:
hydroflame 2022-08-23 12:44:27 -03:00 committed by GitHub
commit fa099c22ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 19 additions and 30 deletions

@ -1,5 +1,7 @@
import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Player as player } from "../Player"; import { Player as player } from "../Player";
import { is2DArray } from "../utils/helpers/is2DArray"; import { is2DArray } from "../utils/helpers/is2DArray
import { CodingContract } from "../CodingContracts"; import { CodingContract } from "../CodingContracts";
import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions"; import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
@ -34,20 +36,11 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
const hostname = helpers.string(ctx, "hostname", _hostname); const hostname = helpers.string(ctx, "hostname", _hostname);
const contract = getCodingContract(ctx, "attempt", hostname, filename); const contract = getCodingContract(ctx, "attempt", hostname, filename);
// Convert answer to string. If the answer is a 2D array, then we have to if (typeof answer !== "number" && typeof answer !== "string" && !Array.isArray(answer))
// manually add brackets for the inner arrays throw new Error("The answer provided was not a number, string, or array");
let answerStr = "";
if (is2DArray(answer)) {
const answerComponents = [];
for (let i = 0; i < answer.length; ++i) {
answerComponents.push(["[", String(answer[i]), "]"].join(""));
}
answerStr = answerComponents.join(",");
} else {
answerStr = String(answer);
}
// Convert answer to string.
const answerStr = JSON.stringify(answer);
const creward = contract.reward; const creward = contract.reward;
if (creward === null) throw new Error("Somehow solved a contract that didn't have a reward"); if (creward === null) throw new Error("Somehow solved a contract that didn't have a reward");

@ -3222,7 +3222,12 @@ export interface CodingContract {
* @param opts - Optional parameters for configuring function behavior. * @param opts - Optional parameters for configuring function behavior.
* @returns True if the solution was correct, false otherwise. If the returnReward option is configured, then the function will instead return a string. If the contract is successfully solved, the string will contain a description of the contracts reward. Otherwise, it will be an empty string. * @returns True if the solution was correct, false otherwise. If the returnReward option is configured, then the function will instead return a string. If the contract is successfully solved, the string will contain a description of the contracts reward. Otherwise, it will be an empty string.
*/ */
attempt(answer: string[] | number, filename: string, host?: string, opts?: CodingAttemptOptions): boolean | string; attempt(
answer: string | number | any[],
filename: string,
host?: string,
opts?: CodingAttemptOptions,
): boolean | string;
/** /**
* Get the type of a coding contract. * Get the type of a coding contract.

@ -1422,9 +1422,13 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
}, },
solver: (_data: unknown, ans: string): boolean => { solver: (_data: unknown, ans: string): boolean => {
const data = _data as [number, [number, number][]]; const data = _data as [number, [number, number][]];
//Sanitize player input
const sanitizedPlayerAns: string = removeBracketsFromArrayString(ans);
//Case where the player believes there is no solution. //Case where the player believes there is no solution.
//Attempt to construct one to check if this is correct. //Attempt to construct one to check if this is correct.
if (ans == "[]") { if (sanitizedPlayerAns === "") {
//Helper function to get neighbourhood of a vertex //Helper function to get neighbourhood of a vertex
function neighbourhood(vertex: number): number[] { function neighbourhood(vertex: number): number[] {
const adjLeft = data[1].filter(([a]) => a == vertex).map(([, b]) => b); const adjLeft = data[1].filter(([a]) => a == vertex).map(([, b]) => b);
@ -1473,12 +1477,9 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
return false; return false;
} }
//Sanitize player input //Solution provided case
const sanitizedPlayerAns: string = removeBracketsFromArrayString(ans);
const sanitizedPlayerAnsArr: string[] = sanitizedPlayerAns.split(","); const sanitizedPlayerAnsArr: string[] = sanitizedPlayerAns.split(",");
const coloring: number[] = sanitizedPlayerAnsArr.map((val) => parseInt(val)); const coloring: number[] = sanitizedPlayerAnsArr.map((val) => parseInt(val));
//Solution provided case
if (coloring.length == data[0]) { if (coloring.length == data[0]) {
const edges = data[1]; const edges = data[1];
const validColors = [0, 1]; const validColors = [0, 1];

@ -1,10 +0,0 @@
export function isArray(arr: unknown): arr is unknown[] {
return Array.isArray(arr);
}
// Checks whether an array is a 2D array.
// For this, a 2D array is an array which contains only other arrays.
// If one element in the array is a number or string, it is NOT a 2D array
export function is2DArray(arr: unknown): arr is unknown[][] {
return isArray(arr) && arr.every((u) => isArray(u));
}