Skip to content

Commit

Permalink
Merge pull request #30 from cwegrzyn:cwegrzyn/use-progresstrack-in-re…
Browse files Browse the repository at this point in the history
…nder

Use ProgressTrack in progress renderer
  • Loading branch information
cwegrzyn authored May 20, 2024
2 parents 0d9e64b + 2554961 commit 657b45d
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 87 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,19 +265,19 @@ Box/tick amounts can be given either as a single `from` argument, or with
- `from-boxes` (optional): the starting value of the progress track, in boxes.
- `from-ticks` (optional): the starting value of the progress track, in ticks
filled into the last unfilled box.
- `level` - the difficulty level of the progress track (e.g. `"formidable"`, `"epic"`, etc).
- `rank` - the challenge rank of the progress track (e.g. `"formidable"`, `"epic"`, etc).
- `steps` (optional, default: 1) - number of times to mark progress.

##### Example

```kdl
progress "My Background Vow" from-boxes=3 from-ticks=2 level="formidable" steps=2
progress "My Background Vow" from-boxes=3 from-ticks=2 rank="formidable" steps=2
```

#### `track`

Marks progress on a progress track. Can be used interchangeably with
`progress`, but doesn't encode the track difficulty level or the number of
`progress`, but doesn't encode the track challenge rank or the number of
times progress was marked. Most often, this node would be used for moves that
say something like "erase two ticks from TKTK".

Expand Down
2 changes: 1 addition & 1 deletion src/characters/lens.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ describe("Special Tracks", () => {
progress: 4,
unbounded: true,
complete: false,
difficulty: ChallengeRanks.Epic,
rank: ChallengeRanks.Epic,
});
});

Expand Down
2 changes: 1 addition & 1 deletion src/characters/lens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ function legacyTrack(
lens: {
get(source) {
return ProgressTrack.create_({
difficulty: ChallengeRanks.Epic,
rank: ChallengeRanks.Epic,
// SAFE: a validated character will satisfy the above schema
progress: source[progressKey] as number,
complete: false,
Expand Down
2 changes: 1 addition & 1 deletion src/mechanics/css/dlist-progress.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
}
}

&.level {
&.rank {
text-transform: capitalize;
color: var(--text-faint);
&:before {
Expand Down
67 changes: 26 additions & 41 deletions src/mechanics/mechanics-blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import {
MarkdownRenderer,
} from "obsidian";

import ForgedPlugin from "../index";
import { MoveModal } from "moves/move-modal";
import { ProgressTrack } from "tracks/progress";
import ForgedPlugin from "../index";

export default function registerMechanicsBlock(plugin: ForgedPlugin): void {
plugin.registerMarkdownCodeBlockProcessor(
Expand Down Expand Up @@ -317,29 +318,38 @@ export class MechanicsRenderer {

async renderProgress(target: HTMLElement, node: KdlNode) {
const trackName = (node.properties.name ?? node.values[0]) as string;
let from = node.properties.from as number;
const fromBoxes =
(node.properties["from-boxes"] as number) ??
(from != null ? Math.floor(from / 4) : 0);
const fromTicks =
(node.properties["from-ticks"] as number) ??
(from != null ? from % 4 : 0);
if (from == null) {
from = fromBoxes * 4 + fromTicks;
const result = ProgressTrack.create({
progress:
node.properties.from ??
((node.properties["from-boxes"] as number) ?? 0) * 4 +
((node.properties["from-ticks"] as number) ?? 0),
rank: node.properties.rank ?? node.properties.level,
unbounded: (node.properties.unbounded ?? false) as boolean,
complete: false,
});
if (result.isLeft()) {
// todo: Better error display
target.createEl("pre", {
text: `Invalid track:\n${result.error.toString()}`,
cls: "error",
});
return;
}
const level = (node.properties.level ?? node.values[2]) as string;
const startTrack = result.value;

const [fromBoxes, fromTicks] = startTrack.boxesAndTicks();
const rank = startTrack.rank;
const steps = (node.properties.steps ?? node.values[3] ?? 1) as number;
const delta = levelTicks(level) * steps;
const to = from + delta;
const toBoxes = Math.floor(to / 4);
const toTicks = to % 4;

const endTrack = startTrack.advanced(steps);
const [toBoxes, toTicks] = endTrack.boxesAndTicks();
await this.renderDlist(target, "progress", {
"Track Name": { cls: "track-name", value: trackName, md: true },
Steps: {
cls: "steps " + (steps < 0 ? "negative" : "positive"),
value: steps,
},
Level: { cls: "level", value: level },
Rank: { cls: "rank", value: rank },
"From Boxes": { cls: "from-boxes", value: fromBoxes },
"From Ticks": { cls: "from-ticks", value: fromTicks },
"To Boxes": { cls: "to-boxes", value: toBoxes },
Expand Down Expand Up @@ -625,28 +635,3 @@ function rollOutcome(
match: challenge1 === challenge2,
};
}

enum Level {
Troublesome = 12,
Dangerous = 8,
Formidable = 4,
Extreme = 2,
Epic = 1,
}

function levelTicks(level: string): number {
switch (level.toLowerCase()) {
case "troublesome":
return Level.Troublesome;
case "dangerous":
return Level.Dangerous;
case "formidable":
return Level.Formidable;
case "extreme":
return Level.Extreme;
case "epic":
return Level.Epic;
default:
return 0;
}
}
2 changes: 1 addition & 1 deletion src/mechanics/node-builders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function createProgressNode(
properties: {
name: `[[${trackContext.location}|${trackContext.name}]]`,
from: trackContext.track.progress,
level: trackContext.track.difficulty,
rank: trackContext.track.rank,
steps,
},
});
Expand Down
10 changes: 5 additions & 5 deletions src/tracks/progress-create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function generateTrackName(name: string): string {

export class ProgressTrackCreateModal extends Modal {
public result = {
difficulty: ChallengeRanks.Dangerous,
rank: ChallengeRanks.Dangerous,
progress: 0,
name: "",
tracktype: "",
Expand Down Expand Up @@ -114,13 +114,13 @@ export class ProgressTrackCreateModal extends Modal {

// TODO: since the string value equals the display string, i don't actually know if this
// is working as intended with the options
new Setting(contentEl).setName("Difficulty").addDropdown((dropdown) =>
new Setting(contentEl).setName("Rank").addDropdown((dropdown) =>
dropdown
.addOptions(ChallengeRanks)
.onChange((value) => {
this.result.difficulty = value as ChallengeRanks;
this.result.rank = value as ChallengeRanks;
})
.setValue(this.result.difficulty),
.setValue(this.result.rank),
);

new Setting(contentEl).setName("Type").addSearch((search) => {
Expand Down Expand Up @@ -166,7 +166,7 @@ export class ProgressTrackCreateModal extends Modal {
tracktype: this.result.tracktype,
fileName: this.result.fileName,
track: ProgressTrack.create_({
difficulty: this.result.difficulty,
rank: this.result.rank,
progress: this.result.progress,
complete: false,
unbounded: false,
Expand Down
46 changes: 33 additions & 13 deletions src/tracks/progress.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {

describe("ProgressTrack", () => {
const TEST_DATA: ProgressTrackSchema = {
difficulty: ChallengeRanks.Dangerous,
rank: ChallengeRanks.Dangerous,
progress: 10,
complete: false,
unbounded: false,
Expand All @@ -27,7 +27,22 @@ describe("ProgressTrack", () => {
expect(result.isRight()).toBeTruthy();
const track = result.unwrap();
expect(track).toMatchObject<ProgressTrackSchema>({
difficulty: ChallengeRanks.Dangerous,
rank: ChallengeRanks.Dangerous,
progress: 10,
complete: false,
unbounded: false,
});
});

it("interprets the rank case insensitively", () => {
const result = ProgressTrack.create({
...TEST_DATA,
rank: "DANGERous",
});
expect(result.isRight()).toBeTruthy();
const track = result.unwrap();
expect(track).toMatchObject<ProgressTrackSchema>({
rank: ChallengeRanks.Dangerous,
progress: 10,
complete: false,
unbounded: false,
Expand All @@ -46,7 +61,7 @@ describe("ProgressTrack", () => {
{ rank: ChallengeRanks.Extreme, steps: 1 },
{ rank: ChallengeRanks.Extreme, steps: 2 },
])("advances $rank track by $steps steps", ({ rank, steps }) => {
const start = make({ difficulty: rank });
const start = make({ rank: rank });
const startingProgress = start.progress;
expect(start.advanced(steps).progress).toBe(
startingProgress + CHALLENGE_STEPS[rank] * steps,
Expand Down Expand Up @@ -91,26 +106,24 @@ describe("ProgressTrack", () => {
])(
"#stepsRemaining calculates $steps steps from $ticks ticks for $rank",
({ ticks, steps, rank }) => {
expect(make({ progress: ticks, difficulty: rank }).stepsRemaining).toBe(
steps,
);
expect(make({ progress: ticks, rank: rank }).stepsRemaining).toBe(steps);
},
);
});

describe("ProgressTrackFileAdapter", () => {
const TEST_DATA = {
Name: "Test",
Difficulty: "Dangerous",
rank: "Dangerous",
Progress: 10,
tags: "incomplete",
TrackImage: "[[progress-track-10.svg]]",
tracktype: "Vow",
};

function make(
overrides: Omit<Partial<ProgressTrackerInputSchema>, "Difficulty"> & {
Difficulty?: ChallengeRanks | string;
overrides: Omit<Partial<ProgressTrackerInputSchema>, "rank"> & {
rank?: ChallengeRanks | string;
} = {},
): Either<ZodError, ProgressTrackFileAdapter> {
return ProgressTrackFileAdapter.create(
Expand All @@ -126,8 +139,8 @@ describe("ProgressTrackFileAdapter", () => {
}

function make_(
overrides: Omit<Partial<ProgressTrackerInputSchema>, "Difficulty"> & {
Difficulty?: ChallengeRanks | string;
overrides: Omit<Partial<ProgressTrackerInputSchema>, "rank"> & {
Rank?: ChallengeRanks | string;
} = {},
): ProgressTrackFileAdapter {
return make(overrides).unwrap();
Expand All @@ -136,14 +149,21 @@ describe("ProgressTrackFileAdapter", () => {
it("#track extracts the progress track data", () => {
expect(make_().track).toEqual(
ProgressTrack.create_({
difficulty: ChallengeRanks.Dangerous,
rank: ChallengeRanks.Dangerous,
progress: 10,
complete: false,
unbounded: false,
}),
);
});

it("parses a track with Difficulty instead of rank", () => {
expect(
make_({ rank: undefined, Difficulty: ChallengeRanks.Troublesome }).track
.rank,
).toEqual(ChallengeRanks.Troublesome);
});

it("requires a completion tag", () => {
expect(make({ tags: ["missing_completion"] })).toEqual(
Left.create(
Expand Down Expand Up @@ -240,7 +260,7 @@ describe("legacyTrackXpEarned", () => {
expect(
legacyTrackXpEarned(
ProgressTrack.create_({
difficulty: ChallengeRanks.Epic,
rank: ChallengeRanks.Epic,
progress: boxes * 4,
complete: false,
unbounded: true,
Expand Down
Loading

0 comments on commit 657b45d

Please sign in to comment.