feat: upgrade to .NET 9 / C# 13, latest packages & actions, add Copilot instructions (#2)

This commit is contained in:
Copilot
2026-03-06 02:39:56 +02:00
committed by GitHub
parent 7639eb1cfc
commit 76ff24b34c
12 changed files with 224 additions and 596 deletions

94
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,94 @@
# GitHub Copilot Instructions for HihaArvio
## Authoritative Reference
**CLAUDE.md is the single source of truth for this repository.**
All guidelines, architecture decisions, implementation requirements, and coding standards defined in [`CLAUDE.md`](../CLAUDE.md) at the repository root MUST be followed without exception. CLAUDE.md takes absolute precedence over any other instruction, convention, or assumption.
Before suggesting, generating, or reviewing any code for this repository, read and internalize CLAUDE.md in its entirety.
## Non-Negotiable Rules
The following rules are derived from CLAUDE.md and additional Copilot-specific code quality guidelines. All MUST be enforced in every interaction:
### Language & Framework
- **Target framework:** .NET 9, using C# 13
- **UI framework:** .NET MAUI (multi-platform)
- **Nullable reference types MUST be enabled** across all projects
- **All compiler warnings MUST be treated as errors** (`<TreatWarningsAsErrors>true</TreatWarningsAsErrors>`)
- Language version MUST be set to `13` in all project files
### Architecture (MVVM Strict Separation)
- **Models**: Plain data objects only — no business logic
- **ViewModels**: All presentation logic — 100% testable without UI dependencies
- **Views**: Thin layer — data binding only, minimal code-behind
- **Services**: All business logic and infrastructure concerns
### Dependency Injection
- All services MUST be injected via constructor — never use the service locator pattern or `new` inside ViewModels
- Register all services in `MauiProgram.cs`
- Platform-specific implementations use `#if IOS`, `#elif WINDOWS || MACCATALYST`
### Testing Requirements
- Test coverage MUST be ≥ 95 % (measured by Coverlet; threshold enforcement is a future CI/CD enhancement)
- Testing stack: **xUnit + NSubstitute + FluentAssertions**
- All tests MUST use deterministic, seeded randomness — never `Random.Shared`
- All external dependencies (sensors, database, file system) MUST be mocked
- Use test-data builders for complex objects
### Security
- Estimate selection MUST use `System.Security.Cryptography.RandomNumberGenerator` — never `System.Random`
- No external data transmission — all data is stored locally only
- Request the minimum required platform permissions
### Commit & Code Quality
- Use **semantic / conventional commit** messages (e.g. `feat:`, `fix:`, `chore:`, `docs:`, `test:`, `refactor:`)
- Make **atomic commits** — one logical change per commit
- Run all linting and build tools; automatically fix all reported issues before committing
- Follow the `.editorconfig` rules present in the repository root
## Technology Stack (Current Versions)
| Component | Version |
|---|---|
| .NET SDK | 9.0.x |
| C# Language | 13 |
| Microsoft.Maui.Controls | 9.0.120 |
| Microsoft.Maui.Controls.Compatibility | 9.0.120 |
| CommunityToolkit.Mvvm | 8.4.0 |
| SQLite (sqlite-net-pcl) | 1.9.172 |
| SQLitePCLRaw.bundle_green | 2.1.11 |
| Microsoft.Extensions.Logging.Debug | 9.0.13 |
| xUnit | 2.9.3 |
| xunit.runner.visualstudio | 2.8.2 |
| Microsoft.NET.Test.Sdk | 18.3.0 |
| NSubstitute | 5.3.0 |
| FluentAssertions | 8.8.0 |
| coverlet.collector | 8.0.0 |
## Key Files
| File | Purpose |
|---|---|
| `CLAUDE.md` | **Authoritative project guide** — always read first |
| `spec.md` | Formal RFC 2119 requirements (MUST / SHALL / REQUIRED) |
| `docs/plans/2025-11-18-hiha-arvio-design.md` | Validated architecture decisions |
| `src/HihaArvio/HihaArvio.csproj` | Main MAUI project |
| `tests/HihaArvio.Tests/HihaArvio.Tests.csproj` | Unit & integration tests |
| `.editorconfig` | Code style enforcement |
## Easter Egg — Never Expose
The hidden humorous mode triggered by shaking for > 15 seconds MUST NOT have any visible UI indication and MUST NOT be mentioned in any UI element, setting, or documentation visible to users.
## When in Doubt
If there is any ambiguity, consult **CLAUDE.md** and **spec.md** — in that order.
Do not invent architecture, add dependencies, or change platform targets without explicit justification grounded in those documents.

View File

@@ -12,9 +12,9 @@ This directory contains the CI/CD workflows for HihaArvio.
**What it does**:
- Runs on Ubuntu (fastest, cheapest for tests)
- Sets up .NET 8.0
- Builds the solution for `net8.0` target
- Runs all 189 xUnit tests
- Sets up .NET 9.0
- Restores and builds `tests/HihaArvio.Tests/HihaArvio.Tests.csproj` for the `net9.0` target
- Runs all xUnit tests in `tests/HihaArvio.Tests/HihaArvio.Tests.csproj`
- Publishes test results and coverage reports
- Uploads test artifacts for review
@@ -32,8 +32,8 @@ This directory contains the CI/CD workflows for HihaArvio.
**Purpose**: Build the application for all supported platforms.
**What it does**:
- **iOS Job**: Builds for iOS 15.0+ on macOS-14 runner
- **macOS Catalyst Job**: Builds for macOS 12.0+ on macOS-14 runner
- **iOS Job**: Builds for iOS 15.0+ on macOS-26 runner
- **macOS Catalyst Job**: Builds for macOS 12.0+ on macOS-26 runner
- Installs .NET MAUI workload
- Builds without code signing (for CI verification)
- Uploads build artifacts (`.app` bundles)
@@ -98,16 +98,16 @@ Tags containing `alpha`, `beta`, or `rc` are marked as pre-releases.
### Running Tests Locally
```bash
dotnet test HihaArvio.sln -f net8.0
dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0
```
### Building Locally
```bash
# iOS
dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-ios -c Release
dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-ios -c Release
# macOS Catalyst
dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-maccatalyst -c Release
dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-maccatalyst -c Release
```
### Creating a Release
@@ -146,16 +146,16 @@ For signed releases, add:
### Runner Requirements
- **Test**: `ubuntu-latest` (any Linux runner)
- **Build**: `macos-14` (Apple Silicon runner for MAUI workloads)
- **Publish**: `macos-14` (Apple Silicon runner for MAUI workloads)
- **Build**: `macos-26` (Apple Silicon runner with Xcode 26 for MAUI workloads)
- **Publish**: `macos-26` (Apple Silicon runner with Xcode 26 for MAUI workloads)
### External Actions Used
- `actions/checkout@v4` - Checkout repository
- `actions/setup-dotnet@v4` - Setup .NET SDK
- `actions/upload-artifact@v4` - Upload build artifacts
- `actions/create-release@v1` - Create GitHub releases
- `actions/upload-release-asset@v1` - Upload release assets
- `dorny/test-reporter@v1` - Generate test reports
- `actions/checkout@v6.0.2` - Checkout repository
- `actions/setup-dotnet@v5.2.0` - Setup .NET SDK
- `actions/upload-artifact@v7.0.0` - Upload build artifacts
- `softprops/action-gh-release@v2.5.0` - Create GitHub releases
- `actions/download-artifact@v8.0.0` - Download build artifacts for release
- `dorny/test-reporter@v2.6.0` - Generate test reports
---
@@ -164,7 +164,7 @@ For signed releases, add:
### Tests Failing
Check test output in workflow logs. Run locally with:
```bash
dotnet test HihaArvio.sln -f net8.0 --verbosity detailed
dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 --verbosity detailed
```
### Build Failing

View File

@@ -10,64 +10,74 @@ on:
jobs:
build-ios:
name: Build iOS
runs-on: macos-latest
runs-on: macos-26
permissions:
contents: read
actions: write
steps:
- name: Checkout code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with:
dotnet-version: '8.0.x'
dotnet-version: '9.0.x'
- name: Select Xcode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
xcode-version: '26.0'
- name: Restore workloads
run: dotnet workload restore src/HihaArvio/HihaArvio.csproj
- name: Build iOS
run: dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-ios -c Release /p:ArchiveOnBuild=false /p:EnableCodeSigning=false
run: dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-ios -c Release /p:ArchiveOnBuild=false /p:EnableCodeSigning=false
- name: Upload iOS build artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ios-build
path: |
src/HihaArvio/bin/Release/net8.0-ios/**/*.app
src/HihaArvio/bin/Release/net8.0-ios/**/*.ipa
src/HihaArvio/bin/Release/net9.0-ios/**/*.app
src/HihaArvio/bin/Release/net9.0-ios/**/*.ipa
retention-days: 7
build-maccatalyst:
name: Build macOS Catalyst
runs-on: macos-latest
runs-on: macos-26
permissions:
contents: read
actions: write
steps:
- name: Checkout code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with:
dotnet-version: '8.0.x'
dotnet-version: '9.0.x'
- name: Select Xcode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
xcode-version: '26.0'
- name: Restore workloads
run: dotnet workload restore src/HihaArvio/HihaArvio.csproj
- name: Build macOS Catalyst
run: dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-maccatalyst -c Release /p:ArchiveOnBuild=false /p:EnableCodeSigning=false
run: dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-maccatalyst -c Release /p:ArchiveOnBuild=false /p:EnableCodeSigning=false
- name: Upload macOS build artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: maccatalyst-build
path: |
src/HihaArvio/bin/Release/net8.0-maccatalyst/**/*.app
src/HihaArvio/bin/Release/net8.0-maccatalyst/**/*.pkg
src/HihaArvio/bin/Release/net9.0-maccatalyst/**/*.app
src/HihaArvio/bin/Release/net9.0-maccatalyst/**/*.pkg
retention-days: 7
build-status:

View File

@@ -12,19 +12,19 @@ on:
type: string
env:
DOTNET_VERSION: '8.0.x'
DOTNET_VERSION: '9.0.x'
jobs:
build-ios:
name: Build iOS
runs-on: macos-latest
runs-on: macos-26
permissions:
contents: read
actions: write
steps:
- name: Checkout code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Get version
id: get_version
@@ -36,17 +36,22 @@ jobs:
fi
- name: Setup .NET
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Select Xcode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
xcode-version: '26.0'
- name: Restore workloads
run: dotnet workload restore src/HihaArvio/HihaArvio.csproj
- name: Build iOS Release
run: |
dotnet publish src/HihaArvio/HihaArvio.csproj \
-f net8.0-ios \
-f net9.0-ios \
-c Release \
/p:ApplicationDisplayVersion=${{ steps.get_version.outputs.version }} \
/p:ApplicationVersion=${{ github.run_number }} \
@@ -55,7 +60,7 @@ jobs:
- name: Create iOS artifact archive
run: |
cd src/HihaArvio/bin/Release/net8.0-ios
cd src/HihaArvio/bin/Release/net9.0-ios
# Find the .app bundle (it's in a subdirectory like iossimulator-arm64 or ios-arm64)
APP_PATH=$(find . -name "*.app" -type d | head -n 1)
if [ -z "$APP_PATH" ]; then
@@ -66,7 +71,7 @@ jobs:
mv HihaArvio-iOS-${{ steps.get_version.outputs.version }}.zip ${{ github.workspace }}/
- name: Upload iOS artifact
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ios-release
path: HihaArvio-iOS-${{ steps.get_version.outputs.version }}.zip
@@ -74,14 +79,14 @@ jobs:
build-maccatalyst:
name: Build macOS
runs-on: macos-latest
runs-on: macos-26
permissions:
contents: read
actions: write
steps:
- name: Checkout code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Get version
id: get_version
@@ -93,17 +98,22 @@ jobs:
fi
- name: Setup .NET
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Select Xcode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
xcode-version: '26.0'
- name: Restore workloads
run: dotnet workload restore src/HihaArvio/HihaArvio.csproj
- name: Build macOS Catalyst Release
run: |
dotnet publish src/HihaArvio/HihaArvio.csproj \
-f net8.0-maccatalyst \
-f net9.0-maccatalyst \
-c Release \
/p:ApplicationDisplayVersion=${{ steps.get_version.outputs.version }} \
/p:ApplicationVersion=${{ github.run_number }} \
@@ -112,7 +122,7 @@ jobs:
- name: Create macOS artifact archive
run: |
cd src/HihaArvio/bin/Release/net8.0-maccatalyst
cd src/HihaArvio/bin/Release/net9.0-maccatalyst
# Find the .app bundle (it's in a subdirectory like maccatalyst-x64 or maccatalyst-arm64)
APP_PATH=$(find . -name "*.app" -type d | head -n 1)
if [ -z "$APP_PATH" ]; then
@@ -123,7 +133,7 @@ jobs:
mv HihaArvio-macOS-${{ steps.get_version.outputs.version }}.zip ${{ github.workspace }}/
- name: Upload macOS artifact
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: maccatalyst-release
path: HihaArvio-macOS-${{ steps.get_version.outputs.version }}.zip
@@ -140,7 +150,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
@@ -172,17 +182,17 @@ jobs:
fi
- name: Download iOS artifact
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: ios-release
- name: Download macOS artifact
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: maccatalyst-release
- name: Create Release
uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
tag_name: ${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }}
name: Release ${{ steps.get_version.outputs.version }}

View File

@@ -17,21 +17,21 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with:
dotnet-version: '8.0.x'
dotnet-version: '9.0.x'
- name: Restore dependencies
run: dotnet restore tests/HihaArvio.Tests/HihaArvio.Tests.csproj /p:TargetFrameworks=net8.0
run: dotnet restore tests/HihaArvio.Tests/HihaArvio.Tests.csproj /p:TargetFrameworks=net9.0
- name: Build test project
run: dotnet build tests/HihaArvio.Tests/HihaArvio.Tests.csproj --configuration Release --no-restore /p:TargetFrameworks=net8.0
run: dotnet build tests/HihaArvio.Tests/HihaArvio.Tests.csproj --configuration Release --no-restore /p:TargetFrameworks=net9.0
- name: Run tests with coverage
run: dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj --configuration Release --no-build --verbosity normal /p:TargetFrameworks=net8.0 --collect:"XPlat Code Coverage" --logger "trx;LogFileName=test-results.trx"
run: dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj --configuration Release --no-build --verbosity normal /p:TargetFrameworks=net9.0 --collect:"XPlat Code Coverage" --logger "trx;LogFileName=test-results.trx"
- name: Install ReportGenerator
run: dotnet tool install --global dotnet-reportgenerator-globaltool
@@ -43,14 +43,14 @@ jobs:
run: |
# Extract and display line coverage percentage
COVERAGE=$(grep -oP 'Line coverage: \K[\d.]+' coverage/Summary.txt | head -1)
echo "📊 Code coverage for net8.0 target: ${COVERAGE}%"
echo "📊 Code coverage for net9.0 target: ${COVERAGE}%"
echo ""
echo "Note: Multi-target MAUI projects cannot achieve full coverage on Linux runners."
echo "Platform-specific code (iOS/macOS) is excluded when building net8.0 only."
echo "Platform-specific code (iOS/macOS) is excluded when building net9.0 only."
echo "Full coverage measurement requires macOS runners with all target frameworks."
- name: Upload coverage report
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always()
with:
name: coverage-report
@@ -58,7 +58,7 @@ jobs:
retention-days: 30
- name: Publish test results
uses: dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3 # v2.1.1
uses: dorny/test-reporter@3d76b34a4535afbd0600d347b09a6ee5deb3ed7f # v2.6.0
if: always()
with:
name: Test Results
@@ -67,7 +67,7 @@ jobs:
fail-on-error: true
- name: Upload test results
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always()
with:
name: test-results

1
.gitignore vendored
View File

@@ -44,6 +44,7 @@ _ReSharper*/
*.trx
*.coverage
*.coveragexml
**/TestResults/
# NuGet Packages
*.nupkg

View File

@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
Hiha-Arvio (Finnish: "Sleeve Estimate") is a .NET 8 MAUI cross-platform application that generates semi-random time estimates based on physical shake input (accelerometer on mobile, mouse movement on desktop). This is a humor app for "pulling an estimate from your sleeve."
Hiha-Arvio (Finnish: "Sleeve Estimate") is a .NET 9 MAUI cross-platform application that generates semi-random time estimates based on physical shake input (accelerometer on mobile, mouse movement on desktop). This is a humor app for "pulling an estimate from your sleeve."
**Platforms (in priority order):** iOS (primary) → Web (Blazor) → macOS
@@ -41,8 +41,8 @@ Hiha-Arvio (Finnish: "Sleeve Estimate") is a .NET 8 MAUI cross-platform applicat
## Technology Stack
- **Framework:** .NET 8 MAUI (LTS)
- **Language:** C# 12 with nullable reference types
- **Framework:** .NET 9 MAUI
- **Language:** C# 13 with nullable reference types
- **Database:** SQLite via `sqlite-net-pcl`
- **MVVM:** CommunityToolkit.Mvvm (source generators)
- **Testing:** xUnit, NSubstitute, FluentAssertions, Coverlet
@@ -139,9 +139,9 @@ HihaArvio.sln
### Build Commands
- **Build all platforms:** `dotnet build HihaArvio.sln`
- **Build specific framework:** `dotnet build HihaArvio.sln -f net8.0`
- **Build iOS:** `dotnet build HihaArvio.sln -f net8.0-ios`
- **Build macOS:** `dotnet build HihaArvio.sln -f net8.0-maccatalyst`
- **Build specific framework:** `dotnet build HihaArvio.sln -f net9.0`
- **Build iOS:** `dotnet build HihaArvio.sln -f net9.0-ios`
- **Build macOS:** `dotnet build HihaArvio.sln -f net9.0-maccatalyst`
### Test Commands
- **Run all tests:** `dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj`
@@ -153,8 +153,8 @@ HihaArvio.sln
- **Coverage files:** Located in `tests/HihaArvio.Tests/TestResults/{guid}/coverage.cobertura.xml`
### Run Commands
- **iOS Simulator:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net8.0-ios`
- **macOS:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net8.0-maccatalyst`
- **iOS Simulator:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net9.0-ios`
- **macOS:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net9.0-maccatalyst`
### Notes
- All commands should be run from the repository root directory
@@ -205,7 +205,7 @@ HihaArvio.sln
- Solution structure with src/HihaArvio and tests/HihaArvio.Tests
- Core models: EstimateMode, EstimateResult, ShakeData, AppSettings
- 48 tests, all passing
- Build verification: all platforms (net8.0, iOS, macOS)
- Build verification: all platforms (net9.0, iOS, macOS)
**Milestone 2: Services Layer (✅ Complete)**
- IEstimateService + EstimateService (25 tests)
@@ -280,7 +280,7 @@ HihaArvio.sln
- TabBar with 3 tabs: Estimate, History, Settings
- Each tab uses ContentTemplate for lazy loading
- **Total: 165 tests still passing (no UI tests yet)**
- **Build:** 0 warnings, 0 errors across all platforms (net8.0, iOS, macOS Catalyst)
- **Build:** 0 warnings, 0 errors across all platforms (net9.0, iOS, macOS Catalyst)
**Milestone 5: Platform-Specific Implementations (✅ Complete)**
- IAccelerometerService interface
@@ -314,7 +314,7 @@ HihaArvio.sln
- Dispose pattern implemented for cleanup
- Final verification
- **189 tests passing** across all layers
- **0 warnings, 0 errors** on all platforms (net8.0, iOS, macOS Catalyst)
- **0 warnings, 0 errors** on all platforms (net9.0, iOS, macOS Catalyst)
- Models (48 tests) + Services (71 tests) + ViewModels (46 tests) + Accelerometer (24 tests)
- Build artifacts verified for all target frameworks

View File

@@ -24,7 +24,7 @@ A playful Finnish take on agile estimation through shake gestures. Instead of po
## 🏗️ Architecture
Built with **.NET 8 MAUI** using modern C# 12 and strict MVVM architecture:
Built with **.NET 9 MAUI** using modern C# 13 and strict MVVM architecture:
- **Models**: Core domain models (EstimateResult, ShakeData, AppSettings)
- **Services**: Business logic layer
@@ -37,7 +37,7 @@ Built with **.NET 8 MAUI** using modern C# 12 and strict MVVM architecture:
### Technology Stack
- **.NET 8.0** with C# 12
- **.NET 9.0** with C# 13
- **MAUI** for cross-platform UI
- **CommunityToolkit.Mvvm** for MVVM patterns
- **SQLite** (sqlite-net-pcl) for local storage
@@ -53,20 +53,20 @@ Comprehensive test suite covering all layers:
```bash
# Run all tests
dotnet test HihaArvio.sln -f net8.0
dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0
# Run with detailed output
dotnet test HihaArvio.sln -f net8.0 --verbosity detailed
dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 --verbosity detailed
# Generate coverage report
dotnet test HihaArvio.sln -f net8.0 --collect:"XPlat Code Coverage"
dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 --collect:"XPlat Code Coverage"
```
## 🚀 Getting Started
### Prerequisites
- **.NET 8 SDK**: [Download here](https://dotnet.microsoft.com/download/dotnet/8.0)
- **.NET 9 SDK**: [Download here](https://dotnet.microsoft.com/download/dotnet/9.0)
- **MAUI Workload**: Install via `dotnet workload install maui`
- **Xcode 15+**: Required for iOS/macOS builds (macOS only)
- **Visual Studio 2022** or **VS Code** with C# extension
@@ -85,19 +85,19 @@ dotnet restore HihaArvio.sln
dotnet build HihaArvio.sln -c Release
# Run tests
dotnet test HihaArvio.sln -f net8.0
dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0
```
### Running the App
```bash
# iOS Simulator
dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-ios -c Debug
dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-ios -c Debug
# Then deploy via Xcode or Visual Studio
# macOS Catalyst
dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-maccatalyst -c Debug
# Then run the .app bundle from bin/Debug/net8.0-maccatalyst/
dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-maccatalyst -c Debug
# Then run the .app bundle from bin/Debug/net9.0-maccatalyst/
```
## 📦 CI/CD Workflows
@@ -174,20 +174,20 @@ hiha-arvio/
-**MVVM architecture** strictly followed
-**Dependency injection** throughout
-**Nullable reference types** enabled
-**C# 12** with modern language features
-**C# 13** with modern language features
### Building for Release
```bash
# iOS
dotnet publish src/HihaArvio/HihaArvio.csproj \
-f net8.0-ios \
-f net9.0-ios \
-c Release \
/p:ArchiveOnBuild=true
# macOS Catalyst
dotnet publish src/HihaArvio/HihaArvio.csproj \
-f net8.0-maccatalyst \
-f net9.0-maccatalyst \
-c Release \
/p:ArchiveOnBuild=true
```

View File

@@ -5,7 +5,10 @@ public partial class App : Application
public App()
{
InitializeComponent();
}
MainPage = new AppShell();
protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(new AppShell());
}
}

View File

@@ -2,11 +2,11 @@
<PropertyGroup>
<!-- Per spec: iOS (primary), Web (Blazor), macOS (tertiary) -->
<!-- net8.0 included for unit testing without platform dependencies -->
<!-- net9.0 included for unit testing without platform dependencies -->
<!-- Include iOS/macOS targets only on macOS (where they can be built) -->
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('OSX'))">net8.0;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<!-- On Linux/Windows, only include net8.0 -->
<TargetFrameworks Condition="!$([MSBuild]::IsOSPlatform('OSX'))">net8.0</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('OSX'))">net9.0;net9.0-ios;net9.0-maccatalyst</TargetFrameworks>
<!-- On Linux/Windows, only include net9.0 -->
<TargetFrameworks Condition="!$([MSBuild]::IsOSPlatform('OSX'))">net9.0</TargetFrameworks>
<!-- Note for MacCatalyst:
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
@@ -15,17 +15,17 @@
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
<OutputType Condition="'$(TargetFramework)' != 'net8.0'">Exe</OutputType>
<OutputType Condition="'$(TargetFramework)' == 'net8.0'">Library</OutputType>
<OutputType Condition="'$(TargetFramework)' != 'net9.0'">Exe</OutputType>
<OutputType Condition="'$(TargetFramework)' == 'net9.0'">Library</OutputType>
<RootNamespace>HihaArvio</RootNamespace>
<UseMaui Condition="'$(TargetFramework)' != 'net8.0'">true</UseMaui>
<UseMaui Condition="'$(TargetFramework)' != 'net9.0'">true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- Per spec: treat warnings as errors, C# 12 -->
<!-- Per spec: treat warnings as errors, C# 13 -->
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
<!-- Display name -->
<ApplicationTitle>HihaArvio</ApplicationTitle>
@@ -61,11 +61,11 @@
</ItemGroup>
<ItemGroup>
<!-- Per spec: MAUI 8.x with explicit lower bound -->
<!-- Per spec: MAUI 9.x with explicit lower bound -->
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.3" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.3" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" />
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.120" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="9.0.120" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.13" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.11" />
</ItemGroup>

View File

@@ -1,25 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<!-- Per spec: treat warnings as errors, C# 12 -->
<!-- Per spec: treat warnings as errors, C# 13 -->
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>12</LangVersion>
<LangVersion>13</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="coverlet.collector" Version="8.0.0" />
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageReference Include="NSubstitute" Version="5.3.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,490 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="0.5128" branch-rate="0.875" version="1.9" timestamp="1763460415" lines-covered="60" lines-valid="117" branches-covered="14" branches-valid="16">
<sources>
<source>/Users/ivuorinen/Code/ivuorinen/hiha-arvio/src/HihaArvio/</source>
</sources>
<packages>
<package name="HihaArvio" line-rate="0.5128" branch-rate="0.875" complexity="41">
<classes>
<class name="__XamlGeneratedCode__.__Type416C8673F66D9458" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/Resources_Styles_Colors.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="2">
<methods>
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="29" hits="0" branch="False" />
<line number="30" hits="0" branch="False" />
<line number="31" hits="0" branch="False" />
</lines>
</method>
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="20" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="29" hits="0" branch="False" />
<line number="30" hits="0" branch="False" />
<line number="31" hits="0" branch="False" />
<line number="20" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</class>
<class name="__XamlGeneratedCode__.__Type76D52C8BE0F320C6" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/Resources_Styles_Styles.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="2">
<methods>
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="29" hits="0" branch="False" />
<line number="30" hits="0" branch="False" />
<line number="31" hits="0" branch="False" />
</lines>
</method>
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="20" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="29" hits="0" branch="False" />
<line number="30" hits="0" branch="False" />
<line number="31" hits="0" branch="False" />
<line number="20" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</class>
<class name="HihaArvio.App" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/App.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="1">
<methods>
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</class>
<class name="HihaArvio.App" filename="App.xaml.cs" line-rate="0" branch-rate="1" complexity="1">
<methods>
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="5" hits="0" branch="False" />
<line number="6" hits="0" branch="False" />
<line number="7" hits="0" branch="False" />
<line number="9" hits="0" branch="False" />
<line number="10" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="5" hits="0" branch="False" />
<line number="6" hits="0" branch="False" />
<line number="7" hits="0" branch="False" />
<line number="9" hits="0" branch="False" />
<line number="10" hits="0" branch="False" />
</lines>
</class>
<class name="HihaArvio.AppShell" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/AppShell.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="1">
<methods>
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</class>
<class name="HihaArvio.AppShell" filename="AppShell.xaml.cs" line-rate="0" branch-rate="1" complexity="1">
<methods>
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="5" hits="0" branch="False" />
<line number="6" hits="0" branch="False" />
<line number="7" hits="0" branch="False" />
<line number="8" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="5" hits="0" branch="False" />
<line number="6" hits="0" branch="False" />
<line number="7" hits="0" branch="False" />
<line number="8" hits="0" branch="False" />
</lines>
</class>
<class name="HihaArvio.MainPage" filename="MainPage.xaml.cs" line-rate="0" branch-rate="0" complexity="3">
<methods>
<method name="OnCounterClicked" signature="(System.Object,System.EventArgs)" line-rate="0" branch-rate="0" complexity="2">
<lines>
<line number="13" hits="0" branch="False" />
<line number="14" hits="0" branch="False" />
<line number="16" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="26" type="jump" coverage="0%" />
</conditions>
</line>
<line number="17" hits="0" branch="False" />
<line number="19" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
</lines>
</method>
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="5" hits="0" branch="False" />
<line number="7" hits="0" branch="False" />
<line number="8" hits="0" branch="False" />
<line number="9" hits="0" branch="False" />
<line number="10" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="13" hits="0" branch="False" />
<line number="14" hits="0" branch="False" />
<line number="16" hits="0" branch="True" condition-coverage="0% (0/2)">
<conditions>
<condition number="26" type="jump" coverage="0%" />
</conditions>
</line>
<line number="17" hits="0" branch="False" />
<line number="19" hits="0" branch="False" />
<line number="21" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="5" hits="0" branch="False" />
<line number="7" hits="0" branch="False" />
<line number="8" hits="0" branch="False" />
<line number="9" hits="0" branch="False" />
<line number="10" hits="0" branch="False" />
</lines>
</class>
<class name="HihaArvio.MainPage" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/MainPage.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="1">
<methods>
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="25" hits="0" branch="False" />
<line number="26" hits="0" branch="False" />
<line number="27" hits="0" branch="False" />
<line number="28" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="25" hits="0" branch="False" />
<line number="26" hits="0" branch="False" />
<line number="27" hits="0" branch="False" />
<line number="28" hits="0" branch="False" />
</lines>
</class>
<class name="HihaArvio.MauiProgram" filename="MauiProgram.cs" line-rate="0" branch-rate="1" complexity="1">
<methods>
<method name="CreateMauiApp" signature="()" line-rate="0" branch-rate="1" complexity="1">
<lines>
<line number="8" hits="0" branch="False" />
<line number="9" hits="0" branch="False" />
<line number="10" hits="0" branch="False" />
<line number="11" hits="0" branch="False" />
<line number="12" hits="0" branch="False" />
<line number="13" hits="0" branch="False" />
<line number="14" hits="0" branch="False" />
<line number="15" hits="0" branch="False" />
<line number="16" hits="0" branch="False" />
<line number="19" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="8" hits="0" branch="False" />
<line number="9" hits="0" branch="False" />
<line number="10" hits="0" branch="False" />
<line number="11" hits="0" branch="False" />
<line number="12" hits="0" branch="False" />
<line number="13" hits="0" branch="False" />
<line number="14" hits="0" branch="False" />
<line number="15" hits="0" branch="False" />
<line number="16" hits="0" branch="False" />
<line number="19" hits="0" branch="False" />
<line number="22" hits="0" branch="False" />
<line number="23" hits="0" branch="False" />
</lines>
</class>
<class name="HihaArvio.Models.AppSettings" filename="Models/AppSettings.cs" line-rate="1" branch-rate="1" complexity="5">
<methods>
<method name="get_SelectedMode" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="14" hits="22" branch="False" />
</lines>
</method>
<method name="get_MaxHistorySize" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="23" hits="7" branch="False" />
</lines>
</method>
<method name="set_MaxHistorySize" signature="(System.Int32)" line-rate="1" branch-rate="1" complexity="2">
<lines>
<line number="25" hits="8" branch="False" />
<line number="26" hits="8" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="10" type="jump" coverage="100%" />
</conditions>
</line>
<line number="27" hits="3" branch="False" />
<line number="28" hits="3" branch="False" />
<line number="29" hits="3" branch="False" />
<line number="30" hits="3" branch="False" />
<line number="31" hits="3" branch="False" />
<line number="34" hits="5" branch="False" />
<line number="35" hits="5" branch="False" />
</lines>
</method>
<method name=".ctor" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="8" hits="14" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="14" hits="22" branch="False" />
<line number="23" hits="7" branch="False" />
<line number="25" hits="8" branch="False" />
<line number="26" hits="8" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="10" type="jump" coverage="100%" />
</conditions>
</line>
<line number="27" hits="3" branch="False" />
<line number="28" hits="3" branch="False" />
<line number="29" hits="3" branch="False" />
<line number="30" hits="3" branch="False" />
<line number="31" hits="3" branch="False" />
<line number="34" hits="5" branch="False" />
<line number="35" hits="5" branch="False" />
<line number="8" hits="14" branch="False" />
</lines>
</class>
<class name="HihaArvio.Models.EstimateResult" filename="Models/EstimateResult.cs" line-rate="1" branch-rate="1" complexity="16">
<methods>
<method name="get_Id" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="14" hits="10" branch="False" />
</lines>
</method>
<method name="get_Timestamp" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="19" hits="8" branch="False" />
</lines>
</method>
<method name="get_EstimateText" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="28" hits="2" branch="False" />
</lines>
</method>
<method name="set_EstimateText" signature="(System.String)" line-rate="1" branch-rate="1" complexity="4">
<lines>
<line number="30" hits="8" branch="False" />
<line number="31" hits="8" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="7" type="jump" coverage="100%" />
</conditions>
</line>
<line number="32" hits="1" branch="False" />
<line number="33" hits="1" branch="False" />
<line number="36" hits="7" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="34" type="jump" coverage="100%" />
</conditions>
</line>
<line number="37" hits="2" branch="False" />
<line number="38" hits="2" branch="False" />
<line number="41" hits="5" branch="False" />
<line number="42" hits="5" branch="False" />
</lines>
</method>
<method name="get_Mode" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="48" hits="7" branch="False" />
</lines>
</method>
<method name="get_ShakeIntensity" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="56" hits="6" branch="False" />
</lines>
</method>
<method name="set_ShakeIntensity" signature="(System.Double)" line-rate="1" branch-rate="1" complexity="4">
<lines>
<line number="58" hits="12" branch="False" />
<line number="59" hits="12" branch="True" condition-coverage="100% (4/4)">
<conditions>
<condition number="11" type="jump" coverage="100%" />
<condition number="30" type="jump" coverage="100%" />
</conditions>
</line>
<line number="60" hits="3" branch="False" />
<line number="61" hits="3" branch="False" />
<line number="62" hits="3" branch="False" />
<line number="63" hits="3" branch="False" />
<line number="64" hits="3" branch="False" />
<line number="67" hits="9" branch="False" />
<line number="68" hits="9" branch="False" />
</lines>
</method>
<method name="get_ShakeDuration" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="74" hits="9" branch="False" />
</lines>
</method>
<method name="Create" signature="(System.String,HihaArvio.Models.EstimateMode,System.Double,System.TimeSpan)" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="89" hits="4" branch="False" />
<line number="90" hits="4" branch="False" />
<line number="91" hits="4" branch="False" />
<line number="92" hits="4" branch="False" />
<line number="93" hits="4" branch="False" />
<line number="94" hits="4" branch="False" />
<line number="95" hits="4" branch="False" />
<line number="96" hits="4" branch="False" />
<line number="97" hits="4" branch="False" />
<line number="98" hits="4" branch="False" />
<line number="99" hits="4" branch="False" />
</lines>
</method>
<method name=".ctor" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="8" hits="16" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="14" hits="10" branch="False" />
<line number="19" hits="8" branch="False" />
<line number="28" hits="2" branch="False" />
<line number="30" hits="8" branch="False" />
<line number="31" hits="8" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="7" type="jump" coverage="100%" />
</conditions>
</line>
<line number="32" hits="1" branch="False" />
<line number="33" hits="1" branch="False" />
<line number="36" hits="7" branch="True" condition-coverage="100% (2/2)">
<conditions>
<condition number="34" type="jump" coverage="100%" />
</conditions>
</line>
<line number="37" hits="2" branch="False" />
<line number="38" hits="2" branch="False" />
<line number="41" hits="5" branch="False" />
<line number="42" hits="5" branch="False" />
<line number="48" hits="7" branch="False" />
<line number="56" hits="6" branch="False" />
<line number="58" hits="12" branch="False" />
<line number="59" hits="12" branch="True" condition-coverage="100% (4/4)">
<conditions>
<condition number="11" type="jump" coverage="100%" />
<condition number="30" type="jump" coverage="100%" />
</conditions>
</line>
<line number="60" hits="3" branch="False" />
<line number="61" hits="3" branch="False" />
<line number="62" hits="3" branch="False" />
<line number="63" hits="3" branch="False" />
<line number="64" hits="3" branch="False" />
<line number="67" hits="9" branch="False" />
<line number="68" hits="9" branch="False" />
<line number="74" hits="9" branch="False" />
<line number="89" hits="4" branch="False" />
<line number="90" hits="4" branch="False" />
<line number="91" hits="4" branch="False" />
<line number="92" hits="4" branch="False" />
<line number="93" hits="4" branch="False" />
<line number="94" hits="4" branch="False" />
<line number="95" hits="4" branch="False" />
<line number="96" hits="4" branch="False" />
<line number="97" hits="4" branch="False" />
<line number="98" hits="4" branch="False" />
<line number="99" hits="4" branch="False" />
<line number="8" hits="16" branch="False" />
</lines>
</class>
<class name="HihaArvio.Models.ShakeData" filename="Models/ShakeData.cs" line-rate="1" branch-rate="1" complexity="7">
<methods>
<method name="get_Intensity" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="16" hits="7" branch="False" />
</lines>
</method>
<method name="set_Intensity" signature="(System.Double)" line-rate="1" branch-rate="1" complexity="4">
<lines>
<line number="18" hits="10" branch="False" />
<line number="19" hits="10" branch="True" condition-coverage="100% (4/4)">
<conditions>
<condition number="11" type="jump" coverage="100%" />
<condition number="30" type="jump" coverage="100%" />
</conditions>
</line>
<line number="20" hits="4" branch="False" />
<line number="21" hits="4" branch="False" />
<line number="22" hits="4" branch="False" />
<line number="23" hits="4" branch="False" />
<line number="24" hits="4" branch="False" />
<line number="27" hits="6" branch="False" />
<line number="28" hits="6" branch="False" />
</lines>
</method>
<method name="get_Duration" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="34" hits="7" branch="False" />
</lines>
</method>
<method name="get_IsShaking" signature="()" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="39" hits="7" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="16" hits="7" branch="False" />
<line number="18" hits="10" branch="False" />
<line number="19" hits="10" branch="True" condition-coverage="100% (4/4)">
<conditions>
<condition number="11" type="jump" coverage="100%" />
<condition number="30" type="jump" coverage="100%" />
</conditions>
</line>
<line number="20" hits="4" branch="False" />
<line number="21" hits="4" branch="False" />
<line number="22" hits="4" branch="False" />
<line number="23" hits="4" branch="False" />
<line number="24" hits="4" branch="False" />
<line number="27" hits="6" branch="False" />
<line number="28" hits="6" branch="False" />
<line number="34" hits="7" branch="False" />
<line number="39" hits="7" branch="False" />
</lines>
</class>
</classes>
</package>
</packages>
</coverage>