Skip to content

Commit

Permalink
Roll out use of dedent
Browse files Browse the repository at this point in the history
  • Loading branch information
gausie committed Oct 24, 2023
1 parent 0bbe14c commit 4091619
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 83 deletions.
5 changes: 3 additions & 2 deletions src/entityTypes/classes.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { expect, test, vi } from "vitest";
import { createFetchResponse } from "../testUtils";
import { loadClasses } from "./classes";
import { dedent } from "ts-dedent";

global.fetch = vi.fn();

test("Can read classes", async () => {
vi.mocked(fetch).mockResolvedValue(
createFetchResponse(`
createFetchResponse(dedent`
package net.sourceforge.kolmafia;
public enum AscensionClass {
Expand Down Expand Up @@ -97,7 +98,7 @@ test("Can read classes", async () => {

const classes = await loadClasses();

expect(classes.size).toBe(3645);
expect(classes.size).toBe(3165);

expect(classes.data).toHaveLength(22);

Expand Down
8 changes: 5 additions & 3 deletions src/entityTypes/effects.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { expect, test, vi } from "vitest";
import { loadEffects } from "./effects";
import { createFetchResponse, expectNotNull } from "../testUtils";
import { dedent } from "ts-dedent";

global.fetch = vi.fn();

test("Can read effects", async () => {
vi.mocked(fetch).mockResolvedValue(
createFetchResponse(
"1\n5\tFar Out\tfarout.gif\t5ad503e9df2df73bfbbb5377b622c8c4\tgood\tnone\tuse 1 patchouli incense stick",
),
createFetchResponse(dedent`
1
5\tFar Out\tfarout.gif\t5ad503e9df2df73bfbbb5377b622c8c4\tgood\tnone\tuse 1 patchouli incense stick
`),
);

const effects = await loadEffects();
Expand Down
9 changes: 6 additions & 3 deletions src/entityTypes/familiars.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { expect, test, vi } from "vitest";
import { dedent } from "ts-dedent";

import { createFetchResponse, expectNotNull } from "../testUtils";
import { FamiliarCategory, loadFamiliars } from "./familiars";

global.fetch = vi.fn();

test("Can read familiars", async () => {
vi.mocked(fetch).mockResolvedValue(
createFetchResponse(
"1\n7\tSpooky Pirate Skeleton\tfamiliar7.gif\tcombat1,delevel\tspooky pirate skeleton\tblundarrrbus\t2\t3\t1\t0\thashands,haseyes,undead,cantalk",
),
createFetchResponse(dedent`
1
7\tSpooky Pirate Skeleton\tfamiliar7.gif\tcombat1,delevel\tspooky pirate skeleton\tblundarrrbus\t2\t3\t1\t0\thashands,haseyes,undead,cantalk
`),
);

const familiars = await loadFamiliars();
Expand Down
9 changes: 6 additions & 3 deletions src/entityTypes/items.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { expect, test, vi } from "vitest";
import { dedent } from "ts-dedent";

import { createFetchResponse, expectNotNull } from "../testUtils";
import { ItemUse, loadItems } from "./items";

global.fetch = vi.fn();

test("Can read items", async () => {
vi.mocked(fetch).mockResolvedValue(
createFetchResponse(
"1\n87\tmeat from yesterday\t653772183\tmeat.gif\tnone, paste\tt,d\t5\tmeats from yesterday",
),
createFetchResponse(dedent`
1
87\tmeat from yesterday\t653772183\tmeat.gif\tnone, paste\tt,d\t5\tmeats from yesterday
`),
);

const items = await loadItems();
Expand Down
30 changes: 16 additions & 14 deletions src/entityTypes/locations.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { expect, test, vi } from "vitest";
import { dedent } from "ts-dedent";
import { createFetchResponse, expectNotNull } from "../testUtils";
import { LocationDifficulty, LocationEnvironment, loadLocations } from "./locations";
import {
LocationDifficulty,
LocationEnvironment,
loadLocations,
} from "./locations";

global.fetch = vi.fn();

test("Can read locations", async () => {
vi.mocked(fetch).mockResolvedValue(
createFetchResponse(
dedent`
1
Hobopolis adventure=168 DiffLevel: unknown Env: underground Stat: 350 Burnbarrel Blvd. +1 jar of squeeze
# No snarfblat
Gyms clan_gym=MUSCLE DiffLevel: none Env: none Stat: 0 Pump Up Muscle
# Water level
Manor0 place=manor4_chamberboss DiffLevel: none Env: none Stat: 0 Level: 4 Summoning Chamber
# Nowander
HiddenCity adventure=346 DiffLevel: high Env: outdoor Stat: 140 nowander An Overgrown Shrine (Northwest)
`,
),
createFetchResponse(dedent`
1
Hobopolis adventure=168 DiffLevel: unknown Env: underground Stat: 350 Burnbarrel Blvd. +1 jar of squeeze
# No snarfblat
Gyms clan_gym=MUSCLE DiffLevel: none Env: none Stat: 0 Pump Up Muscle
# Water level
Manor0 place=manor4_chamberboss DiffLevel: none Env: none Stat: 0 Level: 4 Summoning Chamber
# Nowander
HiddenCity adventure=346 DiffLevel: high Env: outdoor Stat: 140 nowander An Overgrown Shrine (Northwest)
`),
);

const locations = await loadLocations();
Expand All @@ -41,7 +43,7 @@ test("Can read locations", async () => {
overdrunk: false,
nowander: false,
});

expect(locations.data).toContainEqual({
id: -1,
name: "Pump Up Muscle",
Expand Down
106 changes: 61 additions & 45 deletions src/entityTypes/locations.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,74 @@
import { loadMafiaData, memberOfEnumElse } from "../utils";

export enum LocationDifficulty {
None = "none",
Unknown = "unknown",
Low = "low",
Medium = "medium",
High = "high"
};
None = "none",
Unknown = "unknown",
Low = "low",
Medium = "medium",
High = "high",
}

const validDifficulty = memberOfEnumElse(LocationDifficulty, LocationDifficulty.Unknown);
const validDifficulty = memberOfEnumElse(
LocationDifficulty,
LocationDifficulty.Unknown,
);

export enum LocationEnvironment {
None = "none",
Indoor = "indoor",
Outdoor = "outdoor",
Underground = "underground",
Underwater = "underwater"
};
None = "none",
Indoor = "indoor",
Outdoor = "outdoor",
Underground = "underground",
Underwater = "underwater",
}

const validEnvironment = memberOfEnumElse(LocationEnvironment, LocationEnvironment.None);
const validEnvironment = memberOfEnumElse(
LocationEnvironment,
LocationEnvironment.None,
);

export type LocationType = {
id: number;
name: string;
zone: string;
url: string;
difficulty: LocationDifficulty;
environment: LocationEnvironment;
statRequirement: number;
/** Water level, for Heavy Rains locations without an environment */
waterLevel: number | null;
/** Location in which one cannot adventure while overdrunk */
overdrunk: boolean;
/** Location in which wandering monsters cannot appear */
nowander: boolean;
id: number;
name: string;
zone: string;
url: string;
difficulty: LocationDifficulty;
environment: LocationEnvironment;
statRequirement: number;
/** Water level, for Heavy Rains locations without an environment */
waterLevel: number | null;
/** Location in which one cannot adventure while overdrunk */
overdrunk: boolean;
/** Location in which wandering monsters cannot appear */
nowander: boolean;
};

const parseSnarfblat = (url: string) => Number(url.match(/^adventure=(\d+)$/)?.[1] ?? "-1");
const parseSnarfblat = (url: string) =>
Number(url.match(/^adventure=(\d+)$/)?.[1] ?? "-1");

const parseAttributes = (attributesString: string) => {
const [attributes,] = attributesString.toLowerCase().split(" ").reduce(([acc, current], token) => {
if (current === null) {
if (token.endsWith(":")) return [acc, token.slice(0, -1)];
return [{ ...acc, [token]: true }, null];
}
return [{ ...acc, [current]: token }, null];
}, [{}, null] as [Record<string, string | boolean>, string | null]);
const [attributes] = attributesString
.toLowerCase()
.split(" ")
.reduce(
([acc, current], token) => {
if (current === null) {
if (token.endsWith(":")) return [acc, token.slice(0, -1)];
return [{ ...acc, [token]: true }, null];
}
return [{ ...acc, [current]: token }, null];
},
[{}, null] as [Record<string, string | boolean>, string | null],
);

return {
difficulty: validDifficulty(attributes["difflevel"]),
environment: validEnvironment(attributes["env"]),
statRequirement: Number(attributes["stat"] ?? "0"),
waterLevel: Number(attributes["level"] ?? null),
overdrunk: !!attributes["overdrunk"],
nowander: !!attributes["nowander"],
};
}
return {
difficulty: validDifficulty(attributes["difflevel"]),
environment: validEnvironment(attributes["env"]),
statRequirement: Number(attributes["stat"] ?? "0"),
waterLevel: Number(attributes["level"] ?? null),
overdrunk: !!attributes["overdrunk"],
nowander: !!attributes["nowander"],
};
};

const parseLocation = (parts: string[]): LocationType => ({
id: parseSnarfblat(parts[1]),
Expand All @@ -65,7 +78,10 @@ const parseLocation = (parts: string[]): LocationType => ({
...parseAttributes(parts[2]),
});

export async function loadLocations(): Promise<{ size: number; data: LocationType[] }>;
export async function loadLocations(): Promise<{
size: number;
data: LocationType[];
}>;
export async function loadLocations(
lastKnownSize: number,
): Promise<{ size: number; data: LocationType[] } | null>;
Expand Down
9 changes: 6 additions & 3 deletions src/entityTypes/outfits.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { expect, test, vi } from "vitest";
import { dedent } from "ts-dedent";

import { createFetchResponse, expectNotNull } from "../testUtils";
import { loadOutfits } from "./outfits";

global.fetch = vi.fn();

test("Can read outfits", async () => {
vi.mocked(fetch).mockResolvedValue(
createFetchResponse(
"1\n35\tBlack Armaments\tblacktat.gif\tblack helmet, black sword, black shield, black greaves\tblack pudding (0.16), Blackfly Chardonnay (0.16), black & tan (0.16), black pepper (0.16), black forest cake (0.16), black forest ham (0.16)",
),
createFetchResponse(dedent`
1
35\tBlack Armaments\tblacktat.gif\tblack helmet, black sword, black shield, black greaves\tblack pudding (0.16), Blackfly Chardonnay (0.16), black & tan (0.16), black pepper (0.16), black forest cake (0.16), black forest ham (0.16)
`),
);

const outfits = await loadOutfits();
Expand Down
5 changes: 3 additions & 2 deletions src/entityTypes/paths.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, test, vi } from "vitest";
import { dedent } from "ts-dedent";

import { createFetchResponse, expectNotNull } from "../testUtils";
import { loadPaths } from "./paths";
Expand All @@ -7,7 +8,7 @@ global.fetch = vi.fn();

test("Can read paths", async () => {
vi.mocked(fetch).mockResolvedValue(
createFetchResponse(`
createFetchResponse(dedent`
package net.sourceforge.kolmafia;
public class AscensionPath {
Expand Down Expand Up @@ -120,7 +121,7 @@ test("Can read paths", async () => {

expectNotNull(paths);

expect(paths.size).toBe(5833);
expect(paths.size).toBe(5203);

expect(paths.data).toHaveLength(48);

Expand Down
9 changes: 6 additions & 3 deletions src/entityTypes/skills.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { expect, test, vi } from "vitest";
import { dedent } from "ts-dedent";

import { createFetchResponse, expectNotNull } from "../testUtils";
import { SkillCategory, loadSkills } from "./skills";

global.fetch = vi.fn();

test("Can read skills", async () => {
vi.mocked(fetch).mockResolvedValue(
createFetchResponse(
"1\n3035\tBind Penne Dreadful\tt_dreadful.gif\t3\t150\t0\t11",
),
createFetchResponse(dedent`
1
3035\tBind Penne Dreadful\tt_dreadful.gif\t3\t150\t0\t11
`),
);

const skills = await loadSkills();
Expand Down
15 changes: 10 additions & 5 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,16 @@ export const isMemberOfEnum =
(token: EnumValue): token is Enum[keyof Enum] =>
Object.values(e).includes(token as Enum[keyof Enum]);

export const memberOfEnumElse =
<EnumValue, Enum extends { [s: string]: EnumValue }>(e: Enum, fallback: Enum[keyof Enum]) => {
const isMember = isMemberOfEnum(e);
return (token: EnumValue) => isMember(token) ? token : fallback;
};
export const memberOfEnumElse = <
EnumValue,
Enum extends { [s: string]: EnumValue },
>(
e: Enum,
fallback: Enum[keyof Enum],
) => {
const isMember = isMemberOfEnum(e);
return (token: EnumValue) => (isMember(token) ? token : fallback);
};

export function zip<A, B>(a1: A[], a2: B[]): [A, B][];
export function zip<A, B, C>(a1: A[], a2: B[], a3: C[]): [A, B, C][];
Expand Down

0 comments on commit 4091619

Please sign in to comment.