@semanticintent/semantic-chirp-intelligence-mcp 3.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.chirp-data/opponent.json +24 -0
- package/.chirp-data/roster.json +34 -0
- package/.chirp-data/standings.json +17 -0
- package/.nhl-schedule-cache/20262027.json +1 -0
- package/.nhl-schedule-cache/players-20262027-20252026.json +1 -0
- package/README.md +129 -79
- package/build/analyses/BreakoutAnalysis.js +25 -36
- package/build/analyses/DraftPickAnalysis.js +431 -0
- package/build/analyses/GamesInHandAnalysis.js +52 -121
- package/build/analyses/IceAnalysis.js +66 -57
- package/build/analyses/LineupAnalysis.js +26 -46
- package/build/analyses/ScheduleValueAnalysis.js +279 -0
- package/build/analyses/StreamingAnalysis.js +40 -76
- package/build/analyses/WeekendStreamAnalysis.js +130 -66
- package/build/config/tool-metadata.js +54 -0
- package/build/domain/nhl-teams.js +67 -0
- package/build/index.js +561 -653
- package/build/services/LeagueDataService.js +130 -0
- package/build/services/NhlScheduleService.js +357 -0
- package/build/services/NhlStatsService.js +297 -0
- package/build/services/RosterStore.js +233 -0
- package/package.json +12 -10
- package/scripts/preflight.mjs +67 -0
- package/scripts/smoke.mjs +92 -0
- package/.env.example +0 -8
- package/authenticate.js +0 -207
- package/build/experimental/semantic-breakout-tool.js +0 -188
- package/build/experimental/semantic-intent-parser.js +0 -222
- package/build/experimental/semantic-tool-integration.js +0 -146
- package/build/experimental/test-parser.js +0 -61
- package/build/services/YahooApiClient.js +0 -309
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# 🏒 Semantic CHIRP Intelligence MCP
|
|
2
2
|
|
|
3
|
-
> **
|
|
4
|
-
> A Model Context Protocol (MCP) server that turns
|
|
3
|
+
> **Universal fantasy hockey intelligence.**
|
|
4
|
+
> A Model Context Protocol (MCP) server that turns any roster into an AI advisor —
|
|
5
|
+
> no account, no API key, no platform lock-in. Paste your team, get the cold truth.
|
|
5
6
|
|
|
6
7
|
[](https://chirp.semanticintent.dev)
|
|
7
8
|

|
|
@@ -15,15 +16,25 @@
|
|
|
15
16
|
|
|
16
17
|
## What this is
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
CHIRP is a **players-and-teams intelligence layer**. You tell it who is on your
|
|
20
|
+
roster — by pasting it from anywhere — and it reasons about schedules, statistics,
|
|
21
|
+
lineups, trades and draft value using the NHL's public API.
|
|
19
22
|
|
|
20
|
-
It
|
|
23
|
+
It is not tied to a fantasy platform. Yahoo, ESPN, Sleeper, CBS, a spreadsheet or a
|
|
24
|
+
paper league all work the same way, because the only thing CHIRP needs from you is
|
|
25
|
+
a list of names.
|
|
26
|
+
|
|
27
|
+
Every tool carries intent metadata, analyses run through a shared template, and
|
|
28
|
+
results come back with a *point of view* — schedule edges, roster truths, and the
|
|
29
|
+
occasional chirp.
|
|
21
30
|
|
|
22
31
|
### Highlights
|
|
23
32
|
|
|
33
|
+
- 🚀 **Zero setup** — no OAuth, no API key, no application to any platform. Install, paste a roster, done.
|
|
34
|
+
- 📋 **Paste from anywhere** — names resolve against live NHL rosters, so team and position fill themselves in. Accents, `Lastname, Firstname` and punctuation all handled.
|
|
24
35
|
- ❄️ **ICE — the Intent Chirp Engine** — championship-level roster analysis with brutal honesty
|
|
25
|
-
-
|
|
26
|
-
-
|
|
36
|
+
- 🎯 **Draft intelligence** — who to take at pick N, scored on real production and playoff-week schedule
|
|
37
|
+
- 🗓️ **Schedule intelligence** — every game count comes from the NHL's public club-schedule API, per club, per week
|
|
27
38
|
- 🏛️ **Semantic Anchoring Governance** — every tool declares its intent; a dashboard surfaces the health metrics
|
|
28
39
|
- 🧩 **Template Pattern architecture** — analyses are composable, consistent, and testable
|
|
29
40
|
- 🔒 **Read-only & local** — OAuth 2.0, minimum permissions, no third-party data egress
|
|
@@ -46,7 +57,10 @@ It's built on the same **Semantic Intent** philosophy as its sibling project, th
|
|
|
46
57
|
├─────────────────────────────────────────────────────────────┤
|
|
47
58
|
│ Services (src/services/) │
|
|
48
59
|
│ • ChirpIntelligence — turns data into chirp │
|
|
49
|
-
│ •
|
|
60
|
+
│ • NhlScheduleService — schedules, standings (NHL public API)│
|
|
61
|
+
│ • NhlStatsService — player identity + season statistics │
|
|
62
|
+
│ • RosterStore — parses and stores what you paste │
|
|
63
|
+
│ • LeagueDataService — league state, source-agnostic │
|
|
50
64
|
├─────────────────────────────────────────────────────────────┤
|
|
51
65
|
│ Domain (src/domain/) — types + governance │
|
|
52
66
|
└─────────────────────────────────────────────────────────────┘
|
|
@@ -59,90 +73,97 @@ It's built on the same **Semantic Intent** philosophy as its sibling project, th
|
|
|
59
73
|
|
|
60
74
|
## Available Tools
|
|
61
75
|
|
|
62
|
-
###
|
|
76
|
+
### Setting up your league (paste-based)
|
|
63
77
|
|
|
64
78
|
| Tool | Description |
|
|
65
79
|
|------|-------------|
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
| `compare_matchup` | Category-by-category breakdown of your matchup |
|
|
73
|
-
| `optimize_lineup` | Lineup recommendations based on health and positions |
|
|
74
|
-
| `get_trending_players` | Most-added / most-owned players — hot pickups |
|
|
75
|
-
| `debug_api_call` | Inspect raw Yahoo API responses for troubleshooting |
|
|
76
|
-
|
|
77
|
-
### CHIRP intelligence tools (Template Pattern + semantic analysis)
|
|
80
|
+
| `set_roster` | 📋 Paste your roster. Names resolve against live NHL rosters; team and position fill themselves in |
|
|
81
|
+
| `set_opponent_roster` | 📋 Paste your weekly opponent, enabling head-to-head analysis |
|
|
82
|
+
| `set_standings` | 📊 Paste league standings for league context |
|
|
83
|
+
| `show_stored_data` | 🗂️ Show (or clear) what CHIRP currently knows |
|
|
84
|
+
|
|
85
|
+
### Core data tools
|
|
78
86
|
|
|
79
87
|
| Tool | Description |
|
|
80
88
|
|------|-------------|
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `governance_dashboard` | 🏛️ Semantic Anchoring Governance health, analysis metrics, and violations |
|
|
89
|
+
| `get_team_roster` | Your roster with live NHL club, position, season stats and games this week |
|
|
90
|
+
| `get_league_standings` | The standings you pasted |
|
|
91
|
+
| `search_players` | Search all 1,200+ NHL players by position, ranked by production |
|
|
92
|
+
| `get_player_stats` | Full stats for any player — by name, not an internal id |
|
|
93
|
+
| `compare_matchup` | Category-by-category comparison of your roster against your opponent's |
|
|
87
94
|
|
|
88
|
-
|
|
95
|
+
### CHIRP intelligence tools
|
|
89
96
|
|
|
90
|
-
|
|
97
|
+
| Tool | Description |
|
|
98
|
+
|------|-------------|
|
|
99
|
+
| `ice` | ❄️ **Intent Chirp Engine** — the flagship advisor; ice-cold, championship-level roster analysis |
|
|
100
|
+
| `get_roster_transaction_recommendations` | 🏒 ICE roster optimization — savage, brutally honest calls |
|
|
101
|
+
| `optimize_lineup` | Lineup recommendations from health, position and who actually plays tonight |
|
|
102
|
+
| `get_games_in_hand` | Schedule-advantage analysis, you vs. your opponent |
|
|
103
|
+
| `get_streaming_recommendations` | Schedule-aware pickup candidates |
|
|
104
|
+
| `analyze_weekend_streams` | 🌊 Weekend classifier — desperation filler vs. genuine upside |
|
|
105
|
+
| `analyze_breakout_players` | 📈 Breakout candidates scored on real production, opportunity and risk |
|
|
106
|
+
| `analyze_trade` | Category-by-category trade breakdown with an ACCEPT / DECLINE / PUSH verdict |
|
|
107
|
+
| `chirp_opponent` | Scouts your opponent's roster and chirps its weaknesses |
|
|
108
|
+
| `governance_dashboard` | 🏛️ Semantic Anchoring Governance health and analysis metrics |
|
|
109
|
+
|
|
110
|
+
### Draft tools
|
|
91
111
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
112
|
+
| Tool | Description |
|
|
113
|
+
|------|-------------|
|
|
114
|
+
| `chirp_draft_pick` | 🎯 **ICE at the draft table** — who to take at pick N, given who is gone, what you need, and playoff-week schedule |
|
|
115
|
+
| `schedule_value` | 🗓️ All 32 clubs rated — total games, four-game weeks, light weeks, back-to-backs, playoff-window volume |
|
|
95
116
|
|
|
96
|
-
|
|
117
|
+
> **On availability:** CHIRP knows every NHL player, but it cannot know who is
|
|
118
|
+
> *unowned in your league* — ownership is league-private and no public source
|
|
119
|
+
> exposes it. Pool-based tools therefore return "players not on the rosters you
|
|
120
|
+
> provided", ranked by production, and say so. Check availability before adding.
|
|
97
121
|
|
|
98
|
-
|
|
122
|
+
## Where the numbers come from
|
|
99
123
|
|
|
100
|
-
|
|
124
|
+
Every figure is fetched, not estimated — and none of it needs an account:
|
|
101
125
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
-
|
|
126
|
+
| Signal | Source |
|
|
127
|
+
|--------|--------|
|
|
128
|
+
| Games per week, back-to-backs, playoff-window volume | NHL public API (`club-schedule-season`) — all 32 clubs, cached per season |
|
|
129
|
+
| Player identity, club, position | NHL public API (`roster`) — 1,268 players |
|
|
130
|
+
| Season statistics (skaters and goalies) | NHL public API (`club-stats`) |
|
|
131
|
+
| Opponent difficulty | NHL standings, ranked by goals allowed per game |
|
|
132
|
+
| Your roster, opponent, standings | What you paste |
|
|
105
133
|
|
|
106
|
-
|
|
134
|
+
When a source is unreachable, the tool says so in its output and drops that
|
|
135
|
+
component from its scoring — it does not substitute an estimate for a fact.
|
|
107
136
|
|
|
108
|
-
|
|
137
|
+
---
|
|
109
138
|
|
|
110
|
-
|
|
139
|
+
## Prerequisites
|
|
111
140
|
|
|
112
|
-
|
|
141
|
+
- **Node.js 20+**
|
|
142
|
+
- An MCP client — e.g. **Claude Desktop**
|
|
113
143
|
|
|
114
|
-
|
|
144
|
+
That is the whole list. There is no account to create, no application to file, and
|
|
145
|
+
no credential to store.
|
|
115
146
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
147
|
+
> **Coming from v3?** v3 read your league through the Yahoo Fantasy API. In 2026
|
|
148
|
+
> Yahoo put that API behind a manual approval process that also revoked existing
|
|
149
|
+
> access, so a working install could stop working without any change to the code.
|
|
150
|
+
> v4 removes the dependency entirely: CHIRP now reasons about any roster you paste,
|
|
151
|
+
> on any platform. The Yahoo integration is preserved at the
|
|
152
|
+
> [v3.2.0 tag](https://github.com/semanticintent/semantic-chirp-intelligence-mcp/releases/tag/v3.2.0).
|
|
122
153
|
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
YAHOO_CLIENT_ID=your_client_id
|
|
126
|
-
YAHOO_CLIENT_SECRET=your_client_secret
|
|
127
|
-
YAHOO_LEAGUE_ID=your_league_id
|
|
128
|
-
YAHOO_TEAM_ID=your_team_id
|
|
129
|
-
```
|
|
154
|
+
---
|
|
130
155
|
|
|
131
|
-
|
|
156
|
+
## Setup
|
|
132
157
|
|
|
133
158
|
```bash
|
|
159
|
+
git clone https://github.com/semanticintent/semantic-chirp-intelligence-mcp.git
|
|
160
|
+
cd semantic-chirp-intelligence-mcp
|
|
161
|
+
npm install
|
|
134
162
|
npm run build
|
|
163
|
+
npm run preflight # checks the build and the NHL API — no credentials involved
|
|
135
164
|
```
|
|
136
165
|
|
|
137
|
-
###
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
node authenticate.js
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
Open the printed URL, click through the self-signed-certificate warning (it's a local callback), sign in, and authorize. The token is saved to `.yahoo-oauth.json` (git-ignored). The server auto-refreshes it after that.
|
|
144
|
-
|
|
145
|
-
### 6. Add to Claude Desktop
|
|
166
|
+
### Add to Claude Desktop
|
|
146
167
|
|
|
147
168
|
Edit your Claude Desktop config:
|
|
148
169
|
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
@@ -155,10 +176,6 @@ Edit your Claude Desktop config:
|
|
|
155
176
|
"command": "node",
|
|
156
177
|
"args": ["/absolute/path/to/semantic-chirp-intelligence-mcp/build/index.js"],
|
|
157
178
|
"env": {
|
|
158
|
-
"YAHOO_CLIENT_ID": "your_client_id",
|
|
159
|
-
"YAHOO_CLIENT_SECRET": "your_client_secret",
|
|
160
|
-
"YAHOO_LEAGUE_ID": "your_league_id",
|
|
161
|
-
"YAHOO_TEAM_ID": "your_team_id",
|
|
162
179
|
"DOTENV_CONFIG_QUIET": "true"
|
|
163
180
|
}
|
|
164
181
|
}
|
|
@@ -168,12 +185,20 @@ Edit your Claude Desktop config:
|
|
|
168
185
|
|
|
169
186
|
Use an **absolute path** to `build/index.js` (forward slashes, even on Windows). Restart Claude Desktop — the CHIRP tools will appear.
|
|
170
187
|
|
|
188
|
+
Your credentials stay in the project's git-ignored `.env`; the server resolves
|
|
189
|
+
it from its own install directory, so it is found regardless of the working
|
|
190
|
+
directory the client launches it with. You do **not** need to copy secrets into
|
|
191
|
+
the client config. If you prefer to set them there anyway, a client `env` block
|
|
192
|
+
still overrides the file.
|
|
193
|
+
|
|
171
194
|
---
|
|
172
195
|
|
|
173
196
|
## Usage
|
|
174
197
|
|
|
175
198
|
Once connected, just talk to Claude about your team:
|
|
176
199
|
|
|
200
|
+
- *"I'm on the clock at pick 47 — who should I take?"*
|
|
201
|
+
- *"Which teams have the best schedule during my league's playoff weeks?"*
|
|
177
202
|
- *"Run ICE on my roster — what should I actually do this week?"*
|
|
178
203
|
- *"Where do I have a games-in-hand edge over my opponent?"*
|
|
179
204
|
- *"Find me streaming goalies for the weekend — real value, not desperation pickups."*
|
|
@@ -191,6 +216,8 @@ npm run type-check # tsc --noEmit
|
|
|
191
216
|
npm test # run the vitest suite once
|
|
192
217
|
npm run test:watch # watch mode
|
|
193
218
|
npm run test:coverage
|
|
219
|
+
npm run preflight # build + NHL API reachability
|
|
220
|
+
npm run smoke # call every tool and flag crash-like responses
|
|
194
221
|
```
|
|
195
222
|
|
|
196
223
|
### Project structure
|
|
@@ -199,25 +226,48 @@ npm run test:coverage
|
|
|
199
226
|
semantic-chirp-intelligence-mcp/
|
|
200
227
|
├── src/
|
|
201
228
|
│ ├── index.ts # MCP server (stdio) + tool registration
|
|
202
|
-
│ ├── analyses/ # Template-Pattern analyses (Ice, Streaming, GamesInHand,
|
|
229
|
+
│ ├── analyses/ # Template-Pattern analyses (Ice, Streaming, GamesInHand,
|
|
230
|
+
│ │ # WeekendStream, Lineup, Breakout, ScheduleValue, DraftPick)
|
|
203
231
|
│ ├── template/ # AnalysisTemplate base
|
|
204
|
-
│ ├── services/ #
|
|
232
|
+
│ ├── services/ # NhlScheduleService, NhlStatsService, RosterStore,
|
|
233
|
+
│ │ # LeagueDataService, ChirpIntelligence
|
|
205
234
|
│ ├── config/ # tool-metadata, personality-modes, chirp-styles
|
|
206
|
-
│ ├── domain/ # types, governance
|
|
207
|
-
│ └── experimental/ # semantic-intent parser experiments
|
|
235
|
+
│ ├── domain/ # types, governance, nhl-teams, yahoo-stats
|
|
208
236
|
├── tests/ # vitest tests
|
|
209
|
-
├──
|
|
237
|
+
├── scripts/preflight.mjs # build + NHL API check
|
|
238
|
+
├── scripts/smoke.mjs # calls every tool, flags crash-like responses
|
|
210
239
|
├── docs/ # documentation (architecture, setup, dev notes)
|
|
211
|
-
└── .env.example
|
|
212
240
|
```
|
|
213
241
|
|
|
214
242
|
---
|
|
215
243
|
|
|
244
|
+
## Troubleshooting
|
|
245
|
+
|
|
246
|
+
**A name did not resolve**
|
|
247
|
+
`set_roster` reports every line it could not match to exactly one NHL player,
|
|
248
|
+
under `needs_attention`. Ambiguous surnames come back with their candidates —
|
|
249
|
+
give a full name and re-run. Nothing is ever guessed onto your roster.
|
|
250
|
+
|
|
251
|
+
**Tools say no roster has been provided**
|
|
252
|
+
Paste one with `set_roster`. `show_stored_data` shows what is currently stored.
|
|
253
|
+
|
|
254
|
+
**Game counts are zero**
|
|
255
|
+
Check the dates. Outside the regular season there are genuinely no games to count;
|
|
256
|
+
`schedule_value` still works year-round because it reads the whole published season.
|
|
257
|
+
|
|
258
|
+
**Stats look like last season**
|
|
259
|
+
They are. Before opening night the current season has no statistics at all, so
|
|
260
|
+
CHIRP attaches the last completed season — which is the right basis at a draft.
|
|
261
|
+
Every response names the season it used.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
216
265
|
## Security
|
|
217
266
|
|
|
218
|
-
- **
|
|
219
|
-
- **
|
|
220
|
-
- **
|
|
267
|
+
- **No credentials at all** — v4 holds no API keys, tokens or account bindings. There is nothing to leak.
|
|
268
|
+
- **Read-only** — the only network calls are GETs to the NHL's public API. CHIRP cannot modify a roster anywhere.
|
|
269
|
+
- **Local-only** — runs over stdio. Your pasted roster stays in `.chirp-data/` on your machine and is git-ignored.
|
|
270
|
+
- See [SECURITY.md](./SECURITY.md) for the full policy.
|
|
221
271
|
|
|
222
272
|
## Part of Cormorant Foraging
|
|
223
273
|
|
|
@@ -242,7 +292,7 @@ Contributions welcome — see [CONTRIBUTING.md](./CONTRIBUTING.md) and the [Code
|
|
|
242
292
|
## Acknowledgments
|
|
243
293
|
|
|
244
294
|
- [Model Context Protocol](https://modelcontextprotocol.io) by Anthropic
|
|
245
|
-
- [
|
|
295
|
+
- [NHL public API](https://api-web.nhle.com) — schedules, rosters, statistics and standings, free and unauthenticated
|
|
246
296
|
- Sibling project: [`semantic-wake-intelligence-mcp`](https://github.com/semanticintent/semantic-wake-intelligence-mcp)
|
|
247
297
|
|
|
248
298
|
---
|
|
@@ -12,42 +12,25 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { AnalysisTemplate } from '../template/AnalysisTemplate.js';
|
|
14
14
|
import { ChirpIntelligence } from '../services/ChirpIntelligence.js';
|
|
15
|
+
import { LEAGUE_DATA, LeagueDataService } from '../services/LeagueDataService.js';
|
|
16
|
+
import { NHL_STATS } from '../services/NhlStatsService.js';
|
|
17
|
+
import { NHL_SCHEDULE } from '../services/NhlScheduleService.js';
|
|
15
18
|
export class BreakoutAnalysis extends AnalysisTemplate {
|
|
16
|
-
|
|
17
|
-
leagueId;
|
|
18
|
-
teamId;
|
|
19
|
-
constructor(yahooClient, leagueId, teamId) {
|
|
19
|
+
constructor() {
|
|
20
20
|
super('get_breakout_analysis', 'streaming_recommendations');
|
|
21
|
-
this.yahooClient = yahooClient;
|
|
22
|
-
this.leagueId = leagueId;
|
|
23
|
-
this.teamId = teamId;
|
|
24
21
|
}
|
|
25
22
|
/**
|
|
26
23
|
* Fetch raw data: free agents, trending players, roster
|
|
27
24
|
*/
|
|
28
25
|
async fetchData(args) {
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
const freeAgentPromises = positions.map(pos => this.yahooClient.searchPlayers(pos, 50, this.leagueId));
|
|
33
|
-
const [freeAgentResults, trendingAdds, roster] = await Promise.all([
|
|
34
|
-
Promise.all(freeAgentPromises),
|
|
35
|
-
this.yahooClient.getTrendingPlayers('add', 25, this.leagueId),
|
|
36
|
-
this.yahooClient.getTeamRoster(this.leagueId, this.teamId)
|
|
37
|
-
]);
|
|
38
|
-
// Combine and deduplicate free agents
|
|
39
|
-
const allFreeAgents = [];
|
|
40
|
-
for (const result of freeAgentResults) {
|
|
41
|
-
if (result.players) {
|
|
42
|
-
allFreeAgents.push(...result.players);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
// Remove duplicates and filter by ownership
|
|
46
|
-
const uniqueFreeAgents = Array.from(new Map(allFreeAgents.map(p => [p.player_id, p])).values()).filter(p => (p.percent_owned || 0) < ownershipThreshold);
|
|
26
|
+
await Promise.all([NHL_STATS.load(), NHL_SCHEDULE.load()]);
|
|
27
|
+
// Breakout candidates are drawn from every NHL player not already on a
|
|
28
|
+
// roster you provided, scored on their real season line.
|
|
47
29
|
return {
|
|
48
|
-
freeAgents:
|
|
49
|
-
trendingAdds:
|
|
50
|
-
roster
|
|
30
|
+
freeAgents: LEAGUE_DATA.getPlayerPool({ limit: 200 }),
|
|
31
|
+
trendingAdds: [],
|
|
32
|
+
roster: LEAGUE_DATA.getRoster(),
|
|
33
|
+
pool_caveat: LeagueDataService.POOL_CAVEAT
|
|
51
34
|
};
|
|
52
35
|
}
|
|
53
36
|
/**
|
|
@@ -228,17 +211,23 @@ export class BreakoutAnalysis extends AnalysisTemplate {
|
|
|
228
211
|
return 'sleeper';
|
|
229
212
|
}
|
|
230
213
|
/**
|
|
231
|
-
*
|
|
214
|
+
* Real season stat line for a candidate, from Yahoo.
|
|
215
|
+
*
|
|
216
|
+
* Missing categories come back as 0 rather than absent so the scoring
|
|
217
|
+
* formula keeps its shape; `has_stats` distinguishes a genuine zero from a
|
|
218
|
+
* player Yahoo returned nothing for.
|
|
232
219
|
*/
|
|
233
220
|
async getPlayerMetrics(player) {
|
|
234
|
-
//
|
|
235
|
-
|
|
221
|
+
// v4: the pool carries NHL season statistics on each player already.
|
|
222
|
+
const stats = player.stats ?? null;
|
|
236
223
|
return {
|
|
237
|
-
G:
|
|
238
|
-
A:
|
|
239
|
-
GP:
|
|
240
|
-
|
|
241
|
-
|
|
224
|
+
G: stats?.goals ?? 0,
|
|
225
|
+
A: stats?.assists ?? 0,
|
|
226
|
+
GP: stats?.games_played ?? 0,
|
|
227
|
+
// The NHL feed publishes power-play goals, not power-play points.
|
|
228
|
+
PPP: stats?.power_play_goals ?? 0,
|
|
229
|
+
SOG: stats?.shots ?? 0,
|
|
230
|
+
has_stats: Boolean(stats)
|
|
242
231
|
};
|
|
243
232
|
}
|
|
244
233
|
/**
|