Skip to content

Instantly share code, notes, and snippets.

@msikma
Last active May 24, 2022 17:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msikma/bcd6161221fef37a6d3b76e646d0fc76 to your computer and use it in GitHub Desktop.
Save msikma/bcd6161221fef37a6d3b76e646d0fc76 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name SumoDB - Rikishi win/loss record highlighter
// @namespace http://sumodb.sumogames.de/
// @version 0.1.1
// @description Highlights wrestlers' kachikoshi records
// @author dada78641
// @match http*://sumodb.sumogames.de/Rikishi.aspx?r=*
// @grant none
// ==/UserScript==
// TODO: add support for earlier basho (5 half, 11 full / 7 half, 13 full)
// support for 'a' (?) and 'd' (draw)
(function() {
'use strict';
/** Adds a style tag to make our enhancements visible. */
const addStyles = () => {
document.head.insertAdjacentHTML(
'beforeend',
`<style>
tr.kachikoshi td { background: rgba(255, 155, 0, 0.1) }
tr.kachikoshi.yuushou td { background: rgba(255, 95, 0, 0.2) }
tr.makuuchi.kachikoshi td { background: rgba(0, 255, 0, 0.1) }
tr.makuuchi.kachikoshi.junyuushou td { background: rgba(0, 255, 255, 0.1) }
tr.makuuchi.kachikoshi.yuushou td { background: rgba(0, 255, 255, 0.3) }
</style>`
);
}
/** Returns true if a given rank ('Ms', 'O', 'J', etc.) is makuuchi. */
const _isMakuuchiRank = (rank) => {
return rank === 'M' || rank === 'S' || rank === 'K' || rank === 'O' || rank === 'Y'
}
/** Converts a Japanese rank string to English. */
const _jpnRankToEng = (rank) => {
if (rank === '口') return 'Jk'
if (rank === '二') return 'Jd'
if (rank === '三') return 'Sd'
if (rank === '下') return 'Ms'
if (rank === '十') return 'J'
if (rank === '前') return 'M'
if (rank === '小結') return 'K'
if (rank === '関脇') return 'S'
if (rank === '大関') return 'O'
if (rank === '横綱') return 'Y'
return null
}
/** Returns the type of basho the wrestler competed in (half or full number of matches). */
const getBashoType = (win, loss, kyu) => {
const combined = win + loss + kyu
if (combined === 7) return [combined, 'lowerRanks']
if (combined === 15) return [combined, 'higherRanks']
return [combined, 'maezumo']
}
/** Returns whether the wrestler had a KK. */
const getKachikoshiStatus = (win, bouts) => {
return win > Math.floor(bouts / 2)
}
/**
* Returns information about a wrestler's rank, and whether it's in makuuchi or not.
*
* Given strings are either Japanese or English, but the result is returned in English.
*/
const getRankType = (rankStr) => {
// Hardcoded setting for maezumo since it's outside the regular ranking.
if (rankStr === '前相' || rankStr === 'Mz') {
return [{ rank: 'Mz', level: 0, dir: null }, false]
}
const matchEng = rankStr.match(/^([a-z]+)([0-9]+)?([a-z]+)?/i)
const matchJpn = rankStr.match(/^(東|西)([^0-9]*)([0-9]+)?/i)
if (matchJpn) {
const [_, dirVal, rankVal, level] = matchJpn
const dir = dirVal === '東' ? 'e' : 'w'
const rank = _jpnRankToEng(rankVal)
return [{ rank, level: Number(matchJpn[3]), dir }, _isMakuuchiRank(rank)]
}
if (matchEng) {
const [_, rank, level, dir] = matchEng
return [{ rank, level: Number(level), dir }, _isMakuuchiRank(rank)]
}
return [{ rank: null, level: 0, dir: null }, false]
}
/** Returns whether this basho was a jun-yuushou or yuushou. */
const getYuushouStatus = (etc) => {
const isJunYuushou = etc === 'J' || etc === '準'
const isYuushou = etc === 'Y' || etc === '優'
return [isJunYuushou, isYuushou]
}
/** Returns a basho's win/loss/kyuujou record. */
const getWinLossAbsenceStatus = (wlText) => {
if (~wlText.indexOf('勝')) {
const wl = wlText.match(/(([0-9]{1,2})勝)(([0-9]{1,2})敗)(([0-9]{1,2})休)? ?(.*)?$/)
const [_, __, win, ___, loss, ____, kyu] = wl.map(i => Number(i) || 0)
const status = wl[7]
return [win, loss, kyu, status]
}
else {
const wl = wlText.match(/([0-9]{1,2})-([0-9]{1,2})-?([0-9]{1,2})? ?(.*)?$/)
const [_, win, loss, kyu] = wl.map(i => Number(i) || 0)
const status = wl[4]
return [win, loss, kyu, status]
}
}
/**
* Highlights a wrestler's basho records.
*/
const highlightBasho = () => {
document.querySelectorAll('.rikishi tr').forEach(tr => {
const tds = tr.querySelectorAll('td')
// Skip headers.
if (tds.length === 0) return
// Match the wrestler's win/loss/absence record.
const [win, loss, kyu, etc] = getWinLossAbsenceStatus(tr.querySelector('.wl').innerText.trim())
const [isJunYuushou, isYuushou] = getYuushouStatus(etc)
// Determine the basho type (half number of matches or full number), rank, and winning record.
const [bouts, bashoType] = getBashoType(win, loss, kyu)
const [rank, isMakuuchi] = getRankType(tr.querySelector('td:nth-child(2)').innerText.trim())
const isKK = getKachikoshiStatus(win, bouts)
if (bashoType === 'maezumo') return
if (isMakuuchi) tr.classList.add('makuuchi')
if (isJunYuushou) tr.classList.add('junyuushou')
if (isYuushou) tr.classList.add('yuushou')
tr.classList.add(isKK ? 'kachikoshi' : 'makekoshi')
})
}
addStyles()
highlightBasho()
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment