fitzroy 1.4.0 → 1.4.1
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/dist/cli.js +80 -30
- package/dist/index.js +29 -29
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -315,27 +315,6 @@ var init_team_mapping = __esm({
|
|
|
315
315
|
}
|
|
316
316
|
});
|
|
317
317
|
|
|
318
|
-
// src/lib/parse-utils.ts
|
|
319
|
-
function safeInt(text) {
|
|
320
|
-
const cleaned = text.replace(/[^0-9-]/g, "").trim();
|
|
321
|
-
if (!cleaned) return null;
|
|
322
|
-
const n = Number.parseInt(cleaned, 10);
|
|
323
|
-
return Number.isNaN(n) ? null : n;
|
|
324
|
-
}
|
|
325
|
-
function parseIntOr0(text) {
|
|
326
|
-
const n = Number.parseInt(text.replace(/[^0-9-]/g, ""), 10);
|
|
327
|
-
return Number.isNaN(n) ? 0 : n;
|
|
328
|
-
}
|
|
329
|
-
function parseFloatOr0(text) {
|
|
330
|
-
const n = Number.parseFloat(text.replace(/[^0-9.-]/g, ""));
|
|
331
|
-
return Number.isNaN(n) ? 0 : n;
|
|
332
|
-
}
|
|
333
|
-
var init_parse_utils = __esm({
|
|
334
|
-
"src/lib/parse-utils.ts"() {
|
|
335
|
-
"use strict";
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
|
|
339
318
|
// src/lib/venue-mapping.ts
|
|
340
319
|
function normaliseVenueName(raw) {
|
|
341
320
|
const trimmed = raw.trim();
|
|
@@ -392,6 +371,27 @@ var init_venue_mapping = __esm({
|
|
|
392
371
|
}
|
|
393
372
|
});
|
|
394
373
|
|
|
374
|
+
// src/lib/parse-utils.ts
|
|
375
|
+
function safeInt(text) {
|
|
376
|
+
const cleaned = text.replace(/[^0-9-]/g, "").trim();
|
|
377
|
+
if (!cleaned) return null;
|
|
378
|
+
const n = Number.parseInt(cleaned, 10);
|
|
379
|
+
return Number.isNaN(n) ? null : n;
|
|
380
|
+
}
|
|
381
|
+
function parseIntOr0(text) {
|
|
382
|
+
const n = Number.parseInt(text.replace(/[^0-9-]/g, ""), 10);
|
|
383
|
+
return Number.isNaN(n) ? 0 : n;
|
|
384
|
+
}
|
|
385
|
+
function parseFloatOr0(text) {
|
|
386
|
+
const n = Number.parseFloat(text.replace(/[^0-9.-]/g, ""));
|
|
387
|
+
return Number.isNaN(n) ? 0 : n;
|
|
388
|
+
}
|
|
389
|
+
var init_parse_utils = __esm({
|
|
390
|
+
"src/lib/parse-utils.ts"() {
|
|
391
|
+
"use strict";
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
|
|
395
395
|
// src/transforms/footywire-player-stats.ts
|
|
396
396
|
import * as cheerio from "cheerio";
|
|
397
397
|
function cleanPlayerName(raw) {
|
|
@@ -413,7 +413,7 @@ function parseStatsTable(html, expectedCols, rowParser) {
|
|
|
413
413
|
const headerText = teamHeader.text().trim();
|
|
414
414
|
const match = /^(\w[\w\s]+?)\s+Match Statistics/i.exec(headerText);
|
|
415
415
|
if (match?.[1]) {
|
|
416
|
-
teamName = match[1].trim();
|
|
416
|
+
teamName = normaliseTeamName(match[1].trim());
|
|
417
417
|
}
|
|
418
418
|
}
|
|
419
419
|
const parsed = [];
|
|
@@ -586,6 +586,7 @@ var init_footywire_player_stats = __esm({
|
|
|
586
586
|
"src/transforms/footywire-player-stats.ts"() {
|
|
587
587
|
"use strict";
|
|
588
588
|
init_parse_utils();
|
|
589
|
+
init_team_mapping();
|
|
589
590
|
BASIC_COLS = [
|
|
590
591
|
"Player",
|
|
591
592
|
"K",
|
|
@@ -780,7 +781,7 @@ function parseMatchList(html, year) {
|
|
|
780
781
|
roundNumber: currentRound,
|
|
781
782
|
roundType: currentRoundType,
|
|
782
783
|
date,
|
|
783
|
-
venue,
|
|
784
|
+
venue: normaliseVenueName(venue),
|
|
784
785
|
homeTeam,
|
|
785
786
|
awayTeam,
|
|
786
787
|
homeGoals,
|
|
@@ -856,7 +857,7 @@ function parseFixtureList(html, year) {
|
|
|
856
857
|
roundNumber: currentRound,
|
|
857
858
|
roundType: currentRoundType,
|
|
858
859
|
date,
|
|
859
|
-
venue,
|
|
860
|
+
venue: normaliseVenueName(venue),
|
|
860
861
|
homeTeam,
|
|
861
862
|
awayTeam,
|
|
862
863
|
status: hasScore ? "Complete" : "Upcoming",
|
|
@@ -1002,6 +1003,7 @@ var init_footywire = __esm({
|
|
|
1002
1003
|
init_errors();
|
|
1003
1004
|
init_result();
|
|
1004
1005
|
init_team_mapping();
|
|
1006
|
+
init_venue_mapping();
|
|
1005
1007
|
init_footywire_player_stats();
|
|
1006
1008
|
init_match_results();
|
|
1007
1009
|
FOOTYWIRE_BASE = "https://www.footywire.com/afl/footy";
|
|
@@ -2329,7 +2331,7 @@ function transformSquiggleGamesToFixture(games, season) {
|
|
|
2329
2331
|
roundNumber: g.round,
|
|
2330
2332
|
roundType: inferRoundType(g.roundname),
|
|
2331
2333
|
date: new Date(g.unixtime * 1e3),
|
|
2332
|
-
venue: g.venue,
|
|
2334
|
+
venue: normaliseVenueName(g.venue),
|
|
2333
2335
|
homeTeam: normaliseTeamName(g.hteam),
|
|
2334
2336
|
awayTeam: normaliseTeamName(g.ateam),
|
|
2335
2337
|
status: toMatchStatus2(g.complete),
|
|
@@ -2368,7 +2370,7 @@ function toFixture(item, season, fallbackRoundNumber, competition) {
|
|
|
2368
2370
|
roundNumber: item.round?.roundNumber ?? fallbackRoundNumber,
|
|
2369
2371
|
roundType: inferRoundType(item.round?.name ?? ""),
|
|
2370
2372
|
date: new Date(item.match.utcStartTime),
|
|
2371
|
-
venue: item.venue?.name ?? "",
|
|
2373
|
+
venue: normaliseVenueName(item.venue?.name ?? ""),
|
|
2372
2374
|
homeTeam: normaliseTeamName(item.match.homeTeam.name),
|
|
2373
2375
|
awayTeam: normaliseTeamName(item.match.awayTeam.name),
|
|
2374
2376
|
status: toMatchStatus(item.match.status),
|
|
@@ -2437,6 +2439,7 @@ var init_fixture = __esm({
|
|
|
2437
2439
|
init_errors();
|
|
2438
2440
|
init_result();
|
|
2439
2441
|
init_team_mapping();
|
|
2442
|
+
init_venue_mapping();
|
|
2440
2443
|
init_afl_api();
|
|
2441
2444
|
init_footywire();
|
|
2442
2445
|
init_squiggle();
|
|
@@ -2613,7 +2616,7 @@ function parseSeasonPage(html, year) {
|
|
|
2613
2616
|
const awayPoints = Number.parseInt($(awayCells[2]).text().trim(), 10) || 0;
|
|
2614
2617
|
const infoText = $(homeCells[3]).text().trim();
|
|
2615
2618
|
const date = parseDateFromInfo(infoText, year);
|
|
2616
|
-
const venue = parseVenueFromInfo($(homeCells[3]).html() ?? "");
|
|
2619
|
+
const venue = normaliseVenueName(parseVenueFromInfo($(homeCells[3]).html() ?? ""));
|
|
2617
2620
|
const attendance = parseAttendanceFromInfo(infoText);
|
|
2618
2621
|
const homeFinal = homeQuarters[3];
|
|
2619
2622
|
const awayFinal = awayQuarters[3];
|
|
@@ -2801,6 +2804,7 @@ var init_afl_tables = __esm({
|
|
|
2801
2804
|
init_errors();
|
|
2802
2805
|
init_result();
|
|
2803
2806
|
init_team_mapping();
|
|
2807
|
+
init_venue_mapping();
|
|
2804
2808
|
init_afl_tables_player_stats();
|
|
2805
2809
|
init_match_results();
|
|
2806
2810
|
AFL_TABLES_BASE = "https://afltables.com/afl/seas";
|
|
@@ -3913,9 +3917,17 @@ function escapeField(value) {
|
|
|
3913
3917
|
}
|
|
3914
3918
|
return value;
|
|
3915
3919
|
}
|
|
3920
|
+
function dateToAestIso(date) {
|
|
3921
|
+
const parts = AEST_ISO_FORMATTER.formatToParts(date);
|
|
3922
|
+
const get = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
3923
|
+
const offset = get("timeZoneName");
|
|
3924
|
+
const sign = offset.includes("-") ? "-" : "+";
|
|
3925
|
+
const offsetHours = offset.replace(/[^0-9]/g, "").padStart(2, "0");
|
|
3926
|
+
return `${get("year")}-${get("month")}-${get("day")}T${get("hour")}:${get("minute")}:${get("second")}${sign}${offsetHours}:00`;
|
|
3927
|
+
}
|
|
3916
3928
|
function toStringValue(value) {
|
|
3917
3929
|
if (value === null || value === void 0) return "";
|
|
3918
|
-
if (value instanceof Date) return value
|
|
3930
|
+
if (value instanceof Date) return dateToAestIso(value);
|
|
3919
3931
|
if (typeof value === "object") return JSON.stringify(value);
|
|
3920
3932
|
return String(value);
|
|
3921
3933
|
}
|
|
@@ -3931,19 +3943,57 @@ function formatCsv(data) {
|
|
|
3931
3943
|
}
|
|
3932
3944
|
return lines.join("\n");
|
|
3933
3945
|
}
|
|
3946
|
+
var AEST_ISO_FORMATTER;
|
|
3934
3947
|
var init_csv = __esm({
|
|
3935
3948
|
"src/cli/formatters/csv.ts"() {
|
|
3936
3949
|
"use strict";
|
|
3950
|
+
AEST_ISO_FORMATTER = new Intl.DateTimeFormat("en-AU", {
|
|
3951
|
+
timeZone: "Australia/Melbourne",
|
|
3952
|
+
year: "numeric",
|
|
3953
|
+
month: "2-digit",
|
|
3954
|
+
day: "2-digit",
|
|
3955
|
+
hour: "2-digit",
|
|
3956
|
+
minute: "2-digit",
|
|
3957
|
+
second: "2-digit",
|
|
3958
|
+
hour12: false,
|
|
3959
|
+
timeZoneName: "shortOffset"
|
|
3960
|
+
});
|
|
3937
3961
|
}
|
|
3938
3962
|
});
|
|
3939
3963
|
|
|
3940
3964
|
// src/cli/formatters/json.ts
|
|
3965
|
+
function dateToAestIso2(date) {
|
|
3966
|
+
const parts = AEST_ISO_FORMATTER2.formatToParts(date);
|
|
3967
|
+
const get = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
3968
|
+
const offset = get("timeZoneName");
|
|
3969
|
+
const sign = offset.includes("-") ? "-" : "+";
|
|
3970
|
+
const offsetHours = offset.replace(/[^0-9]/g, "").padStart(2, "0");
|
|
3971
|
+
return `${get("year")}-${get("month")}-${get("day")}T${get("hour")}:${get("minute")}:${get("second")}${sign}${offsetHours}:00`;
|
|
3972
|
+
}
|
|
3973
|
+
function jsonReplacer(_key, value) {
|
|
3974
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
|
|
3975
|
+
return dateToAestIso2(new Date(value));
|
|
3976
|
+
}
|
|
3977
|
+
return value;
|
|
3978
|
+
}
|
|
3941
3979
|
function formatJson(data) {
|
|
3942
|
-
return JSON.stringify(data,
|
|
3980
|
+
return JSON.stringify(data, jsonReplacer, 2);
|
|
3943
3981
|
}
|
|
3982
|
+
var AEST_ISO_FORMATTER2;
|
|
3944
3983
|
var init_json = __esm({
|
|
3945
3984
|
"src/cli/formatters/json.ts"() {
|
|
3946
3985
|
"use strict";
|
|
3986
|
+
AEST_ISO_FORMATTER2 = new Intl.DateTimeFormat("en-AU", {
|
|
3987
|
+
timeZone: "Australia/Melbourne",
|
|
3988
|
+
year: "numeric",
|
|
3989
|
+
month: "2-digit",
|
|
3990
|
+
day: "2-digit",
|
|
3991
|
+
hour: "2-digit",
|
|
3992
|
+
minute: "2-digit",
|
|
3993
|
+
second: "2-digit",
|
|
3994
|
+
hour12: false,
|
|
3995
|
+
timeZoneName: "shortOffset"
|
|
3996
|
+
});
|
|
3947
3997
|
}
|
|
3948
3998
|
});
|
|
3949
3999
|
|
|
@@ -5229,7 +5279,7 @@ resolveAliases();
|
|
|
5229
5279
|
var main = defineCommand11({
|
|
5230
5280
|
meta: {
|
|
5231
5281
|
name: "fitzroy",
|
|
5232
|
-
version: "1.4.
|
|
5282
|
+
version: "1.4.1",
|
|
5233
5283
|
description: "TypeScript port of the fitzRoy R package \u2014 fetch AFL data from the command line"
|
|
5234
5284
|
},
|
|
5235
5285
|
subCommands: {
|
package/dist/index.js
CHANGED
|
@@ -264,25 +264,6 @@ var AFL_API_TEAM_IDS = /* @__PURE__ */ new Map([
|
|
|
264
264
|
["CD_T140", "Western Bulldogs"]
|
|
265
265
|
]);
|
|
266
266
|
|
|
267
|
-
// src/transforms/footywire-player-stats.ts
|
|
268
|
-
import * as cheerio from "cheerio";
|
|
269
|
-
|
|
270
|
-
// src/lib/parse-utils.ts
|
|
271
|
-
function safeInt(text) {
|
|
272
|
-
const cleaned = text.replace(/[^0-9-]/g, "").trim();
|
|
273
|
-
if (!cleaned) return null;
|
|
274
|
-
const n = Number.parseInt(cleaned, 10);
|
|
275
|
-
return Number.isNaN(n) ? null : n;
|
|
276
|
-
}
|
|
277
|
-
function parseIntOr0(text) {
|
|
278
|
-
const n = Number.parseInt(text.replace(/[^0-9-]/g, ""), 10);
|
|
279
|
-
return Number.isNaN(n) ? 0 : n;
|
|
280
|
-
}
|
|
281
|
-
function parseFloatOr0(text) {
|
|
282
|
-
const n = Number.parseFloat(text.replace(/[^0-9.-]/g, ""));
|
|
283
|
-
return Number.isNaN(n) ? 0 : n;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
267
|
// src/lib/venue-mapping.ts
|
|
287
268
|
var VENUE_ALIASES = [
|
|
288
269
|
["MCG", "M.C.G.", "Melbourne Cricket Ground"],
|
|
@@ -333,6 +314,25 @@ function normaliseVenueName(raw) {
|
|
|
333
314
|
return VENUE_ALIAS_MAP.get(trimmed.toLowerCase()) ?? trimmed;
|
|
334
315
|
}
|
|
335
316
|
|
|
317
|
+
// src/transforms/footywire-player-stats.ts
|
|
318
|
+
import * as cheerio from "cheerio";
|
|
319
|
+
|
|
320
|
+
// src/lib/parse-utils.ts
|
|
321
|
+
function safeInt(text) {
|
|
322
|
+
const cleaned = text.replace(/[^0-9-]/g, "").trim();
|
|
323
|
+
if (!cleaned) return null;
|
|
324
|
+
const n = Number.parseInt(cleaned, 10);
|
|
325
|
+
return Number.isNaN(n) ? null : n;
|
|
326
|
+
}
|
|
327
|
+
function parseIntOr0(text) {
|
|
328
|
+
const n = Number.parseInt(text.replace(/[^0-9-]/g, ""), 10);
|
|
329
|
+
return Number.isNaN(n) ? 0 : n;
|
|
330
|
+
}
|
|
331
|
+
function parseFloatOr0(text) {
|
|
332
|
+
const n = Number.parseFloat(text.replace(/[^0-9.-]/g, ""));
|
|
333
|
+
return Number.isNaN(n) ? 0 : n;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
336
|
// src/transforms/footywire-player-stats.ts
|
|
337
337
|
var BASIC_COLS = [
|
|
338
338
|
"Player",
|
|
@@ -393,7 +393,7 @@ function parseStatsTable(html, expectedCols, rowParser) {
|
|
|
393
393
|
const headerText = teamHeader.text().trim();
|
|
394
394
|
const match = /^(\w[\w\s]+?)\s+Match Statistics/i.exec(headerText);
|
|
395
395
|
if (match?.[1]) {
|
|
396
|
-
teamName = match[1].trim();
|
|
396
|
+
teamName = normaliseTeamName(match[1].trim());
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
const parsed = [];
|
|
@@ -920,7 +920,7 @@ function parseMatchList(html, year) {
|
|
|
920
920
|
roundNumber: currentRound,
|
|
921
921
|
roundType: currentRoundType,
|
|
922
922
|
date,
|
|
923
|
-
venue,
|
|
923
|
+
venue: normaliseVenueName(venue),
|
|
924
924
|
homeTeam,
|
|
925
925
|
awayTeam,
|
|
926
926
|
homeGoals,
|
|
@@ -996,7 +996,7 @@ function parseFixtureList(html, year) {
|
|
|
996
996
|
roundNumber: currentRound,
|
|
997
997
|
roundType: currentRoundType,
|
|
998
998
|
date,
|
|
999
|
-
venue,
|
|
999
|
+
venue: normaliseVenueName(venue),
|
|
1000
1000
|
homeTeam,
|
|
1001
1001
|
awayTeam,
|
|
1002
1002
|
status: hasScore ? "Complete" : "Upcoming",
|
|
@@ -1175,7 +1175,7 @@ function parseBrownlowVotes(html, season) {
|
|
|
1175
1175
|
const tds = $(row).find("td");
|
|
1176
1176
|
if (tds.length < 9) return;
|
|
1177
1177
|
const player = $(tds[0]).text().trim();
|
|
1178
|
-
const team = $(tds[1]).text().trim();
|
|
1178
|
+
const team = normaliseTeamName($(tds[1]).text().trim());
|
|
1179
1179
|
if (!player || player.toLowerCase() === "player") return;
|
|
1180
1180
|
const votes3 = safeInt($(tds[2]).text()) ?? 0;
|
|
1181
1181
|
const votes2 = safeInt($(tds[3]).text()) ?? 0;
|
|
@@ -1212,7 +1212,7 @@ function parseAllAustralian(html, season) {
|
|
|
1212
1212
|
const playerLink = $(cell).find("a");
|
|
1213
1213
|
const playerName = playerLink.text().trim();
|
|
1214
1214
|
const teamSpan = $(cell).find("span.playerflag");
|
|
1215
|
-
const team = teamSpan.text().trim();
|
|
1215
|
+
const team = normaliseTeamName(teamSpan.text().trim());
|
|
1216
1216
|
if (playerName && team) {
|
|
1217
1217
|
results.push({
|
|
1218
1218
|
type: "all-australian",
|
|
@@ -1250,8 +1250,8 @@ function parseRisingStarNominations(html, season) {
|
|
|
1250
1250
|
const round = safeInt(roundText);
|
|
1251
1251
|
if (round == null) return;
|
|
1252
1252
|
const player = $(tds[1]).text().trim();
|
|
1253
|
-
const team = $(tds[2]).text().trim();
|
|
1254
|
-
const opponent = $(tds[3]).text().trim();
|
|
1253
|
+
const team = normaliseTeamName($(tds[2]).text().trim());
|
|
1254
|
+
const opponent = normaliseTeamName($(tds[3]).text().trim());
|
|
1255
1255
|
if (!player || player.toLowerCase() === "name") return;
|
|
1256
1256
|
results.push({
|
|
1257
1257
|
type: "rising-star",
|
|
@@ -2351,7 +2351,7 @@ function transformSquiggleGamesToFixture(games, season) {
|
|
|
2351
2351
|
roundNumber: g.round,
|
|
2352
2352
|
roundType: inferRoundType(g.roundname),
|
|
2353
2353
|
date: new Date(g.unixtime * 1e3),
|
|
2354
|
-
venue: g.venue,
|
|
2354
|
+
venue: normaliseVenueName(g.venue),
|
|
2355
2355
|
homeTeam: normaliseTeamName(g.hteam),
|
|
2356
2356
|
awayTeam: normaliseTeamName(g.ateam),
|
|
2357
2357
|
status: toMatchStatus2(g.complete),
|
|
@@ -2382,7 +2382,7 @@ function toFixture(item, season, fallbackRoundNumber, competition) {
|
|
|
2382
2382
|
roundNumber: item.round?.roundNumber ?? fallbackRoundNumber,
|
|
2383
2383
|
roundType: inferRoundType(item.round?.name ?? ""),
|
|
2384
2384
|
date: new Date(item.match.utcStartTime),
|
|
2385
|
-
venue: item.venue?.name ?? "",
|
|
2385
|
+
venue: normaliseVenueName(item.venue?.name ?? ""),
|
|
2386
2386
|
homeTeam: normaliseTeamName(item.match.homeTeam.name),
|
|
2387
2387
|
awayTeam: normaliseTeamName(item.match.awayTeam.name),
|
|
2388
2388
|
status: toMatchStatus(item.match.status),
|
|
@@ -2780,7 +2780,7 @@ function parseSeasonPage(html, year) {
|
|
|
2780
2780
|
const awayPoints = Number.parseInt($(awayCells[2]).text().trim(), 10) || 0;
|
|
2781
2781
|
const infoText = $(homeCells[3]).text().trim();
|
|
2782
2782
|
const date = parseDateFromInfo(infoText, year);
|
|
2783
|
-
const venue = parseVenueFromInfo($(homeCells[3]).html() ?? "");
|
|
2783
|
+
const venue = normaliseVenueName(parseVenueFromInfo($(homeCells[3]).html() ?? ""));
|
|
2784
2784
|
const attendance = parseAttendanceFromInfo(infoText);
|
|
2785
2785
|
const homeFinal = homeQuarters[3];
|
|
2786
2786
|
const awayFinal = awayQuarters[3];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fitzroy",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "TypeScript port of the fitzRoy R package — programmatic access to AFL data including match results, player stats, fixtures, ladders, and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|