Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
6f3d7a4
bump deps
jamesshenry Apr 30, 2026
49eb1af
Merge branch 'main' into feat/stats-tracking
jamesshenry May 1, 2026
510bac4
chore: cleanup files
jamesshenry May 3, 2026
8e0b3be
chore: formatting
jamesshenry May 5, 2026
0e5664a
feat: support for non-english languages
jamesshenry May 7, 2026
51920b0
Merge remote-tracking branch 'origin/main' into feat/stats-tracking
jamesshenry May 7, 2026
2ff86e1
fix: text rendering for AsGrapheme
jamesshenry May 8, 2026
cce8c05
cleanup test file warnings
jamesshenry May 12, 2026
140edc9
fix
jamesshenry May 13, 2026
0f77fd1
wip: recording snapshots
jamesshenry May 13, 2026
0c171fa
mv file
jamesshenry May 13, 2026
f4b15a8
refactor: extract KeystrokeCollection
jamesshenry May 18, 2026
15bbf3e
refactor: TypingBuffer for text management in enging
jamesshenry May 18, 2026
4bdb971
add TypingBuffer and KeystrokeCollection
jamesshenry May 18, 2026
50a1148
renamings
jamesshenry May 19, 2026
e5154bb
test: considerably more
jamesshenry May 19, 2026
3dc7413
update build config
jamesshenry May 19, 2026
a88c68e
test: fixes
jamesshenry May 20, 2026
b70ab7f
fix: replace WeakReferenceMessenger calls with IMessenger
jamesshenry May 20, 2026
0fdd9e8
wip: stats persistence
jamesshenry May 20, 2026
b4796e4
refactor typing view refresh logic
jamesshenry May 20, 2026
56a34cd
chore: fix tests
jamesshenry May 20, 2026
a0d7dfa
test: update
jamesshenry May 21, 2026
c37a86b
ci: update loom to 0.6.0
jamesshenry May 22, 2026
d67b5fc
wip: ResultsView
jamesshenry May 22, 2026
d315eaa
renames
jamesshenry May 23, 2026
18cfd74
wip
jamesshenry May 23, 2026
4cf646c
wip
jamesshenry May 23, 2026
3fd9aff
wip: telemetry builder
jamesshenry May 27, 2026
0dd3433
wip Telemetry tracking
jamesshenry May 27, 2026
36f0a6d
align namespaces
jamesshenry May 27, 2026
e27806c
todo: improve storage of textSample in Tests
jamesshenry May 27, 2026
d72b24a
refactor: rename
jamesshenry May 27, 2026
55d569b
refactor: rename
jamesshenry May 27, 2026
efdc3c1
fix: allow delay game reset until UI has time to render final update
jamesshenry May 27, 2026
cd034d8
feat: persist test telemetry
jamesshenry May 27, 2026
548d4a4
wip
jamesshenry May 28, 2026
3b95fa3
wip: ResultsView
jamesshenry May 28, 2026
794d511
wip: ResultsView
jamesshenry May 29, 2026
812a5cd
test: remove obsolete test
jamesshenry May 29, 2026
43b5a7f
chore: fix warnings
jamesshenry May 29, 2026
82ef086
wip
jamesshenry Jun 2, 2026
89bf6c1
experiment: add Stanza
jamesshenry Jun 2, 2026
11e8ae1
rm test
jamesshenry Jun 2, 2026
53da66e
update loom
jamesshenry Jun 2, 2026
ceaad48
wip: stanza experiment
jamesshenry Jun 3, 2026
21b0f36
wip: stanza experiment
jamesshenry Jun 4, 2026
4051a8f
chore: csharpier format
jamesshenry Jun 4, 2026
a2a0e60
wip: Stanza.TerminalGui 0.1.0-preview.3
jamesshenry Jun 7, 2026
6726c9f
adopt stanza
jamesshenry Jun 10, 2026
9986d1d
wip: Results
jamesshenry Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .build/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Loom Build Instructions

## Prerequisites

- .NET SDK from `global.json`
- Tool manifest in `dotnet-tools.json`

Install/restore tools:

```bash
dotnet tool restore
```

Required tools and dependent Loom modules:

| Tool Command | Tool Package | Dependent Module(s) |
| --- | --- | --- |
| `loom` | `loom.build` | CLI entry point used to run all targets/modules |
| `minver` | `minver-cli` | `MinVerModule` |
| `vpk` | `vpk` | `VelopackReleaseModule` |
| `reportgenerator` | `dotnet-reportgenerator-globaltool` | `ReportGeneratorModule` |

## Setup

Initialize Loom files:

```bash
dotnet loom init
```

Run tests:

```bash
dotnet loom test
```

Run release pipeline:

```bash
dotnet loom release
```

## Enable NuGet and GitHub Releases

To allow upload/publishing modules to run, enable the following flags in `.build/loom.json`:

```json
{
"workspace": {
"enableNugetUpload": true,
"enableGithubRelease": true
}
}
```

Also configure required GitHub secrets:

- `GITHUB_TOKEN` is the built-in GitHub Actions token (`secrets.GITHUB_TOKEN`).
- Create a repository secret named `NUGET_API_KEY`.

See release workflow setup in [.github/workflows/release.yml](../.github/workflows/release.yml).
1 change: 1 addition & 0 deletions .build/loom.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"cleanDirectories": [],
"enableNugetUpload": false,
"enableGithubRelease": true,
"defaultPreReleaseIdentifiers": "preview.0",
"enableVelopackRelease": true
},
"artifacts": {
Expand Down
4 changes: 4 additions & 0 deletions .build/loom.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
"type": "boolean",
"description": "Whether to create a GitHub release during a release."
},
"defaultPreReleaseIdentifiers": {
"type": "string",
"description": "Maps to MinVer.DefaultPreReleaseIdentifiers"
},
"enableVelopackRelease": {
"type": "boolean",
"description": "Whether to create velopack packages during a release."
Expand Down
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"rollForward": false
},
"loom.build": {
"version": "0.5.0",
"version": "0.6.0",
"commands": [
"loom"
],
Expand Down
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ dotnet_diagnostic.RCS1042.severity = suggestion
dotnet_diagnostic.RCS1043.severity = suggestion
dotnet_diagnostic.RCS1045.severity = warning
dotnet_diagnostic.RCS1050.severity = silent # Simplify object creation
dotnet_diagnostic.RCS1051.severity = suggestion
dotnet_diagnostic.RCS1051.severity = none
dotnet_diagnostic.RCS1060.severity = suggestion
dotnet_diagnostic.RCS1061.severity = suggestion
dotnet_diagnostic.RCS1062.severity = suggestion
Expand Down
19 changes: 19 additions & 0 deletions .foam/templates/adr-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
status: proposed
---

# ADR 2: MVVM Binding Logic and Lifecycle Management

## Context

ENTER HERE

## Decision

ENTER HERE

## Conesquences

### Pros

### Cons
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@ updates:
interval: weekly
day: monday
open-pull-requests-limit: 5
groups:
nuget-dependencies:
patterns:
- "*"

- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
groups:
github-actions-dependencies:
patterns:
- "*"
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
run: dotnet tool restore

- name: Run Loom Test Pipeline
run: dotnet loom Test
run: dotnet loom test

- name: Upload test results
if: always()
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
run: dotnet tool restore

- name: Run tests
run: dotnet loom Test
run: dotnet loom test

release:
name: Release Artifacts for ${{ matrix.rid }}
Expand Down Expand Up @@ -73,4 +73,4 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Nuget__ApiKey: ${{ secrets.NUGET_API_KEY }}
run: dotnet loom Release
run: dotnet loom release
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"[csharp]": {
"editor.defaultFormatter": "ms-dotnettools.csharp"
}
}
6 changes: 0 additions & 6 deletions Directory.Build.props

This file was deleted.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## TODO

- add separate stats view and viewmodel that can receive messages during game.
- add separate stats view and viewmodel that can receive messages during test.
- finishing wireframes
9 changes: 9 additions & 0 deletions Typical.slnx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
<Solution>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
<File Path=".gitignore" />
<File Path="src/Directory.Build.props" />
<File Path="src/Directory.Packages.props" />
<File Path="global.json" />
<File Path="LICENSE.md" />
<File Path="nuget.config" />
<File Path="README.md" />
<File Path="run.ps1" />
<File Path="todo.md" />
</Folder>
<Folder Name="/src/">
<Project Path="src/Typical.Core/Typical.Core.csproj" />
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "11.0.100-preview.3.26207.106",
"version": "11.0.100-preview.4.26230.115",
"allowPrerelease": true
},
"test": {
Expand Down
2 changes: 1 addition & 1 deletion nuget.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
Expand Down
2 changes: 2 additions & 0 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
<Nullable>enable</Nullable>
<DebugType>embedded</DebugType>
<ArtifactsPath>$(MSBuildThisFileDirectory)..\.artifacts</ArtifactsPath>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<Features>runtime-async=on</Features>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Roslynator.Analyzers">
Expand Down
25 changes: 14 additions & 11 deletions Directory.Packages.props → src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,30 @@
<PackageVersion Include="Bogus" Version="35.6.5" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
<PackageVersion Include="CommunityToolkit.Diagnostics" Version="8.4.2" />
<PackageVersion Include="Dapper" Version="2.1.79" />
<PackageVersion Include="Dapper.AOT" Version="1.0.52" />
<PackageVersion Include="dbup" Version="5.0.41" />
<PackageVersion Include="dbup-sqlite" Version="6.0.4" />
<PackageVersion Include="DbUp.SourceGen" Version="0.0.1" />
<PackageVersion Include="DotNetPathUtils" Version="0.3.1" />
<PackageVersion Include="Kuddle.Net" Version="0.8.0" />
<PackageVersion Include="Kuddle.Net.Extensions.Configuration" Version="0.8.0" />
<PackageVersion Include="LiteDB" Version="5.0.21" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.6" />
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" />
<PackageVersion
Include="Microsoft.Extensions.DependencyInjection.Abstractions"
Version="10.0.6"
Version="10.0.7"
/>
<PackageVersion
Include="Microsoft.Extensions.Options.ConfigurationExtensions"
Version="10.0.6"
Version="10.0.7"
/>
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.6" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.7" />
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.5.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.17.0" />
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.6.2" />
Expand All @@ -45,12 +47,13 @@
<PackageVersion Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageVersion Include="Spectre.Console" Version="0.55.2" />
<PackageVersion Include="Stanza.TerminalGui" Version="0.1.0-preview.6" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.17.0" />
<PackageVersion Include="Terminal.Gui" Version="2.0.0-rc.4" />
<PackageVersion Include="Terminal.Gui" Version="2.4.3" />
<PackageVersion Include="Velopack" Version="0.0.1298" />
<PackageVersion Include="Vogen" Version="8.0.5" />
<PackageVersion Include="Xdg.Directories" Version="0.1.2" />
<PackageVersion Include="Imposter" Version="0.1.9" />
<PackageVersion Include="TUnit" Version="1.37.0" />
<PackageVersion Include="TUnit" Version="1.41.0" />
</ItemGroup>
</Project>
8 changes: 8 additions & 0 deletions src/Typical.Core/Data/IStatsRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Typical.Core.Statistics;

namespace Typical.Core.Data;

public interface IStatsRepository
{
Task SaveTestResultAsync(TestResult result);
}
8 changes: 8 additions & 0 deletions src/Typical.Core/Data/ITextRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Typical.Core.Data;

public interface ITextRepository
{
Task<Quote> GetRandomQuoteAsync();
Task<Quote> GetQuoteAsync(int currentId);
Task<bool> HasAnyAsync();
}
13 changes: 4 additions & 9 deletions src/Typical.Core/Data/Quote.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;

namespace Typical.Core.Data;

public class Quote
{
public int Id { get; set; }
public required string Text { get; set; }
public required string Author { get; set; }
public IEnumerable<string> Tags { get; set; } = [];
public List<string> Tags { get; set; } = [];
public int WordCount { get; set; }
public int CharCount { get; set; }
}

public interface ITextRepository
{
Task<Quote> GetRandomQuoteAsync();
Task<Quote> GetQuoteAsync(int currentId);
Task AddQuotesAsync(IEnumerable<Quote> quotes);
Task<bool> HasAnyAsync();
}
3 changes: 0 additions & 3 deletions src/Typical.Core/Events/BackspacePressedEvent.cs

This file was deleted.

3 changes: 0 additions & 3 deletions src/Typical.Core/Events/GameEndedEvent.cs

This file was deleted.

3 changes: 0 additions & 3 deletions src/Typical.Core/Events/GameQuitEvent.cs

This file was deleted.

5 changes: 0 additions & 5 deletions src/Typical.Core/Events/KeyPressedEvent.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

namespace Typical.Core.Events;

public record GameStateUpdatedMessage(
GameSnapshot State
public record TestSessionUpdatedMessage(
TestSnapshot Snapshot
);

public record GameResetMessage(ModeSettings Settings);

public record WordsMode(int Count, bool Punctuation, bool Numbers);
public record TimeMode(TimeSpan Duration, bool Punctuation, bool Numbers);
public record QuoteMode(QuoteLength Length);
Expand Down
5 changes: 5 additions & 0 deletions src/Typical.Core/Events/TestCompletedMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Typical.Core.Statistics;

namespace Typical.Core.Events;

public record TestCompletedMessage(TestResult Result);
3 changes: 3 additions & 0 deletions src/Typical.Core/Events/TestResetMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Typical.Core.Events;

public record TestResetMessage(ModeSettings Settings);
Loading
Loading