Start writing out user stories for game creation
Some checks failed
Monorepo build / build-flake (push) Has been cancelled
Some checks failed
Monorepo build / build-flake (push) Has been cancelled
This commit is contained in:
@@ -22,7 +22,7 @@ tasks:
|
||||
|
||||
report:
|
||||
cmds:
|
||||
- cargo run --bin planning-report planning/
|
||||
- cargo watch -x 'run --bin planning-report planning/'
|
||||
|
||||
test-all:
|
||||
cmds:
|
||||
|
||||
@@ -17,7 +17,7 @@ As a player, I want to see my character sheet while I am in a game so that I can
|
||||
- [[T000-task-example]] <!-- use Obsidian wikilinks -->
|
||||
|
||||
## Planning
|
||||
- [[planning/US000-planning]] <!-- link to planning doc (see planning template) -->
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
@@ -16,9 +16,6 @@ As a player, I want to adjust scores on my character sheet so that I can always
|
||||
## Linked Tasks
|
||||
- [[T0004 Add Cypher system Spin Box for the pools]]
|
||||
- [[T0005 Add a Candela mechanism to set and clear Marks]]
|
||||
- [[T0006 Add a Candela mechanism to mark a Scar]]
|
||||
- [[T0007 Add a Candela mechanism to set and clear Drives]]
|
||||
- [[T0008 Add a Candela mechanism to set and clear Resistances]]
|
||||
- [[T0014 Add pool meters to the GM view of a Cypher system character]]
|
||||
- [[T0015 Add health meters to the GM view of a Candela system character]]
|
||||
- [[T0016 Persist character sheets to disk]]
|
||||
@@ -26,7 +23,7 @@ As a player, I want to adjust scores on my character sheet so that I can always
|
||||
- [[T0018 Create APIs for Character CRUD]]
|
||||
|
||||
## Planning
|
||||
- [[planning/US000-planning]] <!-- link to planning doc (see planning template) -->
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
@@ -16,7 +16,7 @@ As a user, I want my session to be preserved through server restarts so that my
|
||||
- [[T0012 Create a database and persist sessions]]
|
||||
|
||||
## Planning
|
||||
- [[planning/US000-planning]] <!-- link to planning doc (see planning template) -->
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
@@ -16,7 +16,7 @@ As a Storyteller, I want to be able to create characters for my game without pla
|
||||
- [[T000-task-example]] <!-- use Obsidian wikilinks -->
|
||||
|
||||
## Planning
|
||||
- [[planning/US000-planning]] <!-- link to planning doc (see planning template) -->
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
id: US0008
|
||||
type: userstory
|
||||
status: Not Started
|
||||
---
|
||||
## Story
|
||||
As a player, I want to be able to edit my full Candela character sheet so that I can track the status of my character and reflect my character's growth over time.
|
||||
## Acceptance Criteria
|
||||
- The user can add abilities to their character sheet
|
||||
- The user can add scars to the character sheet
|
||||
- The user can set and clear drives and resistances
|
||||
- The user can move an action score from one action to another
|
||||
|
||||
## Linked Tasks
|
||||
- [[T0006 Add a Candela mechanism to mark a Scar]]
|
||||
- [[T0007 Add a Candela mechanism to set and clear Drives]]
|
||||
- [[T0008 Add a Candela mechanism to set and clear Resistances]]
|
||||
|
||||
## Planning
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
## Status
|
||||
- Status: Not Started / In Progress / Blocked / Done
|
||||
- Remaining tasks: 0 / N <!-- keep updated or automate -->
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
id: US0009
|
||||
type: userstory
|
||||
status: Not Started
|
||||
---
|
||||
|
||||
## Story
|
||||
|
||||
|
||||
## Acceptance Criteria
|
||||
- AC1
|
||||
- AC2
|
||||
- AC3
|
||||
|
||||
## Linked Tasks
|
||||
- [[T000-task-example]] <!-- use Obsidian wikilinks -->
|
||||
|
||||
## Planning
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
## Status
|
||||
- Status: Not Started / In Progress / Blocked / Done
|
||||
- Remaining tasks: 0 / N <!-- keep updated or automate -->
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
id: US0010
|
||||
type: userstory
|
||||
status: Not Started
|
||||
---
|
||||
|
||||
## Story
|
||||
As a user, I want to create a new game and configure my existing games so that I can host a game for players.
|
||||
## Acceptance Criteria
|
||||
- The user can create a new game.
|
||||
- The user is automatically assigned as the GM for a game they create.
|
||||
- The GM for a game can add and remove users.
|
||||
- The GM for a game can view and edit all characters in the game.
|
||||
|
||||
## Linked Tasks
|
||||
- [[T000-task-example]] <!-- use Obsidian wikilinks -->
|
||||
|
||||
## Planning
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
## Status
|
||||
- Status: Not Started / In Progress / Blocked / Done
|
||||
- Remaining tasks: 0 / N <!-- keep updated or automate -->
|
||||
28
planning/01 user stories/US0011.md
Normal file
28
planning/01 user stories/US0011.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
id: US0011
|
||||
type: userstory
|
||||
status: Not Started
|
||||
---
|
||||
|
||||
## Story
|
||||
**As a** [role]
|
||||
**I want** [goal]
|
||||
**So that** [benefit]
|
||||
|
||||
## Acceptance Criteria
|
||||
- AC1
|
||||
- AC2
|
||||
- AC3
|
||||
|
||||
## Linked Tasks
|
||||
- [[T000-task-example]] <!-- use Obsidian wikilinks -->
|
||||
|
||||
## Planning
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
## Status
|
||||
- Status: Not Started / In Progress / Blocked / Done
|
||||
- Remaining tasks: 0 / N <!-- keep updated or automate -->
|
||||
@@ -2,7 +2,7 @@
|
||||
id: T0005
|
||||
type: task
|
||||
story: US0005
|
||||
status: In Progress
|
||||
status: Done
|
||||
assignee:
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: T0006
|
||||
type: task
|
||||
story: US0005
|
||||
story: US0008
|
||||
status: Not Started
|
||||
assignee:
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: T0007
|
||||
type: task
|
||||
story: US0005
|
||||
story: US0008
|
||||
status: Not Started
|
||||
assignee:
|
||||
---
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: T0008
|
||||
type: task
|
||||
story: US0005
|
||||
story: US0008
|
||||
status: Not Started
|
||||
assignee:
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: T0014
|
||||
type: task
|
||||
story: US0005
|
||||
status: In Progress
|
||||
status: Done
|
||||
assignee:
|
||||
---
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
id: T0015
|
||||
type: task
|
||||
story: US0005
|
||||
status: In Progress
|
||||
status: Done
|
||||
assignee:
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: D0005
|
||||
type: defect
|
||||
story:
|
||||
status: Not Started
|
||||
assignee:
|
||||
---
|
||||
|
||||
## Description
|
||||
Any time the user updates the health or bleed marks for their character, the character sheet should be broadcast to the GM. At this time, GMs must refresh the page to see any updates.
|
||||
|
||||
## Definition of Done
|
||||
- DoD 1
|
||||
- DoD 2
|
||||
|
||||
## Notes
|
||||
- code paths, files to touch, tests to add
|
||||
42
planning/05 defects/US0010-planning.md
Normal file
42
planning/05 defects/US0010-planning.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Planning / US0010 — Detailed plan
|
||||
|
||||
## Overview
|
||||
The goal here is to build basic game setup and editing.
|
||||
|
||||
Creating a new game is easy. Simply click the "New Game" button on the game management screen.
|
||||
|
||||
The game editing screen must contain a variety of details:
|
||||
- The name of the game
|
||||
- The system
|
||||
- A list of scenes
|
||||
- A list of images
|
||||
- A list of all the cards
|
||||
- A list of all the characters
|
||||
|
||||
The user will need to be able to
|
||||
- create a new scene
|
||||
- edit a scene -- this implies a scene editing dialog
|
||||
- add image resources
|
||||
- associate images with the scene background and with tabletop images
|
||||
- create a card
|
||||
- edit a card
|
||||
|
||||
## Architecture / Design notes
|
||||
- components, models, API sketches
|
||||
|
||||
## Implementation plan (steps)
|
||||
1. Step 1
|
||||
2. Step 2
|
||||
3. Step 3
|
||||
|
||||
## Risks & Dependencies
|
||||
- external systems, third-party libs, design decisions
|
||||
|
||||
## Estimation
|
||||
- Rough estimate (hours / story points)
|
||||
|
||||
## Acceptance / QA notes
|
||||
- Anything QA must verify beyond ACs.
|
||||
|
||||
## Open questions
|
||||
- Q1, Q2
|
||||
@@ -18,7 +18,7 @@ status: Not Started
|
||||
- [[T000-task-example]] <!-- use Obsidian wikilinks -->
|
||||
|
||||
## Planning
|
||||
- [[planning/US000-planning]] <!-- link to planning doc (see planning template) -->
|
||||
- [[US0010-planning]] <!-- link to planning doc (see planning template) -->
|
||||
|
||||
## Manual Tests (links)
|
||||
- [[M000-login-success]]
|
||||
|
||||
@@ -18,6 +18,8 @@ struct FrontMatter {
|
||||
fn main() -> std::io::Result<()> {
|
||||
let planning_dir = std::env::args().skip(1).next().unwrap();
|
||||
let mut user_stories: HashMap<String, Vec<String>> = HashMap::new();
|
||||
let mut story_titles: HashMap<String, String> = HashMap::new();
|
||||
let mut task_titles: HashMap<String, String> = HashMap::new();
|
||||
|
||||
// Traverse the planning directory
|
||||
for entry in walkdir::WalkDir::new(planning_dir) {
|
||||
@@ -27,13 +29,31 @@ fn main() -> std::io::Result<()> {
|
||||
if let Some(frontmatter) = extract_frontmatter(&content) {
|
||||
if frontmatter.item_type == "userstory" && frontmatter.status != "Done" {
|
||||
user_stories.entry(frontmatter.id.clone()).or_insert(vec![]);
|
||||
story_titles.insert(
|
||||
frontmatter.id.clone(),
|
||||
entry
|
||||
.path()
|
||||
.file_name()
|
||||
.and_then(|p| p.to_str())
|
||||
.map(|s| story_title(s.to_owned()))
|
||||
.unwrap(),
|
||||
);
|
||||
} else if frontmatter.item_type == "task" && frontmatter.status != "Done" {
|
||||
if let Some(story_id) = frontmatter.story {
|
||||
user_stories
|
||||
.entry(story_id)
|
||||
.or_insert(vec![])
|
||||
.push(frontmatter.id);
|
||||
.push(frontmatter.id.clone());
|
||||
}
|
||||
task_titles.insert(
|
||||
frontmatter.id.clone(),
|
||||
entry
|
||||
.path()
|
||||
.file_name()
|
||||
.and_then(|p| p.to_str())
|
||||
.map(|s| task_title(s.to_owned()))
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,13 +62,17 @@ fn main() -> std::io::Result<()> {
|
||||
// Generate the report
|
||||
println!("Open User Stories Report:");
|
||||
for (story, tasks) in &user_stories {
|
||||
println!("\nUser Story: {}", story);
|
||||
println!(
|
||||
"\nUser Story: {} {}",
|
||||
story,
|
||||
story_titles.get(story).unwrap()
|
||||
);
|
||||
if tasks.is_empty() {
|
||||
println!(" No open tasks.");
|
||||
} else {
|
||||
println!(" Open Tasks:");
|
||||
for task in tasks {
|
||||
println!(" - {}", task);
|
||||
println!(" - {} {}", task, task_titles.get(task).unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,3 +96,13 @@ fn extract_frontmatter(content: &str) -> Option<FrontMatter> {
|
||||
let yaml = &content[start + 3..end];
|
||||
serde_yaml::from_str(yaml).ok()
|
||||
}
|
||||
|
||||
fn story_title(content: String) -> String {
|
||||
let file_stem: String = content.chars().rev().skip(3).collect();
|
||||
file_stem.chars().rev().skip(7).collect()
|
||||
}
|
||||
|
||||
fn task_title(content: String) -> String {
|
||||
let file_stem: String = content.chars().rev().skip(3).collect();
|
||||
file_stem.chars().rev().skip(6).collect()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user