Commit ebe595e
authored








Closes #315
## <img
src="https://mojiemoji.jozo.beer/emoji/%E6%A6%82%E8%A6%81?font=toge&color=f43f5e&animation=kage_neon&background=transparent&outline=5ef43f&outline_width=2"
alt="概要" height="20" align="absmiddle">
<img
src="https://mojiemoji.jozo.beer/emoji/PR?font=hachimaru&color=ef4444&animation=bure&background=transparent&outline=44ef44&outline_width=2"
alt="PR" height="20" align="absmiddle"> #314 で独立モジュール化した
`CoreAudioTapGateway` に<img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=zero&color=a78bfa&animation=chirichiri&background=transparent&outline=ed7c3a&outline_width=2"
alt="テスト" height="20" align="absmiddle">ターゲットが無く<img
src="https://mojiemoji.jozo.beer/emoji/%E3%82%AB%E3%83%90%E3%83%AC?font=maru&color=facc15&animation=kirari&background=transparent&outline=04ca8a&outline_width=2"
alt="カバレ" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%83%E3%82%B8?font=maru&color=facc15&animation=kirari&background=transparent&outline=04ca8a&outline_width=2"
alt="ッジ" height="20" align="absmiddle"> 0% だったのを、<img
src="https://mojiemoji.jozo.beer/emoji/CI?font=rampart&color=c084fc&animation=gatagata&background=transparent&outline=fcc084&outline_width=2"
alt="CI" height="20" align="absmiddle"> 実行<img
src="https://mojiemoji.jozo.beer/emoji/%E5%8F%AF%E8%83%BD?font=noto&color=4ade80&animation=mochimochi&background=transparent&outline=4a16a3&outline_width=2"
alt="可能" height="20" align="absmiddle">なスモーク<img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2"
alt="テスト" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/5?font=zero&color=fb923c&animation=kira&background=transparent&outline_width=0"
alt="5" height="20" align="absmiddle">本で<img
src="https://mojiemoji.jozo.beer/emoji/%E8%A7%A3%E6%B6%88?font=gothic-bold&color=34d399&animation=mochimochi&speed=slow&background=transparent&outline=9934d3&outline_width=2"
alt="解消" height="24" align="absmiddle">する。ローカル<img
src="https://mojiemoji.jozo.beer/emoji/%E8%A8%88%E6%B8%AC?font=kurobara&color=f43f5e&animation=patapata&background=transparent&outline=5ef43f&outline_width=2"
alt="計測" height="20" align="absmiddle">で行<img
src="https://mojiemoji.jozo.beer/emoji/%E3%82%AB%E3%83%90%E3%83%AC?font=maru&color=facc15&animation=kirari&background=transparent&outline=04ca8a&outline_width=2"
alt="カバレ" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%83%E3%82%B8?font=maru&color=facc15&animation=kirari&background=transparent&outline=04ca8a&outline_width=2"
alt="ッジ" height="20" align="absmiddle"> **0% → 85.5%**(関数 10/12)。
## <img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=maru-bold&color=fbbf24&animation=yokomoya&background=transparent&outline=06d977&outline_width=2"
alt="テスト" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E5%86%85%E5%AE%B9?font=gothic&color=fdba74&animation=kira&background=transparent&outline_width=0"
alt="内容" height="20" align="absmiddle">
| <img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=zero&color=a78bfa&animation=chirichiri&background=transparent&outline=ed7c3a&outline_width=2"
alt="テスト" height="20" align="absmiddle"> | <img
src="https://mojiemoji.jozo.beer/emoji/%E6%A4%9C%E8%A8%BC?font=gothic&color=22c55e&animation=nami&background=transparent&outline=5e22c5&outline_width=2"
alt="検証" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E5%86%85%E5%AE%B9?font=maru-bold&color=a855f7&animation=mochimochi&background=transparent&outline=f7a855&outline_width=2"
alt="内容" height="20" align="absmiddle"> | <img
src="https://mojiemoji.jozo.beer/emoji/%E6%B1%BA%E5%AE%9A?font=noto&color=fb923c&animation=zairu&background=transparent&outline=0cea58&outline_width=2"
alt="決定" height="20" align="absmiddle">性 |
|---|---|---|
| invalid object IDs → nil | `processPid` / `tapFormat` / `createIOProc`
の guard <img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%91%E3%82%B9?font=pixel&color=a78bfa&animation=mabataki&background=transparent&outline=ed7c3a&outline_width=2"
alt="パス" height="20" align="absmiddle"> | <img
src="https://mojiemoji.jozo.beer/emoji/%E6%B1%BA%E5%AE%9A?font=noto&color=fb923c&animation=zairu&background=transparent&outline=0cea58&outline_width=2"
alt="決定" height="20" align="absmiddle">的 |
| destroy on invalid IDs | `destroyAggregateDevice` /
`destroyProcessTap` がエラーを<img
src="https://mojiemoji.jozo.beer/emoji/%E5%AE%89%E5%85%A8?font=chikara&color=f472b6&animation=disco&background=transparent&outline_width=0"
alt="安全" height="20" align="absmiddle">に無視 | <img
src="https://mojiemoji.jozo.beer/emoji/%E6%B1%BA%E5%AE%9A?font=noto&color=fb923c&animation=zairu&background=transparent&outline=0cea58&outline_width=2"
alt="決定" height="20" align="absmiddle">的 |
| `processObjects` + pid 解決 | TCC <img
src="https://mojiemoji.jozo.beer/emoji/%E4%B8%8D%E8%A6%81?font=mincho&color=8b5cf6&animation=gatagata&background=transparent&outline=f68b5c&outline_width=2"
alt="不要" height="20" align="absmiddle">の HAL メタデータクエリ。実プロセスオブジェクトで
`processPid` の<img
src="https://mojiemoji.jozo.beer/emoji/%E6%88%90%E5%8A%9F?font=maru&color=10b981&animation=bure&background=transparent&outline=8110b9&outline_width=2"
alt="成功" height="20" align="absmiddle">系もカバー | 環境依存(nil 許容) |
| aggregate device round-trip | `createAggregateDevice` → `createIOProc`
→ `start`/`stop` → `destroyIOProc` → `destroyAggregateDevice` | 環境依存(nil
許容) |
| `createProcessTap` guard <img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%91%E3%82%B9?font=chikara&color=facc15&animation=patapata&background=transparent&outline=04ca8a&outline_width=2"
alt="パス" height="20" align="absmiddle"> | TCC 未<img
src="https://mojiemoji.jozo.beer/emoji/%E8%A8%B1%E5%8F%AF?font=tamanegi&color=c084fc&animation=zairu&background=transparent&outline=fcc084&outline_width=2"
alt="許可" height="20" align="absmiddle">の無人ランナーでエラー → nil | **<img
src="https://mojiemoji.jozo.beer/emoji/CI?font=kurobara&color=22c55e&animation=tatemoya&background=transparent&outline=5e22c5&outline_width=2"
alt="CI" height="20" align="absmiddle"> 限定** |
## <img
src="https://mojiemoji.jozo.beer/emoji/%E8%A8%AD%E8%A8%88?font=tamanegi&color=3b82f6&animation=yurayura&background=transparent&outline=f63b82&outline_width=2"
alt="設計" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E5%88%A4%E6%96%AD?font=kurobara&color=06b6d4&animation=yurayura&background=transparent&outline=d406b6&outline_width=2"
alt="判断" height="20" align="absmiddle">
- **nil 許容のスモーク粒度** — HAL の状態に依存するステップは<img
src="https://mojiemoji.jozo.beer/emoji/%E6%88%90%E5%8A%9F?font=gothic-bold&color=facc15&animation=mochimochi&background=transparent&outline=04ca8a&outline_width=2"
alt="成功" height="20" align="absmiddle">を assert せず、<img
src="https://mojiemoji.jozo.beer/emoji/%E5%A4%B1%E6%95%97?font=maru-bold&color=3b82f6&animation=yokomoya&background=transparent&outline=f63b82&outline_width=2"
alt="失敗" height="20" align="absmiddle">時は<img
src="https://mojiemoji.jozo.beer/emoji/%E6%97%A9%E6%9C%9F?font=gothic-bold&color=f472b6&animation=tatemoya&background=transparent&outline=77db27&outline_width=2"
alt="早期" height="20" align="absmiddle"> return。ヘッドレス <img
src="https://mojiemoji.jozo.beer/emoji/CI?font=rampart&color=c084fc&animation=gatagata&background=transparent&outline=fcc084&outline_width=2"
alt="CI" height="20" align="absmiddle"> ランナーでの flaky を避ける(issue #315
の方針どおり)。ローカル実機では round-trip が実際に<img
src="https://mojiemoji.jozo.beer/emoji/%E5%AE%8C%E8%B5%B0?font=gothic-bold&color=60a5fa&animation=zairu&speed=slow&background=transparent&outline=fa60a5&outline_width=2"
alt="完走" height="24" align="absmiddle">することを<img
src="https://mojiemoji.jozo.beer/emoji/%E7%A2%BA%E8%AA%8D?font=gothic-bold&color=d946ef&animation=zairu&background=transparent&outline=efd946&outline_width=2"
alt="確認" height="20" align="absmiddle">済み
- **`createProcessTap` は `CI` 環境変数でゲート** — ローカルの `swift test` で System
Audio Recording の TCC プロンプトが出るのを防ぐ。GitHub Actions では `CI=true` が立つので
guard <img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%91%E3%82%B9?font=chikara&color=facc15&animation=patapata&background=transparent&outline=04ca8a&outline_width=2"
alt="パス" height="20" align="absmiddle">が実行される
- **codecov ignore への<img
src="https://mojiemoji.jozo.beer/emoji/%E8%BF%BD%E5%8A%A0?font=kurobara&color=60a5fa&animation=psycho&background=transparent&outline_width=0"
alt="追加" height="20" align="absmiddle">はしない** — ignore は protocol / stub
/ wiring 専用(coverage-ignored-modules の<img
src="https://mojiemoji.jozo.beer/emoji/%E5%8E%9F%E5%89%87?font=pixel&color=fbbf24&animation=tatemoya&background=transparent&outline=06d977&outline_width=2"
alt="原則" height="20" align="absmiddle">)。covered module として<img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=zero&color=a78bfa&animation=chirichiri&background=transparent&outline=ed7c3a&outline_width=2"
alt="テスト" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E5%8F%AF%E8%83%BD?font=noto&color=4ade80&animation=mochimochi&background=transparent&outline=4a16a3&outline_width=2"
alt="可能" height="20" align="absmiddle">な<img
src="https://mojiemoji.jozo.beer/emoji/%E7%AF%84%E5%9B%B2?font=gothic-bold&color=8b5cf6&animation=zairu&background=transparent&outline=f68b5c&outline_width=2"
alt="範囲" height="20" align="absmiddle">を<img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2"
alt="テスト" height="20" align="absmiddle">する `DarwinGateway` との<img
src="https://mojiemoji.jozo.beer/emoji/%E5%AF%BE%E7%A7%B0?font=mincho&color=10b981&animation=zairu&background=transparent&outline=8110b9&outline_width=2"
alt="対称" height="20" align="absmiddle">性を保つ
## <img
src="https://mojiemoji.jozo.beer/emoji/%E5%AF%BE%E8%B1%A1?font=gothic-bold&color=f97316&animation=gatagata&background=transparent&outline=16f973&outline_width=2"
alt="対象" height="20" align="absmiddle">外(Humble Object の残渣)
`createProcessTap` の<img
src="https://mojiemoji.jozo.beer/emoji/%E6%88%90%E5%8A%9F?font=gothic-bold&color=facc15&animation=mochimochi&background=transparent&outline=04ca8a&outline_width=2"
alt="成功" height="20" align="absmiddle">系(noErr 分岐)は TCC <img
src="https://mojiemoji.jozo.beer/emoji/%E8%A8%B1%E5%8F%AF?font=gothic&color=34d399&animation=gatagata&background=transparent&outline=9934d3&outline_width=2"
alt="許可" height="20" align="absmiddle">+実音源が<img
src="https://mojiemoji.jozo.beer/emoji/%E5%BF%85%E9%A0%88?font=akzk&color=60a5fa&animation=ekken&background=transparent&outline=fa60a5&outline_width=2"
alt="必須" height="20" align="absmiddle">で無人 <img
src="https://mojiemoji.jozo.beer/emoji/CI?font=rampart&color=c084fc&animation=gatagata&background=transparent&outline=fcc084&outline_width=2"
alt="CI" height="20" align="absmiddle"> では実行不<img
src="https://mojiemoji.jozo.beer/emoji/%E5%8F%AF%E8%83%BD?font=noto&color=4ade80&animation=mochimochi&background=transparent&outline=4a16a3&outline_width=2"
alt="可能" height="20" align="absmiddle">。VM レーン/実機<img
src="https://mojiemoji.jozo.beer/emoji/%E6%A4%9C%E8%A8%BC?font=tamanegi&color=06b6d4&animation=yoko_scroll&background=transparent&outline=d406b6&outline_width=2"
alt="検証" height="20" align="absmiddle">の領分として未カバーを<img
src="https://mojiemoji.jozo.beer/emoji/%E8%A8%B1%E5%AE%B9?font=maru&color=94a3b8&animation=yurayura&speed=slow&background=transparent&outline=b894a3&outline_width=2"
alt="許容" height="24" align="absmiddle">する。
## <img
src="https://mojiemoji.jozo.beer/emoji/CI?font=rampart&color=c084fc&animation=gatagata&background=transparent&outline=fcc084&outline_width=2"
alt="CI" height="20" align="absmiddle"> プロセス<img
src="https://mojiemoji.jozo.beer/emoji/%E5%88%86%E9%9B%A2?font=mincho&color=22c55e&animation=ekken&background=transparent&outline=5e22c5&outline_width=2"
alt="分離" height="20" align="absmiddle">(初回<img
src="https://mojiemoji.jozo.beer/emoji/CI?font=rampart&color=c084fc&animation=gatagata&background=transparent&outline=fcc084&outline_width=2"
alt="CI" height="20" align="absmiddle">の<img
src="https://mojiemoji.jozo.beer/emoji/%E5%A4%B1%E6%95%97?font=hachimaru&color=f472b6&animation=mozaiku&background=transparent&outline=b6f472&outline_width=2"
alt="失敗" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E5%AF%BE%E5%BF%9C?font=maru&color=fdba74&animation=chirichiri&background=transparent&outline=74fdba&outline_width=2"
alt="対応" height="20" align="absmiddle">)
初回の<img
src="https://mojiemoji.jozo.beer/emoji/CI?font=rampart&color=c084fc&animation=gatagata&background=transparent&outline=fcc084&outline_width=2"
alt="CI" height="20" align="absmiddle">実行で、本スイートと<img
src="https://mojiemoji.jozo.beer/emoji/%E5%90%8C%E4%B8%80?font=dela&color=34d399&animation=ekken&background=transparent&outline=9934d3&outline_width=2"
alt="同一" height="20" align="absmiddle">プロセス内で並列実行される
`WallpaperPresenterTests`(実 `AVPlayer` を使用)が約20件タイムアウトする<img
src="https://mojiemoji.jozo.beer/emoji/%E5%B9%B2%E6%B8%89?font=zero&color=a78bfa&animation=poyoon&background=transparent&outline=ed7c3a&outline_width=2"
alt="干渉" height="20" align="absmiddle">が<img
src="https://mojiemoji.jozo.beer/emoji/%E7%99%BA%E7%94%9F?font=noto&color=60a5fa&animation=tate_scroll&background=transparent&outline=eb2563&outline_width=2"
alt="発生" height="20" align="absmiddle">した(新スイート<img
src="https://mojiemoji.jozo.beer/emoji/5?font=zero&color=fb923c&animation=kira&background=transparent&outline_width=0"
alt="5" height="20" align="absmiddle">本自体は全<img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%91%E3%82%B9?font=gothic&color=a855f7&animation=kirari&background=transparent&outline=f7a855&outline_width=2"
alt="パス" height="20"
align="absmiddle">・各0.9秒未満)。ヘッドレスランナー上でのHAL接触(aggregate device の<img
src="https://mojiemoji.jozo.beer/emoji/%E7%94%9F%E6%88%90?font=maru&color=facc15&animation=tate_scroll&background=transparent&outline=04ca8a&outline_width=2"
alt="生成" height="20" align="absmiddle">/破棄・tap 試行)が AVFoundation 系の<img
src="https://mojiemoji.jozo.beer/emoji/%E5%88%9D%E6%9C%9F?font=zero&color=3b82f6&animation=mabataki&background=transparent&outline=f63b82&outline_width=2"
alt="初期" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E5%8C%96?font=zero&color=3b82f6&animation=mabataki&background=transparent&outline=f63b82&outline_width=2"
alt="化" height="20" align="absmiddle">を不<img
src="https://mojiemoji.jozo.beer/emoji/%E5%AE%89%E5%AE%9A?font=gothic&color=c084fc&animation=bure&background=transparent&outline=fcc084&outline_width=2"
alt="安定" height="20" align="absmiddle">化させたと推定される。`test.yml` で本スイートのみを別の
swift-test プロセスで実行するよう<img
src="https://mojiemoji.jozo.beer/emoji/%E5%88%86%E9%9B%A2?font=mincho&color=22c55e&animation=ekken&background=transparent&outline=5e22c5&outline_width=2"
alt="分離" height="20" align="absmiddle">し(`--skip` / `--filter`)、profdata
は<img
src="https://mojiemoji.jozo.beer/emoji/%E6%97%A2%E5%AD%98?font=dela&color=f472b6&animation=kira&background=transparent&outline_width=0"
alt="既存" height="20" align="absmiddle">の `*.profdata` マージへ<img
src="https://mojiemoji.jozo.beer/emoji/%E5%90%88%E6%B5%81?font=noto&color=fbbf24&animation=yoko_scroll&background=transparent&outline=06d977&outline_width=2"
alt="合流" height="20" align="absmiddle">させた。ローカルの `swift test`
は従来どおり全スイート一括で<img
src="https://mojiemoji.jozo.beer/emoji/%E5%95%8F%E9%A1%8C?font=mincho&color=facc15&animation=zairu&background=transparent&outline=04ca8a&outline_width=2"
alt="問題" height="20" align="absmiddle">ない(実オーディオデバイスのある環境では<img
src="https://mojiemoji.jozo.beer/emoji/%E5%B9%B2%E6%B8%89?font=akzk&color=eab308&animation=yokomoya&background=transparent&outline=08eab3&outline_width=2"
alt="干渉" height="20" align="absmiddle">は<img
src="https://mojiemoji.jozo.beer/emoji/%E5%86%8D%E7%8F%BE?font=maru&color=eab308&animation=ekken&background=transparent&outline=08eab3&outline_width=2"
alt="再現" height="20" align="absmiddle">しない)。
## <img
src="https://mojiemoji.jozo.beer/emoji/%E6%A4%9C%E8%A8%BC?font=tamanegi&color=06b6d4&animation=yoko_scroll&background=transparent&outline=d406b6&outline_width=2"
alt="検証" height="20" align="absmiddle">
- `swift test` — 全 1151 <img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=hachimaru&color=f43f5e&animation=yoko_scroll&background=transparent&outline=5ef43f&outline_width=2"
alt="テスト" height="20" align="absmiddle">(273 スイート)<img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%91%E3%82%B9?font=pixel&color=4ade80&animation=yatta&speed=normal&background=transparent&outline=804ade&outline_width=2"
alt="パス" height="24" align="absmiddle">
- `make lint` — クリーン
- `xcrun llvm-cov report` — <img
src="https://mojiemoji.jozo.beer/emoji/%E5%AF%BE%E8%B1%A1?font=maru-bold&color=8b5cf6&animation=psycho&background=transparent&outline_width=0"
alt="対象" height="20" align="absmiddle">ファイル行<img
src="https://mojiemoji.jozo.beer/emoji/%E3%82%AB%E3%83%90%E3%83%AC?font=kurobara&color=22c55e&animation=chirichiri&background=transparent&outline=5e22c5&outline_width=2"
alt="カバレ" height="20" align="absmiddle"><img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%83%E3%82%B8?font=kurobara&color=22c55e&animation=chirichiri&background=transparent&outline=5e22c5&outline_width=2"
alt="ッジ" height="20" align="absmiddle"> 85.54%(ローカル、<img
src="https://mojiemoji.jozo.beer/emoji/CI?font=rampart&color=c084fc&animation=gatagata&background=transparent&outline=fcc084&outline_width=2"
alt="CI" height="20" align="absmiddle"> 限定<img
src="https://mojiemoji.jozo.beer/emoji/%E3%83%86%E3%82%B9%E3%83%88?font=zero&color=a78bfa&animation=chirichiri&background=transparent&outline=ed7c3a&outline_width=2"
alt="テスト" height="20" align="absmiddle">除く)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added automated coverage for Core Audio tap and aggregate-device
workflows, including creation, startup, shutdown, and cleanup scenarios.
* Added validation for handling invalid audio object identifiers safely.
* **Chores**
* Updated the application version to **2.20.6**.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
4 files changed
Lines changed: 94 additions & 3 deletions
File tree
- .github/workflows
- Sources/VersionHandler/Resources
- Tests/CoreAudioTapGatewayTests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | | - | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
52 | 56 | | |
53 | 57 | | |
54 | 58 | | |
55 | 59 | | |
56 | 60 | | |
| 61 | + | |
57 | 62 | | |
58 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
59 | 70 | | |
60 | 71 | | |
61 | 72 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
515 | 515 | | |
516 | 516 | | |
517 | 517 | | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
518 | 522 | | |
519 | 523 | | |
520 | 524 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
Lines changed: 76 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
0 commit comments