-
- `;
- }
- }
-}
customElements.define("teamtracker-card", TeamTrackerCard);
+customElements.define("my-custom-card-editor", MyCustomCardEditor);
-//=====
+console.info("%c TEAMTRACKER-CARD %s IS INSTALLED",
+ "color: blue; font-weight: bold",
+ VERSION);
//
// Add card to list of Custom Cards in the Card Picker
//
window.customCards = window.customCards || []; // Create the list if it doesn't exist. Careful not to overwrite it
window.customCards.push({
- type: "teamtracker-card",
- name: "Team Tracker Card",
- preview: false,
- description: "Card to display the ha-teamtracker sensor",
-});
-
-//
-// Define and register the UI Card Editor
-//
-class MyCustomCardEditor extends LitElement {
-
- static get properties() {
- return {
- hass: {},
- _config: {},
- };
- }
-
- // setConfig works the same way as for the card itself
- setConfig(config) {
- this._config = config;
- }
-
- // This function is called when the input element of the editor loses focus
- entityChanged(ev) {
-
- // We make a copy of the current config so we don't accidentally overwrite anything too early
- const _config = Object.assign({}, this._config);
- // Then we update the entity value with what we just got from the input field
- _config.entity = ev.target.value;
- // And finally write back the updated configuration all at once
- this._config = _config;
-
- // A config-changed event will tell lovelace we have made changed to the configuration
- // this make sure the changes are saved correctly later and will update the preview
- const event = new CustomEvent("config-changed", {
- detail: { config: _config },
- bubbles: true,
- composed: true,
- });
- this.dispatchEvent(event);
- }
-
- render() {
- if (!this.hass || !this._config) {
- return html``;
- }
-
- // @focusout below will call entityChanged when the input field loses focus (e.g. the user tabs away or clicks outside of it)
- return html`
- Entity:
-
- `;
- }
-}
-
-customElements.define("my-custom-card-editor", MyCustomCardEditor);
+ type: "teamtracker-card",
+ name: "Team Tracker Card",
+ preview: false,
+ description: "Card to display the ha-teamtracker sensor",
+});
\ No newline at end of file
diff --git a/dist/render_bye.js b/dist/render_bye.js
new file mode 100644
index 0000000..2a23aa2
--- /dev/null
+++ b/dist/render_bye.js
@@ -0,0 +1,33 @@
+import { html } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
+
+
+// Define the rendering function
+export function renderBye(c) {
+ // Render the HTML template using the provided object `c`
+ const htmlTemplate = html`
+
+
+
+
+
+
+
+
${c.name[team]}
+
+
${c.byeTerm}
+
+
+
+`;
+ // Return the HTML template
+ return htmlTemplate;
+}
\ No newline at end of file
diff --git a/dist/render_error.js b/dist/render_error.js
new file mode 100644
index 0000000..7414dfe
--- /dev/null
+++ b/dist/render_error.js
@@ -0,0 +1,42 @@
+import { html } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
+
+
+export function renderMissingConfig() {
+ const htmlTemplate = html``;
+ // Return the HTML template
+ return htmlTemplate;
+}
+
+export function renderMissingObj(entity) {
+ const htmlTemplate = html`
+ Unknown entity: ${entity}
+ `;
+ // Return the HTML template
+ return htmlTemplate;
+}
+
+export function renderStateUnavailable(entity) {
+ const htmlTemplate = html`
+
+
+ Sensor unavailable: ${entity}
+
+ `;
+ // Return the HTML template
+ return htmlTemplate;
+}
+
+export function renderStateInvalid() {
+ const htmlTemplate = html`
+
+
+ State Invalid: ${this._config.state}
+
+ `;
+ // Return the HTML template
+ return htmlTemplate;
+}
diff --git a/dist/render_in.js b/dist/render_in.js
new file mode 100644
index 0000000..dcacfe9
--- /dev/null
+++ b/dist/render_in.js
@@ -0,0 +1,127 @@
+import { html } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
+
+
+// Define the rendering function
+export function renderIn(c) {
+ // Render the HTML template using the provided object `c`
+ const htmlTemplate = html`
+
+
+
+
${c.title}
+
+
+
+
+
+
${c.initials[1]}
+
${c.rank[1]} ${c.name[1]}
+
${c.record[1]}
+
+
+
+
+
+
+
•
+
${c.score[1]}
+
   
+
${c.score[2]}
+
•
+
+
+
${c.initials[2]}
+
${c.rank[2]} ${c.name[2]}
+
${c.record[2]}
+
+
+
+
+
+
+
+
${c.playClock}
+
+
•
+
+
+
•
+
+
•
+
+
${c.in0}
+
+
+
${c.venue}
+
${c.in1}
+
+
+
${c.location}
+
${c.in2}
+
+
+
+
${c.lastPlay}
+
+
+
${c.gameBar}
+
+
${c.barLabel[1]}
+
+
+
+
+
${c.barLabel[2]}
+
+
+
+
+ `; // Return the HTML template
+ return htmlTemplate;
+}
\ No newline at end of file
diff --git a/dist/render_not_found.js b/dist/render_not_found.js
new file mode 100644
index 0000000..a1c2c8b
--- /dev/null
+++ b/dist/render_not_found.js
@@ -0,0 +1,38 @@
+import { html } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
+
+
+// Define the rendering function
+export function renderNotFound(c) {
+ // Render the HTML template using the provided object `c`
+ const htmlTemplate = html`
+
+
+
+
${c.title}
+
+
+
+
+
${c.notFoundLeague}
+
+
+
${c.notFoundTerm1}
+
${c.notFoundTerm2}
+
+
+
+
+ `;
+ // Return the HTML template
+ return htmlTemplate;
+}
\ No newline at end of file
diff --git a/dist/render_post.js b/dist/render_post.js
new file mode 100644
index 0000000..26f62f9
--- /dev/null
+++ b/dist/render_post.js
@@ -0,0 +1,53 @@
+import { html } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
+
+
+// Define the rendering function
+export function renderPost(c) {
+ // Render the HTML template using the provided object `c`
+ const htmlTemplate = html`
+
+
+
+
${c.title}
+
+
+
+
+
+
${c.initials[1]}
+
${c.rank[1]} ${c.name[1]}
+
${c.record[1]}
+
+
${c.score[1]}
+
   
+
${c.score[2]}
+
+
+
${c.initials[2]}
+
${c.rank[2]} ${c.name[2]}
+
${c.record[2]}
+
+
+
${c.finalTerm}
+
+
+ `; // Return the HTML template
+ return htmlTemplate;
+}
\ No newline at end of file
diff --git a/dist/render_pre.js b/dist/render_pre.js
new file mode 100644
index 0000000..180adb7
--- /dev/null
+++ b/dist/render_pre.js
@@ -0,0 +1,68 @@
+import { html } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
+
+
+// Define the rendering function
+export function renderPre(c) {
+ // Render the HTML template using the provided object `c`
+ const htmlTemplate = html`
+
+
+
+
${c.title}
+
+
+
+
+
+
${c.initials[1]}
+
${c.rank[1]} ${c.name[1]}
+
${c.record[1]}
+
+
+
${c.gameWeekday}
+
${c.gameDatePRE}
+
${c.gameTime}
+
+
+
+
${c.initials[2]}
+
${c.rank[2]} ${c.name[2]}
+
${c.record[2]}
+
+
+
+
+
${c.startTerm} ${c.startTime}
+
${c.pre1}
+
+
+
${c.venue}
+
${c.pre2}
+
+
+
${c.location}
+
${c.pre3}
+
+
+
+ `; // Return the HTML template
+ return htmlTemplate;
+}
\ No newline at end of file
diff --git a/dist/set_defaults.js b/dist/set_defaults.js
new file mode 100644
index 0000000..adef9a3
--- /dev/null
+++ b/dist/set_defaults.js
@@ -0,0 +1,238 @@
+//
+// Initialize card data
+//
+export function initCardData(c) {
+ c.logoBG = [];
+ c.logo = [];
+ c.name = [];
+ c.initials = [];
+ c.rank = [];
+ c.record = [];
+ c.score = [];
+ c.scoreOp = [];
+ c.scoreSize = "3em";
+ c.barLabel = [];
+ c.barLength = [];
+ c.color = [];
+ c.timeouts = [];
+ c.possessionOp = [];
+}
+
+//
+// Set default values for variable components
+//
+export function setDefaults(t, lang, stateObj, c, o, sport, team, oppo) {
+
+ // Set default sections to display / hide
+
+ c.initialsDisplay = 'none';
+ c.outsDisplay = 'none';
+ c.basesDisplay = 'none';
+ c.barDisplay = 'inherit';
+ c.barWrapDisplay = "flex";
+ c.timeoutsDisplay = 'inline';
+ c.rankDisplay = 'inline';
+
+ if (o.show_timeouts == false) {
+ c.timeoutsDisplay = 'none';
+ }
+ if (o.show_rank == false) {
+ c.rankDisplay = 'none';
+ }
+ c.onFirstOp = 0.2;
+ c.onSecondOp = 0.2;
+ c.onThirdOp = 0.2;
+ if (stateObj.attributes.on_first) {
+ c.onFirstOp = 1;
+ }
+ if (stateObj.attributes.on_second) {
+ c.onSecondOp = 1;
+ }
+ if (stateObj.attributes.on_third) {
+ c.onThirdOp = 1;
+ }
+
+ // Set Title data
+
+ c.title = o.cardTitle;
+ if (o.showLeague) {
+ c.title = c.title || stateObj.attributes.league
+ }
+
+ // Set Scoreboard data
+
+ c.logo[team] = stateObj.attributes.team_logo;
+ c.logoBG[team] = stateObj.attributes.team_logo;
+ c.name[team] = stateObj.attributes.team_name;
+ c.rank[team] = stateObj.attributes.team_rank;
+ c.record[team] = stateObj.attributes.team_record;
+ c.logo[oppo] = stateObj.attributes.opponent_logo;
+ c.logoBG[oppo] = stateObj.attributes.opponent_logo;
+ c.name[oppo] = stateObj.attributes.opponent_name;
+ c.rank[oppo] = stateObj.attributes.opponent_rank;
+ c.record[oppo] = stateObj.attributes.opponent_record;
+ c.playClock = stateObj.attributes.clock;
+ if (o.showLeague) {
+ c.logoBG[team] = stateObj.attributes.league_logo
+ c.logoBG[oppo] = stateObj.attributes.league_logo
+ }
+
+ c.score[team] = stateObj.attributes.team_score;
+ c.score[oppo] = stateObj.attributes.opponent_score;
+
+ c.scoreOp[1] = 1;
+ c.scoreOp[2] = 1;
+ if (Number(c.score[1]) < Number(c.score[2])) {
+ c.scoreOp[1] = 0.6;
+ }
+ if (Number(c.score[2]) < Number(c.score[1])) {
+ c.scoreOp[2] = 0.6;
+ }
+
+ if (stateObj.attributes.team_homeaway == 'home') {
+ c.color[team] = stateObj.attributes.team_colors[0];
+ c.color[oppo] = stateObj.attributes.opponent_colors[1];
+ }
+ else if (stateObj.attributes.team_homeaway == 'away') {
+ c.color[team] = stateObj.attributes.team_colors[1];
+ c.color[oppo] = stateObj.attributes.opponent_colors[0];
+ }
+ else {
+ c.color[team] = '#ffffff';
+ c.color[oppo] = '#000000';
+ }
+
+ c.possessionOp[team] = 0;
+ c.possessionOp[oppo] = 0;
+ if (stateObj.attributes.possession == stateObj.attributes.team_id) {
+ c.possessionOp[team] = 1;
+ }
+ if (stateObj.attributes.possession == stateObj.attributes.opponent_id) {
+ c.possessionOp[oppo] = 1;
+ }
+ c.timeouts[team] = stateObj.attributes.team_timeouts;
+ c.timeouts[oppo] = stateObj.attributes.opponent_timeouts;
+
+ // Set Location / Context data
+
+ c.startTerm = t.translate(sport + ".startTerm");
+ c.startTime = stateObj.attributes.kickoff_in;
+ c.venue = stateObj.attributes.venue;
+ c.location = stateObj.attributes.location;
+
+ c.pre1 = stateObj.attributes.odds;
+ c.pre2 = '';
+ if (stateObj.attributes.overunder) {
+ c.pre2 = t.translate(sport + ".overUnder", "%s", String(stateObj.attributes.overunder));
+ }
+ c.pre3 = stateObj.attributes.tv_network;
+
+ c.in0 = '';
+ c.in1 = '';
+ if (stateObj.attributes.down_distance_text) {
+ c.in1 = t.translate(sport + ".gameStat1", "%s", stateObj.attributes.down_distance_text);
+ }
+ c.in2 = '';
+ if (stateObj.attributes.tv_network) {
+ c.in2 = t.translate(sport + ".gameStat2", "%s", stateObj.attributes.tv_network);
+ }
+ c.finalTerm = stateObj.attributes.clock + " - " + c.gameDatePOST;
+
+ // Set Play data
+
+ c.lastPlay = stateObj.attributes.last_play;
+ c.lastPlaySpeed = 18;
+ if (c.lastPlay) {
+ c.lastPlaySpeed = 18 + Math.floor(c.lastPlay.length / 40) * 5;
+ }
+
+ // Set Game Bar data
+
+ c.gameBar = t.translate(sport + ".gameBar");
+ c.barLength[team] = 0;
+ if (stateObj.attributes.team_win_probability) {
+ c.barLength[team] = (stateObj.attributes.team_win_probability * 100).toFixed(0);
+ }
+ c.barLength[oppo] = 0;
+ if (stateObj.attributes.opponent_win_probability) {
+ c.barLength[oppo] = (stateObj.attributes.opponent_win_probability * 100).toFixed(0);
+ }
+ c.barLabel[team] = t.translate(sport + ".teamBarLabel", "%s", String(c.barLength[team]));
+ c.barLabel[oppo] = t.translate(sport + ".oppoBarLabel", "%s", String(c.barLength[oppo]));
+
+ // Situation specific data
+
+ c.notFoundLogo = stateObj.attributes.league_logo;
+ c.notFoundLogoBG = c.notFoundLogo;
+ c.notFoundLeague = null;
+
+ if (stateObj.attributes.league != "XXX") {
+ c.notFoundLeague = stateObj.attributes.league;
+ }
+
+ c.notFoundTerm1 = stateObj.attributes.team_abbr;
+ c.notFoundTerm2 = "NOT_FOUND"
+ if (stateObj.attributes.api_message) {
+ c.notFoundTerm2 = t.translate("common.api_error")
+ var apiTail = stateObj.attributes.api_message.substring(stateObj.attributes.api_message.length - 17)
+ if (apiTail.slice(-1) == "Z") {
+ var lastDateForm = new Date(apiTail)
+ c.notFoundTerm2 = t.translate("common.no_upcoming_games", "%s", lastDateForm.toLocaleDateString(lang))
+ }
+ }
+
+ c.byeTerm = t.translate("common.byeTerm");
+
+}
+
+export function setCardFormat(o, c) {
+
+ c.clrOut = 0;
+ c.outColor = o.outlineColor;
+
+ if (o.outline == true) {
+ c.clrOut = 1;
+ }
+}
+
+
+export function setStartInfo(c, stateObj, t, lang, time_format) {
+
+ var gameDate = new Date(stateObj.attributes.date);
+ var gameDateStr = gameDate.toLocaleDateString(lang, { month: 'short', day: '2-digit' });
+
+ var todayDate = new Date();
+ var todayDateStr = todayDate.toLocaleDateString(lang, { month: 'short', day: '2-digit' });
+
+ var tomorrowDate = new Date();
+ tomorrowDate.setDate(todayDate.getDate() + 1);
+ var tomorrowDateStr = tomorrowDate.toLocaleDateString(lang, { month: 'short', day: '2-digit' });
+
+ var nextweekDate = new Date();
+ nextweekDate.setDate(todayDate.getDate() + 6);
+
+ c.gameWeekday = gameDate.toLocaleDateString(lang, { weekday: 'long' });
+ if (gameDateStr === todayDateStr) {
+ c.gameWeekday = t.translate("common.today");
+ }
+ else if (gameDateStr === tomorrowDateStr) {
+ c.gameWeekday = t.translate("common.tomorrow");
+ }
+ c.gameDatePOST = gameDateStr;
+ c.gameDatePRE = null;
+ if (gameDate > nextweekDate) {
+ c.gameDatePRE = gameDateStr;
+ }
+
+ c.gameTime = gameDate.toLocaleTimeString(lang, { hour: '2-digit', minute: '2-digit' });
+ if (time_format == "24") {
+ c.gameTime = gameDate.toLocaleTimeString(lang, { hour: '2-digit', minute: '2-digit', hour12: false });
+ }
+ if (time_format == "12") {
+ c.gameTime = gameDate.toLocaleTimeString(lang, { hour: '2-digit', minute: '2-digit', hour12: true });
+ }
+ if (time_format == "system") {
+ var sys_lang = navigator.language || "en"
+ c.gameTime = gameDate.toLocaleTimeString(sys_lang, { hour: '2-digit', minute: '2-digit' });
+ }
+}
\ No newline at end of file
diff --git a/dist/set_sports.js b/dist/set_sports.js
new file mode 100644
index 0000000..c140838
--- /dev/null
+++ b/dist/set_sports.js
@@ -0,0 +1,322 @@
+//
+// Call function to set the data for the sport
+//
+export function setSportData(sport, t, stateObj, c, team, oppo) {
+
+ switch (sport) {
+ case "baseball":
+ return setBaseball(t, stateObj, c, team, oppo);
+ case "basketball":
+ return setBasketball(t, stateObj, c, team, oppo);
+ case "cricket":
+ return setCricket(t, stateObj, c, team, oppo);
+ case "golf":
+ return setGolf(t, stateObj, c, team, oppo);
+ case "hockey":
+ return setHockey(t, stateObj, c, team, oppo);
+ case "mma":
+ return setMMA(t, stateObj, c, team, oppo);
+ case "racing":
+ return setRacing(t, stateObj, c, team, oppo);
+ case "soccer":
+ return setSoccer(t, stateObj, c, team, oppo);
+ case "tennis":
+ return setTennis(t, stateObj, c, team, oppo);
+ case "volleyball":
+ return setVolleyball(t, stateObj, c, team, oppo);
+ default:
+ return;
+ }
+}
+
+//
+// setBaseball()
+// in1 = balls
+// in2 = strikes
+// in0 = outs
+// outsDisplay = 'inherit';
+// timeoutsDisplay = 'none';
+// basesDisplay = 'inherit';
+//
+export function setBaseball(t, stateObj, c, team, oppo) {
+ c.in1 = t.translate("baseball.gameStat1", "%s", String(stateObj.attributes.balls));
+ c.in2 = t.translate("baseball.gameStat2", "%s", String(stateObj.attributes.strikes));
+ c.in0 = t.translate("baseball.gameStat3", "%s", String(stateObj.attributes.outs));
+ c.outsDisplay = 'inherit';
+ c.timeoutsDisplay = 'none';
+ c.basesDisplay = 'inherit';
+}
+
+
+//
+// setBasketball()
+// timeoutsDisplay = 'none';
+// barDisplay = "none";
+// barWrapDisplay = "none";
+//
+export function setBasketball(t, stateObj, c, team, oppo) {
+ c.timeoutsDisplay = 'none';
+ c.barDisplay = 'none';
+ c.barWrapDisplay = "none";
+}
+
+
+//
+// SetCricket()
+// timeoutsDisplay = 'none';
+// barDisplay = "none";
+// barWrapDisplay = "none";
+// in1 = odds;
+// in2 = quarter;
+// score = split score into 2 parts
+// record = set to second part of split score
+// scoreOP = adjust opacity based on total runs
+
+export function setCricket(t, stateObj, c, team, oppo) {
+ var runs_substring = [];
+ var runs = [];
+ var total_runs = [];
+ var subscores = [];
+ var i = 0;
+
+ c.timeoutsDisplay = 'none';
+ c.barDisplay = "none";
+ c.barWrapDisplay = "none";
+
+ c.in1 = stateObj.attributes.odds;
+ c.in2 = stateObj.attributes.quarter;
+
+ if (c.score != []) {
+ if (c.score[1] || c.score[2]) {
+ subscores[1] = c.score[1].split("(");
+ subscores[2] = c.score[2].split("(");
+
+ c.score[1] = subscores[1][0];
+ c.score[2] = subscores[2][0];
+
+ if (subscores[1].length > 1) {
+ c.record[1] = "(" + subscores[1][1];
+ }
+ if (subscores[2].length > 1) {
+ c.record[2] = "(" + subscores[2][1];
+ }
+
+ if (stateObj.state == 'POST') {
+ runs_substring[1] = c.score[1].split("/");
+ runs_substring[2] = c.score[2].split("/");
+
+ runs[1] = runs_substring[1][0].split("&");
+ runs[2] = runs_substring[2][0].split("&");
+
+ total_runs[1] = 0;
+ total_runs[2] = 0;
+
+ i = 0;
+ while (i < runs[1].length) {
+ total_runs[1] = total_runs[1] + Number(runs[1][i]);
+ i = i + 1;
+ }
+ i = 0;
+ while (i < runs[2].length) {
+ total_runs[2] = total_runs[2] + Number(runs[2][i]);
+ i = i + 1;
+ }
+
+ if (total_runs[1] > total_runs[2]) {
+ c.scoreOp[1] = 1.0;
+ c.scoreOp[2] = 0.6;
+ }
+ if (total_runs[1] < total_runs[2]) {
+ c.scoreOp[1] = 0.6;
+ c.scoreOp[2] = 1.0;
+ }
+ }
+ }
+ }
+}
+
+
+//
+// setGolf()
+// title = use event_name if title is not set
+// venue = event_name
+// barLength = team_shots_on_target, opponent_shots_on_target
+// barLabel = team_total_shots, opponent_total_shots
+// finalTerm = clock
+// timeoutsDisplay = 'none';
+// scoreOp = adjust opacity to show lowest score as winner
+//
+export function setGolf(t, stateObj, c, team, oppo) {
+ c.title = c.title || stateObj.attributes.event_name;
+ c.venue = stateObj.attributes.event_name;
+ c.barLength[team] = stateObj.attributes.team_shots_on_target;
+ c.barLength[oppo] = stateObj.attributes.opponent_shots_on_target;
+ c.barLabel[team] = t.translate("golf.teamBarLabel", "%s", stateObj.attributes.team_total_shots +'(' + stateObj.attributes.team_shots_on_target + ')');
+ c.barLabel[oppo] = t.translate("golf.oppoBarLabel", "%s", stateObj.attributes.opponent_total_shots +'(' + stateObj.attributes.opponent_shots_on_target + ')');
+ c.finalTerm = stateObj.attributes.clock;
+ c.timeoutsDisplay = 'none';
+
+ if (Number(c.score[1]) < Number(c.score[2])) {
+ c.scoreOp[1] = 1.0;
+ c.scoreOp[2] = 0.6;
+ }
+ if (Number(c.score[2]) < Number(c.score[1])) {
+ c.scoreOp[1] = 0.6;
+ c.scoreOp[2] = 1.0;
+ }
+}
+
+//
+// setHockey()
+// barLength = team_shots_on_target, opponent_shots_on_target
+// barLabel = "Shots on Target"
+// timeoutsDisplay = 'none';
+//
+export function setHockey(t, stateObj, c, team, oppo) {
+ c.barLength[team] = stateObj.attributes.team_shots_on_target;
+ c.barLength[oppo] = stateObj.attributes.opponent_shots_on_target;
+ c.barLabel[team] = t.translate("hockey.teamBarLabel", "%s", String(stateObj.attributes.team_shots_on_target));
+ c.barLabel[oppo] = t.translate("hockey.oppoBarLabel", "%s", String(stateObj.attributes.opponent_shots_on_target));
+
+ c.timeoutsDisplay = 'none';
+}
+
+
+//
+// setMMA()
+// title = use event_name if title is not set
+// timeoutsDisplay = 'none';
+// barDisplay = "none";
+// barWrapDisplay = "none";
+//
+export function setMMA(t, stateObj, c, team, oppo) {
+ c.title = c.title || stateObj.attributes.event_name;
+ c.timeoutsDisplay = 'none';
+ c.barDisplay = "none";
+ c.barWrapDisplay = "none";
+}
+
+
+//
+// setRacing()
+// title = use event_name if title is not set
+// pre1 = quarter (race type)
+// in1 = quarter (race type)
+// finalTerm = adjust for type of race (race, qualifying, etc.)
+// timeoutsDisplay = 'none';
+// barLength = team_total_shots, opponent_total_shots (laps)
+// barLabel = (laps)
+// scoreOp = adjust opacity to show lowest score as winner
+// If NASCAR, remove logos and use initials
+//
+export function setRacing(t, stateObj, c, team, oppo) {
+ c.title = c.title || stateObj.attributes.event_name;
+ if (stateObj.attributes.quarter) {
+ c.pre1 = stateObj.attributes.quarter;
+ c.in1 = stateObj.attributes.quarter;
+ c.finalTerm = stateObj.attributes.clock + " - " + c.gameDatePOST + " (" + stateObj.attributes.quarter + ")";
+ }
+ c.timeoutsDisplay = 'none';
+
+ c.barLength[team] = stateObj.attributes.team_total_shots;
+ c.barLength[oppo] = stateObj.attributes.team_total_shots;
+ c.barLabel[team] = t.translate("racing.teamBarLabel", "%s", String(stateObj.attributes.team_total_shots));
+ c.barLabel[oppo] = t.translate("racing.teamBarLabel", "%s", String(stateObj.attributes.team_total_shots));
+
+ if (Number(c.score[1]) < Number(c.score[2])) {
+ c.scoreOp[1] = 1.0;
+ c.scoreOp[2] = 0.6;
+ }
+ if (Number(c.score[2]) < Number(c.score[1])) {
+ c.scoreOp[1] = 0.6;
+ c.scoreOp[2] = 1.0;
+ }
+
+ if (stateObj.attributes.league.includes("NASCAR")) {
+ c.logo[team] = null;
+ c.logo[oppo] = null;
+ c.initials[team] = "";
+ c.initials[oppo] = "";
+ if (c.name[team] && c.name[oppo]) {
+ c.initials[team] = c.name[team].split(" ").map((n)=>n[0]).join("");
+ c.initials[oppo] = c.name[oppo].split(" ").map((n)=>n[0]).join("");
+ c.initialsDisplay = 'inline';
+ }
+ }
+}
+
+//
+// setSoccer()
+// barLength = team_total_shots, opponent_total_shots
+// barLabel = "Shots on Target"
+// timeoutsDisplay = 'none';
+//
+export function setSoccer(t, stateObj, c, team, oppo) {
+ c.barLength[team] = stateObj.attributes.team_total_shots;
+ c.barLength[oppo] = stateObj.attributes.opponent_total_shots;
+ c.barLabel[team] = t.translate("soccer.teamBarLabel", "%s", stateObj.attributes.team_total_shots +'(' + stateObj.attributes.team_shots_on_target + ')');
+ c.barLabel[oppo] = t.translate("soccer.oppoBarLabel", "%s", stateObj.attributes.opponent_total_shots +'(' + stateObj.attributes.opponent_shots_on_target + ')');
+ c.timeoutsDisplay = 'none';
+}
+
+//
+// setTennis()
+// venue = event_name
+// pre1 = odds
+// in1 = odds
+// finalTerm = adjust for round (odds)
+// gameBar = clock
+// barLength = team_score, opponent_score
+// barLabel = "score"
+// timeouts = sets won
+// title = use event_name if title is not set
+// timeoutsDisplay = 'inline';
+//
+export function setTennis(t, stateObj, c, team, oppo) {
+ c.venue = stateObj.attributes.event_name;
+ c.pre1 = t.translate("common.tourney" + stateObj.attributes.odds)
+ c.in1 = c.pre1;
+ c.finalTerm = stateObj.attributes.clock + " - " + c.gameDatePOST + " (" + c.pre1 + ")";
+
+ c.gameBar = t.translate("tennis.gameBar", "%s", stateObj.attributes.clock);
+ c.barLength[team] = stateObj.attributes.team_score;
+ c.barLength[oppo] = stateObj.attributes.opponent_score;
+ if (stateObj.attributes.team_shots_on_target) {
+ c.gameBar = t.translate("tennis.gameBar", "%s", stateObj.attributes.clock + "(tiebreak)");
+ c.barLabel[team] = t.translate("tennis.teamBarLabel", "%s", stateObj.attributes.team_score +'(' + stateObj.attributes.team_shots_on_target + ')');
+ }
+ else {
+ c.barLabel[team] = t.translate("tennis.teamBarLabel", "%s", String(stateObj.attributes.team_score));
+ }
+ if (stateObj.attributes.team_shots_on_target) {
+ c.gameBar = t.translate("tennis.gameBar", "%s", stateObj.attributes.clock + "(tiebreak)");
+ c.barLabel[oppo] = t.translate("tennis.oppoBarLabel", "%s", stateObj.attributes.opponent_score +'(' + stateObj.attributes.opponent_shots_on_target + ')');
+ }
+ else {
+ c.barLabel[oppo] = t.translate("tennis.oppoBarLabel", "%s", String(stateObj.attributes.opponent_score ));
+ }
+ c.timeouts[team] = stateObj.attributes.team_sets_won;
+ c.timeouts[oppo] = stateObj.attributes.opponent_sets_won;
+ c.title = c.title || stateObj.attributes.event_name
+
+ c.timeoutsDisplay = 'inline';
+}
+
+//
+// setVolleyball()
+// gameBar = clock
+// barLength = team_score, opponent_score
+// barLabel = "score"
+// timeouts = sets won
+// timeoutsDisplay = 'inline';
+//
+export function setVolleyball(t, stateObj, c, team, oppo) {
+ c.gameBar = t.translate("volleyball.gameBar", "%s", stateObj.attributes.clock);
+ c.barLength[team] = stateObj.attributes.team_score;
+ c.barLength[oppo] = stateObj.attributes.opponent_score;
+ c.barLabel[team] = t.translate("volleyball.teamBarLabel", "%s", String(stateObj.attributes.team_score));
+ c.barLabel[oppo] = t.translate("volleyball.oppoBarLabel", "%s", String(stateObj.attributes.opponent_score));
+ c.timeouts[team] = stateObj.attributes.team_sets_won;
+ c.timeouts[team] = stateObj.attributes.opponent_sets_won;
+ c.timeoutsDisplay = 'inline';
+}
diff --git a/dist/teamtracker_card.js b/dist/teamtracker_card.js
new file mode 100644
index 0000000..4e1200e
--- /dev/null
+++ b/dist/teamtracker_card.js
@@ -0,0 +1,181 @@
+import { LitElement } from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";
+import { Translator } from "./localize/translator.js";
+import { VERSION } from "./const.js";
+import { renderBye } from './render_bye.js';
+import { renderMissingConfig, renderMissingObj, renderStateInvalid, renderStateUnavailable } from './render_error.js';
+import { renderIn } from './render_in.js';
+import { renderNotFound } from './render_not_found.js';
+import { renderPost } from './render_post.js';
+import { renderPre } from './render_pre.js';
+import { initCardData, setCardFormat, setDefaults, setStartInfo } from './set_defaults.js';
+import { setSportData } from './set_sports.js';
+
+
+export class TeamTrackerCard extends LitElement {
+
+ static get properties() {
+ return {
+ hass: {},
+ _config: {},
+ };
+ }
+
+ setConfig(config) {
+ this._config = config;
+ }
+
+ getCardSize() {
+ const stateObj = this.hass.states[this._config.entity];
+
+ switch (stateObj.state) {
+ case 'PRE':
+ return 7;
+ case 'IN':
+ return 10;
+ case 'POST':
+ return 5;
+ case 'BYE':
+ return 4;
+ case 'NOT_FOUND':
+ return 4;
+ default:
+ return 4;
+ }
+ }
+
+ render() {
+ var o = {}; // o is the object that holds the card options from the configuration
+ var c = {}; // c is the object that holds the card data used to render the HTML
+
+ //
+ // Render error message if missing configuration, entity, or state
+ //
+ if (!this.hass || !this._config) {
+ return renderMissingConfig();
+ }
+ const stateObj = this.hass.states[this._config.entity];
+ if (!stateObj) {
+ return renderMissingObj(this._config.entity);
+ }
+ if (stateObj.state == 'unavailable') {
+ return renderStateUnavailable(this._config.entity);
+ }
+
+ //
+ // Set card options based on configuration
+ //
+ o.cardTitle = this._config.card_title || "";
+ o.outline = this._config.outline;
+ o.outlineColor = this._config.outline_color || '#ffffff';
+ o.showLeague = this._config.show_league;
+ o.homeSide = String(this._config.home_side).toUpperCase();
+ o.show_timeouts = true;
+ if (this._config.show_timeouts == false) {
+ o.show_timeouts = false;
+ }
+ o.show_rank = true;
+ if (this._config.show_rank == false) {
+ o.show_rank = false;
+ }
+ o.debug = this._config.debug
+
+ //
+ // Set sport, team, and oppo
+ //
+ var sport = stateObj.attributes.sport || "default";
+ var team = 1;
+ var oppo = 2;
+ if (((o.homeSide == "RIGHT") && (stateObj.attributes.team_homeaway == "home")) ||
+ ((o.homeSide == "LEFT") && (stateObj.attributes.opponent_homeaway == "home"))) {
+ team = 2;
+ oppo = 1;
+ }
+
+ //
+ // Set language, time_format (12hr or 24hr), and translator
+ //
+ var lang = this.hass.selectedLanguage || this.hass.language || navigator.language || "en"
+ var time_format = "language";
+ try {
+ time_format = this.hass.locale["time_format"] || "language";
+ }
+ catch (e) {
+ time_format = "language"
+ }
+ var t = new Translator(lang);
+
+ //
+ // Set card data
+ //
+ initCardData(c);
+ setStartInfo(c, stateObj, t, lang, time_format);
+ setCardFormat(o, c);
+ setDefaults(t, lang, stateObj, c, o, sport, team, oppo);
+ setSportData(sport, t, stateObj, c, team, oppo)
+
+ //
+ // NCAA Specific Changes
+ //
+ if (stateObj.attributes.league) {
+ if (stateObj.attributes.league.includes("NCAA")) {
+ c.notFoundLogo = 'https://a.espncdn.com/i/espn/misc_logos/500/ncaa.png'
+ }
+ }
+
+ //
+ // Reduce score font size if needed
+ //
+
+ if (Math.max(String(c.score[1]).length, String(c.score[2]).length) > 4) {
+ c.scoreSize = "2em"
+ }
+
+ //
+ // Add info to title if debug mode is turned on
+ //
+
+ if (o.debug) {
+ var lastUpdate = new Date(stateObj.attributes.last_update);
+ var updateTime = lastUpdate.toLocaleTimeString(lang, { hour: '2-digit', minute: '2-digit', second: '2-digit' });
+
+ c.title = this._config.entity + " " + c.title + "(";
+ if (stateObj.attributes.api_message) {
+ c.title = c.title + stateObj.attributes.api_message[0];
+ }
+ c.title = c.title + updateTime + ") " + VERSION;
+ }
+
+ //
+ // Render the card based on the state
+ //
+ switch (stateObj.state) {
+ case 'PRE':
+ return renderPre(c);
+ case 'IN':
+ return renderIn(c);
+ case 'POST':
+ return renderPost(c);
+ case 'BYE':
+ return renderBye(c);
+ case 'NOT_FOUND':
+ return renderNotFound(c);
+ default:
+ return renderStateInvalid(c);
+ }
+ }
+
+//
+// Trigger the UI Card Editor from Card Picker
+// Uncomment to enable visual editor
+//
+ // static getConfigElement() {
+ // // Create and return an editor element
+ // return document.createElement("my-custom-card-editor");
+ // }
+ //
+ // static getStubConfig() {
+ // // Return a minimal configuration that will result in a working card configuration
+ // return { entity: "" };
+ // }
+
+}
\ No newline at end of file