Skip to content

Commit

Permalink
internal type improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
G4mingJon4s committed Jan 10, 2025
1 parent 16afb06 commit 9f6b1c8
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 147 deletions.
8 changes: 2 additions & 6 deletions src/CodingContractGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import {
CodingContract,
CodingContractRewardType,
CodingContractTypes,
ICodingContractReward,
} from "./CodingContracts";
import { CodingContract, CodingContractRewardType, ICodingContractReward } from "./CodingContracts";
import { CodingContractTypes } from "./data/codingcontracttypes";
import { currentNodeMults } from "./BitNode/BitNodeMultipliers";
import { Factions } from "./Faction/Factions";
import { Player } from "@player";
Expand Down
11 changes: 6 additions & 5 deletions src/CodingContracts.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { FactionName, CodingContractName } from "@enums";
import { codingContractTypesMetadata } from "./data/codingcontracttypes";
import { CodingContractTypes } from "./data/codingcontracttypes";

import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "./utils/JSONReviver";
import { CodingContractEvent } from "./ui/React/CodingContractModal";
import { ContractFilePath, resolveContractFilePath } from "./Paths/ContractFilePath";
import { objectAssert } from "./utils/helpers/typeAssertion";

/* Contract Types */
export const CodingContractTypes = Object.fromEntries(codingContractTypesMetadata.map((x) => [x.name, x]));

// Numeric enum
/** Enum representing the different types of rewards a Coding Contract can give */
export enum CodingContractRewardType {
Expand Down Expand Up @@ -64,7 +61,11 @@ export class CodingContract {
/* String representing the contract's type. Must match type in ContractTypes */
type: CodingContractName;

constructor(fn = "default.cct", type = CodingContractName.FindLargestPrimeFactor, reward: ICodingContractReward | null = null) {
constructor(
fn = "default.cct",
type = CodingContractName.FindLargestPrimeFactor,
reward: ICodingContractReward | null = null,
) {
const path = resolveContractFilePath(fn);
if (!path) throw new Error(`Bad file path while creating a coding contract: ${fn}`);
if (!CodingContractTypes[type]) {
Expand Down
10 changes: 5 additions & 5 deletions src/DevMenu/ui/CodingContractsDev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import Button from "@mui/material/Button";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import { generateContract, generateRandomContract, generateRandomContractOnHome } from "../../CodingContractGenerator";
import { CodingContractTypes } from "../../CodingContracts";
import { isCodingContractName } from "../../data/codingcontracttypes";
import { CodingContractName } from "@enums";

export function CodingContractsDev(): React.ReactElement {
const [codingcontract, setCodingcontract] = useState(CodingContractName.FindLargestPrimeFactor);
function setCodingcontractDropdown(event: SelectChangeEvent): void {
const value = event.target.value;
if (!((v: any): v is CodingContractName => Object.values(CodingContractName).includes(v))(value)) return;
if (!isCodingContractName(value)) return;
setCodingcontract(value);
}

Expand Down Expand Up @@ -45,9 +45,9 @@ export function CodingContractsDev(): React.ReactElement {
<tr>
<td>
<Select onChange={setCodingcontractDropdown} value={codingcontract}>
{Object.values(CodingContractTypes).map((cc) => (
<MenuItem key={cc.name} value={cc.name}>
{cc.name}
{Object.values(CodingContractName).map((name) => (
<MenuItem key={name} value={name}>
{name}
</MenuItem>
))}
</Select>
Expand Down
2 changes: 1 addition & 1 deletion src/Enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ export * from "./Programs/Enums";
export * from "./StockMarket/Enums";
export * from "./ui/Enums";
export * from "./Work/Enums";
export { CodingContractName } from "./data/codingcontracttypes";
export { CodingContractName } from "./data/codingcontracttypes";
36 changes: 24 additions & 12 deletions src/NetscriptFunctions/CodingContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { helpers } from "../Netscript/NetscriptHelpers";
import { CodingContractName } from "@enums";
import { generateDummyContract } from "../CodingContractGenerator";
import { isCodingContractName } from "../data/codingcontracttypes";

export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
const getCodingContract = function (ctx: NetscriptContext, hostname: string, filename: string): CodingContract {
Expand All @@ -25,7 +26,11 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {

if (_type) {
const type = helpers.string(ctx, "type", _type);
if (contract.type !== type) return helpers.errorMessage(ctx, `The given type '${type}' is not the same as the one of contract '${contract.fn}' of type '${contract.type}'.`);
if (contract.type !== type)
throw helpers.errorMessage(
ctx,
`The given type '${type}' is not the same as the one of contract '${contract.fn}' of type '${contract.type}'.`,
);
}

if (!contract.isValid(answer))
Expand Down Expand Up @@ -64,16 +69,22 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
const contract = getCodingContract(ctx, hostname, filename);
return contract.getType();
},
getData: (ctx) => (_filename: unknown, _hostname?: unknown, _type?: unknown): any => {
const filename = helpers.string(ctx, "filename", _filename);
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
const contract = getCodingContract(ctx, hostname, filename);
if (_type) {
const type = helpers.string(ctx, "type", _type);
if (contract.type !== type) return helpers.errorMessage(ctx, `The given type '${type}' is not the same as the one of contract '${contract.fn}' of type '${contract.type}'.`);
}
return structuredClone(contract.getData());
},
getData:
(ctx) =>
(_filename: unknown, _hostname?: unknown, _type?: unknown): any => {
const filename = helpers.string(ctx, "filename", _filename);
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
const contract = getCodingContract(ctx, hostname, filename);
if (_type) {
const type = helpers.string(ctx, "type", _type);
if (contract.type !== type)
throw helpers.errorMessage(
ctx,
`The given type '${type}' is not the same as the one of contract '${contract.fn}' of type '${contract.type}'.`,
);
}
return structuredClone(contract.getData());
},
getDescription: (ctx) => (_filename, _hostname?) => {
const filename = helpers.string(ctx, "filename", _filename);
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
Expand All @@ -88,7 +99,8 @@ export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
},
createDummyContract: (ctx) => (_type) => {
const type = helpers.string(ctx, "type", _type);
if (!((v: any): v is CodingContractName => Object.values(CodingContractName).includes(v))(type)) return helpers.errorMessage(ctx, `The given type is not a valid contract type. Got '${type}'`);
if (!isCodingContractName(type))
return helpers.errorMessage(ctx, `The given type is not a valid contract type. Got '${type}'`);
return generateDummyContract(type);
},
getContractTypes: () => () => Object.values(CodingContractName),
Expand Down
49 changes: 36 additions & 13 deletions src/ScriptEditor/NetscriptDefinitions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3853,24 +3853,35 @@ export interface CodingContract {
*
* Attempts to solve the Coding Contract with the provided solution.
*
* There is an optional fourth parameter where you can assert the contract type.
* This will type the answer format you need to provide.
* Be aware that this function throws if the specified type does not match the type of the contract with that filename.
*
* @example
* ```js
* const reward = ns.codingcontract.attempt(yourSolution, filename, hostname);
* const reward = ns.codingcontract.attempt("solution as a string", filename, hostname);
* // or
* const reward = ns.codingcontract.attempt(["answer", "in", "the", "correct", "format"], filename, hostname);
* if (reward) {
* ns.tprint(`Contract solved successfully! Reward: ${reward}`);
* } else {
* ns.tprint("Failed to solve contract.");
* }
* ```
*
* @param answer - Attempted solution for the contract.
* @param answer - Attempted solution for the contract. This can be a string formatted like submitting manually, or the answer in the format of the specific contract type.
* @param filename - Filename of the contract.
* @param host - Hostname of the server containing the contract. Optional. Defaults to current server if not
* provided.
* @returns A reward description string on success, or an empty string on failure.
*/
attempt(answer: string | any, filename: string, host?: string): string;
attempt<T extends CodingContractName | `${CodingContractName}`>(answer: CodingContractAnswer<T>, filename: string, host: string | undefined, type: T): string;
attempt(answer: any, filename: string, host?: string): string;
attempt<T extends CodingContractName | `${CodingContractName}`>(
answer: CodingContractAnswer<T>,
filename: string,
host: string | undefined,
type: T,
): string;

/**
* Get the type of a coding contract.
Expand Down Expand Up @@ -3908,12 +3919,20 @@ export interface CodingContract {
* Note that this is not the same as the contract’s description.
* This is just the data that the contract wants you to act on in order to solve the contract.
*
* There is an optional third parameter where you can assert the contract type.
* This will type the data returned for that specific contract type.
* Be aware that this function will throw if the type in the fourth parameter is not the same as the type of the contract with that filename.
*
* @param filename - Filename of the contract.
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
* @returns The specified contract’s data, data type depends on contract type.
*/
getData(filename: string, host?: string): any;
getData<T extends CodingContractName | `${CodingContractName}`>(filename: string, host: string | undefined, type: T): CodingContractData<T>;
getData<T extends CodingContractName | `${CodingContractName}`>(
filename: string,
host: string | undefined,
type: T,
): CodingContractData<T>;

/**
* Get the number of attempts remaining.
Expand Down Expand Up @@ -3945,7 +3964,7 @@ export interface CodingContract {
* @remarks
* RAM cost: 0 GB
*/
getContractTypes(): (`${CodingContractName}`)[];
getContractTypes(): `${CodingContractName}`[];
}

/**
Expand Down Expand Up @@ -8318,26 +8337,30 @@ export type CodingContractSignatures = {
[CodingContractName.AlgorithmicStockTraderI]: [number[], number];
[CodingContractName.AlgorithmicStockTraderII]: [number[], number];
[CodingContractName.AlgorithmicStockTraderIII]: [number[], number];
[CodingContractName.AlgorithmicStockTraderIV]: [number[], number];
[CodingContractName.AlgorithmicStockTraderIV]: [[number, number[]], number];
[CodingContractName.MinimumPathSumInATriangle]: [number[][], number];
[CodingContractName.UniquePathsInAGridI]: [[number, number], number];
[CodingContractName.UniquePathsInAGridII]: [(1 | 0)[][], number];
[CodingContractName.ShortestPathInAGrid]: [(1 | 0)[][], string];
[CodingContractName.SanitizeParenthesesInExpression]: [string, string[]];
[CodingContractName.FindAllValidMathExpressions]: [[string, number], string[]];
[CodingContractName.HammingCodesIntegerToEncodedBinary]: [string, string];
[CodingContractName.HammingCodesEncodedBinaryToInteger]: [string, string];
[CodingContractName.HammingCodesIntegerToEncodedBinary]: [number, string];
[CodingContractName.HammingCodesEncodedBinaryToInteger]: [string, number];
[CodingContractName.Proper2ColoringOfAGraph]: [[number, [number, number][]], (1 | 0)[]];
[CodingContractName.CompressionIRLECompression]: [string, string];
[CodingContractName.CompressionIILZDecompression]: [string, string];
[CodingContractName.CompressionIIILZCompression]: [string, string];
[CodingContractName.EncryptionICaesarCipher]: [[string, number], string];
[CodingContractName.EncryptionIIVigenereCipher]: [[string, number], string];
[CodingContractName.SquareRoot]: [bigint, bigint];
[CodingContractName.EncryptionIIVigenereCipher]: [[string, string], string];
[CodingContractName.SquareRoot]: [bigint, bigint, [string, string]];
};

export type CodingContractData<T extends string> = T extends `${keyof CodingContractSignatures}` ? CodingContractSignatures[T][0] : any;
export type CodingContractAnswer<T extends string> = T extends `${keyof CodingContractSignatures}` ? CodingContractSignatures[T][1] : any;
export type CodingContractData<T extends string> = T extends `${keyof CodingContractSignatures}`
? CodingContractSignatures[T][0]
: any;
export type CodingContractAnswer<T extends string> = T extends `${keyof CodingContractSignatures}`
? CodingContractSignatures[T][1]
: any;

/** @public */
export type NSEnums = {
Expand Down
Loading

0 comments on commit 9f6b1c8

Please sign in to comment.