strikeout.co scores

inclues game info on strikeout.co main page

当前为 2016-04-16 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         strikeout.co scores
// @namespace    http://your.homepage/
// @version      0.9
// @description  inclues game info on strikeout.co main page
// @author       muffleyd
// @match        http://www.strikeout.co/
// @grant        $
// ==/UserScript==

/** Copywrite David Muffley 2015-2016.
 * Use however you like, with acknowledgement.
 */

(function () {
//_main() won't run through if tab is hidden, this stores when that occurs so on tab visibility it can run again
var SKIPPED = false

var addedClasses = ['_tmMLBFree', '_tmESPN']
var selectorParent = '#content h1[league="Major League Baseball"]'

function parseTime(time) {
    //time can be in format of "10:35" or timezone like "-03:30" or "+9:30"
    var mod = 1
    if (time[0] == '-' || time[0] == '+') {
        if (time[0] == '-') {
            mod = -1
        }
        time = time.substring(1)
    }
    time = time.split(':')
    return mod * ((parseInt(time[0]) * 60) + parseInt(time[1]))
}
//set "mlbgday" attr to match mlb.com's scoreboard since "gday" attribute may not match mlb's date, based on timezone
(function () {
    var timezoneMod = parseTime(timezone) + 240 // + 240 makes this effectively eastern time, close enough
    $(selectorParent + ' .matchtime').each(function (index, el) {
        var val = el.getAttribute('gday')
        //even at -12:00 it can't be behind by a day, it can only ever be ahead by a day all the way to +13:00
        if (parseTime(el.innerText) - timezoneMod < 0) {
            var dateObj = new Date(val)
            dateObj.setTime(dateObj.getTime() - (86400 * 1000))
            val = dateObj.toJSON().slice(0, 10)
        }
        el.setAttribute('mlbgday', val)
    })
})()

//pass an optional delay in
// when waking up from sleep the network connection is not immediately active, this allows you to compensate for that
function main(delay) {
    if (!delay) {
        delay = 0
    }
    setTimeout(_main, delay * 1000)
}

// 5 hours in the past, for when it's after midnight, not sure if needed
function _main() {
    //skip when tab is hidden or window is minimized, and set so event is later told to run main()
    if (document.hidden) {
        SKIPPED = true
        return
    }
    var dateObj = new Date()

    //offset the computer's timezone to get UTC, then go back 10 hours to guarantee you use the correct date for mlb.com
    var date = new Date(dateObj.getTime() + (dateObj.getTimezoneOffset() * 60 * 1000) - (1000 * 60 * 60 * 10))
    var year = date.getFullYear().toString()

    //January is 0, etc, so add 1
    var month = date.getMonth() + 1
    if (month < 10) {
        month = "0" + month.toString()
    } else {
        month = month.toString()
    }
    var day = date.getDate()
    if (day < 10) {
        day = "0" + day.toString()
    } else {
        day = day.toString()
    }
    $.getJSON('http://gd2.mlb.com/components/game/mlb/year_' + year + '/month_' + month + '/day_' + day + '/miniscoreboard.json', function (resp, type) {
        if (type == 'success') {
            $(document).ready(function () {
                //clear previously added classes to elements
                addedClasses.forEach(function (item) {
                    $(selectorParent).removeClass(item)
                })
                var info = resp.data.games.game
                if (info.length === undefined) { //if only one game, it's not passed back as an array
                    info = [info]
                }
                var gameObj = {}
                //on later runs, remove added text immediately
                $(selectorParent + ' a ._tmInfo').remove()
                //get all team names from today
                $(selectorParent + ' a:has(span[mlbgday="' + year + '-' + month + '-' + day + '"])').each(function (index, el) {
                    var gameText = el.lastChild.textContent.trim()
                    //Find games missing the colon before "Game #" and add it in
                    gameText = gameText.replace(/([^:])(\s+[Gg]ame\s+[0-9]+)$/, '$1:$2')
                    //this match regex handles things like:
                    //   Team vs Team
                    //   Team vs Team: Game 2
                    //   MLB Wildcard: Team vs Team
                    //   ALDS: Team vs Team: Game 1
                    //regex split is for occasional non-space blank character (tab has been there)
                    var txt = gameText.match(/([^:]+:|^)(.*?vs[^:$]+)(.*)/)
                    if (txt === null) {
                        console.log('not a game', gameText)
                        //something like "MLB on Fox Sports 1 Pregame"
                        return
                    }
                    var texts = txt[2].split(/\s+vs\s+/)
                    texts.forEach(function (item) {
                        var splitItems = item.trim().split(/\s+/)
                        //strip out this special thing that has appeared during spring training
                        if (splitItems[splitItems.length-1] == '(ss)') {
                            splitItems.pop()
                        }
                        splitItems.forEach (function (item, index, arr) {
                            //combine all words after the first, getting smaller and smaller,
                            //because of things like "Chicago White Sox" while avoiding "Los Angeles Dodgers"
                            if (index == 0) {
                                return
                            }
                            var key = arr.slice(index).join(' ')
                            if (!gameObj.hasOwnProperty(key)) {
                                gameObj[key] = []
                            }
                            //place at the head since the (reversed) game array goes from the beginning of gameObj[key]
                            //include the original text so extra stuff can stay when rewriting it later
                            gameObj[key].unshift([el, txt])
                        })
                    })
                })
                //fix differences
                if (gameObj.hasOwnProperty('Diamondbacks')) {
                    gameObj['D-backs'] = gameObj['Diamondbacks']
                }
                console.log(gameObj)
                //sort handles out of order games in the info list which happens sometimes with resumed games or double headers
                info.sort(function (a, b) {
                    //test for NaN because sometimes "time" is like "Game 2"
                    var t1 = a.time.split(':')
                    t1 = (t1[0] * 60) + (1*t1[1])
                    if (isNaN(t1)) {
                        return 0
                    }
                    var t2 = b.time.split(':')
                    t2 = (t2[0] * 60) + (1*t2[1])
                    if (isNaN(t2)) {
                        return 0
                    }
                    //note that mlb.com returns all times as ET
                    //some games start at 12:35pm, and rarely in the 11am hour, while never being 11pm or later
                    //since there's no 24 hour time these need to be set as being before 1pm
                    if (t1 >= 11*60) {
                        t1 -= (12*60)
                    }
                    if (t2 >= 11*60) {
                        t2 -= (12*60)
                    }
                    //
                    if (t1 < t2) {
                        return -1
                    }
                    if (t1 > t2) {
                        return 1
                    }
                    return 0
                })
                info.reverse()
                info.forEach(function (item, index, arr) {
                    var unknownStatus = false
                    var delayed = false
                    var postponed = false
                    var stop = false
                    var media = true
                    if (item.status == 'Pre-Game' || item.status == 'Preview') {
                        //after removing the first item this will return
                        stop = true
                    } else if (item.status == 'In Progress' || item.status == 'Review' || item.status == 'Manager Challenge') {
                        //good
                    } else if (item.status == 'Game Over' || item.status == 'Final') {
                        //good
                        media = false
                    } else if (item.status == 'Delayed Start' || item.status == 'Delayed') {
                        //delay, but good
                        delayed = true
                    } else if (item.status == 'Warmup') {
                        //good
                    } else if (item.status == 'Postponed' || item.status == 'Suspended') {
                        postponed = true
                    } else {
                        unknownStatus = true
                        console.log('other status:', item.status, item)
                    }
                    console.log(item.away_team_name, item.home_team_name)
                    if (!gameObj.hasOwnProperty(item.away_team_name) || !gameObj.hasOwnProperty(item.home_team_name)) {
                        return
                    }
                    var gameEl = gameObj[item.away_team_name][0][0]
                    var originalMainText = gameObj[item.away_team_name][0][1]
                    if (gameEl !== gameObj[item.home_team_name][0][0]) {
                        //cry
                        console.log('mismatch', item)
                    } else if (gameEl) {
                        //pop off the game values, in case of double header
                        gameObj[item.away_team_name].shift()
                        gameObj[item.home_team_name].shift()
                        console.log(item, gameEl)

                        //for double headers, now that the game is popped off we can return
                        if (stop) {
                            return
                        }

                        if (media) {
                            handle_game_media(item, gameEl)
                        }

                        var text = ''
                        var cls = ''
                        if (item.status == 'Warmup') {
                            text = 'Warmup'
                            cls = 'warmup'
                        } else {
                            if (item.status == 'Game Over' || item.status == 'Final') {
                                text = 'Final'
                                cls = 'final'
                            } else {
                                if (postponed) {
                                    cls = 'postponed'
                                }
                                //Top 3, Bottom 5, Middle 7, etc
                                if (item.hasOwnProperty('inning')) {
                                    text = (item.top_inning == "Y" ? "Top" : "Bottom") + ' ' + item.inning
                                    if (item.inning >= 7 && (item.away_team_hits == 0 || item.home_team_hits == 0)) {
                                        cls += ' noHitter'
                                    }
                                }
                            }
                            if (item.hasOwnProperty('away_team_runs') && item.hasOwnProperty('home_team_runs')) {
                                text += ', ' + item.away_team_runs + '-' + item.home_team_runs
                                var parens = true
                            } else {
                                parens = false
                            }
                            if (delayed || postponed) {
                                text += ' '
                                if (parens) {
                                    text += '('
                                }
                                text += item.status
                                if (item.reason) {
                                    text += ': ' + item.reason
                                }
                                if (parens) {
                                    text += ')'
                                }
                            }
                        }
                        if (unknownStatus) {
                            text += ' DEBUG:' + item.status
                        }
                        //get original text surrounding the 'Team vs Team' to include along with the reordering of the Teams to Away vs Home
                        gameEl.lastChild.textContent = originalMainText[1] + ' ' + getTeamName(item, 'away') + ' vs ' + getTeamName(item, 'home') + originalMainText[3]
                        if (text) {
                            $('<span class="_tmInfo">, <span class="_tmText ' + cls + '">' + text + '</span></span>').appendTo(gameEl)
                        }
                    }
                })
            })
        }
    })
}

function handle_game_media(item, gameEl) {
    if (item.game_media && item.game_media.media) {
        var media = item.game_media.media
        if ($.isArray(item.game_media.media)) {
            media = item.game_media.media[0]
        }
        if (media.free != "NO") {
            if (media.free != "ALL") {
                console.log('different media free info', media)
            }
            gameEl.parentElement.classList.add('_tmMLBFree')
        }
    }
    if (item.tv_station) {
        item.tv_station.split(', ').forEach(function (station) {
            if (station == 'ESPN' || station == 'ESPN2') {
                gameEl.parentElement.classList.add('_tmESPN')
            }
        })
    }
}

//example why this is needed:
//team_city: 'NY Yankees'
//team_name: 'Yankees'
//Should return 'NY Yankees' rather than 'NY Yankees Yankees'
function getTeamName(item, homeaway) {
    var city = item[homeaway + '_team_city']
    var name = item[homeaway + '_team_name']
    if (city.slice(-name.length) == name) {
        return city
    } else {
        return city + ' ' + name
    }
}

var initial_delay = 6
var constant_delay = 120

main()
//this blob compensates for 'initial_delay'
// e.g. main loop runs every 2 minutes, with a 6 second initial delay,
// this will wait 115 seconds to run main(6) and register the Interval of 120 seconds at the same time to run main(6)
setTimeout(function () {
    main(initial_delay)
    setInterval(main, 1000 * constant_delay, initial_delay)
}, 1000 * (constant_delay - initial_delay))

//since we don't do anything when the tab is invisible, force an update when made visible if one was skipped
document.addEventListener('visibilitychange', function () {
    if (!document.hidden) {
        if (SKIPPED) {
            SKIPPED = false
            main()
        }
    }
})


function addGlobalStyle(css) {
    var head, style;
    head = document.getElementsByTagName('head')[0];
    if (!head) { return; }
    style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = css;
    head.appendChild(style);
}

addGlobalStyle('._tmInfo ._tmText { color: red; }');
addGlobalStyle('._tmInfo ._tmText.warmup { color: goldenrod; }');
addGlobalStyle('._tmInfo ._tmText.final { color: grey; }');
addGlobalStyle('._tmInfo ._tmText.postponed { color: blue; }');
addGlobalStyle('._tmInfo ._tmText.noHitter { background: chartreuse; }');

addGlobalStyle(selectorParent + '._tmMLBFree { background: gold; }');
addGlobalStyle(selectorParent + '._tmESPN { background: rgba(255,7,7,.25); }');
})()