playball 3.1.3 → 3.2.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/README.md +16 -1
- package/dist/components/FinishedGame.js +16 -2
- package/dist/components/GameList.js +1 -1
- package/dist/components/LiveGame.js +34 -1
- package/dist/components/PreviewGame.js +22 -1
- package/dist/config.js +7 -1
- package/dist/screen.js +8 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,6 +24,20 @@ Then run it
|
|
|
24
24
|
$ playball
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
### Docker
|
|
28
|
+
```
|
|
29
|
+
$ docker build -t playball .
|
|
30
|
+
$ docker run -it --rm --name playball playball:latest
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
#### Build options
|
|
34
|
+
|
|
35
|
+
Update the language encoding of by adding `--build-args`
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
$ docker build --build-arg LANG=en_US.UTF-8 -t playball .
|
|
39
|
+
```
|
|
40
|
+
|
|
27
41
|
### Keys
|
|
28
42
|
#### Global
|
|
29
43
|
key | action
|
|
@@ -106,7 +120,8 @@ key | description | default | allowed values
|
|
|
106
120
|
`color.strike` | Color of dots representing strikes in top row of game view | red | _See above_
|
|
107
121
|
`color.strike-out` | Color of result where play ends on a strike (strike out) in list of plays in game view | red | _See above_
|
|
108
122
|
`color.walk` | Color of result where play ends on a ball (walk, hit by pitch) in list of plays in game view | green | _See above_
|
|
109
|
-
`favorites` | Teams to highlight in schedule and standings views | | Any one of the following: `ATL`, `AZ`, `BAL`, `BOS`, `CHC`, `CIN`, `CLE`, `COL`, `CWS`, `DET`, `HOU`, `KC`, `LAA`, `LAD`, `MIA`, `MIL`, `MIN`, `NYM`, `NYY`, `OAK`, `PHI`, `PIT`, `SD`, `SEA`, `SF`, `STL`, `TB`, `TEX`, `TOR`, `WSH`. Or a comma-separated list of multiple (e.g. `SEA,MIL`)
|
|
123
|
+
`favorites` | Teams to highlight in schedule and standings views | | Any one of the following: `ATL`, `AZ`, `BAL`, `BOS`, `CHC`, `CIN`, `CLE`, `COL`, `CWS`, `DET`, `HOU`, `KC`, `LAA`, `LAD`, `MIA`, `MIL`, `MIN`, `NYM`, `NYY`, `OAK`, `PHI`, `PIT`, `SD`, `SEA`, `SF`, `STL`, `TB`, `TEX`, `TOR`, `WSH`. Or a comma-separated list of multiple (e.g. `SEA,MIL`).<br/><br />Note: in some terminals the list must be quoted: `playball config favorites "SEA,MIL"`
|
|
124
|
+
`title` | If enabled, the terminal title will be set to the score of the current game | `false` | `false`, `true`
|
|
110
125
|
|
|
111
126
|
### Development
|
|
112
127
|
```
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
2
|
import { useSelector } from "react-redux/lib/alternate-renderers.js";
|
|
3
|
-
import { selectLineScore, selectTeams, selectDecisions, selectBoxscore, selectGameStatus } from "../features/games.js";
|
|
4
3
|
import LineScore from "./LineScore.js";
|
|
4
|
+
import { get } from "../config.js";
|
|
5
|
+
import { selectLineScore, selectTeams, selectDecisions, selectBoxscore, selectGameStatus } from "../features/games.js";
|
|
6
|
+
import { resetTitle, setTitle } from "../screen.js";
|
|
5
7
|
const getPlayer = (id, boxscore) => {
|
|
6
8
|
var _boxscore$home, _boxscore$away;
|
|
7
9
|
const homePlayer = (_boxscore$home = boxscore.home) === null || _boxscore$home === void 0 || (_boxscore$home = _boxscore$home.players) === null || _boxscore$home === void 0 ? void 0 : _boxscore$home['ID' + id];
|
|
@@ -53,6 +55,18 @@ function FinishedGame() {
|
|
|
53
55
|
const linescore = useSelector(selectLineScore);
|
|
54
56
|
const status = useSelector(selectGameStatus);
|
|
55
57
|
const teams = useSelector(selectTeams);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (get('title')) {
|
|
60
|
+
const homeRuns = linescore.teams['home'].runs;
|
|
61
|
+
const awayRuns = linescore.teams['away'].runs;
|
|
62
|
+
const home = teams.home.abbreviation;
|
|
63
|
+
const away = teams.away.abbreviation;
|
|
64
|
+
setTitle(`${away} ${awayRuns} - ${home} ${homeRuns} F`);
|
|
65
|
+
return () => {
|
|
66
|
+
resetTitle();
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}, [get, linescore, resetTitle, setTitle, teams]);
|
|
56
70
|
const awayTeam = `${teams.away.teamName}\n(${teams.away.record.wins}-${teams.away.record.losses})`;
|
|
57
71
|
const homeTeam = `${teams.home.teamName}\n(${teams.home.record.wins}-${teams.home.record.losses})`;
|
|
58
72
|
return /*#__PURE__*/React.createElement("element", null, /*#__PURE__*/React.createElement("element", {
|
|
@@ -8,7 +8,7 @@ import { teamFavoriteStar } from "../utils.js";
|
|
|
8
8
|
import Grid from "./Grid.js";
|
|
9
9
|
import useKey from "../hooks/useKey.js";
|
|
10
10
|
const formatGame = game => {
|
|
11
|
-
const startTime = format(new Date(game.gameDate), 'p');
|
|
11
|
+
const startTime = game.status.startTimeTBD ? 'TBD' : format(new Date(game.gameDate), 'p');
|
|
12
12
|
const start = game.doubleHeader === 'Y' && game.gameNumber > 1 ? 'Game ' + game.gameNumber : startTime;
|
|
13
13
|
const teamName = team => {
|
|
14
14
|
const star = teamFavoriteStar(team.team);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { useSelector } from "react-redux/lib/alternate-renderers.js";
|
|
2
3
|
import Count from "./Count.js";
|
|
3
4
|
import Bases from "./Bases.js";
|
|
4
5
|
import LineScore from "./LineScore.js";
|
|
@@ -6,7 +7,39 @@ import Matchup from "./Matchup.js";
|
|
|
6
7
|
import AtBat from "./AtBat.js";
|
|
7
8
|
import AllPlays from "./AllPlays.js";
|
|
8
9
|
import InningDisplay from "./InningDisplay.js";
|
|
10
|
+
import { get } from "../config.js";
|
|
11
|
+
import { selectGameStatus, selectLineScore, selectTeams } from "../features/games.js";
|
|
12
|
+
import { resetTitle, setTitle } from "../screen.js";
|
|
9
13
|
function LiveGame() {
|
|
14
|
+
const gameStatus = useSelector(selectGameStatus);
|
|
15
|
+
const linescore = useSelector(selectLineScore);
|
|
16
|
+
const teams = useSelector(selectTeams);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (get('title')) {
|
|
19
|
+
const homeRuns = linescore.teams['home'].runs;
|
|
20
|
+
const awayRuns = linescore.teams['away'].runs;
|
|
21
|
+
const home = teams.home.abbreviation;
|
|
22
|
+
const away = teams.away.abbreviation;
|
|
23
|
+
let inning = '';
|
|
24
|
+
if (gameStatus.detailedState === 'Postponed') {
|
|
25
|
+
inning = 'PPD';
|
|
26
|
+
} else if (gameStatus.detailedState === 'Cancelled') {
|
|
27
|
+
inning = 'C';
|
|
28
|
+
} else if (gameStatus.detailedState === 'Final') {
|
|
29
|
+
inning = 'F';
|
|
30
|
+
} else if (gameStatus.detailedState !== 'Pre-Game' && gameStatus.detailedState !== 'Warmup') {
|
|
31
|
+
const currentInning = linescore.currentInning;
|
|
32
|
+
if (currentInning) {
|
|
33
|
+
const upDown = linescore.isTopInning ? '▲' : '▼';
|
|
34
|
+
inning = ` ${upDown} ${currentInning}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
setTitle(`${away} ${awayRuns} - ${home} ${homeRuns}${inning}`);
|
|
38
|
+
return () => {
|
|
39
|
+
resetTitle();
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}, [gameStatus, get, linescore, resetTitle, setTitle, teams]);
|
|
10
43
|
return /*#__PURE__*/React.createElement("element", null, /*#__PURE__*/React.createElement("element", {
|
|
11
44
|
top: 0,
|
|
12
45
|
left: 1,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
2
|
import { useSelector } from "react-redux/lib/alternate-renderers.js";
|
|
3
3
|
import { format } from 'date-fns';
|
|
4
|
+
import { get } from "../config.js";
|
|
4
5
|
import { selectTeams, selectVenue, selectStartTime, selectBoxscore, selectProbablePitchers, selectGameStatus } from "../features/games.js";
|
|
6
|
+
import { resetTitle, setTitle } from "../screen.js";
|
|
5
7
|
const formatPitcherName = pitcher => {
|
|
6
8
|
let display = pitcher.person.fullName;
|
|
7
9
|
const number = pitcher.jerseyNumber;
|
|
@@ -33,6 +35,25 @@ function PreviewGame() {
|
|
|
33
35
|
const away = formatTeam(teams, probables, boxscore, 'away');
|
|
34
36
|
const home = formatTeam(teams, probables, boxscore, 'home');
|
|
35
37
|
const formattedStart = status.startTimeTBD ? 'Start time TBD' : format(new Date(startTime), 'MMMM d, yyy p');
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (get('title')) {
|
|
40
|
+
const home = teams.home.abbreviation;
|
|
41
|
+
const away = teams.away.abbreviation;
|
|
42
|
+
|
|
43
|
+
// Only show the date if it's not today.
|
|
44
|
+
const startDate = new Date(startTime);
|
|
45
|
+
const today = format(new Date(), 'yyyy-DDD');
|
|
46
|
+
const gameDay = format(startDate, 'yyyy-DDD');
|
|
47
|
+
let start = format(startDate, 'p');
|
|
48
|
+
if (today !== gameDay) {
|
|
49
|
+
start = `${format(startDate, 'MMMM d, yyy')} ${start}`;
|
|
50
|
+
}
|
|
51
|
+
setTitle(`${away} - ${home} @ ${start}`);
|
|
52
|
+
return () => {
|
|
53
|
+
resetTitle();
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}, [get, resetTitle, setTitle, startTime, teams]);
|
|
36
57
|
return /*#__PURE__*/React.createElement("element", null, /*#__PURE__*/React.createElement("element", {
|
|
37
58
|
height: "60%"
|
|
38
59
|
}, /*#__PURE__*/React.createElement("box", {
|
package/dist/config.js
CHANGED
|
@@ -75,6 +75,10 @@ const schema = {
|
|
|
75
75
|
enum: ['ATL', 'AZ', 'BAL', 'BOS', 'CHC', 'CIN', 'CLE', 'COL', 'CWS', 'DET', 'HOU', 'KC', 'LAA', 'LAD', 'MIA', 'MIL', 'MIN', 'NYM', 'NYY', 'OAK', 'PHI', 'PIT', 'SD', 'SEA', 'SF', 'STL', 'TB', 'TEX', 'TOR', 'WSH']
|
|
76
76
|
},
|
|
77
77
|
default: []
|
|
78
|
+
},
|
|
79
|
+
'title': {
|
|
80
|
+
type: 'boolean',
|
|
81
|
+
default: false
|
|
78
82
|
}
|
|
79
83
|
};
|
|
80
84
|
const config = new Conf({
|
|
@@ -88,9 +92,11 @@ function serialize(value) {
|
|
|
88
92
|
return value;
|
|
89
93
|
}
|
|
90
94
|
function deserialize(key, value) {
|
|
91
|
-
var _schema$key;
|
|
95
|
+
var _schema$key, _schema$key2;
|
|
92
96
|
if (value && ((_schema$key = schema[key]) === null || _schema$key === void 0 ? void 0 : _schema$key.type) === 'array') {
|
|
93
97
|
return value.split(/\s*,\s*/);
|
|
98
|
+
} else if (((_schema$key2 = schema[key]) === null || _schema$key2 === void 0 ? void 0 : _schema$key2.type) === 'boolean') {
|
|
99
|
+
return value === 'true';
|
|
94
100
|
}
|
|
95
101
|
return value;
|
|
96
102
|
}
|
package/dist/screen.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import blessed from 'blessed';
|
|
2
2
|
let screen;
|
|
3
|
+
const DEFAULT_TITLE = 'Playball!';
|
|
3
4
|
function getScreen() {
|
|
4
5
|
if (screen === undefined) {
|
|
5
6
|
screen = blessed.screen({
|
|
6
7
|
autoPadding: true,
|
|
7
8
|
debug: true,
|
|
8
9
|
smartCSR: true,
|
|
9
|
-
title:
|
|
10
|
+
title: DEFAULT_TITLE,
|
|
10
11
|
handleUncaughtExceptions: false
|
|
11
12
|
});
|
|
12
13
|
screen.key(['escape', 'q', 'C-c'], () => process.exit(0));
|
|
13
14
|
}
|
|
14
15
|
return screen;
|
|
15
16
|
}
|
|
17
|
+
export function resetTitle() {
|
|
18
|
+
getScreen().title = DEFAULT_TITLE;
|
|
19
|
+
}
|
|
20
|
+
export function setTitle(title) {
|
|
21
|
+
getScreen().title = title;
|
|
22
|
+
}
|
|
16
23
|
export default getScreen;
|