MediaWiki:Gadget-resign-calculator.js: Difference between revisions
Re-sign calculator |
The league is NBA RealGM |
||
| (10 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
/** | /** | ||
* | * NBA RealGM — re-sign salary calculator. | ||
* Implements the formula on [[NBA:Re-Signing]]. If the two ever disagree, | * Implements the formula on [[NBA:Re-Signing]]. If the two ever disagree, | ||
* the wiki page is the rule and this script is the bug. | * the wiki page is the rule and this script is the bug. | ||
| Line 7: | Line 7: | ||
'use strict'; | 'use strict'; | ||
var MAX = 11500000, | // The league numbers a season by the year it ends in, so the season being | ||
// signed for is always the next one up from the current calendar year. | |||
var NEW_POST_URL = 'https://2teams1cup.com/forum/index.php?act=post&do=new_post&f=70'; | |||
var UPCOMING_SEASON = new Date().getFullYear() + 1, | |||
MAX = 11500000, | |||
DISCOUNT = 1500000, | DISCOUNT = 1500000, | ||
CUTOFF = 85; | CUTOFF = 85; | ||
| Line 32: | Line 37: | ||
nonPositive: capped <= 0 | nonPositive: capped <= 0 | ||
}; | }; | ||
} | |||
/** A monospace post block with a copy button. */ | |||
function postBlock( text ) { | |||
var wrap = document.createElement( 'div' ); | |||
wrap.className = 'tc-calc-postwrap'; | |||
var pre = document.createElement( 'div' ); | |||
pre.className = 'tc-calc-post'; | |||
pre.textContent = text; | |||
wrap.appendChild( pre ); | |||
var btn = document.createElement( 'button' ); | |||
btn.className = 'tc-calc-copy'; | |||
btn.type = 'button'; | |||
btn.textContent = 'Copy'; | |||
btn.addEventListener( 'click', function () { | |||
function done( ok ) { | |||
btn.textContent = ok ? 'Copied' : 'Press \u2318C / Ctrl+C'; | |||
setTimeout( function () { btn.textContent = 'Copy'; }, 2000 ); | |||
} | |||
if ( navigator.clipboard && navigator.clipboard.writeText ) { | |||
navigator.clipboard.writeText( text ).then( function () { done( true ); }, | |||
function () { selectFallback( pre ); done( false ); } ); | |||
} else { | |||
selectFallback( pre ); | |||
done( false ); | |||
} | |||
} ); | |||
wrap.appendChild( btn ); | |||
var actions = document.createElement( 'div' ); | |||
actions.className = 'tc-calc-actions'; | |||
var link = document.createElement( 'a' ); | |||
link.href = NEW_POST_URL; | |||
link.target = '_blank'; | |||
link.rel = 'noopener'; | |||
link.textContent = 'Copy and start a new topic in NBA: Re-Signing'; | |||
// IPB has no parameter for seeding the post body, so the next best thing | |||
// is to put it on the clipboard on the way out. | |||
link.addEventListener( 'click', function () { | |||
if ( navigator.clipboard && navigator.clipboard.writeText ) { | |||
navigator.clipboard.writeText( text ); | |||
} | |||
} ); | |||
actions.appendChild( link ); | |||
var outer = document.createElement( 'div' ); | |||
outer.appendChild( wrap ); | |||
outer.appendChild( actions ); | |||
return outer; | |||
} | |||
/** Clipboard API unavailable or refused: select the text so the reader can copy it. */ | |||
function selectFallback( el ) { | |||
var range = document.createRange(); | |||
range.selectNodeContents( el ); | |||
var sel = window.getSelection(); | |||
sel.removeAllRanges(); | |||
sel.addRange( range ); | |||
} | } | ||
| Line 39: | Line 105: | ||
var form = document.createElement( 'div' ); | var form = document.createElement( 'div' ); | ||
form.className = 'tc-calc'; | form.className = 'tc-calc'; | ||
/** | |||
* One labelled row. Controls live in their own flex wrapper so that on a | |||
* narrow screen the label can stack above them while they stay in a row. | |||
*/ | |||
function row( labelText, controls, extraClass ) { | |||
var r = document.createElement( 'div' ); | |||
r.className = 'tc-calc-row' + ( extraClass ? ' ' + extraClass : '' ); | |||
var l = document.createElement( 'label' ); | |||
l.textContent = labelText; | |||
var c = document.createElement( 'div' ); | |||
c.className = 'tc-calc-controls'; | |||
controls.forEach( function ( el ) { c.appendChild( el ); } ); | |||
r.appendChild( l ); | |||
r.appendChild( c ); | |||
form.appendChild( r ); | |||
return c; | |||
} | |||
// --- Fantrax scores --- | // --- Fantrax scores --- | ||
for ( var i = 0; i < 3; i++ ) { | for ( var i = 0; i < 3; i++ ) { | ||
var input = document.createElement( 'input' ); | var input = document.createElement( 'input' ); | ||
| Line 52: | Line 131: | ||
input.min = '0'; | input.min = '0'; | ||
input.placeholder = [ 'season 1', 'season 2', 'season 3' ][ i ]; | input.placeholder = [ 'season 1', 'season 2', 'season 3' ][ i ]; | ||
scoreInputs.push( input ); | scoreInputs.push( input ); | ||
} | } | ||
row( 'Fantrax scores', scoreInputs, 'tc-scores' ); | |||
// --- term --- | // --- term --- | ||
var term = document.createElement( 'select' ); | var term = document.createElement( 'select' ); | ||
[ 3, 4, 5 ].forEach( function ( y ) { | [ 3, 4, 5 ].forEach( function ( y ) { | ||
| Line 75: | Line 143: | ||
term.appendChild( o ); | term.appendChild( o ); | ||
} ); | } ); | ||
row( 'Contract length', [ term ] ); | |||
// --- | // --- first season, to generate the contract line --- | ||
var season = document.createElement( 'input' ); | var season = document.createElement( 'input' ); | ||
season.type = 'number'; | season.type = 'number'; | ||
season.step = '1'; | season.step = '1'; | ||
season.placeholder = ' | season.placeholder = String( UPCOMING_SEASON ); | ||
season.value = String( UPCOMING_SEASON ); | |||
row( 'First season', [ season ] ); | |||
// --- team and player, for the post block --- | |||
var team = document.createElement( 'input' ); | |||
team.type = 'text'; | |||
team.placeholder = 'Sonics'; | |||
team.className = 'tc-calc-wide'; | |||
row( 'Your team (optional)', [ team ] ); | |||
var name = document.createElement( 'input' ); | var name = document.createElement( 'input' ); | ||
name.type = 'text'; | name.type = 'text'; | ||
name.placeholder = 'Larry Bird'; | name.placeholder = 'Larry Bird'; | ||
name. | name.className = 'tc-calc-wide'; | ||
row( 'Player (optional)', [ name ] ); | |||
var out = document.createElement( 'div' ); | var out = document.createElement( 'div' ); | ||
| Line 167: | Line 228: | ||
var years = Number( term.value ), | var years = Number( term.value ), | ||
first = parseInt( season.value, 10 ), | first = parseInt( season.value, 10 ), | ||
who = name.value.trim(); | |||
if ( isNaN( first ) ) { | |||
first = UPCOMING_SEASON; | |||
} | |||
var endYear = first + years - 1; | |||
var | // "Sonics offer Larry Bird 5 years" — team and player drop out if blank. | ||
var tm = team.value.trim(), | |||
term_ = years + ( years === 1 ? ' year' : ' years' ), | |||
prefix = tm && who ? tm + ' offer ' + who : | |||
( who || ( tm ? tm + ' offer' : '' ) ); | |||
var | var lines = [ prefix ? prefix + ' ' + term_ : term_ ]; | ||
lines.push( '(' + scores.join( ', ' ) + ' = ' + | |||
( Number.isInteger( r.average ) ? r.average : r.average.toFixed( 2 ) ) + ')' ); | |||
lines.push( money( r.salary ) + ' (' + endYear + ')' ); | |||
out.appendChild( postBlock( lines.join( '\n' ) ) ); | |||
out.appendChild( | |||
} | } | ||
[].concat( scoreInputs, [ term, season, name ] ).forEach( function ( el ) { | [].concat( scoreInputs, [ term, season, team, name ] ).forEach( function ( el ) { | ||
el.addEventListener( 'input', render ); | el.addEventListener( 'input', render ); | ||
el.addEventListener( 'change', render ); | el.addEventListener( 'change', render ); | ||