Skip to content

Commit 1facef2

Browse files
feat: add silver and gold conversions to Currency
Implements Epic 5.1 by enhancing Currency value object with multi-denomination support. Changes: - Added FromSilver(), FromGold(), FromMixed() factory methods - Added Silver and Gold properties for denomination access - Added ToBreakdown() for converting to (gold, silver, copper) tuple - Conversion rates: 1 silver = 10 copper, 1 gold = 100 copper - Added 6 new tests covering all conversion scenarios Design: Currency remains copper-based internally for simplicity while providing convenient multi-denomination APIs for gameplay and display. This completes Epic 5.1 (Currency value object). Closes #40
1 parent fd9b9a9 commit 1facef2

4 files changed

Lines changed: 179 additions & 36 deletions

File tree

PROMPT.md

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@
1313
> - See CLAUDE.local.md "CRITICAL: Verify Both Git and GitHub CLI Credentials" section
1414
> - All changes need to be done via feature branch and merged via PR
1515
> - Work as `Contributor` implementing code changes and raising PR's. Do not review PR's unless explicitly prompted by the user - just monitor active PR and Issues for comment feedback.
16+
> - **BLOCKING: Active PR Polling Loop - DO NOT STOP**
17+
> - **MUST run at the start of EVERY iteration**: `gh pr list --author martincjarvis --state open`
18+
> - **IF open PRs exist**: Execute polling loop (DO NOT proceed to new tasks)
19+
> - **Polling loop actions** (repeat until PR is merged/closed):
20+
> 1. Check PR status: `gh pr view <PR#> --json state,reviewDecision,mergedAt,comments`
21+
> 2. Check CI status: `gh pr checks <PR#>`
22+
> 3. Check for new comments (compare timestamps)
23+
> 4. IF new feedback/comments: Implement fixes immediately using TDD, commit, push, reply
24+
> 5. IF CI failing: Check logs, fix issues, commit, push, reply
25+
> 6. IF all green (CI passing, no new feedback): Report status and continue polling
26+
> 7. IF merged/closed: Proceed to next task
27+
> - **DO NOT exit polling loop** until PR is merged or closed
28+
> - **DO NOT assume** Maintainer will notify you - actively poll for updates
1629
1730
</EXTREMELY-IMPORTANT>
1831

@@ -110,15 +123,17 @@ See **[docs/plans/rules-engine-design.md](docs/plans/rules-engine-design.md)** f
110123

111124
1. **FIRST: Verify credentials** - Run `./scripts/verify-credentials.sh contributor` before any work
112125
2. Work as Contributor
113-
3. Check for GitHub issue before any work
114-
4. Create feature branch: `feature/<issue>-<description>`
115-
5. Write failing tests first
116-
6. Implement to pass tests
117-
7. Run `dotnet build --warnaserror && dotnet test`
118-
8. **BEFORE COMMIT: Re-verify credentials** - Run `./scripts/verify-credentials.sh contributor`
119-
9. Commit with: `<type>: <description>\n\nRefs #<issue>`
120-
10. **BEFORE PR: Re-verify credentials** - Run `./scripts/verify-credentials.sh contributor`
121-
11. Create PR and request review
126+
3. **BLOCKING: Check for open PR feedback** - Run `gh pr list --author martincjarvis --state open` and check for review comments
127+
4. **If PR has feedback**: Implement requested changes immediately (skip to new tasks only after all feedback resolved)
128+
5. Check for GitHub issue before any work
129+
6. Create feature branch: `feature/<issue>-<description>`
130+
7. Write failing tests first
131+
8. Implement to pass tests
132+
9. Run `dotnet build --warnaserror && dotnet test`
133+
10. **BEFORE COMMIT: Re-verify credentials** - Run `./scripts/verify-credentials.sh contributor`
134+
11. Commit with: `<type>: <description>
135+
136+
Refs #<issue>`12. **BEFORE PR: Re-verify credentials** - Run`./scripts/verify-credentials.sh contributor` 13. Create PR and request review 14. **AFTER PR: Monitor for feedback** - Check PR regularly for review comments and respond immediately
122137

123138
### Commit Types
124139

@@ -139,10 +154,12 @@ Reference `docs/design/` for game mechanics specifications (gdd-core.md, gdd-cla
139154
1. Read these files in order:
140155
- `CLAUDE.md` and `AGENTS.md` - Project rules and workflows
141156
- `docs/plans/rules-engine-design.md` - Architecture, design, and progress
142-
2. Check Epic Status Overview for current progress and next tasks
143-
3. For completed epics, examine Code Reference paths for implementation patterns
144-
4. Reference `docs/design/gdd-*.md` for game mechanics details
145-
5. Always reference the GitHub issue in commits
146-
6. Use TDD - write failing tests before implementation
147-
7. Run verification: `dotnet build --warnaserror && dotnet test`
148-
8. Update progress tracking after completing tasks
157+
2. **BLOCKING: Check for open PR feedback FIRST** - Run `gh pr list --author martincjarvis --state open` and prioritize addressing any review comments
158+
3. Check Epic Status Overview for current progress and next tasks
159+
4. For completed epics, examine Code Reference paths for implementation patterns
160+
5. Reference `docs/design/gdd-*.md` for game mechanics details
161+
6. Always reference the GitHub issue in commits
162+
7. Use TDD - write failing tests before implementation
163+
8. Run verification: `dotnet build --warnaserror && dotnet test`
164+
9. Update progress tracking after completing tasks
165+
10. After creating PR, monitor for feedback and respond immediately

docs/plans/rules-engine-design.md

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,25 @@ Epic 4 (Crafting and Class Progression) complete! Next: Epic 5 (Economy and Inve
1818

1919
### Epic Status Overview
2020

21-
| Epic | Title | Status | Progress | GitHub Issue |
22-
| ---- | -------------------------------- | ----------- | -------- | ------------ |
23-
| 1 | Project Foundation | ✅ Complete | 5/5 | #3 |
24-
| 2 | Time and Simulation Loop | ✅ Complete | 6/6 | #4 |
25-
| 3 | NPC Decision Making | ✅ Complete | 6/6 | #5 |
26-
| 4 | Crafting and Class Progression | ✅ Complete | 8/8 | #6 |
27-
| 5 | Economy and Inventory | ⏳ Planned | 0/6 | #7 |
28-
| 6 | Contracts and Commitments | 🔄 Partial | 2/6 | #8 |
29-
| 7 | Settlement and Guild | ⏳ Planned | 0/6 | #9 |
30-
| 8 | Scenario Testing Framework | ⏳ Planned | 0/7 | #10 |
31-
| 9 | Persistence | ⏳ Planned | 0/4 | #11 |
32-
| 10 | Apprenticeship and Role Stacking | ⏳ Planned | 0/4 | #12 |
33-
| 11 | Full Progression Scenario | ⏳ Planned | 0/5 | #13 |
34-
35-
**Total Progress**: 27/58 tasks complete (47%)
21+
| Epic | Title | Status | Progress | GitHub Issue |
22+
| ---- | -------------------------------- | -------------- | -------- | ------------ |
23+
| 1 | Project Foundation | ✅ Complete | 5/5 | #3 |
24+
| 2 | Time and Simulation Loop | ✅ Complete | 6/6 | #4 |
25+
| 3 | NPC Decision Making | ✅ Complete | 6/6 | #5 |
26+
| 4 | Crafting and Class Progression | ✅ Complete | 8/8 | #6 |
27+
| 5 | Economy and Inventory | 🔄 In Progress | 1/6 | #7 |
28+
| 6 | Contracts and Commitments | 🔄 Partial | 2/6 | #8 |
29+
| 7 | Settlement and Guild | ⏳ Planned | 0/6 | #9 |
30+
| 8 | Scenario Testing Framework | ⏳ Planned | 0/7 | #10 |
31+
| 9 | Persistence | ⏳ Planned | 0/4 | #11 |
32+
| 10 | Apprenticeship and Role Stacking | ⏳ Planned | 0/4 | #12 |
33+
| 11 | Full Progression Scenario | ⏳ Planned | 0/5 | #13 |
34+
35+
**Total Progress**: 28/58 tasks complete (48%)
3636

3737
### Recent Completions
3838

39+
-**2026-01-19**: Epic 5.1 - Currency value object (#40, PR #139 - awaiting review)
3940
-**2026-01-19**: Epic 4.8 - Masterwork → Master rank trigger (#39, PR #136)
4041
-**2026-01-19**: Epic 4.7 - CraftingSystem (#38, PR #135)
4142
-**2026-01-19**: Epic 4.6 - CraftingOutcomeRule (#37, PR #134)
@@ -49,8 +50,9 @@ Epic 4 (Crafting and Class Progression) complete! Next: Epic 5 (Economy and Inve
4950

5051
Priority order for remaining work:
5152

52-
1. **Epic 5** - #7: Economy and Inventory (0/6 tasks)
53-
2. **Epic 6** - #8: Complete Contracts and Commitments (4/6 remaining)
53+
1. **Epic 5.2** - #41: Implement InventoryComponent
54+
2. **Epic 5** - #7: Complete Economy and Inventory (5/6 remaining)
55+
3. **Epic 6** - #8: Complete Contracts and Commitments (4/6 remaining)
5456

5557
## Key Design Decisions
5658

@@ -262,11 +264,23 @@ _For implementation patterns, examine referenced code paths._
262264

263265
---
264266

267+
## Epic 5: Economy and Inventory (🔄 1/6 tasks)
268+
269+
**5.1 Implement Currency value object**_Issue #40, PR #139 (awaiting review)_
270+
271+
- ✅ FromSilver(), FromGold(), FromMixed() factory methods
272+
- ✅ Silver and Gold properties for denomination access
273+
- ✅ ToBreakdown() for converting to (gold, silver, copper) tuple
274+
- ✅ Conversion rates: 1 silver = 10 copper, 1 gold = 100 copper
275+
- **Verified**: 6 tests pass, all 517 tests pass
276+
277+
---
278+
265279
### Planned Epics
266280

267281
| Epic | Title | Status | Issue | Key Components |
268282
| ---- | -------------------------------- | ------ | ----- | --------------------------------------------- |
269-
| 5 | Economy and Inventory | ⏳ 0/6 | #7 | Currency, InventoryComponent, PriceCalculator |
283+
| 5 | Economy and Inventory | 🔄 1/6 | #7 | Currency, InventoryComponent, PriceCalculator |
270284
| 6 | Contracts and Commitments | 🔄 2/6 | #8 | Commitment types, ContractActions |
271285
| 7 | Settlement and Guild | ⏳ 0/6 | #9 | Settlement, Guild, leadership |
272286
| 8 | Scenario Testing Framework | ⏳ 0/7 | #10 | WorldBuilder, CharacterBuilder |

src/FantasyRpgWorld.Core/Domain/ValueObjects/Currency.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,62 @@
11
namespace FantasyRpgWorld.Core.Domain.ValueObjects;
22

33
/// <summary>
4-
/// Represents currency in copper pieces.
5-
/// Simplified currency for Epic 6; detailed economy in Epic 5.
4+
/// Represents currency with copper, silver, and gold denominations.
5+
/// Conversion: 1 silver = 10 copper, 1 gold = 100 copper.
66
/// </summary>
77
public readonly record struct Currency(int Copper)
88
{
9+
private const int CopperPerSilver = 10;
10+
private const int CopperPerGold = 100;
11+
912
/// <summary>
1013
/// Creates currency from a copper amount.
1114
/// </summary>
1215
public static Currency FromCopper(int copper) => new(copper);
1316

17+
/// <summary>
18+
/// Creates currency from a silver amount.
19+
/// </summary>
20+
public static Currency FromSilver(int silver) => new(silver * CopperPerSilver);
21+
22+
/// <summary>
23+
/// Creates currency from a gold amount.
24+
/// </summary>
25+
public static Currency FromGold(int gold) => new(gold * CopperPerGold);
26+
27+
/// <summary>
28+
/// Creates currency from mixed denominations.
29+
/// </summary>
30+
public static Currency FromMixed(int gold, int silver, int copper) =>
31+
new(gold * CopperPerGold + silver * CopperPerSilver + copper);
32+
1433
/// <summary>
1534
/// Returns zero currency.
1635
/// </summary>
1736
public static Currency Zero => new(0);
1837

38+
/// <summary>
39+
/// Gets the silver value (whole silver pieces, not including copper remainder).
40+
/// </summary>
41+
public int Silver => Copper / CopperPerSilver;
42+
43+
/// <summary>
44+
/// Gets the gold value (whole gold pieces, not including copper/silver remainder).
45+
/// </summary>
46+
public int Gold => Copper / CopperPerGold;
47+
48+
/// <summary>
49+
/// Breaks down the currency into gold, silver, and copper components.
50+
/// </summary>
51+
public (int Gold, int Silver, int Copper) ToBreakdown()
52+
{
53+
int gold = Copper / CopperPerGold;
54+
int remaining = Copper % CopperPerGold;
55+
int silver = remaining / CopperPerSilver;
56+
int copper = remaining % CopperPerSilver;
57+
return (gold, silver, copper);
58+
}
59+
1960
public static Currency operator +(Currency a, Currency b) =>
2061
new(a.Copper + b.Copper);
2162

tests/FantasyRpgWorld.Core.Tests/Domain/ValueObjects/CurrencyTests.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,75 @@ public void Equality_WorksCorrectly()
9292
Assert.Equal(a, b);
9393
Assert.NotEqual(a, c);
9494
}
95+
96+
[Fact]
97+
public void FromSilver_ConvertsToCopperCorrectly()
98+
{
99+
// Act
100+
var currency = Currency.FromSilver(5);
101+
102+
// Assert
103+
Assert.Equal(50, currency.Copper);
104+
}
105+
106+
[Fact]
107+
public void FromGold_ConvertsToCopperCorrectly()
108+
{
109+
// Act
110+
var currency = Currency.FromGold(3);
111+
112+
// Assert
113+
Assert.Equal(300, currency.Copper);
114+
}
115+
116+
[Fact]
117+
public void Silver_Property_ReturnsCorrectValue()
118+
{
119+
// Arrange
120+
var currency = Currency.FromCopper(75);
121+
122+
// Act
123+
int silver = currency.Silver;
124+
125+
// Assert
126+
Assert.Equal(7, silver); // 75 copper = 7 silver (with 5 copper remaining)
127+
}
128+
129+
[Fact]
130+
public void Gold_Property_ReturnsCorrectValue()
131+
{
132+
// Arrange
133+
var currency = Currency.FromCopper(350);
134+
135+
// Act
136+
int gold = currency.Gold;
137+
138+
// Assert
139+
Assert.Equal(3, gold); // 350 copper = 3 gold (with 50 copper remaining)
140+
}
141+
142+
[Fact]
143+
public void FromMixed_CreatesCurrencyFromMultipleDenominations()
144+
{
145+
// Act
146+
var currency = Currency.FromMixed(gold: 2, silver: 3, copper: 5);
147+
148+
// Assert
149+
Assert.Equal(235, currency.Copper); // 2*100 + 3*10 + 5 = 235
150+
}
151+
152+
[Fact]
153+
public void ToBreakdown_ReturnsCorrectDenominations()
154+
{
155+
// Arrange
156+
var currency = Currency.FromCopper(347);
157+
158+
// Act
159+
var (gold, silver, copper) = currency.ToBreakdown();
160+
161+
// Assert
162+
Assert.Equal(3, gold); // 300 copper
163+
Assert.Equal(4, silver); // 40 copper
164+
Assert.Equal(7, copper); // 7 copper remaining
165+
}
95166
}

0 commit comments

Comments
 (0)