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 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: 'Playball!',
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playball",
3
- "version": "3.1.3",
3
+ "version": "3.2.0",
4
4
  "description": "Watch MLB games from the comfort of your terminal",
5
5
  "keywords": [
6
6
  "MLB",