diff --git a/main_controller.py b/main_controller.py index c26de70..707c9f7 100644 --- a/main_controller.py +++ b/main_controller.py @@ -1,36 +1,36 @@ -import asyncio, time, datetime, games, json, threading, jinja2, leagues -from flask import Flask, url_for, Response, render_template, request, jsonify +import asyncio, time, datetime, games, json, threading, jinja2, leagues, os +from flask import Flask, url_for, Response, render_template, request, jsonify, send_from_directory from flask_socketio import SocketIO, emit -app = Flask("the-prestige") +app = Flask("the-prestige", static_folder='simmadome/build') app.config['SECRET KEY'] = 'dev' #app.config['SERVER_NAME'] = '0.0.0.0:5000' socketio = SocketIO(app) -@app.route('/') -def index(): - if ('league' in request.args): - return render_template("index.html", league=request.args['league']) - return render_template("index.html") - -@app.route('/game') -def game_page(): - return render_template("game.html") +# Serve React App +@app.route('/', defaults={'path': ''}) +@app.route('/') +def serve(path): + if path != "" and os.path.exists(app.static_folder + '/' + path): + return send_from_directory(app.static_folder, path) + else: + return send_from_directory(app.static_folder, 'index.html') thread2 = threading.Thread(target=socketio.run,args=(app,'0.0.0.0')) thread2.start() master_games_dic = {} #key timestamp : (game game, {} state) -data_to_send = [] +game_states = [] @socketio.on("recieved") def handle_new_conn(data): - socketio.emit("states_update", data_to_send, room=request.sid) + socketio.emit("states_update", game_states, room=request.sid) def update_loop(): + global game_states while True: - game_states = {} + game_states = [] game_ids = iter(master_games_dic.copy().keys()) for game_id in game_ids: this_game, state, discrim_string = master_games_dic[game_id] @@ -125,7 +125,7 @@ def update_loop(): state["top_of_inning"] = this_game.top_of_inning - game_states[game_id] = state + game_states.append([game_id, state]) if state["update_pause"] <= 1 and state["start_delay"] < 0: if this_game.over: @@ -140,17 +140,5 @@ def update_loop(): state["update_pause"] -= 1 - global data_to_send - data_to_send = [] - template = jinja2.Environment(loader=jinja2.FileSystemLoader('templates')).get_template('game_box.html') - - for id in game_states: - data_to_send.append({ - 'timestamp' : id, - 'league' : game_states[id]['leagueoruser'] if game_states[id]['is_league'] else '', - 'state' : game_states[id], - 'html' : template.render(state=game_states[id], timestamp=id) - }) - - socketio.emit("states_update", data_to_send) + socketio.emit("states_update", game_states) time.sleep(8) diff --git a/simmadome/package-lock.json b/simmadome/package-lock.json index 26f635d..25e47fa 100644 --- a/simmadome/package-lock.json +++ b/simmadome/package-lock.json @@ -2178,6 +2178,11 @@ "@babel/types": "^7.3.0" } }, + "@types/component-emitter": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", + "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" + }, "@types/eslint": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz", @@ -2314,6 +2319,11 @@ "@types/node": "*" } }, + "@types/socket.io-client": { + "version": "1.4.34", + "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.34.tgz", + "integrity": "sha512-Lzia5OTQFJZJ5R4HsEEldywiiqT9+W2rDbyHJiiTGqOcju89sCsQ8aUXDljY6Ls33wKZZGC0bfMhr/VpOyjtXg==" + }, "@types/source-list-map": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", @@ -3417,6 +3427,11 @@ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -3472,6 +3487,11 @@ } } }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5256,6 +5276,31 @@ "once": "^1.4.0" } }, + "engine.io-client": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.0.6.tgz", + "integrity": "sha512-5lPh8rrhxIruo5ZlgFt31KM626o5OCXrCHBweieWWuVicDtnYdz/iR93k6N9k0Xs61WrYxZKIWXzeSaJF6fpNA==", + "requires": { + "base64-arraybuffer": "0.1.4", + "component-emitter": "~1.3.0", + "debug": "~4.3.1", + "engine.io-parser": "~4.0.1", + "has-cors": "1.1.0", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~7.4.2", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + } + }, + "engine.io-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", + "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", + "requires": { + "base64-arraybuffer": "0.1.4" + } + }, "enhanced-resolve": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", @@ -6937,6 +6982,11 @@ "function-bind": "^1.1.1" } }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -10694,6 +10744,16 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" }, + "parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" + }, + "parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -13625,6 +13685,30 @@ } } }, + "socket.io-client": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-3.0.5.tgz", + "integrity": "sha512-NNnv3UH5h+aICeVDAdSHll3vSujp1OnzvDtuVz1ukUXliffr1+LTGc1W+qZAm3H7McapGsJhTI5nsBoY1r21dQ==", + "requires": { + "@types/component-emitter": "^1.2.10", + "backo2": "~1.0.2", + "component-emitter": "~1.3.0", + "debug": "~4.3.1", + "engine.io-client": "~4.0.6", + "parseuri": "0.0.6", + "socket.io-parser": "~4.0.3" + } + }, + "socket.io-parser": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.3.tgz", + "integrity": "sha512-m4ybFiP4UYVORRt7jcdqf8UWx+ywVdAqqsJyruXxAdD3Sv6MDemijWij34mOWdMJ55bEdIb9jACBhxUgNK6sxw==", + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + } + }, "sockjs": { "version": "0.3.20", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", @@ -16401,6 +16485,11 @@ "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" }, + "xmlhttprequest-ssl": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", + "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -16455,6 +16544,11 @@ } } }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/simmadome/package.json b/simmadome/package.json index 758d38f..2d10414 100644 --- a/simmadome/package.json +++ b/simmadome/package.json @@ -11,9 +11,11 @@ "@types/node": "^12.19.12", "@types/react": "^16.14.2", "@types/react-dom": "^16.9.10", + "@types/socket.io-client": "^1.4.34", "react": "^17.0.1", "react-dom": "^17.0.1", "react-scripts": "4.0.1", + "socket.io-client": "^3.0.5", "typescript": "^4.1.3", "web-vitals": "^0.2.4" }, diff --git a/simmadome/src/App.tsx b/simmadome/src/App.tsx index 0ddc86c..20fd97b 100644 --- a/simmadome/src/App.tsx +++ b/simmadome/src/App.tsx @@ -1,43 +1,160 @@ import React from 'react'; +import io from 'socket.io-client'; import './App.css'; +import Game from './Game'; + +interface GameState { + bases: (string | null)[]; + outs: number; + display_top_of_inning: boolean + display_inning: number + max_innings: number + title: string + weather_emoji: string + weather_text: string + away_name: string + away_score: number + home_name: string + home_score: number + pitcher: string + batter: string + update_emoji: string + update_text: string + is_league: boolean + leagueoruser: string +} + +type GameList = ([id: string, game: GameState] | null)[]; + +interface AppProps { + filter: string | null + gameId: string | null +} + +interface AppState { + filter: string + games: [string, GameState][] +} + +class App extends React.Component { + gameList: GameList; + + constructor(props: AppProps) { + super(props); + + let socket = io(); + socket.on('connect', () => socket.emit('recieved', {})); + socket.on('states_update', (update: [string, GameState][]) => this.onStatesUpdate(update)); + + this.gameList = []; + this.state = { + filter: props.filter ?? "", + games: [] + }; + this.onSelectNewFilter = this.onSelectNewFilter.bind(this); + } + + onStatesUpdate(newStates: [string, GameState][]) { + console.log(newStates); + this.setState({ games: newStates }); + } + + onSelectNewFilter(newFilter: string) { + this.setState({ filter: newFilter }); + this.gameList = []; + } + + updateGameList() { + let filterGames = this.state.games.filter((game, i) => this.state.filter === "" || game[1].leagueoruser === this.state.filter) + + //remove games no longer present, update games with new info + for (let i = 0; i < this.gameList.length; i ++) { + if (this.gameList[i] !== null) { + let newState = filterGames.find((val) => val[0] === this.gameList[i]![0]); + if (newState !== undefined) { + this.gameList[i] = newState; + } else { + this.gameList[i] = null; + } + } + } + + // add games not present + for (let game of filterGames) { + if (!this.gameList.find((val) => val !== null && val[0] === game[0])) { + let firstEmpty = this.gameList.indexOf(null); + if (firstEmpty < 0) { + this.gameList.push(game) + } else { + this.gameList[firstEmpty] = game; + } + } + } + + //remove trailing empty cells + while (this.gameList[this.gameList.length-1] === null) { + this.gameList.pop(); + } + } -class App extends React.Component { render() { + this.updateGameList(); + + let filters: string[] = []; + this.state.games.forEach((game, id) => { if (game[1].is_league && !filters.includes(game[1].leagueoruser)) { filters.push(game[1].leagueoruser) }}); return (
- - -
+ + +
0}/>
); } } -class Filters extends React.Component { - render() { - return ( -
-
Filter:
- -
- ); - } -} +function Filters (props: {filterList: string[], selectedFilter: string, onSelectNewFilter: (newFilter: string) => void}) { + let filters = props.filterList.map((filter: string) => + + ) -function Grid() { return ( +
+
Filter:
+ + {filters} +
+ ); +} + + +function Grid(props: { gameList: GameList }) { + return (
-
+ {props.gameList.map((game) => {if (game) { + return + } else { + return
+ }})}
); } -function Footer() { +function Footer(props: { has_games: boolean }) { + let text = props.has_games ? "" : "No games right now. Why not head over to Discord and start one?"; return ( ); } export default App; +export type { GameState }; \ No newline at end of file diff --git a/static/css/game.css b/simmadome/src/Game.css similarity index 99% rename from static/css/game.css rename to simmadome/src/Game.css index c60f230..59ae0c5 100644 --- a/static/css/game.css +++ b/simmadome/src/Game.css @@ -1,4 +1,3 @@ - :root { --background-main: #2f3136; /*discord dark theme background-secondary - the same color as the embeds*/ --background-secondary: #4f545c; /*discord's background-tertiary*/ @@ -193,7 +192,7 @@ height: 60px; } -.base_2 { +.field > .base { margin-bottom: -25% } diff --git a/simmadome/src/Game.tsx b/simmadome/src/Game.tsx new file mode 100644 index 0000000..f96fcd8 --- /dev/null +++ b/simmadome/src/Game.tsx @@ -0,0 +1,75 @@ +import { GameState } from './App'; +import './Game.css'; +import base_filled from './img/base_filled.png'; +import base_empty from './img/base_empty.png'; +import out_filled from './img/out_out.png'; +import out_empty from './img/out_in.png'; + +function Game(props: {gameId: string, state : GameState}) { + let state = props.state; + return ( +
+
+
Inning: {state.display_top_of_inning ? "🔼" : "🔽"} {state.display_inning}/{state.max_innings}
+
{state.title}
+
{state.weather_emoji} {state.weather_text}
+
+
+
+ + +
+
+
+ +
+ + +
+
+
+
OUTS
+
+ {[1, 2].map((out) => )} +
+
+
+
+
PITCHER
+
{state.pitcher}
+
BATTER
+
{state.batter}
+
+
+
{state.update_emoji}
+
{state.update_text}
+
+
+
+
{state.display_top_of_inning ? state.away_name : state.home_name} batting.
+
{state.leagueoruser} (share)
+
+
+ ); +} + +function Team(props: {name: string, score: number}) { + return ( +
+
{ props.name }
+
{ props.score }
+
+ ); +} + +function Base(props: {name: string | null}) { + return ( + { + ); +} + +function Out(props: {thisOut: number, totalOuts: number}) { + return ; +} + +export default Game; \ No newline at end of file diff --git a/static/img/base_empty.png b/simmadome/src/img/base_empty.png similarity index 100% rename from static/img/base_empty.png rename to simmadome/src/img/base_empty.png diff --git a/static/img/base_filled.png b/simmadome/src/img/base_filled.png similarity index 100% rename from static/img/base_filled.png rename to simmadome/src/img/base_filled.png diff --git a/static/img/out_in.png b/simmadome/src/img/out_in.png similarity index 100% rename from static/img/out_in.png rename to simmadome/src/img/out_in.png diff --git a/static/img/out_out.png b/simmadome/src/img/out_out.png similarity index 100% rename from static/img/out_out.png rename to simmadome/src/img/out_out.png diff --git a/simmadome/src/index.tsx b/simmadome/src/index.tsx index eaffa81..cb02d92 100644 --- a/simmadome/src/index.tsx +++ b/simmadome/src/index.tsx @@ -8,7 +8,7 @@ import reportWebVitals from './reportWebVitals'; ReactDOM.render(
- + , document.getElementById('root') ); @@ -22,7 +22,7 @@ function Header() { Github
Twitter -

THE SIMMADOME

+

THE SIMMADOME

Join SIBR on to start your own games!

); diff --git a/static/.DS_Store b/static/.DS_Store deleted file mode 100644 index a09a179..0000000 Binary files a/static/.DS_Store and /dev/null differ diff --git a/static/css/common.css b/static/css/common.css deleted file mode 100644 index df22339..0000000 --- a/static/css/common.css +++ /dev/null @@ -1,69 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Alegreya&display=swap'); -@import url('https://fonts.googleapis.com/css2?family=Goldman:wght@700&display=swap'); -body { - background-image: url("naturalblack.png"); -} -/* Background pattern from Toptal Subtle Patterns */ - -div, button, h1, h2, a { - font-family: 'Alegreya', serif; - color: white; -} - -h2 { - text-align: center; -} - -.link{ - position: relative; - top: 10px; -} - -.h1 { - margin: auto; - width: 45%; - color: white; -} - -.page_header { - color: white; - font-family: 'Goldman', cursive; - text-decoration: none; -} - -#header { - width: 100%; - height: max-content; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -#header .page_header { - margin: auto; -} - -#link_div { - text-align: right; - position: absolute; - top: 0px; - right: 30px; -} - -#link_div > a { - background-color: transparent; - text-decoration: underline; -} - -#link_div > a:link, #link_div > a:visited { - color: lightblue; -} - -#link_div > a:hover { - color: white; -} - -img.emoji { - height: 14px; -} \ No newline at end of file diff --git a/static/css/game_page.css b/static/css/game_page.css deleted file mode 100644 index 69f0cc7..0000000 --- a/static/css/game_page.css +++ /dev/null @@ -1,7 +0,0 @@ -#game_container { - margin-top: 3rem; - margin-left: 1rem; - margin-right: 1rem; - display: flex; - justify-content: space-around; -} \ No newline at end of file diff --git a/static/css/games_page.css b/static/css/games_page.css deleted file mode 100644 index d8d9e02..0000000 --- a/static/css/games_page.css +++ /dev/null @@ -1,80 +0,0 @@ -.container { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(32rem, 1fr)); - grid-gap: 50px 30px; /*space between rows, then columns*/ - grid-auto-flow: row; -} - -.emptyslot, .game { - min-height: 18.75rem; - justify-self: center; - max-width: 44rem; -} - -#filters { - display: flex; - justify-content: center; - width: 100%; - align-items: center; - margin-top: 10px; - margin-bottom: 20px; -} - -#filters > * { - padding: 0.25rem 0.5rem; - margin: 0rem 0.5rem; - font-size: 16pt; - background: rgba(0,0,0,0); -} - -#filters > .filter { - border-radius: 0.5rem; - min-width: 6.25rem; - text-align: center; - border: none; - color: white; - text-decoration: none; -} - -#selected_filter { - background: rgb(113, 54, 138); -} - -#footer { - display: flex; - flex-direction: column; - justify-content: center; - width: 100%; - height: 4.5rem; -} - -#footer > div { - text-align: center; - font-size: 16pt; - position: relative; - top: 0.25rem; -} - -.emptyslot { - border: 2px dashed white; - border-radius: 15px; - align-self: stretch; - justify-self: stretch; - text-align: center; - color: white; -} - -@media only screen and (max-device-width: 800px) { - .container { - display: grid; - grid-template-columns: repeat(1, minmax(700px, 90%)); - position: absolute; - left: 50%; - transform: translate(-50%, 0); - } - - .emptyslot { - border: none; - min-height: 0px; - } -} diff --git a/static/css/naturalblack.png b/static/css/naturalblack.png deleted file mode 100644 index e600af5..0000000 Binary files a/static/css/naturalblack.png and /dev/null differ diff --git a/static/css/prism.png b/static/css/prism.png deleted file mode 100644 index 0f02b16..0000000 Binary files a/static/css/prism.png and /dev/null differ diff --git a/static/discord.png b/static/discord.png deleted file mode 100644 index 49dde81..0000000 Binary files a/static/discord.png and /dev/null differ diff --git a/static/js/.DS_Store b/static/js/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/static/js/.DS_Store and /dev/null differ diff --git a/static/js/game_loader.js b/static/js/game_loader.js deleted file mode 100644 index 9bfb447..0000000 --- a/static/js/game_loader.js +++ /dev/null @@ -1,25 +0,0 @@ -$(document).ready(function (){ - var socket = io.connect(); - - socket.on('connect', function () { - console.log("connected") - socket.emit('recieved', {}); - }); - - socket.on("states_update", function (json) { //json is an object containing all game updates - var searchparams = new URLSearchParams(window.location.search); - var exists = false; - for (game of json) { - if (searchparams.get('timestamp') == game.timestamp) { - $('.game').html(game.html); - exists = true; - } - } - if (!exists) { - $('game').remove() - $('#game_container').text("The game you're looking for either doesn't exist or has already ended.") - } - - twemoji.parse(document.body); - }); -}); \ No newline at end of file diff --git a/static/js/grid_loader.js b/static/js/grid_loader.js deleted file mode 100644 index f203bd7..0000000 --- a/static/js/grid_loader.js +++ /dev/null @@ -1,178 +0,0 @@ -var socket = io.connect(); -var lastupdate; -var grid; - -$(document).ready(function (){ - grid = document.getElementById("container") - - socket.on('connect', function () { - socket.emit('recieved', {}); - }); - - socket.on("states_update", function (json) { //json is an object containing all game updates - lastupdate = json; - updateGames(json, $('#selected_filter').text()); - updateLeagues(json); - }); -}); - -const updateGames = (json, filter) => { - - filterjson = []; - for (var game of json) { - if (game.league == filter || filter == "All") { - filterjson.push(game); - } - } - - if (filterjson.length == 0) { - $('#footer div').html("No games right now. Why not head over to Discord and start one?"); - } else { - $('#footer div').html(""); - } - - var searchparams = new URLSearchParams(window.location.search); - if (searchparams.has('game') && filterjson.some(x => x.timestamp == searchparams.get('game')) && grid.children[0].timestamp != searchparams.get('game')) { - var game = filterjson.find(x => x.timestamp == searchparams.get('game')) - var oldbox = Array.prototype.slice.call(grid.children).find(x => x.timestamp == game.timestamp) - if (oldbox) { clearBox(oldbox) } - insertGame(0, game) - } - - //replace games that have ended with empty slots - for (var slotnum = 0; slotnum < grid.children.length; slotnum++) { - if (grid.children[slotnum].className == "game" && !filterjson.some((x) => x.timestamp == grid.children[slotnum].timestamp)) { - clearBox(grid.children[slotnum]) - } - } - - for (var game of filterjson) { - //updates game in list - for (var slotnum = 0; slotnum < grid.children.length; slotnum++) { - if (grid.children[slotnum].timestamp == game.timestamp) { - insertGame(slotnum, game); - }; - }; - - //adds game to list if not there already - if (!Array.prototype.slice.call(grid.children).some(x => x.timestamp == game.timestamp)) { - for (var slotnum = 0; true; slotnum++) { //this is really a while loop but shh don't tell anyone - if (slotnum >= grid.children.length) { - insertEmpty(grid); - } - if (grid.children[slotnum].className == "emptyslot") { - insertGame(slotnum, game); - break; - }; - }; - } - - fillgrid(grid) - }; -} - -const insertEmpty = (grid) => { - var newBox = document.createElement("DIV"); - newBox.className = "emptyslot"; - grid.appendChild(newBox); -} - -const insertGame = (gridboxnum, game) => { - var thisBox = grid.children[gridboxnum]; - thisBox.className = "game"; - thisBox.timestamp = game.timestamp; - thisBox.innerHTML = game.html; - twemoji.parse(thisBox); -}; - -const insertLeague = (league) => { - var btn = document.createElement("BUTTON"); - btn.className = "filter"; - btn.innerHTML = league; - $('#filters').append(btn); - return btn; -} - -const clearBox = (box) => { - box.className = "emptyslot"; - box.timestamp = null; - box.innerHTML = ""; -} - -const fillgrid = (grid) => { - var gridwidth = window.getComputedStyle(grid).getPropertyValue('grid-template-columns').split(" ").length //hack to get number of grid columns - - // add cells to fill last row - while (grid.children.length % gridwidth != 0) { - insertEmpty(grid) - } - - //remove last rows if not needed - while (grid.children.length > gridwidth && Array.prototype.slice.call(grid.children).slice(grid.children.length - gridwidth).every( x => x.className == 'emptyslot')) { - for (var i = 0; i < gridwidth; i++) { - grid.removeChild(grid.children[grid.children.length-1]); - } - } -} - -const updateLeagues = (games) => { - //get all leagues - var leagues = [] - for (var game of games) { - if (game.league != "" && !leagues.includes(game.league)) { - leagues.push(game.league) - } - } - - //remove leagues no longer present - $('#filters .filter').each(function(index) { - if (!leagues.includes($(this).text())) { - if (this.id != 'selected_filter' && $(this).text() != "All") { //don't remove the currently selected filter or the "all" filter - $(this).remove(); - } - } else { - leagues.splice(leagues.indexOf($(this).text()), 1); - } - }) - - // add leagues not already present - for (var league of leagues) { // we removed the entries that are already there in the loop above - insertLeague(league) - } - - //add click handlers to each filter - $('#filters .filter').each(function(index) { - this.onclick = function() { - if ($('#filters #selected_filter').text() == 'All') { - updateGames([], ""); // clear grid when switching off of All, to make games collapse to top - } - $('#filters #selected_filter').attr('id', ''); - this.id = 'selected_filter'; - - var search = new URLSearchParams(); - search.append('league', this.textContent); - history.pushState({}, "", "/" + (this.textContent != 'All' ? "?" + search.toString() : "")); - updateGames(lastupdate, this.textContent); - } - }) -} - -window.onpopstate = function(e) { - var searchparams = new URLSearchParams(window.location.search); - updateLeagues(lastupdate); - $('#filters #selected_filter').attr('id', ''); - if (searchparams.has('league')) { - var filter_found = false - $('#filters .filter').each(function(i) { if (this.textContent == searchparams.get('league')) { this.id = 'selected_filter'; filter_found = true }}); - if (!filter_found) { insertLeague(searchparams.get('league')).id = 'selected_filter' } - - updateGames(lastupdate, searchparams.get('league')); - } else { - $('#filters .filter').each(function(i) { if (this.textContent == 'All') { this.id = 'selected_filter' }}) - updateGames(lastupdate, "All"); - } -} - -window.addEventListener('resize', function(e) { - fillgrid(grid) -}) \ No newline at end of file diff --git a/templates/.DS_Store b/templates/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/templates/.DS_Store and /dev/null differ diff --git a/templates/base.html b/templates/base.html deleted file mode 100644 index ae570d1..0000000 --- a/templates/base.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - ⚾ The Simmadome - - - - - - - - {% block head_tags %}{% endblock %} - - - - - {% block body %}{% endblock %} - - diff --git a/templates/game.html b/templates/game.html deleted file mode 100644 index 944037e..0000000 --- a/templates/game.html +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "base.html" %} -{% block head_tags %} - - - -{% endblock %} -{% block body %} -
-
-
-{% endblock %} \ No newline at end of file diff --git a/templates/game_box.html b/templates/game_box.html deleted file mode 100644 index c4d1d1d..0000000 --- a/templates/game_box.html +++ /dev/null @@ -1,53 +0,0 @@ -{% macro base(number) -%} -src={% if state.bases[number] %}"/static/img/base_filled.png" alt="{{state.bases[number]}}"{% else %}"/static/img/base_empty.png"{% endif %} -{%- endmacro %} -{% macro out(number) -%} -{% if number <= state.outs %}/static/img/out_out.png{% else %}/static/img/out_in.png{% endif %} -{%- endmacro %} -
-
Inning: {% if state.display_top_of_inning == true %}🔼{% else %}🔽{% endif %} {{ state.display_inning }}/{{ state.max_innings }}
-
{{ state.title }}
-
{{ state.weather_emoji }} {{ state.weather_text }}
-
-
-
-
-
{{ state.away_name }}
-
{{ state.away_score }}
-
-
-
{{ state.home_name }}
-
{{ state.home_score }}
-
-
-
-
- -
- - -
-
-
-
OUTS
-
- - -
-
-
-
-
PITCHER
-
{{ state.pitcher }}
-
BATTER
-
{{ state.batter }}
-
-
-
{{ state.update_emoji }}
-
{{ state.update_text }}
-
-
- \ No newline at end of file diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index 0385b01..0000000 --- a/templates/index.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends "base.html" %} -{% block head_tags %} - - - -{% endblock %} -{% block body %} -
-
Filter:
- - {% if league %}{% endif %} -
-
-
-
-
-
- -{% endblock %} \ No newline at end of file