Skip to content

Commit

Permalink
feat: add succeed_by filter (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
fspoettel committed Jun 14, 2024
1 parent d3dc031 commit d3d74e4
Show file tree
Hide file tree
Showing 13 changed files with 65 additions and 34 deletions.
1 change: 1 addition & 0 deletions src/components/filters/properties-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const properties = [
{ key: "exile", label: "Exile" },
{ key: "seal", label: "Seal" },
{ key: "victory", label: "Victory" },
{ key: "succeedBy", label: "Succeed By" },
{
key: "unique",
label: <>Unique (&#10040;)</>,
Expand Down
4 changes: 2 additions & 2 deletions src/store/selectors/filters/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export function filterActions(
) {
const filters: Filter[] = [];

Object.entries(filterState).forEach(([key, value]) => {
for (const [key, value] of Object.entries(filterState)) {
if (value) filters.push((c: Card) => !!actionTable[key][c.code]);
});
}

const filter = or(filters);
return (card: Card) => filter(card);
Expand Down
4 changes: 2 additions & 2 deletions src/store/selectors/filters/investigator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export const selectInvestigatorFilter = createSelector(
if (option.option_select) {
const selectFilters: Filter[] = [];

option.option_select.forEach((select) => {
for (const select of option.option_select) {
const optionSelectFilters: Filter[] = [];

if (select.level) {
Expand All @@ -172,7 +172,7 @@ export const selectInvestigatorFilter = createSelector(
}

selectFilters.push(and(optionSelectFilters));
});
}

filterCount += selectFilters.length;
optionFilter.push(or(selectFilters));
Expand Down
10 changes: 10 additions & 0 deletions src/store/selectors/filters/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ function filterPermanent(slotTable: LookupTables["slots"]) {
return (card: Card) => !!slotTable["Permanent"]?.[card.code];
}

function filterSucceedBy(
succeedByTable: LookupTables["properties"]["succeedBy"],
) {
return (card: Card) => !!succeedByTable[card.code];
}

function filterHealsDamage(
healsDamageTable: LookupTables["properties"]["heals_damage"],
) {
Expand Down Expand Up @@ -98,6 +104,10 @@ export function filterProperties(
filters.push(filterHealsHorror(lookupTables.properties.heals_horror));
}

if (filterState.succeedBy) {
filters.push(filterSucceedBy(lookupTables.properties.succeedBy));
}

const filter = and(filters);

return (card: Card) => {
Expand Down
5 changes: 3 additions & 2 deletions src/store/selectors/filters/skill-icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ function filterSkillIcons(filterState: SkillIconsFilter["value"]) {

const anyV = filterState.any;

SKILL_KEYS.forEach((skill) => {
for (const skill of SKILL_KEYS) {
const v = filterState[skill];

if (v) {
iconFilter.push(filterSkill(skill, v));
}

if (anyV) {
anyFilter.push(filterSkill(skill, anyV));
}
});
}

const filter = anyFilter.length
? and([or(anyFilter), and(iconFilter)])
Expand Down
4 changes: 2 additions & 2 deletions src/store/selectors/filters/traits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export function filterTraits(
) {
const filters: Filter[] = [];

Object.entries(filterState).forEach(([key, value]) => {
for (const [key, value] of Object.entries(filterState)) {
if (value) filters.push((c: Card) => !!traitTable[key][c.code]);
});
}

const filter = or(filters);
return (card: Card) => filter(card);
Expand Down
1 change: 1 addition & 0 deletions src/store/slices/filters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ function getInitialState(): Filters {
victory: false,
heals_horror: false,
heals_damage: false,
succeedBy: false,
},
},
};
Expand Down
1 change: 1 addition & 0 deletions src/store/slices/filters/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export type PropertiesFilter = FilterObject<{
heals_damage: boolean;
heals_horror: boolean;
victory: boolean;
succeedBy: boolean;
}>;

type SharedState = {
Expand Down
43 changes: 26 additions & 17 deletions src/store/slices/lookup-tables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import type { Card } from "@/store/services/types";
import { applyTaboo } from "@/store/utils/taboos";
import { splitMultiValue } from "@/utils/card-utils";
import {
ACTION_TEXT,
ACTION_TEXT_ENTRIES,
REGEX_BONDED,
REGEX_SKILL_BOOST,
REGEX_SUCCEED_BY,
REGEX_USES,
} from "@/utils/constants";

Expand Down Expand Up @@ -44,6 +45,7 @@ export function getInitialLookupTables(): LookupTables {
heals_horror: {},
multislot: {},
seal: {},
succeedBy: {},
},
skillBoosts: {},
slots: {},
Expand Down Expand Up @@ -149,6 +151,8 @@ export function addCardToLookupTables(
indexByHealsHorror(tables, card);
indexByHealsDamage(tables, card);

indexBySucceedsBy(tables, card);

if (card.type_code === "asset") {
indexBySlots(tables, card);
indexBySkillBoosts(tables, card);
Expand Down Expand Up @@ -188,25 +192,24 @@ function indexByCodes(tables: LookupTables, card: Card) {
}

function indexByTraits(tables: LookupTables, card: Card) {
splitMultiValue(card.real_traits).forEach((trait) => {
if (trait) {
setInLookupTable(card.code, tables.traits, trait);
if (card.encounter_code || card.faction_code === "mythos") {
setInLookupTable(trait, tables.traitsByCardTypeSeletion, "encounter");
} else {
setInLookupTable(trait, tables.traitsByCardTypeSeletion, "player");
}
for (const trait of splitMultiValue(card.real_traits)) {
setInLookupTable(card.code, tables.traits, trait);

if (card.encounter_code || card.faction_code === "mythos") {
setInLookupTable(trait, tables.traitsByCardTypeSeletion, "encounter");
} else {
setInLookupTable(trait, tables.traitsByCardTypeSeletion, "player");
}
});
}
}
``;

function indexByActions(tables: LookupTables, card: Card) {
// add card to action tables.
Object.entries(ACTION_TEXT).forEach(([key, value]) => {
for (const [key, value] of ACTION_TEXT_ENTRIES) {
if (card.real_text?.includes(value)) {
setInLookupTable(card.code, tables.actions, key);
}
});
}
}

// TODO: use a regex.
Expand Down Expand Up @@ -264,9 +267,9 @@ function indexBySlots(tables: LookupTables, card: Card) {
setInLookupTable(card.code, tables.properties, "multislot");
}

allSlots.forEach((slot) => {
for (const slot of allSlots) {
setInLookupTable(card.code, tables.slots, slot);
});
}
} else if (card.permanent) {
setInLookupTable(card.code, tables.slots, "Permanent");
} else {
Expand Down Expand Up @@ -311,6 +314,12 @@ function indexByHealsHorror(tables: LookupTables, card: Card) {
}
}

function indexBySucceedsBy(tables: LookupTables, card: Card) {
if (card.real_text?.match(REGEX_SUCCEED_BY)) {
setInLookupTable(card.code, tables.properties, "succeedBy");
}
}

function sortedByName(tables: LookupTables, card: Card, i: number) {
tables.sort.alphabetical[card.code] = i;
}
Expand Down Expand Up @@ -440,7 +449,7 @@ function addPacksToLookupTables(
metadata: Metadata,
lookupTables: LookupTables,
) {
Object.values(metadata.packs).forEach((pack) => {
for (const pack of Object.values(metadata.packs)) {
setInLookupTable(pack.code, lookupTables.packsByCycle, pack.cycle_code);
});
}
}
1 change: 1 addition & 0 deletions src/store/slices/lookup-tables/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export type LookupTables = {
fast: Mapping<1>;
multislot: Mapping<1>;
seal: Mapping<1>; // TODO: link the tokens?
succeedBy: Mapping<1>;
};
skillBoosts: LookupTable<string>;
// cards that occupy multiple slots are added to both slot entries and a separate grouped entry. They are also added to the `properties.multislot` index.
Expand Down
10 changes: 5 additions & 5 deletions src/store/slices/shared/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export const createSharedSlice: StateCreator<
};
}

cards.forEach((c) => {
for (const c of cards) {
if (c.taboo_set_id) {
metadata.taboos[c.id] = {
code: c.code,
Expand All @@ -77,7 +77,7 @@ export const createSharedSlice: StateCreator<
real_customization_change: c.real_customization_change,
};

return;
continue;
}

// SAFE! Diverging fields are added below.
Expand All @@ -99,16 +99,16 @@ export const createSharedSlice: StateCreator<
encounterSet.pack_code = card.pack_code;
}
}
});
}

const lookupTables = createLookupTables(metadata, state.settings);
createRelations(metadata, lookupTables);

Object.keys(metadata.encounterSets).forEach((code) => {
for (const code of Object.keys(metadata.encounterSets)) {
if (!metadata.encounterSets[code].pack_code) {
delete metadata.encounterSets[code];
}
});
}

set({
metadata,
Expand Down
10 changes: 6 additions & 4 deletions src/utils/card-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import { SIDEWAYS_TYPE_CODES, SKILL_KEYS } from "./constants";
* Split multi value card properties. expected format: `Item. Tool.`
*/
export function splitMultiValue(s?: string) {
return (s ?? "")
.split(".")
.map((s) => s.trim())
.filter((s) => s);
if (!s) return [];
return s.split(".").reduce<string[]>((acc, curr) => {
const s = curr.trim();
if (s) acc.push(s);
return acc;
}, []);
}

export function hasSkillIcons(card: Card) {
Expand Down
5 changes: 5 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ export const REGEX_USES = /^Uses\s\(\d+?\s(\w+?)\)/;

export const REGEX_BONDED = /^Bonded\s\((.*?)\)\./;

export const REGEX_SUCCEED_BY =
/succe(ssful|ed(?:s?|ed?))(:? at a skill test)? by(?! 0)/;

export const ACTION_TEXT: { [key: string]: string } = {
fight: "<b>Fight.</b>",
engage: "<b>Engage.</b>",
Expand All @@ -16,6 +19,8 @@ export const ACTION_TEXT: { [key: string]: string } = {
parley: "<b>Parley.</b>",
} as const;

export const ACTION_TEXT_ENTRIES = Object.entries(ACTION_TEXT);

export type SkillKey =
| "agility"
| "combat"
Expand Down

0 comments on commit d3d74e4

Please sign in to comment.